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.
Files changed (413) hide show
  1. wxcli/__init__.py +4 -0
  2. wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
  3. wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
  4. wxcli/_playbook/.claude/rules/cleanup.md +29 -0
  5. wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
  6. wxcli/_playbook/.claude/rules/org-health.md +14 -0
  7. wxcli/_playbook/.claude/settings.json +8 -0
  8. wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
  9. wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
  10. wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
  11. wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
  12. wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
  13. wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
  14. wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
  15. wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
  16. wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
  17. wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
  18. wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
  19. wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
  20. wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
  21. wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
  22. wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
  23. wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
  24. wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
  25. wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
  26. wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
  27. wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
  28. wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
  29. wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
  30. wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
  31. wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
  32. wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
  33. wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
  34. wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
  35. wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
  36. wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
  37. wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
  38. wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
  39. wxcli/_playbook/CLAUDE.md +373 -0
  40. wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
  41. wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
  42. wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
  43. wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
  44. wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
  45. wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
  46. wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
  47. wxcli/_playbook/docs/reference/admin-partner.md +357 -0
  48. wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
  49. wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
  50. wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
  51. wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
  52. wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
  53. wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
  54. wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
  55. wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
  56. wxcli/_playbook/docs/reference/authentication.md +965 -0
  57. wxcli/_playbook/docs/reference/call-control.md +1205 -0
  58. wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
  59. wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
  60. wxcli/_playbook/docs/reference/call-routing.md +2304 -0
  61. wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
  62. wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
  63. wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
  64. wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
  65. wxcli/_playbook/docs/reference/devices-core.md +1869 -0
  66. wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
  67. wxcli/_playbook/docs/reference/devices-platform.md +467 -0
  68. wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
  69. wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
  70. wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
  71. wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
  72. wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
  73. wxcli/_playbook/docs/reference/meetings-content.md +473 -0
  74. wxcli/_playbook/docs/reference/meetings-core.md +903 -0
  75. wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
  76. wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
  77. wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
  78. wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
  79. wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
  80. wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
  81. wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
  82. wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
  83. wxcli/_playbook/docs/reference/provisioning.md +1366 -0
  84. wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
  85. wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
  86. wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
  87. wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
  88. wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
  89. wxcli/_version.py +24 -0
  90. wxcli/auth.py +137 -0
  91. wxcli/commands/__init__.py +0 -0
  92. wxcli/commands/_registry.py +181 -0
  93. wxcli/commands/activation_email.py +103 -0
  94. wxcli/commands/admin_recordings.py +585 -0
  95. wxcli/commands/analytics.py +105 -0
  96. wxcli/commands/announcement_playlists.py +219 -0
  97. wxcli/commands/announcements.py +519 -0
  98. wxcli/commands/archive_users.py +36 -0
  99. wxcli/commands/attachment_actions.py +60 -0
  100. wxcli/commands/audit_events.py +83 -0
  101. wxcli/commands/authorizations.py +113 -0
  102. wxcli/commands/auto_attendant.py +642 -0
  103. wxcli/commands/broadworks_billing_reports.py +126 -0
  104. wxcli/commands/broadworks_enterprises.py +160 -0
  105. wxcli/commands/broadworks_subscribers.py +319 -0
  106. wxcli/commands/broadworks_workspaces.py +108 -0
  107. wxcli/commands/call_controls.py +1304 -0
  108. wxcli/commands/call_park.py +494 -0
  109. wxcli/commands/call_pickup.py +229 -0
  110. wxcli/commands/call_queue.py +1878 -0
  111. wxcli/commands/call_recording.py +707 -0
  112. wxcli/commands/call_routing.py +1610 -0
  113. wxcli/commands/call_settings_for_me_phase_5.py +212 -0
  114. wxcli/commands/caller_reputation.py +169 -0
  115. wxcli/commands/calling_service.py +305 -0
  116. wxcli/commands/cc_address_book.py +770 -0
  117. wxcli/commands/cc_agent_greetings.py +242 -0
  118. wxcli/commands/cc_agent_summaries.py +39 -0
  119. wxcli/commands/cc_agent_wellbeing.py +216 -0
  120. wxcli/commands/cc_agents.py +425 -0
  121. wxcli/commands/cc_ai_assistant.py +55 -0
  122. wxcli/commands/cc_ai_feature.py +294 -0
  123. wxcli/commands/cc_audio_files.py +149 -0
  124. wxcli/commands/cc_auto_csat.py +311 -0
  125. wxcli/commands/cc_aux_code.py +458 -0
  126. wxcli/commands/cc_business_hour.py +353 -0
  127. wxcli/commands/cc_call_monitoring.py +228 -0
  128. wxcli/commands/cc_callbacks.py +194 -0
  129. wxcli/commands/cc_campaign.py +212 -0
  130. wxcli/commands/cc_captures.py +39 -0
  131. wxcli/commands/cc_contact_list.py +169 -0
  132. wxcli/commands/cc_contact_number.py +295 -0
  133. wxcli/commands/cc_data_sources.py +235 -0
  134. wxcli/commands/cc_desktop_layout.py +380 -0
  135. wxcli/commands/cc_desktop_profile.py +322 -0
  136. wxcli/commands/cc_dial_number.py +511 -0
  137. wxcli/commands/cc_dial_plan.py +347 -0
  138. wxcli/commands/cc_dnc.py +101 -0
  139. wxcli/commands/cc_entry_point.py +545 -0
  140. wxcli/commands/cc_ewt.py +51 -0
  141. wxcli/commands/cc_flow.py +477 -0
  142. wxcli/commands/cc_global_vars.py +430 -0
  143. wxcli/commands/cc_holiday_list.py +335 -0
  144. wxcli/commands/cc_journey.py +1261 -0
  145. wxcli/commands/cc_legacy_flows.py +49 -0
  146. wxcli/commands/cc_multimedia_profile.py +436 -0
  147. wxcli/commands/cc_notification.py +51 -0
  148. wxcli/commands/cc_outdial_ani.py +604 -0
  149. wxcli/commands/cc_overrides.py +341 -0
  150. wxcli/commands/cc_queue.py +1083 -0
  151. wxcli/commands/cc_queue_stats.py +55 -0
  152. wxcli/commands/cc_realtime.py +51 -0
  153. wxcli/commands/cc_resource_collection.py +312 -0
  154. wxcli/commands/cc_search.py +46 -0
  155. wxcli/commands/cc_site.py +400 -0
  156. wxcli/commands/cc_skill.py +350 -0
  157. wxcli/commands/cc_skill_profile.py +289 -0
  158. wxcli/commands/cc_subscriptions.py +426 -0
  159. wxcli/commands/cc_summaries.py +130 -0
  160. wxcli/commands/cc_tasks.py +844 -0
  161. wxcli/commands/cc_team.py +325 -0
  162. wxcli/commands/cc_user_profiles.py +349 -0
  163. wxcli/commands/cc_users.py +701 -0
  164. wxcli/commands/cc_work_types.py +363 -0
  165. wxcli/commands/cdr.py +89 -0
  166. wxcli/commands/classifications.py +38 -0
  167. wxcli/commands/cleanup.py +1427 -0
  168. wxcli/commands/client_settings.py +72 -0
  169. wxcli/commands/conference.py +328 -0
  170. wxcli/commands/configure.py +72 -0
  171. wxcli/commands/converged_recordings.py +347 -0
  172. wxcli/commands/converged_recordings_export.py +310 -0
  173. wxcli/commands/cq_playlists.py +42 -0
  174. wxcli/commands/cucm.py +2794 -0
  175. wxcli/commands/cucm_config.py +129 -0
  176. wxcli/commands/customer_assist.py +373 -0
  177. wxcli/commands/data_sources.py +227 -0
  178. wxcli/commands/dect_devices.py +787 -0
  179. wxcli/commands/device_configurations.py +77 -0
  180. wxcli/commands/device_dynamic_settings.py +320 -0
  181. wxcli/commands/device_settings.py +1489 -0
  182. wxcli/commands/devices.py +280 -0
  183. wxcli/commands/domains.py +142 -0
  184. wxcli/commands/ecm.py +178 -0
  185. wxcli/commands/emergency_services.py +827 -0
  186. wxcli/commands/events.py +83 -0
  187. wxcli/commands/external_voicemail.py +52 -0
  188. wxcli/commands/groups.py +206 -0
  189. wxcli/commands/guest_management.py +76 -0
  190. wxcli/commands/hds.py +340 -0
  191. wxcli/commands/hot_desk.py +67 -0
  192. wxcli/commands/hot_desking_members.py +118 -0
  193. wxcli/commands/hot_desking_portal.py +124 -0
  194. wxcli/commands/hunt_group.py +577 -0
  195. wxcli/commands/hybrid_clusters.py +71 -0
  196. wxcli/commands/hybrid_connectors.py +67 -0
  197. wxcli/commands/identity_org.py +159 -0
  198. wxcli/commands/init_playbook.py +155 -0
  199. wxcli/commands/licenses.py +106 -0
  200. wxcli/commands/live_monitoring.py +40 -0
  201. wxcli/commands/location_call_handling.py +577 -0
  202. wxcli/commands/location_schedules.py +341 -0
  203. wxcli/commands/location_settings.py +1297 -0
  204. wxcli/commands/location_voicemail.py +494 -0
  205. wxcli/commands/locations.py +336 -0
  206. wxcli/commands/meeting_captions.py +110 -0
  207. wxcli/commands/meeting_chats.py +63 -0
  208. wxcli/commands/meeting_invitees.py +234 -0
  209. wxcli/commands/meeting_messages.py +28 -0
  210. wxcli/commands/meeting_participants.py +278 -0
  211. wxcli/commands/meeting_polls.py +111 -0
  212. wxcli/commands/meeting_preferences.py +515 -0
  213. wxcli/commands/meeting_qa.py +78 -0
  214. wxcli/commands/meeting_qualities.py +43 -0
  215. wxcli/commands/meeting_reports.py +101 -0
  216. wxcli/commands/meeting_session_types.py +105 -0
  217. wxcli/commands/meeting_site.py +57 -0
  218. wxcli/commands/meeting_slido.py +44 -0
  219. wxcli/commands/meeting_summaries.py +92 -0
  220. wxcli/commands/meeting_tracking_codes.py +233 -0
  221. wxcli/commands/meeting_transcripts.py +230 -0
  222. wxcli/commands/meetings.py +1997 -0
  223. wxcli/commands/memberships.py +164 -0
  224. wxcli/commands/messages.py +213 -0
  225. wxcli/commands/mode_management.py +244 -0
  226. wxcli/commands/my_call_settings.py +3577 -0
  227. wxcli/commands/numbers.py +405 -0
  228. wxcli/commands/operating_modes.py +410 -0
  229. wxcli/commands/org_contacts.py +284 -0
  230. wxcli/commands/org_health_cli.py +55 -0
  231. wxcli/commands/org_settings.py +71 -0
  232. wxcli/commands/organizations.py +83 -0
  233. wxcli/commands/paging_group.py +257 -0
  234. wxcli/commands/partner_admins.py +141 -0
  235. wxcli/commands/partner_reports.py +188 -0
  236. wxcli/commands/partner_tags.py +216 -0
  237. wxcli/commands/people.py +279 -0
  238. wxcli/commands/person_call_settings.py +71 -0
  239. wxcli/commands/pstn.py +280 -0
  240. wxcli/commands/recording_report.py +154 -0
  241. wxcli/commands/report_templates.py +38 -0
  242. wxcli/commands/reports.py +144 -0
  243. wxcli/commands/resource_group_memberships.py +160 -0
  244. wxcli/commands/resource_groups.py +67 -0
  245. wxcli/commands/roles.py +63 -0
  246. wxcli/commands/room_tabs.py +160 -0
  247. wxcli/commands/rooms.py +225 -0
  248. wxcli/commands/scim_bulk.py +46 -0
  249. wxcli/commands/scim_groups.py +246 -0
  250. wxcli/commands/scim_schemas.py +82 -0
  251. wxcli/commands/scim_users.py +283 -0
  252. wxcli/commands/security_audit.py +54 -0
  253. wxcli/commands/service_apps.py +51 -0
  254. wxcli/commands/single_number_reach.py +209 -0
  255. wxcli/commands/team_memberships.py +155 -0
  256. wxcli/commands/teams.py +153 -0
  257. wxcli/commands/ucm_profile.py +42 -0
  258. wxcli/commands/update.py +219 -0
  259. wxcli/commands/user_settings.py +5116 -0
  260. wxcli/commands/video_mesh.py +1090 -0
  261. wxcli/commands/virtual_extensions.py +502 -0
  262. wxcli/commands/virtual_line_settings.py +2072 -0
  263. wxcli/commands/webhooks.py +176 -0
  264. wxcli/commands/wholesale_billing_reports.py +147 -0
  265. wxcli/commands/wholesale_provisioning.py +523 -0
  266. wxcli/commands/workspace_locations.py +339 -0
  267. wxcli/commands/workspace_metrics.py +103 -0
  268. wxcli/commands/workspace_personalization.py +70 -0
  269. wxcli/commands/workspace_settings.py +3347 -0
  270. wxcli/commands/workspaces.py +279 -0
  271. wxcli/commands/xapi.py +114 -0
  272. wxcli/config.py +139 -0
  273. wxcli/errors.py +77 -0
  274. wxcli/main.py +210 -0
  275. wxcli/migration/CLAUDE.md +106 -0
  276. wxcli/migration/__init__.py +1 -0
  277. wxcli/migration/advisory/CLAUDE.md +196 -0
  278. wxcli/migration/advisory/__init__.py +46 -0
  279. wxcli/migration/advisory/advisor.py +107 -0
  280. wxcli/migration/advisory/advisory_patterns.py +2552 -0
  281. wxcli/migration/advisory/recommendation_rules.py +835 -0
  282. wxcli/migration/cucm/CLAUDE.md +74 -0
  283. wxcli/migration/cucm/__init__.py +5 -0
  284. wxcli/migration/cucm/connection.py +265 -0
  285. wxcli/migration/cucm/discovery.py +225 -0
  286. wxcli/migration/cucm/extractors/__init__.py +1 -0
  287. wxcli/migration/cucm/extractors/announcements.py +92 -0
  288. wxcli/migration/cucm/extractors/base.py +90 -0
  289. wxcli/migration/cucm/extractors/device_profiles.py +98 -0
  290. wxcli/migration/cucm/extractors/devices.py +193 -0
  291. wxcli/migration/cucm/extractors/e911.py +103 -0
  292. wxcli/migration/cucm/extractors/features.py +309 -0
  293. wxcli/migration/cucm/extractors/helpers.py +73 -0
  294. wxcli/migration/cucm/extractors/informational.py +295 -0
  295. wxcli/migration/cucm/extractors/locations.py +221 -0
  296. wxcli/migration/cucm/extractors/moh.py +100 -0
  297. wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
  298. wxcli/migration/cucm/extractors/routing.py +493 -0
  299. wxcli/migration/cucm/extractors/shared_lines.py +146 -0
  300. wxcli/migration/cucm/extractors/templates.py +229 -0
  301. wxcli/migration/cucm/extractors/tier4.py +173 -0
  302. wxcli/migration/cucm/extractors/users.py +240 -0
  303. wxcli/migration/cucm/extractors/voicemail.py +243 -0
  304. wxcli/migration/cucm/extractors/workspaces.py +88 -0
  305. wxcli/migration/cucm/unity_connection.py +304 -0
  306. wxcli/migration/execute/CLAUDE.md +372 -0
  307. wxcli/migration/execute/__init__.py +303 -0
  308. wxcli/migration/execute/batch.py +277 -0
  309. wxcli/migration/execute/dependency.py +483 -0
  310. wxcli/migration/execute/engine.py +964 -0
  311. wxcli/migration/execute/handlers.py +2232 -0
  312. wxcli/migration/execute/planner.py +1939 -0
  313. wxcli/migration/execute/runtime.py +571 -0
  314. wxcli/migration/export/CLAUDE.md +49 -0
  315. wxcli/migration/export/__init__.py +8 -0
  316. wxcli/migration/export/csv_export.py +126 -0
  317. wxcli/migration/export/deployment_plan.py +479 -0
  318. wxcli/migration/export/json_export.py +60 -0
  319. wxcli/migration/models.py +941 -0
  320. wxcli/migration/phone_models.py +50 -0
  321. wxcli/migration/preflight/CLAUDE.md +52 -0
  322. wxcli/migration/preflight/__init__.py +89 -0
  323. wxcli/migration/preflight/checks.py +911 -0
  324. wxcli/migration/preflight/runner.py +293 -0
  325. wxcli/migration/rate_limiter.py +144 -0
  326. wxcli/migration/report/CLAUDE.md +245 -0
  327. wxcli/migration/report/__init__.py +7 -0
  328. wxcli/migration/report/appendix.py +2437 -0
  329. wxcli/migration/report/assembler.py +183 -0
  330. wxcli/migration/report/charts.py +263 -0
  331. wxcli/migration/report/executive.py +776 -0
  332. wxcli/migration/report/explainer.py +704 -0
  333. wxcli/migration/report/helpers.py +74 -0
  334. wxcli/migration/report/ingest.py +152 -0
  335. wxcli/migration/report/notice_templates.py +192 -0
  336. wxcli/migration/report/score.py +375 -0
  337. wxcli/migration/report/styles.py +1052 -0
  338. wxcli/migration/report/user_diff.py +1052 -0
  339. wxcli/migration/report/user_notice.py +425 -0
  340. wxcli/migration/state.py +139 -0
  341. wxcli/migration/store.py +860 -0
  342. wxcli/migration/transform/CLAUDE.md +107 -0
  343. wxcli/migration/transform/__init__.py +12 -0
  344. wxcli/migration/transform/analysis_pipeline.py +453 -0
  345. wxcli/migration/transform/analyzers/__init__.py +142 -0
  346. wxcli/migration/transform/analyzers/css_permission.py +189 -0
  347. wxcli/migration/transform/analyzers/css_routing.py +335 -0
  348. wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
  349. wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
  350. wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
  351. wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
  352. wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
  353. wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
  354. wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
  355. wxcli/migration/transform/analyzers/missing_data.py +300 -0
  356. wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
  357. wxcli/migration/transform/analyzers/shared_line.py +170 -0
  358. wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
  359. wxcli/migration/transform/analyzers/workspace_license.py +212 -0
  360. wxcli/migration/transform/cross_reference.py +1136 -0
  361. wxcli/migration/transform/cucm_pattern.py +246 -0
  362. wxcli/migration/transform/decisions.py +301 -0
  363. wxcli/migration/transform/e164.py +145 -0
  364. wxcli/migration/transform/engine.py +256 -0
  365. wxcli/migration/transform/mappers/CLAUDE.md +123 -0
  366. wxcli/migration/transform/mappers/__init__.py +76 -0
  367. wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
  368. wxcli/migration/transform/mappers/base.py +190 -0
  369. wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
  370. wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
  371. wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
  372. wxcli/migration/transform/mappers/css_mapper.py +868 -0
  373. wxcli/migration/transform/mappers/dect_mapper.py +367 -0
  374. wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
  375. wxcli/migration/transform/mappers/device_mapper.py +227 -0
  376. wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
  377. wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
  378. wxcli/migration/transform/mappers/e911_mapper.py +129 -0
  379. wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
  380. wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
  381. wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
  382. wxcli/migration/transform/mappers/line_mapper.py +310 -0
  383. wxcli/migration/transform/mappers/location_mapper.py +235 -0
  384. wxcli/migration/transform/mappers/moh_mapper.py +114 -0
  385. wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
  386. wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
  387. wxcli/migration/transform/mappers/routing_mapper.py +821 -0
  388. wxcli/migration/transform/mappers/snr_mapper.py +201 -0
  389. wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
  390. wxcli/migration/transform/mappers/user_mapper.py +264 -0
  391. wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
  392. wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
  393. wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
  394. wxcli/migration/transform/normalizers.py +2008 -0
  395. wxcli/migration/transform/pattern_converter.py +106 -0
  396. wxcli/migration/transform/pipeline.py +271 -0
  397. wxcli/migration/transform/rules.py +255 -0
  398. wxcli/org_health/CLAUDE.md +63 -0
  399. wxcli/org_health/__init__.py +7 -0
  400. wxcli/org_health/analyze.py +93 -0
  401. wxcli/org_health/checks.py +458 -0
  402. wxcli/org_health/collector.py +62 -0
  403. wxcli/org_health/models.py +78 -0
  404. wxcli/org_health/report.py +300 -0
  405. wxcli/output.py +101 -0
  406. wxcli-1.2.0.dist-info/METADATA +505 -0
  407. wxcli-1.2.0.dist-info/RECORD +413 -0
  408. wxcli-1.2.0.dist-info/WHEEL +5 -0
  409. wxcli-1.2.0.dist-info/entry_points.txt +2 -0
  410. wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
  411. wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
  412. wxcli-1.2.0.dist-info/scm_version.json +8 -0
  413. wxcli-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,101 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+
