light-phone-api 0.1.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 (294) hide show
  1. light_api/__init__.py +11 -0
  2. light_api/client.py +273 -0
  3. light_api/music.py +552 -0
  4. light_api/notes.py +228 -0
  5. light_api/podcast.py +177 -0
  6. light_api/tools.py +175 -0
  7. light_phone_api-0.1.0.dist-info/METADATA +11 -0
  8. light_phone_api-0.1.0.dist-info/RECORD +294 -0
  9. light_phone_api-0.1.0.dist-info/WHEEL +4 -0
  10. open_api_specification_client/__init__.py +8 -0
  11. open_api_specification_client/api/__init__.py +1 -0
  12. open_api_specification_client/api/default/__init__.py +1 -0
  13. open_api_specification_client/api/default/delete_api_audios_audio_id.py +102 -0
  14. open_api_specification_client/api/default/delete_api_device_tools_device_tool_id.py +102 -0
  15. open_api_specification_client/api/default/delete_api_followed_podcasts_followed_podcast_id.py +165 -0
  16. open_api_specification_client/api/default/delete_api_notes_note_id.py +102 -0
  17. open_api_specification_client/api/default/get_api_audio_capacity.py +168 -0
  18. open_api_specification_client/api/default/get_api_devices.py +136 -0
  19. open_api_specification_client/api/default/get_api_followed_podcasts.py +168 -0
  20. open_api_specification_client/api/default/get_api_notes.py +166 -0
  21. open_api_specification_client/api/default/get_api_notes_note_id.py +192 -0
  22. open_api_specification_client/api/default/get_api_notes_note_id_generate_presigned_get_url.py +165 -0
  23. open_api_specification_client/api/default/get_api_notes_note_id_generate_presigned_put_url.py +165 -0
  24. open_api_specification_client/api/default/get_api_playlist_items.py +183 -0
  25. open_api_specification_client/api/default/get_api_playlists.py +168 -0
  26. open_api_specification_client/api/default/get_api_podcasts.py +168 -0
  27. open_api_specification_client/api/default/get_api_tools.py +166 -0
  28. open_api_specification_client/api/default/get_api_tools_tool_id.py +163 -0
  29. open_api_specification_client/api/default/get_api_users_current.py +136 -0
  30. open_api_specification_client/api/default/patch_api_audios_audio_id.py +184 -0
  31. open_api_specification_client/api/default/patch_api_notes_note_id.py +192 -0
  32. open_api_specification_client/api/default/patch_api_playlist_items_playlist_item_id.py +186 -0
  33. open_api_specification_client/api/default/post_api_audios.py +168 -0
  34. open_api_specification_client/api/default/post_api_audios_delete_all.py +103 -0
  35. open_api_specification_client/api/default/post_api_authorizations.py +160 -0
  36. open_api_specification_client/api/default/post_api_device_tools.py +168 -0
  37. open_api_specification_client/api/default/post_api_followed_podcasts.py +168 -0
  38. open_api_specification_client/api/default/post_api_notes.py +168 -0
  39. open_api_specification_client/api/default/post_api_playlists_sort_mode.py +168 -0
  40. open_api_specification_client/api/default/post_api_podcasts.py +168 -0
  41. open_api_specification_client/client.py +268 -0
  42. open_api_specification_client/errors.py +16 -0
  43. open_api_specification_client/models/__init__.py +719 -0
  44. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200.py +117 -0
  45. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_data_item.py +105 -0
  46. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_data_item_attributes.py +69 -0
  47. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_data_item_relationships.py +89 -0
  48. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_data_item_relationships_device_tool.py +73 -0
  49. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_data_item_relationships_device_tool_data.py +69 -0
  50. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_data_item_relationships_podcast.py +73 -0
  51. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_data_item_relationships_podcast_data.py +69 -0
  52. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_included_item.py +115 -0
  53. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_included_item_attributes.py +134 -0
  54. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_included_item_attributes_config.py +47 -0
  55. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_included_item_relationships.py +89 -0
  56. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_included_item_relationships_device.py +73 -0
  57. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_included_item_relationships_device_data.py +69 -0
  58. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_included_item_relationships_tool.py +73 -0
  59. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_included_item_relationships_tool_data.py +69 -0
  60. open_api_specification_client/models/delete_api_followed_podcasts_followed_podcast_id_response_200_jsonapi.py +61 -0
  61. open_api_specification_client/models/get_api_audio_capacity_response_200.py +85 -0
  62. open_api_specification_client/models/get_api_devices_response_200.py +103 -0
  63. open_api_specification_client/models/get_api_devices_response_200_data_item.py +99 -0
  64. open_api_specification_client/models/get_api_devices_response_200_data_item_attributes.py +85 -0
  65. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships.py +115 -0
  66. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships_device_tool_location.py +71 -0
  67. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships_device_tool_location_data.py +69 -0
  68. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships_device_tools.py +79 -0
  69. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships_device_tools_data_item.py +69 -0
  70. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships_sim.py +71 -0
  71. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships_sim_data.py +69 -0
  72. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships_user.py +71 -0
  73. open_api_specification_client/models/get_api_devices_response_200_data_item_relationships_user_data.py +69 -0
  74. open_api_specification_client/models/get_api_devices_response_200_included_item.py +101 -0
  75. open_api_specification_client/models/get_api_devices_response_200_included_item_attributes.py +132 -0
  76. open_api_specification_client/models/get_api_devices_response_200_included_item_attributes_config.py +114 -0
  77. open_api_specification_client/models/get_api_devices_response_200_included_item_attributes_config_address.py +117 -0
  78. open_api_specification_client/models/get_api_devices_response_200_included_item_relationships.py +117 -0
  79. open_api_specification_client/models/get_api_devices_response_200_included_item_relationships_device.py +71 -0
  80. open_api_specification_client/models/get_api_devices_response_200_included_item_relationships_device_data.py +69 -0
  81. open_api_specification_client/models/get_api_devices_response_200_included_item_relationships_tool.py +71 -0
  82. open_api_specification_client/models/get_api_devices_response_200_included_item_relationships_tool_data.py +69 -0
  83. open_api_specification_client/models/get_api_devices_response_200_included_item_relationships_user.py +71 -0
  84. open_api_specification_client/models/get_api_devices_response_200_included_item_relationships_user_data.py +69 -0
  85. open_api_specification_client/models/get_api_devices_response_200_jsonapi.py +61 -0
  86. open_api_specification_client/models/get_api_followed_podcasts_response_200.py +107 -0
  87. open_api_specification_client/models/get_api_followed_podcasts_response_200_data_item.py +101 -0
  88. open_api_specification_client/models/get_api_followed_podcasts_response_200_data_item_attributes.py +69 -0
  89. open_api_specification_client/models/get_api_followed_podcasts_response_200_data_item_relationships.py +85 -0
  90. open_api_specification_client/models/get_api_followed_podcasts_response_200_data_item_relationships_device_tool.py +71 -0
  91. open_api_specification_client/models/get_api_followed_podcasts_response_200_data_item_relationships_device_tool_data.py +69 -0
  92. open_api_specification_client/models/get_api_followed_podcasts_response_200_data_item_relationships_podcast.py +71 -0
  93. open_api_specification_client/models/get_api_followed_podcasts_response_200_data_item_relationships_podcast_data.py +69 -0
  94. open_api_specification_client/models/get_api_followed_podcasts_response_200_included_item.py +111 -0
  95. open_api_specification_client/models/get_api_followed_podcasts_response_200_included_item_attributes.py +155 -0
  96. open_api_specification_client/models/get_api_followed_podcasts_response_200_included_item_attributes_config.py +47 -0
  97. open_api_specification_client/models/get_api_followed_podcasts_response_200_included_item_relationships.py +85 -0
  98. open_api_specification_client/models/get_api_followed_podcasts_response_200_included_item_relationships_device.py +71 -0
  99. open_api_specification_client/models/get_api_followed_podcasts_response_200_included_item_relationships_device_data.py +69 -0
  100. open_api_specification_client/models/get_api_followed_podcasts_response_200_included_item_relationships_tool.py +71 -0
  101. open_api_specification_client/models/get_api_followed_podcasts_response_200_included_item_relationships_tool_data.py +69 -0
  102. open_api_specification_client/models/get_api_followed_podcasts_response_200_jsonapi.py +61 -0
  103. open_api_specification_client/models/get_api_notes_note_id_generate_presigned_get_url_response_200.py +61 -0
  104. open_api_specification_client/models/get_api_notes_note_id_generate_presigned_put_url_response_200.py +61 -0
  105. open_api_specification_client/models/get_api_notes_note_id_response_200.py +97 -0
  106. open_api_specification_client/models/get_api_notes_note_id_response_200_data.py +94 -0
  107. open_api_specification_client/models/get_api_notes_note_id_response_200_data_attributes.py +88 -0
  108. open_api_specification_client/models/get_api_notes_note_id_response_200_included_item.py +96 -0
  109. open_api_specification_client/models/get_api_notes_note_id_response_200_included_item_attributes.py +61 -0
  110. open_api_specification_client/models/get_api_notes_response_200.py +110 -0
  111. open_api_specification_client/models/get_api_notes_response_200_data_item.py +95 -0
  112. open_api_specification_client/models/get_api_notes_response_200_data_item_attributes.py +93 -0
  113. open_api_specification_client/models/get_api_notes_response_200_data_item_relationships.py +71 -0
  114. open_api_specification_client/models/get_api_notes_response_200_data_item_relationships_file.py +71 -0
  115. open_api_specification_client/models/get_api_notes_response_200_data_item_relationships_file_data.py +69 -0
  116. open_api_specification_client/models/get_api_notes_response_200_included_item.py +87 -0
  117. open_api_specification_client/models/get_api_notes_response_200_included_item_attributes.py +113 -0
  118. open_api_specification_client/models/get_api_notes_response_200_jsonapi.py +61 -0
  119. open_api_specification_client/models/get_api_playlist_items_response_200.py +112 -0
  120. open_api_specification_client/models/get_api_playlist_items_response_200_data_item.py +101 -0
  121. open_api_specification_client/models/get_api_playlist_items_response_200_data_item_attributes.py +77 -0
  122. open_api_specification_client/models/get_api_playlist_items_response_200_data_item_relationships.py +71 -0
  123. open_api_specification_client/models/get_api_playlist_items_response_200_data_item_relationships_audio.py +71 -0
  124. open_api_specification_client/models/get_api_playlist_items_response_200_data_item_relationships_audio_data.py +69 -0
  125. open_api_specification_client/models/get_api_playlist_items_response_200_included_item.py +111 -0
  126. open_api_specification_client/models/get_api_playlist_items_response_200_included_item_attributes.py +153 -0
  127. open_api_specification_client/models/get_api_playlist_items_response_200_included_item_relationships.py +87 -0
  128. open_api_specification_client/models/get_api_playlist_items_response_200_included_item_relationships_processed_file.py +71 -0
  129. open_api_specification_client/models/get_api_playlist_items_response_200_included_item_relationships_processed_file_data.py +69 -0
  130. open_api_specification_client/models/get_api_playlist_items_response_200_included_item_relationships_raw_file.py +71 -0
  131. open_api_specification_client/models/get_api_playlist_items_response_200_included_item_relationships_raw_file_data.py +69 -0
  132. open_api_specification_client/models/get_api_playlist_items_response_200_jsonapi.py +61 -0
  133. open_api_specification_client/models/get_api_playlists_response_200.py +103 -0
  134. open_api_specification_client/models/get_api_playlists_response_200_data_item.py +101 -0
  135. open_api_specification_client/models/get_api_playlists_response_200_data_item_attributes.py +101 -0
  136. open_api_specification_client/models/get_api_playlists_response_200_data_item_relationships.py +99 -0
  137. open_api_specification_client/models/get_api_playlists_response_200_data_item_relationships_device_tool.py +71 -0
  138. open_api_specification_client/models/get_api_playlists_response_200_data_item_relationships_device_tool_data.py +69 -0
  139. open_api_specification_client/models/get_api_playlists_response_200_data_item_relationships_playlist_items.py +71 -0
  140. open_api_specification_client/models/get_api_playlists_response_200_data_item_relationships_playlist_items_links.py +61 -0
  141. open_api_specification_client/models/get_api_playlists_response_200_data_item_relationships_user.py +71 -0
  142. open_api_specification_client/models/get_api_playlists_response_200_data_item_relationships_user_data.py +69 -0
  143. open_api_specification_client/models/get_api_playlists_response_200_included_item.py +111 -0
  144. open_api_specification_client/models/get_api_playlists_response_200_included_item_attributes.py +134 -0
  145. open_api_specification_client/models/get_api_playlists_response_200_included_item_attributes_config.py +47 -0
  146. open_api_specification_client/models/get_api_playlists_response_200_included_item_relationships.py +85 -0
  147. open_api_specification_client/models/get_api_playlists_response_200_included_item_relationships_device.py +71 -0
  148. open_api_specification_client/models/get_api_playlists_response_200_included_item_relationships_device_data.py +69 -0
  149. open_api_specification_client/models/get_api_playlists_response_200_included_item_relationships_tool.py +71 -0
  150. open_api_specification_client/models/get_api_playlists_response_200_included_item_relationships_tool_data.py +69 -0
  151. open_api_specification_client/models/get_api_playlists_response_200_jsonapi.py +61 -0
  152. open_api_specification_client/models/get_api_podcasts_response_200.py +85 -0
  153. open_api_specification_client/models/get_api_podcasts_response_200_data_item.py +85 -0
  154. open_api_specification_client/models/get_api_podcasts_response_200_data_item_attributes.py +99 -0
  155. open_api_specification_client/models/get_api_podcasts_response_200_jsonapi.py +61 -0
  156. open_api_specification_client/models/get_api_tools_response_200.py +85 -0
  157. open_api_specification_client/models/get_api_tools_response_200_data_item.py +83 -0
  158. open_api_specification_client/models/get_api_tools_response_200_data_item_attributes.py +93 -0
  159. open_api_specification_client/models/get_api_tools_response_200_jsonapi.py +61 -0
  160. open_api_specification_client/models/get_api_tools_tool_id_response_200.py +77 -0
  161. open_api_specification_client/models/get_api_tools_tool_id_response_200_data.py +85 -0
  162. open_api_specification_client/models/get_api_tools_tool_id_response_200_data_attributes.py +93 -0
  163. open_api_specification_client/models/get_api_tools_tool_id_response_200_jsonapi.py +61 -0
  164. open_api_specification_client/models/get_api_users_current_response_200.py +77 -0
  165. open_api_specification_client/models/get_api_users_current_response_200_data.py +99 -0
  166. open_api_specification_client/models/get_api_users_current_response_200_data_attributes.py +93 -0
  167. open_api_specification_client/models/get_api_users_current_response_200_data_relationships.py +85 -0
  168. open_api_specification_client/models/get_api_users_current_response_200_data_relationships_affiliate.py +61 -0
  169. open_api_specification_client/models/get_api_users_current_response_200_data_relationships_subscriptions.py +61 -0
  170. open_api_specification_client/models/get_api_users_current_response_200_jsonapi.py +61 -0
  171. open_api_specification_client/models/patch_api_audios_audio_id_body.py +67 -0
  172. open_api_specification_client/models/patch_api_audios_audio_id_body_data.py +85 -0
  173. open_api_specification_client/models/patch_api_audios_audio_id_body_data_attributes.py +70 -0
  174. open_api_specification_client/models/patch_api_audios_audio_id_body_data_type.py +8 -0
  175. open_api_specification_client/models/patch_api_audios_audio_id_response_200.py +99 -0
  176. open_api_specification_client/models/patch_api_audios_audio_id_response_200_data.py +101 -0
  177. open_api_specification_client/models/patch_api_audios_audio_id_response_200_data_attributes.py +85 -0
  178. open_api_specification_client/models/patch_api_audios_audio_id_response_200_data_relationships.py +87 -0
  179. open_api_specification_client/models/patch_api_audios_audio_id_response_200_data_relationships_processed_file.py +71 -0
  180. open_api_specification_client/models/patch_api_audios_audio_id_response_200_data_relationships_processed_file_data.py +69 -0
  181. open_api_specification_client/models/patch_api_audios_audio_id_response_200_data_relationships_raw_file.py +71 -0
  182. open_api_specification_client/models/patch_api_audios_audio_id_response_200_data_relationships_raw_file_data.py +69 -0
  183. open_api_specification_client/models/patch_api_audios_audio_id_response_200_included_item.py +87 -0
  184. open_api_specification_client/models/patch_api_audios_audio_id_response_200_included_item_attributes.py +101 -0
  185. open_api_specification_client/models/patch_api_audios_audio_id_response_200_jsonapi.py +61 -0
  186. open_api_specification_client/models/patch_api_notes_note_id_body.py +74 -0
  187. open_api_specification_client/models/patch_api_notes_note_id_body_data.py +110 -0
  188. open_api_specification_client/models/patch_api_notes_note_id_body_data_attributes.py +79 -0
  189. open_api_specification_client/models/patch_api_notes_note_id_body_data_relationships.py +78 -0
  190. open_api_specification_client/models/patch_api_notes_note_id_body_data_relationships_file.py +78 -0
  191. open_api_specification_client/models/patch_api_notes_note_id_body_data_relationships_file_data.py +70 -0
  192. open_api_specification_client/models/patch_api_notes_note_id_response_200.py +74 -0
  193. open_api_specification_client/models/patch_api_notes_note_id_response_200_data.py +96 -0
  194. open_api_specification_client/models/patch_api_notes_note_id_response_200_data_attributes.py +79 -0
  195. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_body.py +69 -0
  196. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_body_data.py +91 -0
  197. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_body_data_attributes.py +61 -0
  198. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_body_data_type.py +8 -0
  199. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_response_200.py +85 -0
  200. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_response_200_data.py +103 -0
  201. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_response_200_data_attributes.py +85 -0
  202. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_response_200_data_relationships.py +87 -0
  203. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_response_200_data_relationships_processed_file.py +61 -0
  204. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_response_200_data_relationships_raw_file.py +61 -0
  205. open_api_specification_client/models/patch_api_playlist_items_playlist_item_id_response_200_jsonapi.py +61 -0
  206. open_api_specification_client/models/post_api_audios_body.py +67 -0
  207. open_api_specification_client/models/post_api_audios_body_data.py +77 -0
  208. open_api_specification_client/models/post_api_audios_body_data_attributes.py +69 -0
  209. open_api_specification_client/models/post_api_audios_body_data_type.py +8 -0
  210. open_api_specification_client/models/post_api_audios_delete_all_body.py +61 -0
  211. open_api_specification_client/models/post_api_audios_response_201.py +95 -0
  212. open_api_specification_client/models/post_api_audios_response_201_data.py +83 -0
  213. open_api_specification_client/models/post_api_audios_response_201_data_relationships.py +85 -0
  214. open_api_specification_client/models/post_api_audios_response_201_data_relationships_processed_file.py +61 -0
  215. open_api_specification_client/models/post_api_audios_response_201_data_relationships_raw_file.py +71 -0
  216. open_api_specification_client/models/post_api_audios_response_201_data_relationships_raw_file_data.py +69 -0
  217. open_api_specification_client/models/post_api_audios_response_201_included_item.py +87 -0
  218. open_api_specification_client/models/post_api_audios_response_201_included_item_attributes.py +101 -0
  219. open_api_specification_client/models/post_api_audios_response_201_jsonapi.py +61 -0
  220. open_api_specification_client/models/post_api_authorizations_body.py +69 -0
  221. open_api_specification_client/models/post_api_authorizations_response_200.py +99 -0
  222. open_api_specification_client/models/post_api_authorizations_response_200_data.py +96 -0
  223. open_api_specification_client/models/post_api_authorizations_response_200_data_attributes.py +79 -0
  224. open_api_specification_client/models/post_api_authorizations_response_200_included_item.py +96 -0
  225. open_api_specification_client/models/post_api_authorizations_response_200_included_item_attributes.py +70 -0
  226. open_api_specification_client/models/post_api_device_tools_body.py +67 -0
  227. open_api_specification_client/models/post_api_device_tools_body_data.py +77 -0
  228. open_api_specification_client/models/post_api_device_tools_body_data_attributes.py +80 -0
  229. open_api_specification_client/models/post_api_device_tools_body_data_type.py +8 -0
  230. open_api_specification_client/models/post_api_device_tools_response_201.py +87 -0
  231. open_api_specification_client/models/post_api_device_tools_response_201_data.py +117 -0
  232. open_api_specification_client/models/post_api_device_tools_response_201_data_attributes.py +98 -0
  233. open_api_specification_client/models/post_api_device_tools_response_201_data_attributes_config.py +47 -0
  234. open_api_specification_client/models/post_api_device_tools_response_201_data_relationships.py +100 -0
  235. open_api_specification_client/models/post_api_device_tools_response_201_data_relationships_device.py +78 -0
  236. open_api_specification_client/models/post_api_device_tools_response_201_data_relationships_device_data.py +69 -0
  237. open_api_specification_client/models/post_api_device_tools_response_201_data_relationships_tool.py +78 -0
  238. open_api_specification_client/models/post_api_device_tools_response_201_data_relationships_tool_data.py +69 -0
  239. open_api_specification_client/models/post_api_device_tools_response_201_jsonapi.py +61 -0
  240. open_api_specification_client/models/post_api_followed_podcasts_body.py +67 -0
  241. open_api_specification_client/models/post_api_followed_podcasts_body_data.py +79 -0
  242. open_api_specification_client/models/post_api_followed_podcasts_body_data_relationships.py +85 -0
  243. open_api_specification_client/models/post_api_followed_podcasts_body_data_relationships_device_tool.py +71 -0
  244. open_api_specification_client/models/post_api_followed_podcasts_body_data_relationships_device_tool_data.py +73 -0
  245. open_api_specification_client/models/post_api_followed_podcasts_body_data_relationships_device_tool_data_type.py +8 -0
  246. open_api_specification_client/models/post_api_followed_podcasts_body_data_relationships_podcast.py +71 -0
  247. open_api_specification_client/models/post_api_followed_podcasts_body_data_relationships_podcast_data.py +73 -0
  248. open_api_specification_client/models/post_api_followed_podcasts_body_data_relationships_podcast_data_type.py +8 -0
  249. open_api_specification_client/models/post_api_followed_podcasts_body_data_type.py +8 -0
  250. open_api_specification_client/models/post_api_followed_podcasts_response_201.py +99 -0
  251. open_api_specification_client/models/post_api_followed_podcasts_response_201_data.py +101 -0
  252. open_api_specification_client/models/post_api_followed_podcasts_response_201_data_attributes.py +69 -0
  253. open_api_specification_client/models/post_api_followed_podcasts_response_201_data_relationships.py +85 -0
  254. open_api_specification_client/models/post_api_followed_podcasts_response_201_data_relationships_device_tool.py +71 -0
  255. open_api_specification_client/models/post_api_followed_podcasts_response_201_data_relationships_device_tool_data.py +69 -0
  256. open_api_specification_client/models/post_api_followed_podcasts_response_201_data_relationships_podcast.py +71 -0
  257. open_api_specification_client/models/post_api_followed_podcasts_response_201_data_relationships_podcast_data.py +69 -0
  258. open_api_specification_client/models/post_api_followed_podcasts_response_201_included_item.py +111 -0
  259. open_api_specification_client/models/post_api_followed_podcasts_response_201_included_item_attributes.py +155 -0
  260. open_api_specification_client/models/post_api_followed_podcasts_response_201_included_item_attributes_config.py +47 -0
  261. open_api_specification_client/models/post_api_followed_podcasts_response_201_included_item_relationships.py +85 -0
  262. open_api_specification_client/models/post_api_followed_podcasts_response_201_included_item_relationships_device.py +71 -0
  263. open_api_specification_client/models/post_api_followed_podcasts_response_201_included_item_relationships_device_data.py +69 -0
  264. open_api_specification_client/models/post_api_followed_podcasts_response_201_included_item_relationships_tool.py +71 -0
  265. open_api_specification_client/models/post_api_followed_podcasts_response_201_included_item_relationships_tool_data.py +69 -0
  266. open_api_specification_client/models/post_api_followed_podcasts_response_201_jsonapi.py +61 -0
  267. open_api_specification_client/models/post_api_notes_body.py +67 -0
  268. open_api_specification_client/models/post_api_notes_body_data.py +77 -0
  269. open_api_specification_client/models/post_api_notes_body_data_attributes.py +87 -0
  270. open_api_specification_client/models/post_api_notes_body_data_attributes_note_type.py +9 -0
  271. open_api_specification_client/models/post_api_notes_body_data_type.py +8 -0
  272. open_api_specification_client/models/post_api_notes_response_201.py +95 -0
  273. open_api_specification_client/models/post_api_notes_response_201_data.py +93 -0
  274. open_api_specification_client/models/post_api_notes_response_201_data_attributes.py +93 -0
  275. open_api_specification_client/models/post_api_notes_response_201_data_relationships.py +71 -0
  276. open_api_specification_client/models/post_api_notes_response_201_data_relationships_file.py +71 -0
  277. open_api_specification_client/models/post_api_notes_response_201_data_relationships_file_data.py +69 -0
  278. open_api_specification_client/models/post_api_notes_response_201_included_item.py +87 -0
  279. open_api_specification_client/models/post_api_notes_response_201_included_item_attributes.py +101 -0
  280. open_api_specification_client/models/post_api_notes_response_201_jsonapi.py +61 -0
  281. open_api_specification_client/models/post_api_playlists_sort_mode_body.py +80 -0
  282. open_api_specification_client/models/post_api_playlists_sort_mode_body_sort_mode.py +10 -0
  283. open_api_specification_client/models/post_api_playlists_sort_mode_response_400.py +67 -0
  284. open_api_specification_client/models/post_api_playlists_sort_mode_response_400_errors.py +61 -0
  285. open_api_specification_client/models/post_api_podcasts_body.py +67 -0
  286. open_api_specification_client/models/post_api_podcasts_body_data.py +77 -0
  287. open_api_specification_client/models/post_api_podcasts_body_data_attributes.py +143 -0
  288. open_api_specification_client/models/post_api_podcasts_body_data_type.py +8 -0
  289. open_api_specification_client/models/post_api_podcasts_response_201.py +77 -0
  290. open_api_specification_client/models/post_api_podcasts_response_201_data.py +83 -0
  291. open_api_specification_client/models/post_api_podcasts_response_201_data_attributes.py +93 -0
  292. open_api_specification_client/models/post_api_podcasts_response_201_jsonapi.py +61 -0
  293. open_api_specification_client/py.typed +1 -0
  294. open_api_specification_client/types.py +54 -0
