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