ksaa 2025.11b1__py3-none-any.whl → 2025.11.post1__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 (352) hide show
  1. kaa/__init__.py +0 -0
  2. kaa/application/__init__.py +0 -0
  3. kaa/application/core/misc_core.py +4 -1
  4. kaa/application/services/__init__.py +0 -0
  5. kaa/application/services/config_service.py +112 -0
  6. kaa/application/services/feedback_service.py +121 -0
  7. kaa/application/services/produce_solution_service.py +83 -0
  8. kaa/application/services/task_service.py +145 -0
  9. kaa/application/services/update_service.py +208 -0
  10. kaa/application/ui/__init__.py +0 -0
  11. kaa/application/ui/common.py +123 -0
  12. kaa/application/ui/components/alert.py +251 -0
  13. kaa/application/ui/components/alert.pyi +257 -0
  14. kaa/application/ui/components/categorized_select.pyi +697 -0
  15. kaa/application/ui/facade.py +189 -0
  16. kaa/application/ui/gradio_view.py +135 -0
  17. kaa/application/ui/views/__init__.py +0 -0
  18. kaa/application/ui/views/feedback_view.py +65 -0
  19. kaa/application/ui/views/produce_view.py +251 -0
  20. kaa/application/ui/views/settings_view.py +581 -0
  21. kaa/application/ui/views/status_view.py +171 -0
  22. kaa/application/ui/views/task_view.py +102 -0
  23. kaa/application/ui/views/update_view.py +106 -0
  24. kaa/config/schema.py +8 -0
  25. kaa/db/constants.py +3 -2
  26. kaa/errors.py +60 -0
  27. kaa/main/gr.py +60 -3132
  28. kaa/main/kaa.py +11 -3
  29. kaa/metadata.py +80 -0
  30. kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
  31. kaa/resources/game.db +0 -0
  32. kaa/resources/game_ver.txt +0 -0
  33. kaa/resources/idol_cards/i_card-skin-amao-3-014_1.png +0 -0
  34. kaa/resources/idol_cards/i_card-skin-amao-3-015_0.png +0 -0
  35. kaa/resources/idol_cards/i_card-skin-atbm-1-000_0.png +0 -0
  36. kaa/resources/idol_cards/i_card-skin-atbm-1-000_1.png +0 -0
  37. kaa/resources/idol_cards/i_card-skin-atbm-2-000_0.png +0 -0
  38. kaa/resources/idol_cards/i_card-skin-atbm-2-000_1.png +0 -0
  39. kaa/resources/idol_cards/i_card-skin-atbm-3-000_0.png +0 -0
  40. kaa/resources/idol_cards/i_card-skin-atbm-3-000_1.png +0 -0
  41. kaa/resources/idol_cards/i_card-skin-fktn-3-016_0.png +0 -0
  42. kaa/resources/idol_cards/i_card-skin-fktn-3-016_1.png +0 -0
  43. kaa/resources/idol_cards/i_card-skin-hmsz-3-003_0.png +0 -0
  44. kaa/resources/idol_cards/i_card-skin-hmsz-3-003_1.png +0 -0
  45. kaa/resources/idol_cards/i_card-skin-hmsz-3-009_0.png +0 -0
  46. kaa/resources/idol_cards/i_card-skin-hmsz-3-009_1.png +0 -0
  47. kaa/resources/idol_cards/i_card-skin-hmsz-3-013_0.png +0 -0
  48. kaa/resources/idol_cards/i_card-skin-hmsz-3-013_1.png +0 -0
  49. kaa/resources/idol_cards/i_card-skin-hrnm-3-015_0.png +0 -0
  50. kaa/resources/idol_cards/i_card-skin-hrnm-3-015_1.png +0 -0
  51. kaa/resources/idol_cards/i_card-skin-hski-3-015_0.png +0 -0
  52. kaa/resources/idol_cards/i_card-skin-hski-3-015_1.png +0 -0
  53. kaa/resources/idol_cards/i_card-skin-hume-3-009_0.png +0 -0
  54. kaa/resources/idol_cards/i_card-skin-hume-3-009_1.png +0 -0
  55. kaa/resources/idol_cards/i_card-skin-hume-3-015_0.png +0 -0
  56. kaa/resources/idol_cards/i_card-skin-hume-3-015_1.png +0 -0
  57. kaa/resources/idol_cards/i_card-skin-jsna-3-009_0.png +0 -0
  58. kaa/resources/idol_cards/i_card-skin-jsna-3-009_1.png +0 -0
  59. kaa/resources/idol_cards/i_card-skin-jsna-3-014_0.png +0 -0
  60. kaa/resources/idol_cards/i_card-skin-jsna-3-014_1.png +0 -0
  61. kaa/resources/idol_cards/i_card-skin-kcna-3-014_1.png +0 -0
  62. kaa/resources/idol_cards/i_card-skin-kcna-3-015_0.png +0 -0
  63. kaa/resources/idol_cards/i_card-skin-kcna-3-015_1.png +0 -0
  64. kaa/resources/idol_cards/i_card-skin-kllj-3-014_0.png +0 -0
  65. kaa/resources/idol_cards/i_card-skin-kllj-3-014_1.png +0 -0
  66. kaa/resources/idol_cards/i_card-skin-shro-3-015_0.png +0 -0
  67. kaa/resources/idol_cards/i_card-skin-shro-3-015_1.png +0 -0
  68. kaa/resources/idol_cards/i_card-skin-ssmk-3-015_0.png +0 -0
  69. kaa/resources/idol_cards/i_card-skin-ssmk-3-015_1.png +0 -0
  70. kaa/resources/idol_cards/i_card-skin-ttmr-3-015_0.png +0 -0
  71. kaa/resources/idol_cards/i_card-skin-ttmr-3-015_1.png +0 -0
  72. kaa/sprites/052ab0f5-8d95-4b5d-8678-3838322d9e5e.png +0 -0
  73. kaa/sprites/18adb1a5-b95d-41ff-9cb9-16613fa4cf6a.png +0 -0
  74. kaa/sprites/2aac3a97-435e-4c02-925f-e2d1673b7982.png +0 -0
  75. kaa/sprites/2cc63c6d-5988-4f72-ae88-b03b8246ad97.png +0 -0
  76. kaa/sprites/3208d803-2c92-4775-80dc-0527df4b63d9.png +0 -0
  77. kaa/sprites/345435d0-5a5c-494b-95ab-1e086fb88f51.png +0 -0
  78. kaa/sprites/3ad30d90-8b57-4641-a9e2-33970e5cea1d.png +0 -0
  79. kaa/sprites/3e0da5df-a4de-42bd-83bd-13df3c393af4.png +0 -0
  80. kaa/sprites/41904062-e218-4b28-972a-b5cfcd058d2c.png +0 -0
  81. kaa/sprites/44a50906-1835-4e29-ae97-496b4cdde9e9.png +0 -0
  82. kaa/sprites/488a1403-d300-4fa6-94c7-da71d09fd4bb.png +0 -0
  83. kaa/sprites/48c16d60-05d6-43bc-97c3-7f099bfc0881.png +0 -0
  84. kaa/sprites/4e3dbeb5-70bb-4642-9f73-01f9f98bc3aa.png +0 -0
  85. kaa/sprites/54987de4-3e1b-4640-b203-1e4c82d7e98d.png +0 -0
  86. kaa/sprites/5a0bfeac-fb22-4b0c-b775-4aa6220bae89.png +0 -0
  87. kaa/sprites/5aad0930-54a3-4b6d-bec8-250228963f69.png +0 -0
  88. kaa/sprites/5c49d3b3-656e-4c8c-ae1a-9b0209b9dcc3.png +0 -0
  89. kaa/sprites/5c9a1581-a14a-449b-a1b0-7a31a965facc.png +0 -0
  90. kaa/sprites/62411b55-7be8-46d9-aa4a-fb56dab6658c.png +0 -0
  91. kaa/sprites/6580ea89-553e-4445-a855-f834d580e6e6.png +0 -0
  92. kaa/sprites/686a2bf5-0498-4d53-8ba1-1110ff36f046.png +0 -0
  93. kaa/sprites/699ca639-3006-45c1-b5fd-8cf9631fd3ea.png +0 -0
  94. kaa/sprites/6e8325f9-7fdb-4729-ac13-ca67244d97bc.png +0 -0
  95. kaa/sprites/71051aa7-81f1-4144-9318-4405e10547ee.png +0 -0
  96. kaa/sprites/732ffc6c-6a17-41f8-9cd1-f218ebc0c23f.png +0 -0
  97. kaa/sprites/744ea25a-9b6e-4f8f-9a00-0ac714571b09.png +0 -0
  98. kaa/sprites/74b50642-0b18-45c3-8a5d-013ef1e0eb78.png +0 -0
  99. kaa/sprites/77e7262f-0d12-4bd9-9f22-e8f41a600bf8.png +0 -0
  100. kaa/sprites/78b928c6-0d24-4e87-a84f-0091d42f8e49.png +0 -0
  101. kaa/sprites/7c193df5-0a1d-444d-9f92-e9c0db79e53a.png +0 -0
  102. kaa/sprites/7e729638-f54a-48bb-8bbf-eeaa4d697502.png +0 -0
  103. kaa/sprites/802e717f-d70a-4f34-8b96-be586a8dfde9.png +0 -0
  104. kaa/sprites/831cac7e-49e9-45d1-bb65-b1db733cda90.png +0 -0
  105. kaa/sprites/8411b102-866d-4e41-ab12-507397b80ca5.png +0 -0
  106. kaa/sprites/84b3c8e2-6e37-443c-be9b-8a95aedc6f37.png +0 -0
  107. kaa/sprites/85308e03-ba72-499a-9d12-870269fa3cd0.png +0 -0
  108. kaa/sprites/8922feef-17db-4b10-93da-1bad30492ac2.png +0 -0
  109. kaa/sprites/8a6ed80c-79c6-4df6-ab65-64d67afb2d5b.png +0 -0
  110. kaa/sprites/8c0439d9-9eb7-43f3-8d1e-7e41c57c1bbd.png +0 -0
  111. kaa/sprites/8dd3de6d-07d5-4d93-9663-71a3a4c57a32.png +0 -0
  112. kaa/sprites/9009323d-1418-4aed-8a93-075b326d2e7a.png +0 -0
  113. kaa/sprites/904d22f7-51be-486f-8dd1-1871c0cf28e3.png +0 -0
  114. kaa/sprites/90943f62-0a03-4a75-804a-0c2fa7b27af4.png +0 -0
  115. kaa/sprites/9180e0e7-2cc4-46c7-95ff-fbe83806baf2.png +0 -0
  116. kaa/sprites/93f5c33e-ec81-4a70-a11f-b2e8cb1751ee.png +0 -0
  117. kaa/sprites/9558b2a5-3961-4ad0-9ce8-379d71920d78.png +0 -0
  118. kaa/sprites/968dff88-5a2f-42c7-b64b-406801e22c87.png +0 -0
  119. kaa/sprites/99d99d78-ee37-4e84-8768-b5a7f4f9bd51.png +0 -0
  120. kaa/sprites/9caa102c-70af-4a8c-b595-82df9f4c05d8.png +0 -0
  121. kaa/sprites/9e06b7d6-5d15-4844-bbfe-ad1af7da3113.png +0 -0
  122. kaa/sprites/__pycache__/__init__.cpython-310.pyc +0 -0
  123. kaa/sprites/a04ed558-25e3-42d7-a662-250cad9fa5df.png +0 -0
  124. kaa/sprites/a0a62dbf-a027-4b63-86e4-2e863b2edb01.png +0 -0
  125. kaa/sprites/a4b898aa-405e-4235-8075-a34640a2b023.png +0 -0
  126. kaa/sprites/a5c3108f-c92d-4ce7-8c4e-93b79f55ceb3.png +0 -0
  127. kaa/sprites/a7e6222f-f8ca-47c2-af1e-f158a87f6a03.png +0 -0
  128. kaa/sprites/ab3d3301-8297-43a8-bf0b-85413c115a7d.png +0 -0
  129. kaa/sprites/ad589feb-6d19-47c7-a582-55ee130ee89d.png +0 -0
  130. kaa/sprites/ae4742aa-acda-442d-bf73-b3fe7b66e85c.png +0 -0
  131. kaa/sprites/aed87cd4-eb05-4c24-8adf-cd3fab20e9a3.png +0 -0
  132. kaa/sprites/afb9e4a9-29a5-4202-9f75-e7d2f1b64aa4.png +0 -0
  133. kaa/sprites/b1f547d4-c1ba-43fc-9398-4ccdc25b8b62.png +0 -0
  134. kaa/sprites/b61bd48f-1fe7-49fd-a588-09aac3b66f5a.png +0 -0
  135. kaa/sprites/b6219452-323a-44eb-9f44-97b2ad0ee49a.png +0 -0
  136. kaa/sprites/b7550a50-5943-45e7-9c1b-771117364844.png +0 -0
  137. kaa/sprites/b865eedf-7bea-46f6-bf14-7f8f4e9ab000.png +0 -0
  138. kaa/sprites/b8f0ed47-6115-4b88-848a-2fc4a1ab25d8.png +0 -0
  139. kaa/sprites/b9224799-d0c1-43d9-9f11-1d35903fc4d9.png +0 -0
  140. kaa/sprites/baa9c530-68cb-4111-85f6-060823ad32c4.png +0 -0
  141. kaa/sprites/bed54f67-d828-403c-9cb3-6a7c85695c2a.png +0 -0
  142. kaa/sprites/befadc5e-862a-4818-9223-5d58e4ac03cb.png +0 -0
  143. kaa/sprites/c0d1896c-71a1-47d6-9847-b87543a942e9.png +0 -0
  144. kaa/sprites/c2984c0f-3e17-45c3-9d7c-dc4f14440b13.png +0 -0
  145. kaa/sprites/c6b53acc-bc89-465e-9814-0138513327ac.png +0 -0
  146. kaa/sprites/c72a4609-6bf0-4568-8ebc-73c30d67c61e.png +0 -0
  147. kaa/sprites/c7829f82-bfce-4259-9ec6-f1cfb7bac925.png +0 -0
  148. kaa/sprites/c82ebc01-0127-417f-831a-9d17a84b2691.png +0 -0
  149. kaa/sprites/c8747b3b-745c-45ed-84b6-dde1b2558ce8.png +0 -0
  150. kaa/sprites/c98ef89e-4a1c-40f0-a82e-6851f7b6bbc9.png +0 -0
  151. kaa/sprites/cb04d87c-f5a9-405c-92ac-b3603e482221.png +0 -0
  152. kaa/sprites/cb43f670-6623-4af9-ac1d-746372e40511.png +0 -0
  153. kaa/sprites/ce357023-436b-4a39-882f-8410acd8f0d7.png +0 -0
  154. kaa/sprites/cea9f5ea-5923-4c6e-bd24-90d2e084112c.png +0 -0
  155. kaa/sprites/cf62e2df-3be1-4d03-9f34-1518280abd90.png +0 -0
  156. kaa/sprites/d0a483a9-400f-4b6e-87a0-9781b4454da0.png +0 -0
  157. kaa/sprites/d10d480c-e96e-475e-815c-0969f37fe3bc.png +0 -0
  158. kaa/sprites/d1839450-8d60-41a4-b035-8e1acd0f1c7a.png +0 -0
  159. kaa/sprites/d19859f3-f7cc-46ef-8bc6-86df7856fd53.png +0 -0
  160. kaa/sprites/d2d3d77d-a06f-4167-b02b-5ca688c0c0c3.png +0 -0
  161. kaa/sprites/d38c5015-e461-4e09-8b56-731472bdf59e.png +0 -0
  162. kaa/sprites/d473b5bd-4be3-4f0f-bb92-b909050f273a.png +0 -0
  163. kaa/sprites/d609a029-5407-43c2-a9a9-07bfd43fcbb8.png +0 -0
  164. kaa/sprites/d6491f82-9637-47eb-8f35-eb272b5ef8df.png +0 -0
  165. kaa/sprites/d8dd8b59-c05c-4350-a15d-be75c94d46cc.png +0 -0
  166. kaa/sprites/d98263bf-15fb-430e-ba39-2558fa99cac0.png +0 -0
  167. kaa/sprites/d9bc9bbb-9a1a-4cbe-b6ed-24112d7c5ac7.png +0 -0
  168. kaa/sprites/da922566-97ba-4477-bcad-35ea02a3ee48.png +0 -0
  169. kaa/sprites/dac8d8fd-006c-4f50-a4e0-d79dbf3f5915.png +0 -0
  170. kaa/sprites/db33ab8d-160d-48c7-b464-dfe194e762d4.png +0 -0
  171. kaa/sprites/dcfdfab4-8dfb-4069-bf88-8e8401ef86f3.png +0 -0
  172. kaa/sprites/de354b53-2fd0-4039-87e2-fcad2e070579.png +0 -0
  173. kaa/sprites/e28ea25e-0bcf-4d52-b501-9ef7a4863870.png +0 -0
  174. kaa/sprites/e2ac927f-257e-4537-995d-fbfbe4983b70.png +0 -0
  175. kaa/sprites/e642b9ef-c8a7-41d5-8d71-5cfbaf3017a1.png +0 -0
  176. kaa/sprites/e749feec-6bf2-4c24-bb12-948e696b8116.png +0 -0
  177. kaa/sprites/ed3aa6e6-4256-416b-9d04-d57ca340e39d.png +0 -0
  178. kaa/sprites/ed4c0554-84df-4c29-af18-7c38523cc59b.png +0 -0
  179. kaa/sprites/ef1bfd47-78e9-4cb7-a344-53d980fc3e5e.png +0 -0
  180. kaa/sprites/ef1ddc7d-75f9-4798-afa1-733e16794a81.png +0 -0
  181. kaa/sprites/efb01328-b6e1-438e-9471-bef3ea77a22c.png +0 -0
  182. kaa/sprites/f06b1a4f-eeb6-4dea-9543-5ec27640bdd9.png +0 -0
  183. kaa/sprites/f07bac27-9201-498f-9f26-a58291a70542.png +0 -0
  184. kaa/sprites/f0fd613b-d2f8-4b18-90d8-0b328373e715.png +0 -0
  185. kaa/sprites/f1fbe46a-759d-467d-b8ca-2158f530f7c5.png +0 -0
  186. kaa/sprites/f2314c76-3a2b-4644-831a-343a601145df.png +0 -0
  187. kaa/sprites/f329d4ba-e836-4be6-a05b-879b53667df3.png +0 -0
  188. kaa/sprites/f469d235-552f-4b07-9d03-9bcae425b6d8.png +0 -0
  189. kaa/sprites/f5177258-a3cf-4d4f-9c69-0b49556f754f.png +0 -0
  190. kaa/sprites/f5dcac82-7c54-4020-84c5-b1334b595612.png +0 -0
  191. kaa/sprites/f6656842-1460-41ab-95ed-561aefaf08e2.png +0 -0
  192. kaa/sprites/f70e9455-7cc8-449c-8282-89a9e69f7ac3.png +0 -0
  193. kaa/sprites/f7fd469f-791e-4bf7-ae3f-b5aaed92f999.png +0 -0
  194. kaa/sprites/f873280f-bc68-40d1-8d8d-3d86964264f0.png +0 -0
  195. kaa/sprites/f9da6eeb-ff9e-45b3-94b0-e7ba34938dec.png +0 -0
  196. kaa/sprites/fa24f5d5-d7e5-4421-8cbc-2ce3a0189654.png +0 -0
  197. kaa/sprites/fb61dbf3-fbc1-400a-adde-83ea08b5027d.png +0 -0
  198. kaa/sprites/fc8457b6-f8a3-4b01-9864-0cd624c312b6.png +0 -0
  199. kaa/sprites/fdbf6a89-b95a-481f-a269-be53e05b18de.png +0 -0
  200. kaa/sprites/fed11307-2186-4ede-875f-ffa0383f410c.png +0 -0
  201. kaa/sprites/ff0d3db2-c4e5-41e7-a85b-df4fd392924c.png +0 -0
  202. kaa/sprites/ff40ff91-4e8c-46cb-a254-66cd5ffd363e.png +0 -0
  203. kaa/sprites/ff614071-c318-4263-af3e-01ea0ab45b73.png +0 -0
  204. kaa/tasks/R.py +136 -128
  205. kaa/tasks/R2.py +24 -0
  206. kaa/tasks/common.py +5 -0
  207. kaa/tasks/daily/club_reward.py +1 -0
  208. kaa/tasks/daily/contest.py +2 -1
  209. kaa/tasks/daily/purchase.py +33 -1
  210. kaa/tasks/daily/upgrade_support_card.py +12 -2
  211. kaa/tasks/produce/cards.py +5 -4
  212. kaa/tasks/produce/common.py +202 -105
  213. kaa/tasks/produce/in_purodyuusu.py +35 -17
  214. kaa/tasks/produce/non_lesson_actions.py +10 -33
  215. kaa/tasks/produce/p_drink.py +5 -1
  216. kaa/tasks/produce/produce.py +2 -1
  217. kaa/tasks/start_game.py +2 -1
  218. kaa/util/reactive.py +182 -0
  219. {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/METADATA +27 -24
  220. {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/RECORD +352 -181
  221. /kaa/sprites/{35341839-4469-4ab6-aa40-33642fe43e82.png → 01e93c2c-28dc-41f8-8f9a-ec62ec12aa01.png} +0 -0
  222. /kaa/sprites/{68d9f340-a3d2-4708-8eb1-c1ed857decda.png → 02ac01e0-00b0-46d8-a6db-56248c843c6d.png} +0 -0
  223. /kaa/sprites/{39f6d657-3b3e-40aa-849b-7ad87a0be1d0.png → 033e73d1-9f45-4bca-bf96-6778410f2fc4.png} +0 -0
  224. /kaa/sprites/{799fe395-2264-4bc5-b515-813dadda8fe1.png → 04036690-5b0f-4ee0-a9d0-022ee822bf0e.png} +0 -0
  225. /kaa/sprites/{256ffeba-8e9e-4cc5-8a1c-9eaee427f1a5.png → 041bd3fc-d040-4773-8641-4e4509300d2f.png} +0 -0
  226. /kaa/sprites/{5ffd3f29-db4f-4f66-b9ed-be5a70b7ebf9.png → 04974917-b1e8-4ccc-807b-6f651026c955.png} +0 -0
  227. /kaa/sprites/{8be81341-a74d-42c8-8231-5d1854bc08e7.png → 04c4e4c2-9908-4be7-bcbe-4d926ca76737.png} +0 -0
  228. /kaa/sprites/{043e753e-db15-45ba-8513-53c3fc9c7f3c.png → 05b97cdf-f7df-4d91-9ec8-5e9594a46382.png} +0 -0
  229. /kaa/sprites/{5431dc38-c257-40b3-8f7b-8bceaa7fe587.png → 061b032f-860b-4c53-889b-aa126797f062.png} +0 -0
  230. /kaa/sprites/{cb6dffd9-6474-4d09-aee6-26352ea51d31.png → 07b43eb9-db32-4046-96d3-9f4314bfd80a.png} +0 -0
  231. /kaa/sprites/{3e087b8d-420d-48ff-b526-29c4a65d8cbe.png → 08b12ded-8230-4c7e-bb9f-27c85b0fdabb.png} +0 -0
  232. /kaa/sprites/{68e20ebf-02fd-46a1-88d7-b4472824e7bc.png → 09364c3a-f892-4911-abdc-2f5fea09289f.png} +0 -0
  233. /kaa/sprites/{c69dcdcf-42a7-420e-aa8e-bb8639ea80b6.png → 09d2a63d-d2f0-4b97-b3cb-22a61b1530f7.png} +0 -0
  234. /kaa/sprites/{d644faa3-ff16-417f-928c-4c62b040bfdb.png → 0cad6e46-276f-424e-a79e-d272ebaa7c8e.png} +0 -0
  235. /kaa/sprites/{db6707a2-2964-4919-9992-4d801fa43dae.png → 0e49fbde-6be6-42b3-b8d1-36e0cb9cc35d.png} +0 -0
  236. /kaa/sprites/{cd00a2d7-af48-48b1-b2e1-5360ceed249f.png → 0e51d671-928c-4972-8ac0-de446202070b.png} +0 -0
  237. /kaa/sprites/{736a9daf-05d6-46ba-810b-5a8f509152d1.png → 0e6f8981-f46c-4c7d-9d90-fe349f0a1d77.png} +0 -0
  238. /kaa/sprites/{92c3de1b-eed1-45b9-82e0-c9e97bb479e7.png → 0e9e3dbf-6e94-4a12-b558-3d8ab500c0a6.png} +0 -0
  239. /kaa/sprites/{913dbd4e-ebb1-4c9f-b145-9960cde59c17.png → 0eafb6c1-9d85-4fe0-8011-7235704ca9d3.png} +0 -0
  240. /kaa/sprites/{ec3cad5f-e0c9-4577-8499-79b50248344e.png → 1002a830-1ad5-47a7-b7dd-ed2989e6fc1b.png} +0 -0
  241. /kaa/sprites/{e5e49b44-dcc2-4e77-9180-0d2beaa3f9ad.png → 10943367-c1d8-41c7-a831-d5d05288875a.png} +0 -0
  242. /kaa/sprites/{c1d502eb-c77f-45cb-86b5-11b4a8a3aef5.png → 10f37db0-8c3e-4790-a5c3-cdb841f106a7.png} +0 -0
  243. /kaa/sprites/{802db04f-77c2-46a4-a6eb-f81d48ea03ce.png → 11f65378-b982-4936-9ac7-68560a74a042.png} +0 -0
  244. /kaa/sprites/{1befe09b-cb77-417a-b21e-7746804d4e03.png → 1660acf7-a420-4d92-a90c-55c5ff208da6.png} +0 -0
  245. /kaa/sprites/{16a0fd47-e85b-4848-8894-9d071ea993ac.png → 170d28bf-d262-4bf1-b35f-8f3d4b4fff6e.png} +0 -0
  246. /kaa/sprites/{5906d986-d0e5-452d-a7c4-ddeb7af8751d.png → 182d8c71-5ce5-4ee1-9f66-ef99aadae654.png} +0 -0
  247. /kaa/sprites/{cfe3563d-a24b-4197-a0cb-5628bd990c08.png → 18d26894-fd12-4644-8269-a09d11be9520.png} +0 -0
  248. /kaa/sprites/{8e5e968b-edad-4c03-abc8-3f2a7e8879ae.png → 1b0dd18b-eb41-4c9c-b031-bab91c93fd5d.png} +0 -0
  249. /kaa/sprites/{3fa5f81c-9223-44ba-bf07-71932350e845.png → 1e7a6e19-760c-4fbc-b0f1-f620f51056b9.png} +0 -0
  250. /kaa/sprites/{9e7eaa8e-3178-44da-a5ec-34b889f8facf.png → 1fbe13d6-3a4d-4935-b687-a76a76a1e32c.png} +0 -0
  251. /kaa/sprites/{1ad89ee4-1bb1-41d2-a92c-79caf6baa38a.png → 1fe31432-a050-48db-acc1-becde42deaf9.png} +0 -0
  252. /kaa/sprites/{94d54ba7-0ccf-4fd9-a5bf-488bac1364c8.png → 20146fe6-e62b-4c57-b229-901994903b70.png} +0 -0
  253. /kaa/sprites/{6c926e92-9af9-402d-8512-6417ca116928.png → 20c673e9-fcbe-469b-be35-7844a1d5a9cd.png} +0 -0
  254. /kaa/sprites/{572a921d-633f-4465-b177-7a0d9ad7e099.png → 21747ae5-d94d-45d1-bda8-939389dc4874.png} +0 -0
  255. /kaa/sprites/{aa1624ff-88b0-447b-8e2b-8a50fd9e4062.png → 21fbbe96-02bf-4835-aa04-068bc5cc6ca3.png} +0 -0
  256. /kaa/sprites/{3b4dc708-1d34-4a88-9fe3-d8de2ec1d5c8.png → 24be7d90-7944-4a0a-a60c-67c9737b322c.png} +0 -0
  257. /kaa/sprites/{b59c0e9b-1f20-4194-ab37-286f505fa656.png → 24d6a47c-2099-45e2-9a67-b37767f459fc.png} +0 -0
  258. /kaa/sprites/{023b8f4c-15ab-4845-b141-446c861ad475.png → 2568d3d3-b642-4ea4-b929-4dee0b09738a.png} +0 -0
  259. /kaa/sprites/{7d7df15f-707e-4e27-826f-21e42af1dae0.png → 263b1037-fb51-4eb1-8c71-5232b03235d2.png} +0 -0
  260. /kaa/sprites/{f0aef696-2106-46a4-8b7f-9f16b6c89d3f.png → 27dbd535-7f95-4698-8fea-2bed67dd6968.png} +0 -0
  261. /kaa/sprites/{81686816-c723-47d1-9824-a68d9ebe1bd4.png → 286801f7-3af5-4cd0-9c25-46c12c2cd8f8.png} +0 -0
  262. /kaa/sprites/{dc97fea3-898f-4135-9c40-ad41570ab4ae.png → 298182ae-747a-44e3-8511-a64d3532b8ac.png} +0 -0
  263. /kaa/sprites/{8e019262-ad23-4cbb-84da-86b34775a91e.png → 2d3470f8-a714-4175-a8fe-71eef80921b6.png} +0 -0
  264. /kaa/sprites/{01247ebe-8d63-4573-90f4-d8dc2b7ca14c.png → 2e3b2982-d14b-4b49-bb64-da8178311d75.png} +0 -0
  265. /kaa/sprites/{fcc72120-2a77-4c26-a27e-e1027c6088c0.png → 2e41df89-a8d7-4e7e-96cb-7f551414823b.png} +0 -0
  266. /kaa/sprites/{31f2de0a-567b-425a-9be6-536e4532d813.png → 31e02e56-f266-47b5-8b10-fe79fe06d614.png} +0 -0
  267. /kaa/sprites/{7daaca55-e3fd-4e12-bf31-872105ceb726.png → 3314dc6c-868f-4045-9f60-1f3a17fed324.png} +0 -0
  268. /kaa/sprites/{fdf0da06-f088-424f-9941-8c883fea3db3.png → 358f1561-c16f-45a0-842d-d62fc735dc80.png} +0 -0
  269. /kaa/sprites/{51b95c81-4ff9-434c-ade2-3518e63337cb.png → 3782897a-f1c2-4f05-a02d-4c760672f52a.png} +0 -0
  270. /kaa/sprites/{847eb5c0-0350-4b7c-9c9c-43c796709795.png → 385e60df-2063-4caf-b1ea-e6ac909bc49d.png} +0 -0
  271. /kaa/sprites/{8e4d8a0f-4a9d-4562-9234-63806b11d85f.png → 39450419-26b5-4fbd-a5d4-1bab369ced30.png} +0 -0
  272. /kaa/sprites/{424a0ef5-102d-4734-a731-2b3b3c7c9682.png → 397c0e24-f35a-48c9-a576-aa1fcfc517b5.png} +0 -0
  273. /kaa/sprites/{23b9cda9-8be8-438e-8e54-57d91a4bd875.png → 3adef8f4-629d-4cb7-b54a-dadabfea155e.png} +0 -0
  274. /kaa/sprites/{2234f709-1703-4589-905c-175f4db09b1b.png → 3b86b4ac-aa29-4309-82da-f47a174d88cc.png} +0 -0
  275. /kaa/sprites/{e933cd55-e47a-4327-89d7-b25995cb4a3f.png → 3c6bbcea-488d-4df8-ab40-21e263aa0b16.png} +0 -0
  276. /kaa/sprites/{49bde219-f9a3-41b5-84b8-e417160a0f40.png → 3db54e0b-672d-4dfd-8a9b-5db37a08be74.png} +0 -0
  277. /kaa/sprites/{2204967a-a0ee-4dd3-aecb-4d531e8e954c.png → 402d430d-b507-4aa6-b3e1-db66b38c71b4.png} +0 -0
  278. /kaa/sprites/{70768479-5d7a-4941-8774-ad556c47bee2.png → 414140a2-de67-4c7f-a7f6-c8b30a6c8d6a.png} +0 -0
  279. /kaa/sprites/{dd7bd6cd-90f1-4773-9b68-5df7f2f84da5.png → 4147514f-4f3f-4dd5-952b-0f2cf5f62181.png} +0 -0
  280. /kaa/sprites/{0562f69f-0300-4a2b-8252-63f3e7180e4c.png → 43e53b71-9d69-4f4f-b217-a1abeea8991e.png} +0 -0
  281. /kaa/sprites/{55c3af20-58dc-4407-a383-312a57417c39.png → 44fab632-3920-4cd8-9967-f7a8a1ee29a0.png} +0 -0
  282. /kaa/sprites/{645909d7-b960-46c7-b208-db44b6b7feec.png → 45f705f9-58fb-4729-ae55-ee10848678d6.png} +0 -0
  283. /kaa/sprites/{da48db0d-09d9-47c3-9e08-8b69ad547be6.png → 4678a5fa-5b1c-4fdc-b7c4-e0b820039546.png} +0 -0
  284. /kaa/sprites/{37215a56-f8e1-4f22-a148-9894136f6ab1.png → 4738974e-60b8-4583-8548-94211c164291.png} +0 -0
  285. /kaa/sprites/{338d7e71-98ce-4cd1-9954-bf7155150780.png → 474c1678-9c36-495b-aef2-cadbb47b237d.png} +0 -0
  286. /kaa/sprites/{01256311-237c-476f-96ce-4136dc4bfbd3.png → 47783412-9cc7-4ba0-904d-8cd300222889.png} +0 -0
  287. /kaa/sprites/{9f7150bc-c0b8-48d6-862c-456aaf518b2b.png → 47ed66a4-9e7e-4646-b554-469dc86322db.png} +0 -0
  288. /kaa/sprites/{5930140e-effe-4bcf-b0be-c20d3990d833.png → 4d0074ad-6db4-4060-b71a-05c0e36e57a6.png} +0 -0
  289. /kaa/sprites/{22dc4cfe-8c66-4461-8660-e2d11bbe6154.png → 4f2f8328-a698-40d3-a40f-1f1ae77dc843.png} +0 -0
  290. /kaa/sprites/{694879e8-ecca-45e2-8ea4-1b447fd43ace.png → 52d0ff68-7a55-4d53-bc20-a1fa05cfe876.png} +0 -0
  291. /kaa/sprites/{962aa0b9-1dd3-4260-a4fb-c069c26e5a84.png → 52d737a7-5b0b-4ce0-ae3f-5d4048060f12.png} +0 -0
  292. /kaa/sprites/{87f3c1ae-5117-4871-a7d6-3f5ff0c9f9fb.png → 54a9cae1-62e5-4546-a46a-a5157f51e8b4.png} +0 -0
  293. /kaa/sprites/{e7f2734f-9fdc-4521-8d7e-8b0fe270a223.png → 56d35e14-ada9-4bfa-a48f-e4601054e7eb.png} +0 -0
  294. /kaa/sprites/{3b4f90c9-6de7-4ac3-8e41-5f8757bf3f3e.png → 575784c1-7c4a-4484-9f38-aa3c280ce56e.png} +0 -0
  295. /kaa/sprites/{57c81080-7b53-4286-8fa5-848ad63e4774.png → 577417ee-6635-4cb4-9f28-d1e1b47ae2cd.png} +0 -0
  296. /kaa/sprites/{72634cb3-4c76-4ca2-8898-ebb837ec19e3.png → 58358122-984b-4c31-91d7-eaf5c8c9353d.png} +0 -0
  297. /kaa/sprites/{179c0fff-ebd2-4a16-8db2-297552cca218.png → 5a06a662-ffa9-49a9-a86d-136e5983abdd.png} +0 -0
  298. /kaa/sprites/{2b6d2eb0-bcf7-4bea-b037-6293d9c6d728.png → 5c8eebc5-6d5e-445e-a3d1-66dce2bb6338.png} +0 -0
  299. /kaa/sprites/{2a8626df-056c-46a2-aaf3-0060a5aef6a3.png → 5d2b03a2-acb6-4bd2-86e8-1b203d1aeaec.png} +0 -0
  300. /kaa/sprites/{0af1d573-1dc7-427e-997d-173308ea3649.png → 5f02656f-1314-44d0-ae31-a176c24d758c.png} +0 -0
  301. /kaa/sprites/{84cabff2-7a1b-4018-b74b-46f4db06304f.png → 608c12e2-95dd-4efa-93b2-e648e9583062.png} +0 -0
  302. /kaa/sprites/{8f7b55d8-0143-4d27-bef8-560d4d510500.png → 647bb09a-13f8-4d54-a8ac-5b534f1a8d87.png} +0 -0
  303. /kaa/sprites/{1cf03f98-63e9-467c-804d-c74dd97b69bd.png → 6483c406-26cc-44ee-ad12-2a30ec47aedb.png} +0 -0
  304. /kaa/sprites/{889a4153-b713-49cb-a4d5-e302bcdd002d.png → 67d6a201-dfb9-4c88-b42b-d968cf9a034c.png} +0 -0
  305. /kaa/sprites/{ea430652-e263-4a15-bb6f-8a8807be6c8f.png → 6a93b483-0848-45e4-a937-51850f296c3d.png} +0 -0
  306. /kaa/sprites/{e4dc3b35-195c-415f-9484-c2459bd8675a.png → 6b4e4351-b370-48cd-8e8f-ca663d44aa0c.png} +0 -0
  307. /kaa/sprites/{f6b042a8-a91e-4811-99f9-18bbb5197468.png → 6c961dee-87f3-42f1-acef-9fe7d6be4df1.png} +0 -0
  308. /kaa/sprites/{ab237c6d-c4d8-4716-8ef7-99b8e995c9a7.png → 6d22b7ee-6e0f-4f5d-96a4-d4cba26a4d04.png} +0 -0
  309. /kaa/sprites/{d7750f81-de10-4d6f-9cc7-35223bda9d70.png → 6d5a3e08-257c-4394-96a6-e0719a66e5ae.png} +0 -0
  310. /kaa/sprites/{847226a3-b7d2-4156-b732-9215a3e14f3a.png → 71d0d086-50f1-4f50-bb24-a0190827bd08.png} +0 -0
  311. /kaa/sprites/{2cec1d6a-9e8c-49b3-b885-0b0d7c4b95ee.png → 71f87e1c-77f1-45c7-bb9c-16f14498682b.png} +0 -0
  312. /kaa/sprites/{30e12bf1-8fa5-4de1-8d7b-28fa0fec0cb6.png → 737570a7-b8f9-4cd7-b5bd-f40cd51b49f8.png} +0 -0
  313. /kaa/sprites/{ae1e70bc-f735-4749-8c23-95735b91897a.png → 745ee069-0f22-4b99-9327-513f365eb922.png} +0 -0
  314. /kaa/sprites/{8bd22fe1-b544-4d2e-b74a-34f3cf0eb512.png → 7601152e-a216-4bf8-92a6-4e3e6ea01d3d.png} +0 -0
  315. /kaa/sprites/{bfdc9b53-2fe5-43f1-8588-7ab71217d31c.png → 7a23d548-4395-40cc-ac19-4497fa3d9fe2.png} +0 -0
  316. /kaa/sprites/{96704aa3-b5ad-4e34-bb88-fad766415362.png → 7a7871dd-fd07-4234-bd01-c3c9e41bad45.png} +0 -0
  317. /kaa/sprites/{43a367e1-91dd-495e-8c30-41903f75a99a.png → 7d3c3a12-8d0f-48a7-9fd4-66db5e58488f.png} +0 -0
  318. /kaa/sprites/{756f4ca7-acac-48e1-8bcd-1c5cd8937e3a.png → 7d9f8ea3-1fdf-4675-8ddf-38393e235746.png} +0 -0
  319. /kaa/sprites/{31e3ac2b-ecd4-4c37-88bc-985ef32e73a3.png → 83f258af-35b8-4918-a971-80ea938a854e.png} +0 -0
  320. /kaa/sprites/{91b30f5e-31b2-4756-a3f7-f0f82a335442.png → 848a6c94-97a5-44f7-b84b-2f3283dc446b.png} +0 -0
  321. /kaa/sprites/{8ed51be4-815c-4a3d-805e-030fdfa341e2.png → 86a56df9-47ff-4741-822d-5b7e024d1598.png} +0 -0
  322. /kaa/sprites/{f0462447-5226-4819-a39b-19ab90583f83.png → 8b04d1a8-6cd6-4d2e-91e7-bdc58c46d939.png} +0 -0
  323. /kaa/sprites/{4a081370-b0a1-4067-8470-e3007cc68a12.png → 8b60ce9f-09c0-48a0-93f0-d51e0aa16afb.png} +0 -0
  324. /kaa/sprites/{91a50322-52d9-4516-9e46-bc121f20667d.png → 8c59d3ca-baff-4260-aa0a-6cedac1c2771.png} +0 -0
  325. /kaa/sprites/{f635499a-943d-47da-952a-1feb58daa25b.png → 8d7b4761-2555-4398-bb74-b70de3b75e22.png} +0 -0
  326. /kaa/sprites/{13cb0309-b713-4725-b10b-26afe46eb9c0.png → 901a2e7a-37f3-4dda-a58b-5a7644ead6b9.png} +0 -0
  327. /kaa/sprites/{cd0e8663-2ea1-436a-b9fb-3caa0c3ed9e8.png → 9cc77f5e-e7d0-4de4-aeb8-587ab8cb212a.png} +0 -0
  328. /kaa/sprites/{9991b19c-7330-42c4-9d7d-db3cb00103b7.png → 9e45adeb-4637-4b8b-a687-f1d2cd8c6c18.png} +0 -0
  329. /kaa/sprites/{5734e48a-1e58-42de-be7b-b7db67db4a01.png → a006054e-61fb-4d2b-a98e-45ce3c663662.png} +0 -0
  330. /kaa/sprites/{d1ea0ea6-4a6a-4036-b140-922c95a648b5.png → a0f98517-e4cf-422c-b29f-395a55939772.png} +0 -0
  331. /kaa/sprites/{3aed50a2-d640-4178-9b8a-4dd7973eebf1.png → a94d76ef-db70-45a9-aeca-ba16344cc572.png} +0 -0
  332. /kaa/sprites/{978873bb-e4d0-451b-9126-6977144f5395.png → afe7f086-723e-4999-a7aa-3342a797d828.png} +0 -0
  333. /kaa/sprites/{dce410ee-fa56-41c4-b75e-e1bff79cd94f.png → b2036053-36fb-4aa7-8348-e31942731a93.png} +0 -0
  334. /kaa/sprites/{ad94041c-f30b-40b9-b11a-1a26e9962274.png → b6da02bf-3f43-4ed0-9b13-f15becb42ce9.png} +0 -0
  335. /kaa/sprites/{a5694c76-3c5d-462e-81d5-1e0e6cef0ec9.png → ba2fd21c-6228-4e2d-b2db-a6d085cb38a6.png} +0 -0
  336. /kaa/sprites/{cba0646d-dffe-4c5b-a44d-1f8d827624a6.png → bb224de8-828e-4bc5-a986-632c72fc9157.png} +0 -0
  337. /kaa/sprites/{5bf2a814-df85-4d0a-b4b5-8883ac2ee434.png → bcc6ee72-ad5a-4d5c-b6c7-1b3fdfc5fa81.png} +0 -0
  338. /kaa/sprites/{edcec31d-d5de-4f22-b666-3e3c656e06d8.png → bebf9f6d-7cca-44c5-9b9f-fa36e29e97b3.png} +0 -0
  339. /kaa/sprites/{9008fbb2-f23f-424f-9be7-5bae6a3697ab.png → c4d0b0c9-ffbe-4b6c-9bf3-b05919e1a07c.png} +0 -0
  340. /kaa/sprites/{f32a41a2-c482-41ba-b718-28f048f5148c.png → c893e762-f328-4ef6-b862-5da8eb049f9c.png} +0 -0
  341. /kaa/sprites/{2d0e9d49-365a-4bcb-a416-38b87defaa3c.png → c944d298-a46b-4799-aea3-eec22fc7d4ac.png} +0 -0
  342. /kaa/sprites/{5c310fe5-7e92-4167-9eba-6e8e14a2863a.png → d28a18db-0f66-45a6-b3cd-69173ecdd790.png} +0 -0
  343. /kaa/sprites/{464b1dd8-ca2e-41e9-a5b5-90545c584db7.png → d8d5019c-52e6-4767-a9aa-d8da6ffcbd00.png} +0 -0
  344. /kaa/sprites/{dd873ac0-ffba-4335-9cf2-2162c6835ed8.png → d9cb2f43-2786-48d8-90f8-8cf1929f6172.png} +0 -0
  345. /kaa/sprites/{e13fc34b-accc-4986-865d-f8d8410b45e9.png → dbc5db78-81f5-41e6-bdc4-dafaa9173320.png} +0 -0
  346. /kaa/sprites/{e9310e38-a418-4561-bf33-eb3e6dccf477.png → e2ac106f-edeb-4375-af8c-45f33e9bfae6.png} +0 -0
  347. /kaa/sprites/{d81b1325-e57a-4f22-93e1-6ad4baa28935.png → e8a33d3f-a4fb-4851-b47a-b5f3d85e882f.png} +0 -0
  348. /kaa/sprites/{2289d38f-dc98-4310-9f34-4cf5023f8545.png → f7facb3a-1b41-4409-b128-d4ad03245845.png} +0 -0
  349. {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/WHEEL +0 -0
  350. {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/entry_points.txt +0 -0
  351. {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/licenses/LICENSE +0 -0
  352. {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/top_level.txt +0 -0
kaa/__init__.py ADDED
File without changes
File without changes
@@ -1,11 +1,14 @@
1
1
  import os
2
2
  import sys
3
3
 
4
- from kotonebot.interop.win.shortcut import create_shortcut
4
+ from kotonebot.util import is_windows, require_windows
5
+ if is_windows():
6
+ from kotonebot.interop.win.shortcut import create_shortcut
5
7
  from kaa.errors import LauncherNotFoundError
6
8
 
7
9
 
8
10
  def create_desktop_shortcut(start_immediately: bool):
11
+ require_windows('create_desktop_shortcut')
9
12
  exe_path = os.path.abspath('./kaa.exe')
10
13
  if not os.path.exists(exe_path):
11
14
  raise LauncherNotFoundError()
File without changes
@@ -0,0 +1,112 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ from kaa.config.schema import BaseConfig
5
+ from kotonebot.config.base_config import BackendConfig, UserConfig
6
+ from kotonebot.config.manager import load_config, save_config, RootConfig
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class ConfigValidationError(ValueError):
12
+ """Custom exception for configuration validation errors."""
13
+ pass
14
+
15
+
16
+ class ConfigService:
17
+ """
18
+ Manages application configuration, including loading, saving, and validation.
19
+ """
20
+
21
+ def __init__(self, config_path: str = "config.json"):
22
+ self.config_path = config_path
23
+ self._root_config: RootConfig[BaseConfig] | None = None
24
+ self._current_user_config: UserConfig[BaseConfig] | None = None
25
+ self.load()
26
+
27
+ def load(self):
28
+ """
29
+ Loads the configuration from the specified config file.
30
+ If the file does not exist or is empty, it creates and saves a default configuration.
31
+ It populates the root configuration and sets the current user config.
32
+ """
33
+ self._root_config = load_config(self.config_path, type=BaseConfig, use_default_if_not_found=True)
34
+
35
+ if not self._root_config.user_configs:
36
+ logger.info("config.json not found or is empty, creating a default configuration.")
37
+ default_config = UserConfig[BaseConfig](
38
+ name="默认配置",
39
+ category="default",
40
+ description="默认配置",
41
+ backend=BackendConfig(),
42
+ options=BaseConfig()
43
+ )
44
+ self._root_config.user_configs.append(default_config)
45
+ save_config(self._root_config, self.config_path)
46
+ logger.info("New default configuration created at %s", self.config_path)
47
+
48
+ self._current_user_config = self._root_config.user_configs[0]
49
+
50
+ def reload(self):
51
+ """Reloads configuration from disk."""
52
+ self.load()
53
+ logger.info("Configuration reloaded from disk.")
54
+
55
+ def get_root_config(self) -> RootConfig[BaseConfig]:
56
+ """Returns the entire root configuration object."""
57
+ if not self._root_config:
58
+ raise RuntimeError("Root config not loaded.")
59
+ return self._root_config
60
+
61
+ def get_current_user_config(self) -> UserConfig[BaseConfig]:
62
+ """Returns the currently active user configuration."""
63
+ if not self._current_user_config:
64
+ raise RuntimeError("User config not loaded.")
65
+ return self._current_user_config
66
+
67
+ def get_options(self) -> BaseConfig:
68
+ """Returns the 'options' part of the current user configuration."""
69
+ if not self._current_user_config:
70
+ raise RuntimeError("User config not loaded.")
71
+ return self._current_user_config.options
72
+
73
+ def save(self):
74
+ """
75
+ Validates and saves the current configuration state to disk.
76
+ """
77
+ if not self._root_config or not self._current_user_config:
78
+ raise RuntimeError("Config not loaded, cannot save.")
79
+
80
+ self._validate(self._current_user_config.backend, self._current_user_config.options)
81
+ save_config(self._root_config, self.config_path)
82
+ logger.info("Configuration saved successfully to %s", self.config_path)
83
+
84
+ def _validate(self, backend_config: BackendConfig, options: BaseConfig):
85
+ """
86
+ Performs validation checks on the configuration.
87
+ Raises ConfigValidationError if any check fails.
88
+ """
89
+ # Rule 1: Validate screenshot method against the backend type
90
+ valid_screenshot_methods = {
91
+ 'mumu12': ['adb', 'adb_raw', 'uiautomator2', 'nemu_ipc'],
92
+ 'mumu12v5': ['adb', 'adb_raw', 'uiautomator2', 'nemu_ipc'],
93
+ 'leidian': ['adb', 'adb_raw', 'uiautomator2'],
94
+ 'custom': ['adb', 'adb_raw', 'uiautomator2'],
95
+ 'dmm': ['remote_windows', 'windows']
96
+ }
97
+ if backend_config.screenshot_impl not in valid_screenshot_methods.get(backend_config.type, []):
98
+ raise ConfigValidationError(
99
+ f"截图方法 '{backend_config.screenshot_impl}' "
100
+ f"不适用于当前选择的模拟器类型 '{backend_config.type}'。"
101
+ )
102
+
103
+ # Rule 2: Ensure a produce solution is selected if produce is enabled
104
+ if options.produce.enabled and not options.produce.selected_solution_id:
105
+ raise ConfigValidationError("启用培育时,必须选择培育方案。")
106
+
107
+ # Rule 3: Ensure item lists are not empty if purchasing is enabled
108
+ if options.purchase.ap_enabled and not options.purchase.ap_items:
109
+ raise ConfigValidationError("启用AP购买时,AP商店购买物品不能为空。")
110
+
111
+ if options.purchase.money_enabled and not options.purchase.money_items:
112
+ raise ConfigValidationError("启用金币购买时,金币商店购买物品不能为空。")
@@ -0,0 +1,121 @@
1
+ import logging
2
+ import os
3
+ import re
4
+ import zipfile
5
+ from datetime import datetime, timedelta
6
+ from typing import Optional, Callable, Dict, Any
7
+
8
+ import cv2
9
+ from pydantic import BaseModel
10
+
11
+ from kaa.errors import ReportCreationError, UploadError
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class BugReportResult(BaseModel):
17
+ """错误报告创建结果的模型"""
18
+ file_path: str
19
+ upload_url: Optional[str] = None
20
+ message: str
21
+
22
+
23
+ def _sanitize_filename(s: str) -> str:
24
+ """过滤掉文件名中的非法字符"""
25
+ return re.sub(r'[\\/:*?"<>|]', '_', s)
26
+
27
+
28
+ class FeedbackService:
29
+ """处理反馈和错误报告的逻辑"""
30
+
31
+ def report(self, title: str, description: str, version: str, upload: bool, on_progress: Optional[Callable[[Dict[str, Any]], None]] = None) -> BugReportResult:
32
+ """
33
+ 创建并可能上传一个错误报告。
34
+
35
+ :param title: 报告标题。
36
+ :param description: 报告描述。
37
+ :param version: 当前版本。
38
+ :param upload: 是否上传报告。
39
+ :param on_progress: 进度回调函数,用于实时回报进度。
40
+ :return: 一个 BugReportResult 对象。
41
+ :raises ReportCreationError: 如果报告创建失败。
42
+ :raises UploadError: 如果报告上传失败。
43
+ """
44
+ from kotonebot import device
45
+ from kotonebot.backend.context import ContextStackVars
46
+
47
+ total_steps = 6 if upload else 5
48
+ def _progress(data: Dict[str, Any]):
49
+ if on_progress:
50
+ on_progress(data)
51
+
52
+ os.makedirs('logs', exist_ok=True)
53
+ os.makedirs('reports', exist_ok=True)
54
+
55
+ safe_title = _sanitize_filename(title)[:30] or "无标题"
56
+ timestamp = datetime.now().strftime("%y-%m-%d-%H-%M-%S")
57
+ path = f'./reports/bug_{timestamp}_{safe_title}.zip'
58
+
59
+ try:
60
+ with zipfile.ZipFile(path, 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zipf:
61
+ _progress({'type': 'packing', 'item': '描述文件', 'step': 1, 'total_steps': total_steps})
62
+ description_content = f"标题:{title}\n类型:bug\n内容:\n{description}"
63
+ zipf.writestr('description.txt', description_content.encode('utf-8'))
64
+
65
+ _progress({'type': 'packing', 'item': '上次截图', 'step': 2, 'total_steps': total_steps})
66
+ try:
67
+ stack = ContextStackVars.current()
68
+ if stack and stack._screenshot is not None:
69
+ img = cv2.imencode('.png', stack._screenshot)[1].tobytes()
70
+ zipf.writestr('last_screenshot.png', img)
71
+ except Exception as e:
72
+ logger.warning(f"保存上次截图失败: {e}")
73
+
74
+ _progress({'type': 'packing', 'item': '当前截图', 'step': 3, 'total_steps': total_steps})
75
+ try:
76
+ screenshot = device.screenshot()
77
+ img = cv2.imencode('.png', screenshot)[1].tobytes()
78
+ zipf.writestr('current_screenshot.png', img)
79
+ except Exception as e:
80
+ logger.warning(f"保存当前截图失败: {e}")
81
+
82
+ _progress({'type': 'packing', 'item': '配置文件', 'step': 4, 'total_steps': total_steps})
83
+ if os.path.exists('config.json'):
84
+ zipf.write('config.json')
85
+
86
+ _progress({'type': 'packing', 'item': '日志', 'step': 5, 'total_steps': total_steps})
87
+ if os.path.exists('logs'):
88
+ for root, _, files in os.walk('logs'):
89
+ for file in files:
90
+ file_path = os.path.join(root, file)
91
+ arcname = os.path.join('logs', os.path.relpath(file_path, 'logs'))
92
+ zipf.write(file_path, arcname)
93
+
94
+ zipf.writestr('version.txt', version)
95
+ except Exception as e:
96
+ raise ReportCreationError(str(e)) from e
97
+
98
+ file_path = os.path.abspath(path)
99
+
100
+ if not upload:
101
+ message = f"报告已保存至 {file_path}"
102
+ _progress({'type': 'done', 'file_path': file_path, 'step': 5, 'total_steps': total_steps})
103
+ return BugReportResult(file_path=file_path, message=message)
104
+
105
+ # 上传报告
106
+ from kotonebot.ui.file_host.sensio import upload as upload_file
107
+ _progress({'type': 'uploading', 'item': '报告', 'step': 6, 'total_steps': total_steps})
108
+ try:
109
+ url = upload_file(file_path)
110
+ except Exception as e:
111
+ raise UploadError(str(e)) from e
112
+
113
+ expire_time = datetime.now() + timedelta(days=7)
114
+ final_msg = (
115
+ f"报告导出成功:{url}\n\n"
116
+ f"此链接将于 {expire_time.strftime('%Y-%m-%d %H:%M:%S')}(7 天后)过期\n\n"
117
+ '**复制以上文本并发送至 QQ 群、Github issue、B站私信等**'
118
+ )
119
+ _progress({'type': 'done', 'url': url, 'step': 6, 'total_steps': total_steps})
120
+ return BugReportResult(file_path=file_path, upload_url=url, message=final_msg)
121
+
@@ -0,0 +1,83 @@
1
+ import logging
2
+ from typing import List
3
+
4
+ from kaa.config.produce import ProduceSolution, ProduceSolutionManager, ProduceData
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+
9
+ class ProduceSolutionService:
10
+ """
11
+ Service layer for managing produce solutions.
12
+ This service acts as a wrapper around ProduceSolutionManager,
13
+ decoupling the UI/facade from the direct file system operations.
14
+ """
15
+
16
+ def __init__(self):
17
+ self._manager = ProduceSolutionManager()
18
+
19
+ def list_solutions(self) -> List[ProduceSolution]:
20
+ """
21
+ Retrieves a list of all available produce solutions.
22
+
23
+ :return: A list of ProduceSolution objects.
24
+ """
25
+ return self._manager.list()
26
+
27
+ def get_solution(self, solution_id: str) -> ProduceSolution:
28
+ """
29
+ Retrieves a single produce solution by its ID.
30
+
31
+ :param solution_id: The ID of the solution to retrieve.
32
+ :return: The ProduceSolution object.
33
+ :raises ProduceSolutionNotFoundError: If no solution with the given ID is found.
34
+ """
35
+ return self._manager.read(solution_id)
36
+
37
+ def create_solution(self, name: str = "新培育方案") -> ProduceSolution:
38
+ """
39
+ Creates a new, empty produce solution with a unique ID and saves it.
40
+
41
+ :param name: The name for the new solution.
42
+ :return: The newly created ProduceSolution object.
43
+ """
44
+ new_solution = self._manager.new(name)
45
+ self._manager.save(new_solution.id, new_solution)
46
+ logger.info(f"Created new produce solution '{name}' with ID {new_solution.id}")
47
+ return new_solution
48
+
49
+ def delete_solution(self, solution_id: str) -> None:
50
+ """
51
+ Deletes a produce solution by its ID.
52
+
53
+ :param solution_id: The ID of the solution to delete.
54
+ """
55
+ self._manager.delete(solution_id)
56
+ logger.info(f"Deleted produce solution with ID {solution_id}")
57
+
58
+ def save_solution(self, solution: ProduceSolution) -> None:
59
+ """
60
+ Saves a ProduceSolution object to the filesystem.
61
+ This can be used for both updating existing solutions and saving new ones.
62
+
63
+ :param solution: The ProduceSolution object to save.
64
+ """
65
+ self._manager.save(solution.id, solution)
66
+ logger.info(f"Saved produce solution '{solution.name}' with ID {solution.id}")
67
+
68
+ def update_solution_data(self, solution_id: str, name: str, description: str, data: ProduceData) -> ProduceSolution:
69
+ """
70
+ Updates an existing produce solution with new data and saves it.
71
+
72
+ :param solution_id: The ID of the solution to update.
73
+ :param name: The new name for the solution.
74
+ :param description: The new description for the solution.
75
+ :param data: The new ProduceData object.
76
+ :return: The updated ProduceSolution object.
77
+ """
78
+ solution = self.get_solution(solution_id)
79
+ solution.name = name
80
+ solution.description = description
81
+ solution.data = data
82
+ self.save_solution(solution)
83
+ return solution
@@ -0,0 +1,145 @@
1
+ import logging
2
+ from datetime import datetime, timedelta
3
+ from typing import List, Tuple, Optional
4
+
5
+ from kaa.main.kaa import Kaa
6
+ from kotonebot.backend.context import task_registry, vars as context_vars
7
+ from kotonebot.backend.bot import RunStatus
8
+ from kotonebot.errors import ContextNotInitializedError
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class TaskService:
14
+ """
15
+ Manages the lifecycle of Kaa tasks, including starting, stopping,
16
+ and pausing. It encapsulates the state related to task execution.
17
+ """
18
+
19
+ def __init__(self, kaa_instance: Kaa):
20
+ self._kaa = kaa_instance
21
+ self.run_status: RunStatus | None = None
22
+ self.is_running_all: bool = False
23
+ self.is_running_single: bool = False
24
+ self.is_stopping: bool = False
25
+ self.task_start_time: Optional[datetime] = None
26
+
27
+ def is_running(self) -> bool:
28
+ """Checks if any task (either all or single) is currently running."""
29
+ return self.is_running_all or self.is_running_single
30
+
31
+ def start_all_tasks(self) -> None:
32
+ """Starts all registered tasks."""
33
+ if self.is_running():
34
+ logger.warning("Cannot start all tasks, a task is already running.")
35
+ return
36
+
37
+ logger.info("Starting all tasks...")
38
+ self.is_running_all = True
39
+ self.is_stopping = False
40
+ self.task_start_time = datetime.now()
41
+ self.run_status = self._kaa.start_all()
42
+
43
+ def start_single_task(self, task_name: str) -> None:
44
+ """
45
+ Starts a single task by its name.
46
+
47
+ :param task_name: The name of the task to start.
48
+ :raises ValueError: If the task name is not found.
49
+ """
50
+ if self.is_running():
51
+ logger.warning(f"Cannot start task '{task_name}', a task is already running.")
52
+ return
53
+
54
+ task = task_registry.get(task_name)
55
+ if not task:
56
+ raise ValueError(f"Task '{task_name}' not found in task registry.")
57
+
58
+ logger.info(f"Starting single task: {task_name}")
59
+ self.is_running_single = True
60
+ self.is_stopping = False
61
+ self.task_start_time = datetime.now()
62
+ self.run_status = self._kaa.start([task])
63
+
64
+ def stop_tasks(self) -> None:
65
+ """Stops the currently running tasks."""
66
+ if not self.is_running() or self.is_stopping:
67
+ logger.warning("No tasks are running or tasks are already stopping.")
68
+ return
69
+
70
+ logger.info("Stopping tasks...")
71
+ self.is_stopping = True
72
+ try:
73
+ if context_vars.flow.is_paused:
74
+ logger.info("Tasks are paused, resuming before stopping.")
75
+ context_vars.flow.request_resume()
76
+ except ContextNotInitializedError:
77
+ pass # Context might not be ready if stopping very early
78
+
79
+ if self.run_status:
80
+ self.run_status.interrupt()
81
+
82
+ def get_task_statuses(self) -> List[Tuple[str, str]]:
83
+ """
84
+ Gets the current status of all registered tasks.
85
+
86
+ :return: A list of tuples, where each tuple contains the task name and its status.
87
+ """
88
+ if not self.run_status:
89
+ return [(task.name, "pending") for task in task_registry.values()]
90
+
91
+ # Reset running flags if the underlying run_status is no longer running
92
+ if not self.run_status.running:
93
+ self.is_running_all = False
94
+ self.is_running_single = False
95
+ self.is_stopping = False
96
+ self.task_start_time = None
97
+
98
+ status_list: List[Tuple[str, str]] = []
99
+ for task_status in self.run_status.tasks:
100
+ status_list.append((task_status.task.name, task_status.status))
101
+ return status_list
102
+
103
+ def toggle_pause(self) -> bool | None:
104
+ """
105
+ Toggles the pause/resume state of the running tasks.
106
+
107
+ :return: True if paused, False if resumed, None if context not initialized.
108
+ """
109
+ try:
110
+ if context_vars.flow.is_paused:
111
+ context_vars.flow.request_resume()
112
+ logger.info("Tasks resumed.")
113
+ return False
114
+ else:
115
+ context_vars.flow.request_pause()
116
+ logger.info("Tasks paused.")
117
+ return True
118
+ except ContextNotInitializedError:
119
+ logger.warning("Cannot toggle pause, context not initialized.")
120
+ return None
121
+
122
+ def get_pause_status(self) -> bool | None:
123
+ """
124
+ Gets the current pause status.
125
+
126
+ :return: True if paused, False if resumed, None if context not initialized.
127
+ """
128
+ try:
129
+ return context_vars.flow.is_paused
130
+ except ContextNotInitializedError:
131
+ return None
132
+
133
+ def get_all_task_names(self) -> List[str]:
134
+ """Returns a list of all registered task names."""
135
+ return list(task_registry.keys())
136
+
137
+ def get_task_runtime(self) -> Optional[timedelta]:
138
+ """
139
+ Gets the current task runtime.
140
+
141
+ :return: A timedelta object representing the runtime, or None if no task is running.
142
+ """
143
+ if self.task_start_time is None:
144
+ return None
145
+ return datetime.now() - self.task_start_time