light_api/__init__.py ADDED
@@ -0,0 +1,11 @@
1
+ import functools
2
+ from .client import Light
3
+
4
+
5
+ def with_light(f):
6
+ @functools.wraps(f)
7
+ def wrapper(*args, **kwargs):
8
+ with Light() as light:
9
+ return f(light, *args, **kwargs)
10
+
11
+ return wrapper
light_api/client.py ADDED
@@ -0,0 +1,273 @@
1
+ from __future__ import annotations
2
+
3
+ import httpx
4
+ import json
5
+ import keyring
6
+ import logging
7
+ import os
8
+
9
+ from typing import TYPE_CHECKING, Any, Callable, final
10
+
11
+ from open_api_specification_client.api.default import get_api_playlists
12
+ from open_api_specification_client.client import AuthenticatedClient
13
+
14
+ if TYPE_CHECKING:
15
+ from light_api.music import LightMusic
16
+ from light_api.podcast import LightPodcasts
17
+ from light_api.notes import LightNotes
18
+ from light_api.tools import LightTools
19
+
20
+ KEYRING_SERVICE = "unofficial-light-api"
21
+ KEYRING_USER = "session"
22
+ API_BASE = "https://production.lightphonecloud.com"
23
+ API_HEADERS = {"Accept": "application/vnd.api+json"}
24
+
25
+ log = logging.getLogger(f"light.{__name__}")
26
+
27
+
28
+ @final
29
+ class Light:
30
+ """Methods for interfacing with Light devices."""
31
+
32
+ def __init__(
33
+ self,
34
+ email: str | None = None,
35
+ email_file: str | None = None,
36
+ password: str | None = None,
37
+ password_file: str | None = None,
38
+ phone: str | None = None,
39
+ phone_file: str | None = None,
40
+ ) -> None:
41
+ self.email: str | None = email or self._resolve(email_file, "LIGHT_EMAIL")
42
+ self.password: str | None = password or self._resolve(
43
+ password_file, "LIGHT_PASSWORD"
44
+ )
45
+ self.phone: str | None = phone or self._resolve(
46
+ phone_file, "LIGHT_PHONE_NUMBER"
47
+ )
48
+ self._api_token: str | None = None
49
+ self._api_client: AuthenticatedClient | None = None
50
+ self._device_tool_ids: dict[str, str] = {}
51
+ self._playlist_id: str | None = None
52
+
53
+ self.music: LightMusic
54
+ self.podcast: LightPodcasts
55
+ self.notes: LightNotes
56
+ self.tools: LightTools
57
+
58
+ def login(self) -> None:
59
+ """Authenticate via the authorizations API and store the bearer token."""
60
+ if self._api_token is not None:
61
+ return
62
+
63
+ if not self.email or not self.password:
64
+ raise RuntimeError("No cached session - provide email and password")
65
+
66
+ resp = httpx.post(
67
+ f"{API_BASE}/api/authorizations",
68
+ json={"email": self.email, "password": self.password},
69
+ headers={**API_HEADERS, "Content-Type": "application/vnd.api+json"},
70
+ timeout=30,
71
+ )
72
+
73
+ if not resp.is_success:
74
+ raise RuntimeError(f"Login failed: {resp.status_code}")
75
+
76
+ included = resp.json()["included"][0]
77
+ token = included["attributes"]["token"]
78
+
79
+ if token is None:
80
+ raise RuntimeError("Login succeeded but no token found in response")
81
+
82
+ self._api_token = token
83
+
84
+ def reauth(self) -> None:
85
+ """Re-authenticate and refresh the API client. Called on 401."""
86
+ log.info("Re-authenticating")
87
+ self._api_token = None
88
+ self.login()
89
+ self._save_cache()
90
+ self._api_client = AuthenticatedClient(
91
+ base_url=API_BASE,
92
+ token=self._api_token,
93
+ headers=API_HEADERS,
94
+ )
95
+
96
+ def call_api(self, func: Callable[..., Any], **kwargs: Any) -> Any:
97
+ """Call an API function, re-authenticating once on 401."""
98
+ resp = func(**kwargs)
99
+ if resp.status_code == 401:
100
+ self.reauth()
101
+ resp = func(**kwargs)
102
+ return resp
103
+
104
+ def __enter__(self) -> Light:
105
+ """Sets up API session."""
106
+ log.info("Authenticating")
107
+
108
+ if self._load_cache() and self._validate_cache():
109
+ log.info("Using cached session")
110
+ else:
111
+ self.login()
112
+ self._save_cache()
113
+
114
+ self._api_client = AuthenticatedClient(
115
+ base_url=API_BASE,
116
+ token=self._api_token,
117
+ headers=API_HEADERS,
118
+ )
119
+
120
+ expected = {"music", "notes", "podcast"}
121
+ if not expected.issubset(self._device_tool_ids) or not self._playlist_id:
122
+ self._fetch_device_tool_ids()
123
+ self._fetch_playlist_id()
124
+ self._save_cache()
125
+
126
+ from light_api.music import LightMusic
127
+ from light_api.podcast import LightPodcasts
128
+ from light_api.notes import LightNotes
129
+ from light_api.tools import LightTools
130
+
131
+ self.music = LightMusic(self)
132
+ self.podcast = LightPodcasts(self)
133
+ self.notes = LightNotes(self)
134
+ self.tools = LightTools(self)
135
+
136
+ log.info("Authentication complete")
137
+ return self
138
+
139
+ def __exit__(self, *_: object) -> None:
140
+ pass
141
+
142
+ def _load_cache(self) -> bool:
143
+ """Load cached data from keyring."""
144
+ log.debug("Loading cache")
145
+
146
+ try:
147
+ raw = keyring.get_password(KEYRING_SERVICE, KEYRING_USER)
148
+ except (keyring.errors.NoKeyringError, keyring.errors.KeyringLocked) as e:
149
+ log.debug(f"Keyring error: {e}")
150
+ return False
151
+
152
+ if raw is None:
153
+ log.debug("Keyring: no entry found")
154
+ return False
155
+
156
+ try:
157
+ data = json.loads(raw)
158
+ self._api_token = data["api_token"]
159
+ self._device_tool_ids = data["device_tool_ids"]
160
+ self._playlist_id = data["playlist_id"]
161
+ log.debug("Cache loaded successfully")
162
+ return True
163
+ except (KeyError, json.JSONDecodeError) as e:
164
+ log.debug(f"Error: {e}")
165
+ return False
166
+
167
+ def _save_cache(self) -> None:
168
+ """Cache data to keyring."""
169
+ try:
170
+ keyring.set_password(
171
+ KEYRING_SERVICE,
172
+ KEYRING_USER,
173
+ json.dumps(
174
+ {
175
+ "api_token": self._api_token,
176
+ "device_tool_ids": self._device_tool_ids,
177
+ "playlist_id": self._playlist_id,
178
+ }
179
+ ),
180
+ )
181
+ except (keyring.errors.NoKeyringError, keyring.errors.KeyringLocked) as e:
182
+ log.warning(f"Keyring error: {e}")
183
+
184
+ def _validate_cache(self) -> bool:
185
+ """Check if cached auth token is valid."""
186
+ client = AuthenticatedClient(
187
+ base_url=API_BASE,
188
+ token=self._api_token,
189
+ headers=API_HEADERS,
190
+ )
191
+ resp = get_api_playlists.sync_detailed(
192
+ client=client,
193
+ device_tool_id=self._device_tool_ids.get("music"),
194
+ )
195
+ return resp.status_code == 200
196
+
197
+ def _fetch_playlist_id(self) -> None:
198
+ music_id = self._device_tool_ids.get("music")
199
+ if not music_id:
200
+ raise RuntimeError("Could not find music device_tool_id in /api/devices")
201
+ resp = get_api_playlists.sync_detailed(
202
+ client=self._api_client,
203
+ device_tool_id=music_id,
204
+ )
205
+ if resp.status_code != 200 or not resp.parsed or not resp.parsed.data:
206
+ raise RuntimeError(f"Could not fetch playlists: {resp.status_code}")
207
+ self._playlist_id = resp.parsed.data[0].id
208
+
209
+ def _fetch_device_tool_ids(self) -> None:
210
+ """Populate _device_tool_ids for all installed tools.
211
+
212
+ The Light API has two relevant endpoints:
213
+ - GET /api/devices: returns the device record plus "included" items which are
214
+ device_tool records (one per installed tool). Each has a unique `id` (the
215
+ device_tool_id used in subsequent API calls) and a relationship pointing to
216
+ its global tool ID.
217
+ - GET /api/tools?device_id=...: returns the global tool catalog with human-readable
218
+ namespace strings (e.g. "com.light.music", "com.light.notes").
219
+
220
+ To get each device tool id, cross-reference the two: build a map of global_tool_id -> namespace
221
+ from /api/tools, then walk the /api/devices included items, look up each item's global tool ID in
222
+ that map, and classify it as "music", "notes", or "podcast" based on the namespace string.
223
+ """
224
+ from open_api_specification_client.api.default import (
225
+ get_api_devices,
226
+ get_api_tools,
227
+ )
228
+ from open_api_specification_client.types import Unset
229
+
230
+ devices_resp = get_api_devices.sync_detailed(client=self._api_client)
231
+ if (
232
+ devices_resp.status_code != 200
233
+ or not devices_resp.parsed
234
+ or not devices_resp.parsed.data
235
+ ):
236
+ raise RuntimeError(f"Could not fetch devices: {devices_resp.status_code}")
237
+ device_id = devices_resp.parsed.data[0].id
238
+
239
+ tools_resp = get_api_tools.sync_detailed(
240
+ client=self._api_client, device_id=device_id
241
+ )
242
+ if tools_resp.status_code != 200 or not tools_resp.parsed:
243
+ raise RuntimeError(f"Could not fetch tools: {tools_resp.status_code}")
244
+
245
+ tool_ns: dict[str, str] = {
246
+ t.id: t.attributes.namespace.lower() for t in tools_resp.parsed.data
247
+ }
248
+
249
+ for item in devices_resp.parsed.included:
250
+ if isinstance(item.relationships.tool, Unset):
251
+ continue
252
+ ns = tool_ns.get(item.relationships.tool.data.id, "")
253
+ if "note" in ns:
254
+ self._device_tool_ids["notes"] = item.id
255
+ elif "podcast" in ns:
256
+ self._device_tool_ids["podcast"] = item.id
257
+ elif "music" in ns or "playlist" in ns:
258
+ self._device_tool_ids["music"] = item.id
259
+
260
+ @staticmethod
261
+ def _resolve(filepath: str | None, env_key: str) -> str | None:
262
+ if filepath:
263
+ try:
264
+ with open(filepath) as f:
265
+ return f.read().strip()
266
+ except OSError as e:
267
+ raise RuntimeError(f"Could not read {filepath}: {e}") from e
268
+ return os.environ.get(env_key)
269
+
270
+ @staticmethod
271
+ def _format_phone(number: str) -> str:
272
+ digits: str = "".join(c for c in number if c.isdigit())[-10:]
273
+ return f"+1 {digits[0:3]} {digits[3:6]} {digits[6:10]}"