7
+
8
+ app = typer.Typer(help="Manage Webex Meetings meeting-reports.")
9
+
10
+
11
+ @app.command("list")
12
+ def cmd_list(
13
+ site_url: str = typer.Option(..., "--site-url", help="URL of the Webex site which the API lists meeting usage repo"),
14
+ service_type: str = typer.Option(None, "--service-type", help="Meeting usage report's service-type. If `serviceType` is spe"),
15
+ from_param: str = typer.Option(None, "--from", help="Starting date and time for meeting usage reports to return,"),
16
+ to: str = typer.Option(None, "--to", help="Ending date and time for meeting usage reports to return, in"),
17
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
18
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
19
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
20
+ debug: bool = typer.Option(False, "--debug"),
21
+ ):
22
+ """List Meeting Usage Reports."""
23
+ api = get_api(debug=debug)
24
+ url = f"https://webexapis.com/v1/meetingReports/usage"
25
+ params = {}
26
+ if site_url is not None:
27
+ params["siteUrl"] = site_url
28
+ if service_type is not None:
29
+ params["serviceType"] = service_type
30
+ if from_param is not None:
31
+ params["from"] = from_param
32
+ if to is not None:
33
+ params["to"] = to
34
+ if limit > 0:
35
+ params["max"] = limit
36
+ if offset > 0:
37
+ params["start"] = offset
38
+ try:
39
+ if limit > 0:
40
+ result = api.session.rest_get(url, params=params)
41
+ result = result or {}
42
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
43
+ else:
44
+ items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
45
+ except WebexError as e:
46
+ handle_rest_error(e)
47
+ if output == "json":
48
+ print_json(items)
49
+ else:
50
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
51
+
52
+
53
+
54
+ @app.command("list-attendees")
55
+ def list_attendees(
56
+ site_url: str = typer.Option(..., "--site-url", help="URL of the Webex site which the API lists meeting attendee r"),
57
+ from_param: str = typer.Option(None, "--from", help="Starting date and time for the meeting attendee reports to r"),
58
+ to: str = typer.Option(None, "--to", help="Ending date and time for the meeting attendee reports to ret"),
59
+ meeting_id: str = typer.Option(None, "--meeting-id", help="Meeting ID for the meeting attendee reports to return. If sp"),
60
+ meeting_number: str = typer.Option(None, "--meeting-number", help="Meeting number for the meeting attendee reports to return. I"),
61
+ meeting_title: str = typer.Option(None, "--meeting-title", help="Meeting title for the meeting attendee reports to return. If"),
62
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
63
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
64
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
65
+ debug: bool = typer.Option(False, "--debug"),
66
+ ):
67
+ """List Meeting Attendee Reports."""
68
+ api = get_api(debug=debug)
69
+ url = f"https://webexapis.com/v1/meetingReports/attendees"
70
+ params = {}
71
+ if site_url is not None:
72
+ params["siteUrl"] = site_url
73
+ if from_param is not None:
74
+ params["from"] = from_param
75
+ if to is not None:
76
+ params["to"] = to
77
+ if meeting_id is not None:
78
+ params["meetingId"] = meeting_id
79
+ if meeting_number is not None:
80
+ params["meetingNumber"] = meeting_number
81
+ if meeting_title is not None:
82
+ params["meetingTitle"] = meeting_title
83
+ if limit > 0:
84
+ params["max"] = limit
85
+ if offset > 0:
86
+ params["start"] = offset
87
+ try:
88
+ if limit > 0:
89
+ result = api.session.rest_get(url, params=params)
90
+ result = result or {}
91
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
92
+ else:
93
+ items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
94
+ except WebexError as e:
95
+ handle_rest_error(e)
96
+ if output == "json":
97
+ print_json(items)
98
+ else:
99
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
100
+
101
+
@@ -0,0 +1,105 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+
7
+
8
+ app = typer.Typer(help="Manage Webex Meetings meeting-session-types.")
9
+
10
+
11
+ @app.command("list")
12
+ def cmd_list(
13
+ site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site to query. If siteUrl is not specified,"),
14
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
15
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
16
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
17
+ debug: bool = typer.Option(False, "--debug"),
18
+ ):
19
+ """List Site Session Types."""
20
+ api = get_api(debug=debug)
21
+ url = f"https://webexapis.com/v1/admin/meeting/config/sessionTypes"
22
+ params = {}
23
+ if site_url is not None:
24
+ params["siteUrl"] = site_url
25
+ if limit > 0:
26
+ params["max"] = limit
27
+ if offset > 0:
28
+ params["start"] = offset
29
+ result = None
30
+ try:
31
+ result = api.session.rest_get(url, params=params)
32
+ except WebexError as e:
33
+ handle_rest_error(e)
34
+ result = result or []
35
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
36
+ if output == "json":
37
+ print_json(items)
38
+ else:
39
+ print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Type', 'type')], limit=limit)
40
+
41
+
42
+
43
+ @app.command("list-session-types")
44
+ def list_session_types(
45
+ site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site to query."),
46
+ person_id: str = typer.Option(None, "--person-id", help="A unique identifier for the user."),
47
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
48
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
49
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
50
+ debug: bool = typer.Option(False, "--debug"),
51
+ ):
52
+ """List User Session Type."""
53
+ api = get_api(debug=debug)
54
+ url = f"https://webexapis.com/v1/admin/meeting/userconfig/sessionTypes"
55
+ params = {}
56
+ if site_url is not None:
57
+ params["siteUrl"] = site_url
58
+ if person_id is not None:
59
+ params["personId"] = person_id
60
+ if limit > 0:
61
+ params["max"] = limit
62
+ if offset > 0:
63
+ params["start"] = offset
64
+ result = None
65
+ try:
66
+ result = api.session.rest_get(url, params=params)
67
+ except WebexError as e:
68
+ handle_rest_error(e)
69
+ result = result or []
70
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
71
+ if output == "json":
72
+ print_json(items)
73
+ else:
74
+ print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Type', 'type')], limit=limit)
75
+
76
+
77
+
78
+ @app.command("update")
79
+ def update(
80
+ site_url: str = typer.Option(None, "--site-url", help="Site URL for the session type."),
81
+ person_id: str = typer.Option(None, "--person-id", help="A unique identifier for the user."),
82
+ email: str = typer.Option(None, "--email", help="The email of the user."),
83
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
84
+ debug: bool = typer.Option(False, "--debug"),
85
+ ):
86
+ """Update User Session Types\n\nExample --json-body:\n '{"siteUrl":"...","sessionTypeIds":["..."],"personId":"...","email":"..."}'."""
87
+ api = get_api(debug=debug)
88
+ url = f"https://webexapis.com/v1/admin/meeting/userconfig/sessionTypes"
89
+ if json_body:
90
+ body = json.loads(json_body)
91
+ else:
92
+ body = {}
93
+ if site_url is not None:
94
+ body["siteUrl"] = site_url
95
+ if person_id is not None:
96
+ body["personId"] = person_id
97
+ if email is not None:
98
+ body["email"] = email
99
+ try:
100
+ result = api.session.rest_put(url, json=body)
101
+ except WebexError as e:
102
+ handle_rest_error(e)
103
+ typer.echo(f"Updated.")
104
+
105
+
@@ -0,0 +1,57 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+
7
+
8
+ app = typer.Typer(help="Manage Webex Meetings meeting-site.")
9
+
10
+
11
+ @app.command("show")
12
+ def show(
13
+ site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site which the API queries common settings"),
14
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
15
+ debug: bool = typer.Option(False, "--debug"),
16
+ ):
17
+ """Get Meeting Common Settings Configuration."""
18
+ api = get_api(debug=debug)
19
+ url = f"https://webexapis.com/v1/admin/meeting/config/commonSettings"
20
+ params = {}
21
+ if site_url is not None:
22
+ params["siteUrl"] = site_url
23
+ try:
24
+ result = api.session.rest_get(url, params=params)
25
+ except WebexError as e:
26
+ handle_rest_error(e)
27
+ if output == "json":
28
+ print_json(result)
29
+ else:
30
+ if isinstance(result, dict):
31
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
32
+ elif isinstance(result, list):
33
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
34
+ else:
35
+ print_json(result)
36
+
37
+
38
+
39
+ @app.command("update")
40
+ def update(
41
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
42
+ debug: bool = typer.Option(False, "--debug"),
43
+ ):
44
+ """Update Meeting Common Settings Configuration\n\nExample --json-body:\n '{"siteOptions":{"allowCustomPersonalRoomURL":true},"defaultSchedulerOptions":{"entryAndExitTone":"NoTone","telephonySupport":"None","joinTeleconfNotPress1":true,"tollFree":true,"VoIP":true},"scheduleMeetingOptions":{"emailReminders":true},"securityOptions":{"joinBeforeHost":true,"audioBeforeHost":true,"firstAttendeeAsPresenter":true,"unlistAllMeetings":true,"requireLoginBeforeAccess":true,"allowMobileScreenCapture":true,"requireStrongPassword":true,"passwordCriteria":{"mixedCase":"...","minLength":"...","minNumeric":"...","minAlpha":"...","minSpecial":"...","disallowDynamicWebText":"...","disallowList":"...","disallowValues":"..."}}}'."""
45
+ api = get_api(debug=debug)
46
+ url = f"https://webexapis.com/v1/admin/meeting/config/commonSettings"
47
+ if json_body:
48
+ body = json.loads(json_body)
49
+ else:
50
+ body = {}
51
+ try:
52
+ result = api.session.rest_patch(url, json=body)
53
+ except WebexError as e:
54
+ handle_rest_error(e)
55
+ typer.echo(f"Updated.")
56
+
57
+
@@ -0,0 +1,44 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+
7
+
8
+ app = typer.Typer(help="Manage Webex Meetings meeting-slido.")
9
+
10
+
11
+ @app.command("list")
12
+ def cmd_list(
13
+ session_org_id: str = typer.Option(..., "--session-org-id", help="Webex organization UUID."),
14
+ session_id: str = typer.Option(..., "--session-id", help="Webex meeting instance ID (`{meetingSeriesId}_I_{conferenceI"),
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
+ """List Compliance Events."""
21
+ api = get_api(debug=debug)
22
+ url = f"https://webexapis.com/v1/slido/compliance/events"
23
+ params = {}
24
+ if session_org_id is not None:
25
+ params["sessionOrgId"] = session_org_id
26
+ if session_id is not None:
27
+ params["sessionId"] = session_id
28
+ if limit > 0:
29
+ params["max"] = limit
30
+ if offset > 0:
31
+ params["start"] = offset
32
+ result = None
33
+ try:
34
+ result = api.session.rest_get(url, params=params)
35
+ except WebexError as e:
36
+ handle_rest_error(e)
37
+ result = result or []
38
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
39
+ if output == "json":
40
+ print_json(items)
41
+ else:
42
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
43
+
44
+
@@ -0,0 +1,92 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+
7
+
8
+ app = typer.Typer(help="Manage Webex Meetings meeting-summaries.")
9
+
10
+
11
+ @app.command("list")
12
+ def cmd_list(
13
+ meeting_id: str = typer.Option(None, "--meeting-id", help="Unique identifier for the [meeting instance](/docs/meetings#"),
14
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
15
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
16
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
17
+ debug: bool = typer.Option(False, "--debug"),
18
+ ):
19
+ """Get Summary by Meeting ID."""
20
+ api = get_api(debug=debug)
21
+ url = f"https://webexapis.com/v1/meetingSummaries"
22
+ params = {}
23
+ if meeting_id is not None:
24
+ params["meetingId"] = meeting_id
25
+ if limit > 0:
26
+ params["max"] = limit
27
+ if offset > 0:
28
+ params["start"] = offset
29
+ result = None
30
+ try:
31
+ result = api.session.rest_get(url, params=params)
32
+ except WebexError as e:
33
+ handle_rest_error(e)
34
+ result = result or []
35
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
36
+ if output == "json":
37
+ print_json(items)
38
+ else:
39
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
40
+
41
+
42
+
43
+ @app.command("list-meeting-summaries")
44
+ def list_meeting_summaries(
45
+ meeting_id: str = typer.Option(None, "--meeting-id", help="Unique identifier for the [meeting instance](/docs/meetings#"),
46
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
47
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
48
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
49
+ debug: bool = typer.Option(False, "--debug"),
50
+ ):
51
+ """Get Summary For Compliance Officer."""
52
+ api = get_api(debug=debug)
53
+ url = f"https://webexapis.com/v1/admin/meetingSummaries"
54
+ params = {}
55
+ if meeting_id is not None:
56
+ params["meetingId"] = meeting_id
57
+ if limit > 0:
58
+ params["max"] = limit
59
+ if offset > 0:
60
+ params["start"] = offset
61
+ result = None
62
+ try:
63
+ result = api.session.rest_get(url, params=params)
64
+ except WebexError as e:
65
+ handle_rest_error(e)
66
+ result = result or []
67
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
68
+ if output == "json":
69
+ print_json(items)
70
+ else:
71
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
72
+
73
+
74
+
75
+ @app.command("delete")
76
+ def delete(
77
+ summary_id: str = typer.Argument(help="summaryId"),
78
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
79
+ debug: bool = typer.Option(False, "--debug"),
80
+ ):
81
+ """Delete a Summary."""
82
+ if not force:
83
+ typer.confirm(f"Delete {summary_id}?", abort=True)
84
+ api = get_api(debug=debug)
85
+ url = f"https://webexapis.com/v1/meetingSummaries/{summary_id}"
86
+ try:
87
+ api.session.rest_delete(url)
88
+ except WebexError as e:
89
+ handle_rest_error(e)
90
+ typer.echo(f"Deleted: {summary_id}")
91
+
92
+
@@ -0,0 +1,233 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+
7
+
8
+ app = typer.Typer(help="Manage Webex Meetings meeting-tracking-codes.")
9
+
10
+
11
+ @app.command("list")
12
+ def cmd_list(
13
+ site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site which the API retrieves the tracking c"),
14
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
15
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
16
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
17
+ debug: bool = typer.Option(False, "--debug"),
18
+ ):
19
+ """List Tracking Codes."""
20
+ api = get_api(debug=debug)
21
+ url = f"https://webexapis.com/v1/admin/meeting/config/trackingCodes"
22
+ params = {}
23
+ if site_url is not None:
24
+ params["siteUrl"] = site_url
25
+ if limit > 0:
26
+ params["max"] = limit
27
+ if offset > 0:
28
+ params["start"] = offset
29
+ result = None
30
+ try:
31
+ result = api.session.rest_get(url, params=params)
32
+ except WebexError as e:
33
+ handle_rest_error(e)
34
+ result = result or []
35
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
36
+ if output == "json":
37
+ print_json(items)
38
+ else:
39
+ print_table(items, columns=[('Name', 'name'), ('Site URL', 'siteUrl'), ('Service', 'service')], limit=limit)
40
+
41
+
42
+
43
+ @app.command("create")
44
+ def create(
45
+ name: str = typer.Option(None, "--name", help="(required) Name for tracking code. The name cannot be empty and the max"),
46
+ site_url: str = typer.Option(None, "--site-url", help="(required) Site URL for the tracking code."),
47
+ input_mode: str = typer.Option(None, "--input-mode", help="(required) Choices: text, select, editableSelect, hostProfileSelect"),
48
+ host_profile_code: str = typer.Option(None, "--host-profile-code", help="(required) Choices: optional, required, adminSet, notUsed"),
49
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
50
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
51
+ debug: bool = typer.Option(False, "--debug"),
52
+ ):
53
+ """Create a Tracking Code\n\nExample --json-body:\n '{"name":"...","siteUrl":"...","options":[{"value":"...","defaultValue":"..."}],"inputMode":"text","hostProfileCode":"optional","scheduleStartCodes":[{"service":"...","type":"..."}]}'."""
54
+ api = get_api(debug=debug)
55
+ url = f"https://webexapis.com/v1/admin/meeting/config/trackingCodes"
56
+ if json_body:
57
+ body = json.loads(json_body)
58
+ else:
59
+ body = {}
60
+ if name is not None:
61
+ body["name"] = name
62
+ if site_url is not None:
63
+ body["siteUrl"] = site_url
64
+ if input_mode is not None:
65
+ body["inputMode"] = input_mode
66
+ if host_profile_code is not None:
67
+ body["hostProfileCode"] = host_profile_code
68
+ _missing = [f for f in ['name', 'siteUrl', 'inputMode', 'hostProfileCode'] if f not in body or body[f] is None]
69
+ if _missing:
70
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
71
+ raise typer.Exit(1)
72
+ try:
73
+ result = api.session.rest_post(url, json=body)
74
+ except WebexError as e:
75
+ handle_rest_error(e)
76
+ if output == "json":
77
+ print_json(result)
78
+ elif isinstance(result, dict) and "id" in result:
79
+ typer.echo(f"Created: {result['id']}")
80
+ elif not result or result == {}:
81
+ typer.echo("Created.")
82
+ else:
83
+ print_json(result)
84
+
85
+
86
+
87
+ @app.command("show")
88
+ def show(
89
+ tracking_code_id: str = typer.Argument(help="trackingCodeId"),
90
+ site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site which the API retrieves the tracking c"),
91
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
92
+ debug: bool = typer.Option(False, "--debug"),
93
+ ):
94
+ """Get a Tracking Code."""
95
+ api = get_api(debug=debug)
96
+ url = f"https://webexapis.com/v1/admin/meeting/config/trackingCodes/{tracking_code_id}"
97
+ params = {}
98
+ if site_url is not None:
99
+ params["siteUrl"] = site_url
100
+ try:
101
+ result = api.session.rest_get(url, params=params)
102
+ except WebexError as e:
103
+ handle_rest_error(e)
104
+ if output == "json":
105
+ print_json(result)
106
+ else:
107
+ if isinstance(result, dict):
108
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
109
+ elif isinstance(result, list):
110
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
111
+ else:
112
+ print_json(result)
113
+
114
+
115
+
116
+ @app.command("update")
117
+ def update(
118
+ name: str = typer.Option(None, "--name", help="Name for tracking code. The name cannot be empty and the max"),
119
+ site_url: str = typer.Option(None, "--site-url", help="Site URL for the tracking code."),
120
+ input_mode: str = typer.Option(None, "--input-mode", help="Choices: text, select, editableSelect, hostProfileSelect"),
121
+ host_profile_code: str = typer.Option(None, "--host-profile-code", help="Choices: optional, required, adminSet, notUsed"),
122
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
123
+ debug: bool = typer.Option(False, "--debug"),
124
+ ):
125
+ """Update a Tracking Code\n\nExample --json-body:\n '{"name":"...","siteUrl":"...","options":[{"value":"...","defaultValue":"..."}],"inputMode":"text","hostProfileCode":"optional","scheduleStartCodes":[{"service":"...","type":"..."}]}'."""
126
+ api = get_api(debug=debug)
127
+ url = f"https://webexapis.com/v1/admin/meeting/config/trackingCodes/{trackingCodeId}"
128
+ if json_body:
129
+ body = json.loads(json_body)
130
+ else:
131
+ body = {}
132
+ if name is not None:
133
+ body["name"] = name
134
+ if site_url is not None:
135
+ body["siteUrl"] = site_url
136
+ if input_mode is not None:
137
+ body["inputMode"] = input_mode
138
+ if host_profile_code is not None:
139
+ body["hostProfileCode"] = host_profile_code
140
+ try:
141
+ result = api.session.rest_put(url, json=body)
142
+ except WebexError as e:
143
+ handle_rest_error(e)
144
+ typer.echo(f"Updated.")
145
+
146
+
147
+
148
+ @app.command("delete")
149
+ def delete(
150
+ tracking_code_id: str = typer.Argument(help="trackingCodeId"),
151
+ site_url: str = typer.Option(..., "--site-url", help="URL of the Webex site from which the API deletes the trackin"),
152
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
153
+ debug: bool = typer.Option(False, "--debug"),
154
+ ):
155
+ """Delete a Tracking Code."""
156
+ if not force:
157
+ typer.confirm(f"Delete {tracking_code_id}?", abort=True)
158
+ api = get_api(debug=debug)
159
+ url = f"https://webexapis.com/v1/admin/meeting/config/trackingCodes/{tracking_code_id}"
160
+ params = {}
161
+ if site_url is not None:
162
+ params["siteUrl"] = site_url
163
+ try:
164
+ api.session.rest_delete(url, params=params)
165
+ except WebexError as e:
166
+ handle_rest_error(e)
167
+ typer.echo(f"Deleted: {tracking_code_id}")
168
+
169
+
170
+
171
+ @app.command("list-tracking-codes")
172
+ def list_tracking_codes(
173
+ site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site from which the API retrieves the track"),
174
+ person_id: str = typer.Option(None, "--person-id", help="Unique identifier for the user whose tracking codes are bein"),
175
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
176
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
177
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
178
+ debug: bool = typer.Option(False, "--debug"),
179
+ ):
180
+ """Get User Tracking Codes."""
181
+ api = get_api(debug=debug)
182
+ url = f"https://webexapis.com/v1/admin/meeting/userconfig/trackingCodes"
183
+ params = {}
184
+ if site_url is not None:
185
+ params["siteUrl"] = site_url
186
+ if person_id is not None:
187
+ params["personId"] = person_id
188
+ if limit > 0:
189
+ params["max"] = limit
190
+ if offset > 0:
191
+ params["start"] = offset
192
+ result = None
193
+ try:
194
+ result = api.session.rest_get(url, params=params)
195
+ except WebexError as e:
196
+ handle_rest_error(e)
197
+ result = result or []
198
+ items = result.get("trackingCodes", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
199
+ if output == "json":
200
+ print_json(items)
201
+ else:
202
+ print_table(items, columns=[('Name', 'name'), ('Site URL', 'siteUrl'), ('Service', 'service')], limit=limit)
203
+
204
+
205
+
206
+ @app.command("update-tracking-codes")
207
+ def update_tracking_codes(
208
+ site_url: str = typer.Option(None, "--site-url", help="Site URL for the tracking code."),
209
+ person_id: str = typer.Option(None, "--person-id", help="Unique identifier for the user. At least one parameter of `p"),
210
+ email: str = typer.Option(None, "--email", help="Email address for the user. At least one parameter of `perso"),
211
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
212
+ debug: bool = typer.Option(False, "--debug"),
213
+ ):
214
+ """Update User Tracking Codes\n\nExample --json-body:\n '{"siteUrl":"...","personId":"...","email":"...","trackingCodes":[{"name":"...","value":"..."}]}'."""
215
+ api = get_api(debug=debug)
216
+ url = f"https://webexapis.com/v1/admin/meeting/userconfig/trackingCodes"
217
+ if json_body:
218
+ body = json.loads(json_body)
219
+ else:
220
+ body = {}
221
+ if site_url is not None:
222
+ body["siteUrl"] = site_url
223
+ if person_id is not None:
224
+ body["personId"] = person_id
225
+ if email is not None:
226
+ body["email"] = email
227
+ try:
228
+ result = api.session.rest_put(url, json=body)
229
+ except WebexError as e:
230
+ handle_rest_error(e)
231
+ typer.echo(f"Updated.")
232
+
233
+