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.
- kaa/__init__.py +0 -0
- kaa/application/__init__.py +0 -0
- kaa/application/core/misc_core.py +4 -1
- kaa/application/services/__init__.py +0 -0
- kaa/application/services/config_service.py +112 -0
- kaa/application/services/feedback_service.py +121 -0
- kaa/application/services/produce_solution_service.py +83 -0
- kaa/application/services/task_service.py +145 -0
- kaa/application/services/update_service.py +208 -0
- kaa/application/ui/__init__.py +0 -0
- kaa/application/ui/common.py +123 -0
- kaa/application/ui/components/alert.py +251 -0
- kaa/application/ui/components/alert.pyi +257 -0
- kaa/application/ui/components/categorized_select.pyi +697 -0
- kaa/application/ui/facade.py +189 -0
- kaa/application/ui/gradio_view.py +135 -0
- kaa/application/ui/views/__init__.py +0 -0
- kaa/application/ui/views/feedback_view.py +65 -0
- kaa/application/ui/views/produce_view.py +251 -0
- kaa/application/ui/views/settings_view.py +581 -0
- kaa/application/ui/views/status_view.py +171 -0
- kaa/application/ui/views/task_view.py +102 -0
- kaa/application/ui/views/update_view.py +106 -0
- kaa/config/schema.py +8 -0
- kaa/db/constants.py +3 -2
- kaa/errors.py +60 -0
- kaa/main/gr.py +60 -3132
- kaa/main/kaa.py +11 -3
- kaa/metadata.py +80 -0
- kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
- kaa/resources/game.db +0 -0
- kaa/resources/game_ver.txt +0 -0
- kaa/resources/idol_cards/i_card-skin-amao-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-amao-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-1-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-1-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-2-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-2-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-3-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-3-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-fktn-3-016_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-fktn-3-016_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-003_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-003_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-013_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-013_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hrnm-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hrnm-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hski-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hski-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-014_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kllj-3-014_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kllj-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-shro-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-shro-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ssmk-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ssmk-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ttmr-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ttmr-3-015_1.png +0 -0
- kaa/sprites/052ab0f5-8d95-4b5d-8678-3838322d9e5e.png +0 -0
- kaa/sprites/18adb1a5-b95d-41ff-9cb9-16613fa4cf6a.png +0 -0
- kaa/sprites/2aac3a97-435e-4c02-925f-e2d1673b7982.png +0 -0
- kaa/sprites/2cc63c6d-5988-4f72-ae88-b03b8246ad97.png +0 -0
- kaa/sprites/3208d803-2c92-4775-80dc-0527df4b63d9.png +0 -0
- kaa/sprites/345435d0-5a5c-494b-95ab-1e086fb88f51.png +0 -0
- kaa/sprites/3ad30d90-8b57-4641-a9e2-33970e5cea1d.png +0 -0
- kaa/sprites/3e0da5df-a4de-42bd-83bd-13df3c393af4.png +0 -0
- kaa/sprites/41904062-e218-4b28-972a-b5cfcd058d2c.png +0 -0
- kaa/sprites/44a50906-1835-4e29-ae97-496b4cdde9e9.png +0 -0
- kaa/sprites/488a1403-d300-4fa6-94c7-da71d09fd4bb.png +0 -0
- kaa/sprites/48c16d60-05d6-43bc-97c3-7f099bfc0881.png +0 -0
- kaa/sprites/4e3dbeb5-70bb-4642-9f73-01f9f98bc3aa.png +0 -0
- kaa/sprites/54987de4-3e1b-4640-b203-1e4c82d7e98d.png +0 -0
- kaa/sprites/5a0bfeac-fb22-4b0c-b775-4aa6220bae89.png +0 -0
- kaa/sprites/5aad0930-54a3-4b6d-bec8-250228963f69.png +0 -0
- kaa/sprites/5c49d3b3-656e-4c8c-ae1a-9b0209b9dcc3.png +0 -0
- kaa/sprites/5c9a1581-a14a-449b-a1b0-7a31a965facc.png +0 -0
- kaa/sprites/62411b55-7be8-46d9-aa4a-fb56dab6658c.png +0 -0
- kaa/sprites/6580ea89-553e-4445-a855-f834d580e6e6.png +0 -0
- kaa/sprites/686a2bf5-0498-4d53-8ba1-1110ff36f046.png +0 -0
- kaa/sprites/699ca639-3006-45c1-b5fd-8cf9631fd3ea.png +0 -0
- kaa/sprites/6e8325f9-7fdb-4729-ac13-ca67244d97bc.png +0 -0
- kaa/sprites/71051aa7-81f1-4144-9318-4405e10547ee.png +0 -0
- kaa/sprites/732ffc6c-6a17-41f8-9cd1-f218ebc0c23f.png +0 -0
- kaa/sprites/744ea25a-9b6e-4f8f-9a00-0ac714571b09.png +0 -0
- kaa/sprites/74b50642-0b18-45c3-8a5d-013ef1e0eb78.png +0 -0
- kaa/sprites/77e7262f-0d12-4bd9-9f22-e8f41a600bf8.png +0 -0
- kaa/sprites/78b928c6-0d24-4e87-a84f-0091d42f8e49.png +0 -0
- kaa/sprites/7c193df5-0a1d-444d-9f92-e9c0db79e53a.png +0 -0
- kaa/sprites/7e729638-f54a-48bb-8bbf-eeaa4d697502.png +0 -0
- kaa/sprites/802e717f-d70a-4f34-8b96-be586a8dfde9.png +0 -0
- kaa/sprites/831cac7e-49e9-45d1-bb65-b1db733cda90.png +0 -0
- kaa/sprites/8411b102-866d-4e41-ab12-507397b80ca5.png +0 -0
- kaa/sprites/84b3c8e2-6e37-443c-be9b-8a95aedc6f37.png +0 -0
- kaa/sprites/85308e03-ba72-499a-9d12-870269fa3cd0.png +0 -0
- kaa/sprites/8922feef-17db-4b10-93da-1bad30492ac2.png +0 -0
- kaa/sprites/8a6ed80c-79c6-4df6-ab65-64d67afb2d5b.png +0 -0
- kaa/sprites/8c0439d9-9eb7-43f3-8d1e-7e41c57c1bbd.png +0 -0
- kaa/sprites/8dd3de6d-07d5-4d93-9663-71a3a4c57a32.png +0 -0
- kaa/sprites/9009323d-1418-4aed-8a93-075b326d2e7a.png +0 -0
- kaa/sprites/904d22f7-51be-486f-8dd1-1871c0cf28e3.png +0 -0
- kaa/sprites/90943f62-0a03-4a75-804a-0c2fa7b27af4.png +0 -0
- kaa/sprites/9180e0e7-2cc4-46c7-95ff-fbe83806baf2.png +0 -0
- kaa/sprites/93f5c33e-ec81-4a70-a11f-b2e8cb1751ee.png +0 -0
- kaa/sprites/9558b2a5-3961-4ad0-9ce8-379d71920d78.png +0 -0
- kaa/sprites/968dff88-5a2f-42c7-b64b-406801e22c87.png +0 -0
- kaa/sprites/99d99d78-ee37-4e84-8768-b5a7f4f9bd51.png +0 -0
- kaa/sprites/9caa102c-70af-4a8c-b595-82df9f4c05d8.png +0 -0
- kaa/sprites/9e06b7d6-5d15-4844-bbfe-ad1af7da3113.png +0 -0
- kaa/sprites/__pycache__/__init__.cpython-310.pyc +0 -0
- kaa/sprites/a04ed558-25e3-42d7-a662-250cad9fa5df.png +0 -0
- kaa/sprites/a0a62dbf-a027-4b63-86e4-2e863b2edb01.png +0 -0
- kaa/sprites/a4b898aa-405e-4235-8075-a34640a2b023.png +0 -0
- kaa/sprites/a5c3108f-c92d-4ce7-8c4e-93b79f55ceb3.png +0 -0
- kaa/sprites/a7e6222f-f8ca-47c2-af1e-f158a87f6a03.png +0 -0
- kaa/sprites/ab3d3301-8297-43a8-bf0b-85413c115a7d.png +0 -0
- kaa/sprites/ad589feb-6d19-47c7-a582-55ee130ee89d.png +0 -0
- kaa/sprites/ae4742aa-acda-442d-bf73-b3fe7b66e85c.png +0 -0
- kaa/sprites/aed87cd4-eb05-4c24-8adf-cd3fab20e9a3.png +0 -0
- kaa/sprites/afb9e4a9-29a5-4202-9f75-e7d2f1b64aa4.png +0 -0
- kaa/sprites/b1f547d4-c1ba-43fc-9398-4ccdc25b8b62.png +0 -0
- kaa/sprites/b61bd48f-1fe7-49fd-a588-09aac3b66f5a.png +0 -0
- kaa/sprites/b6219452-323a-44eb-9f44-97b2ad0ee49a.png +0 -0
- kaa/sprites/b7550a50-5943-45e7-9c1b-771117364844.png +0 -0
- kaa/sprites/b865eedf-7bea-46f6-bf14-7f8f4e9ab000.png +0 -0
- kaa/sprites/b8f0ed47-6115-4b88-848a-2fc4a1ab25d8.png +0 -0
- kaa/sprites/b9224799-d0c1-43d9-9f11-1d35903fc4d9.png +0 -0
- kaa/sprites/baa9c530-68cb-4111-85f6-060823ad32c4.png +0 -0
- kaa/sprites/bed54f67-d828-403c-9cb3-6a7c85695c2a.png +0 -0
- kaa/sprites/befadc5e-862a-4818-9223-5d58e4ac03cb.png +0 -0
- kaa/sprites/c0d1896c-71a1-47d6-9847-b87543a942e9.png +0 -0
- kaa/sprites/c2984c0f-3e17-45c3-9d7c-dc4f14440b13.png +0 -0
- kaa/sprites/c6b53acc-bc89-465e-9814-0138513327ac.png +0 -0
- kaa/sprites/c72a4609-6bf0-4568-8ebc-73c30d67c61e.png +0 -0
- kaa/sprites/c7829f82-bfce-4259-9ec6-f1cfb7bac925.png +0 -0
- kaa/sprites/c82ebc01-0127-417f-831a-9d17a84b2691.png +0 -0
- kaa/sprites/c8747b3b-745c-45ed-84b6-dde1b2558ce8.png +0 -0
- kaa/sprites/c98ef89e-4a1c-40f0-a82e-6851f7b6bbc9.png +0 -0
- kaa/sprites/cb04d87c-f5a9-405c-92ac-b3603e482221.png +0 -0
- kaa/sprites/cb43f670-6623-4af9-ac1d-746372e40511.png +0 -0
- kaa/sprites/ce357023-436b-4a39-882f-8410acd8f0d7.png +0 -0
- kaa/sprites/cea9f5ea-5923-4c6e-bd24-90d2e084112c.png +0 -0
- kaa/sprites/cf62e2df-3be1-4d03-9f34-1518280abd90.png +0 -0
- kaa/sprites/d0a483a9-400f-4b6e-87a0-9781b4454da0.png +0 -0
- kaa/sprites/d10d480c-e96e-475e-815c-0969f37fe3bc.png +0 -0
- kaa/sprites/d1839450-8d60-41a4-b035-8e1acd0f1c7a.png +0 -0
- kaa/sprites/d19859f3-f7cc-46ef-8bc6-86df7856fd53.png +0 -0
- kaa/sprites/d2d3d77d-a06f-4167-b02b-5ca688c0c0c3.png +0 -0
- kaa/sprites/d38c5015-e461-4e09-8b56-731472bdf59e.png +0 -0
- kaa/sprites/d473b5bd-4be3-4f0f-bb92-b909050f273a.png +0 -0
- kaa/sprites/d609a029-5407-43c2-a9a9-07bfd43fcbb8.png +0 -0
- kaa/sprites/d6491f82-9637-47eb-8f35-eb272b5ef8df.png +0 -0
- kaa/sprites/d8dd8b59-c05c-4350-a15d-be75c94d46cc.png +0 -0
- kaa/sprites/d98263bf-15fb-430e-ba39-2558fa99cac0.png +0 -0
- kaa/sprites/d9bc9bbb-9a1a-4cbe-b6ed-24112d7c5ac7.png +0 -0
- kaa/sprites/da922566-97ba-4477-bcad-35ea02a3ee48.png +0 -0
- kaa/sprites/dac8d8fd-006c-4f50-a4e0-d79dbf3f5915.png +0 -0
- kaa/sprites/db33ab8d-160d-48c7-b464-dfe194e762d4.png +0 -0
- kaa/sprites/dcfdfab4-8dfb-4069-bf88-8e8401ef86f3.png +0 -0
- kaa/sprites/de354b53-2fd0-4039-87e2-fcad2e070579.png +0 -0
- kaa/sprites/e28ea25e-0bcf-4d52-b501-9ef7a4863870.png +0 -0
- kaa/sprites/e2ac927f-257e-4537-995d-fbfbe4983b70.png +0 -0
- kaa/sprites/e642b9ef-c8a7-41d5-8d71-5cfbaf3017a1.png +0 -0
- kaa/sprites/e749feec-6bf2-4c24-bb12-948e696b8116.png +0 -0
- kaa/sprites/ed3aa6e6-4256-416b-9d04-d57ca340e39d.png +0 -0
- kaa/sprites/ed4c0554-84df-4c29-af18-7c38523cc59b.png +0 -0
- kaa/sprites/ef1bfd47-78e9-4cb7-a344-53d980fc3e5e.png +0 -0
- kaa/sprites/ef1ddc7d-75f9-4798-afa1-733e16794a81.png +0 -0
- kaa/sprites/efb01328-b6e1-438e-9471-bef3ea77a22c.png +0 -0
- kaa/sprites/f06b1a4f-eeb6-4dea-9543-5ec27640bdd9.png +0 -0
- kaa/sprites/f07bac27-9201-498f-9f26-a58291a70542.png +0 -0
- kaa/sprites/f0fd613b-d2f8-4b18-90d8-0b328373e715.png +0 -0
- kaa/sprites/f1fbe46a-759d-467d-b8ca-2158f530f7c5.png +0 -0
- kaa/sprites/f2314c76-3a2b-4644-831a-343a601145df.png +0 -0
- kaa/sprites/f329d4ba-e836-4be6-a05b-879b53667df3.png +0 -0
- kaa/sprites/f469d235-552f-4b07-9d03-9bcae425b6d8.png +0 -0
- kaa/sprites/f5177258-a3cf-4d4f-9c69-0b49556f754f.png +0 -0
- kaa/sprites/f5dcac82-7c54-4020-84c5-b1334b595612.png +0 -0
- kaa/sprites/f6656842-1460-41ab-95ed-561aefaf08e2.png +0 -0
- kaa/sprites/f70e9455-7cc8-449c-8282-89a9e69f7ac3.png +0 -0
- kaa/sprites/f7fd469f-791e-4bf7-ae3f-b5aaed92f999.png +0 -0
- kaa/sprites/f873280f-bc68-40d1-8d8d-3d86964264f0.png +0 -0
- kaa/sprites/f9da6eeb-ff9e-45b3-94b0-e7ba34938dec.png +0 -0
- kaa/sprites/fa24f5d5-d7e5-4421-8cbc-2ce3a0189654.png +0 -0
- kaa/sprites/fb61dbf3-fbc1-400a-adde-83ea08b5027d.png +0 -0
- kaa/sprites/fc8457b6-f8a3-4b01-9864-0cd624c312b6.png +0 -0
- kaa/sprites/fdbf6a89-b95a-481f-a269-be53e05b18de.png +0 -0
- kaa/sprites/fed11307-2186-4ede-875f-ffa0383f410c.png +0 -0
- kaa/sprites/ff0d3db2-c4e5-41e7-a85b-df4fd392924c.png +0 -0
- kaa/sprites/ff40ff91-4e8c-46cb-a254-66cd5ffd363e.png +0 -0
- kaa/sprites/ff614071-c318-4263-af3e-01ea0ab45b73.png +0 -0
- kaa/tasks/R.py +136 -128
- kaa/tasks/R2.py +24 -0
- kaa/tasks/common.py +5 -0
- kaa/tasks/daily/club_reward.py +1 -0
- kaa/tasks/daily/contest.py +2 -1
- kaa/tasks/daily/purchase.py +33 -1
- kaa/tasks/daily/upgrade_support_card.py +12 -2
- kaa/tasks/produce/cards.py +5 -4
- kaa/tasks/produce/common.py +202 -105
- kaa/tasks/produce/in_purodyuusu.py +35 -17
- kaa/tasks/produce/non_lesson_actions.py +10 -33
- kaa/tasks/produce/p_drink.py +5 -1
- kaa/tasks/produce/produce.py +2 -1
- kaa/tasks/start_game.py +2 -1
- kaa/util/reactive.py +182 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/METADATA +27 -24
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/RECORD +352 -181
- /kaa/sprites/{35341839-4469-4ab6-aa40-33642fe43e82.png → 01e93c2c-28dc-41f8-8f9a-ec62ec12aa01.png} +0 -0
- /kaa/sprites/{68d9f340-a3d2-4708-8eb1-c1ed857decda.png → 02ac01e0-00b0-46d8-a6db-56248c843c6d.png} +0 -0
- /kaa/sprites/{39f6d657-3b3e-40aa-849b-7ad87a0be1d0.png → 033e73d1-9f45-4bca-bf96-6778410f2fc4.png} +0 -0
- /kaa/sprites/{799fe395-2264-4bc5-b515-813dadda8fe1.png → 04036690-5b0f-4ee0-a9d0-022ee822bf0e.png} +0 -0
- /kaa/sprites/{256ffeba-8e9e-4cc5-8a1c-9eaee427f1a5.png → 041bd3fc-d040-4773-8641-4e4509300d2f.png} +0 -0
- /kaa/sprites/{5ffd3f29-db4f-4f66-b9ed-be5a70b7ebf9.png → 04974917-b1e8-4ccc-807b-6f651026c955.png} +0 -0
- /kaa/sprites/{8be81341-a74d-42c8-8231-5d1854bc08e7.png → 04c4e4c2-9908-4be7-bcbe-4d926ca76737.png} +0 -0
- /kaa/sprites/{043e753e-db15-45ba-8513-53c3fc9c7f3c.png → 05b97cdf-f7df-4d91-9ec8-5e9594a46382.png} +0 -0
- /kaa/sprites/{5431dc38-c257-40b3-8f7b-8bceaa7fe587.png → 061b032f-860b-4c53-889b-aa126797f062.png} +0 -0
- /kaa/sprites/{cb6dffd9-6474-4d09-aee6-26352ea51d31.png → 07b43eb9-db32-4046-96d3-9f4314bfd80a.png} +0 -0
- /kaa/sprites/{3e087b8d-420d-48ff-b526-29c4a65d8cbe.png → 08b12ded-8230-4c7e-bb9f-27c85b0fdabb.png} +0 -0
- /kaa/sprites/{68e20ebf-02fd-46a1-88d7-b4472824e7bc.png → 09364c3a-f892-4911-abdc-2f5fea09289f.png} +0 -0
- /kaa/sprites/{c69dcdcf-42a7-420e-aa8e-bb8639ea80b6.png → 09d2a63d-d2f0-4b97-b3cb-22a61b1530f7.png} +0 -0
- /kaa/sprites/{d644faa3-ff16-417f-928c-4c62b040bfdb.png → 0cad6e46-276f-424e-a79e-d272ebaa7c8e.png} +0 -0
- /kaa/sprites/{db6707a2-2964-4919-9992-4d801fa43dae.png → 0e49fbde-6be6-42b3-b8d1-36e0cb9cc35d.png} +0 -0
- /kaa/sprites/{cd00a2d7-af48-48b1-b2e1-5360ceed249f.png → 0e51d671-928c-4972-8ac0-de446202070b.png} +0 -0
- /kaa/sprites/{736a9daf-05d6-46ba-810b-5a8f509152d1.png → 0e6f8981-f46c-4c7d-9d90-fe349f0a1d77.png} +0 -0
- /kaa/sprites/{92c3de1b-eed1-45b9-82e0-c9e97bb479e7.png → 0e9e3dbf-6e94-4a12-b558-3d8ab500c0a6.png} +0 -0
- /kaa/sprites/{913dbd4e-ebb1-4c9f-b145-9960cde59c17.png → 0eafb6c1-9d85-4fe0-8011-7235704ca9d3.png} +0 -0
- /kaa/sprites/{ec3cad5f-e0c9-4577-8499-79b50248344e.png → 1002a830-1ad5-47a7-b7dd-ed2989e6fc1b.png} +0 -0
- /kaa/sprites/{e5e49b44-dcc2-4e77-9180-0d2beaa3f9ad.png → 10943367-c1d8-41c7-a831-d5d05288875a.png} +0 -0
- /kaa/sprites/{c1d502eb-c77f-45cb-86b5-11b4a8a3aef5.png → 10f37db0-8c3e-4790-a5c3-cdb841f106a7.png} +0 -0
- /kaa/sprites/{802db04f-77c2-46a4-a6eb-f81d48ea03ce.png → 11f65378-b982-4936-9ac7-68560a74a042.png} +0 -0
- /kaa/sprites/{1befe09b-cb77-417a-b21e-7746804d4e03.png → 1660acf7-a420-4d92-a90c-55c5ff208da6.png} +0 -0
- /kaa/sprites/{16a0fd47-e85b-4848-8894-9d071ea993ac.png → 170d28bf-d262-4bf1-b35f-8f3d4b4fff6e.png} +0 -0
- /kaa/sprites/{5906d986-d0e5-452d-a7c4-ddeb7af8751d.png → 182d8c71-5ce5-4ee1-9f66-ef99aadae654.png} +0 -0
- /kaa/sprites/{cfe3563d-a24b-4197-a0cb-5628bd990c08.png → 18d26894-fd12-4644-8269-a09d11be9520.png} +0 -0
- /kaa/sprites/{8e5e968b-edad-4c03-abc8-3f2a7e8879ae.png → 1b0dd18b-eb41-4c9c-b031-bab91c93fd5d.png} +0 -0
- /kaa/sprites/{3fa5f81c-9223-44ba-bf07-71932350e845.png → 1e7a6e19-760c-4fbc-b0f1-f620f51056b9.png} +0 -0
- /kaa/sprites/{9e7eaa8e-3178-44da-a5ec-34b889f8facf.png → 1fbe13d6-3a4d-4935-b687-a76a76a1e32c.png} +0 -0
- /kaa/sprites/{1ad89ee4-1bb1-41d2-a92c-79caf6baa38a.png → 1fe31432-a050-48db-acc1-becde42deaf9.png} +0 -0
- /kaa/sprites/{94d54ba7-0ccf-4fd9-a5bf-488bac1364c8.png → 20146fe6-e62b-4c57-b229-901994903b70.png} +0 -0
- /kaa/sprites/{6c926e92-9af9-402d-8512-6417ca116928.png → 20c673e9-fcbe-469b-be35-7844a1d5a9cd.png} +0 -0
- /kaa/sprites/{572a921d-633f-4465-b177-7a0d9ad7e099.png → 21747ae5-d94d-45d1-bda8-939389dc4874.png} +0 -0
- /kaa/sprites/{aa1624ff-88b0-447b-8e2b-8a50fd9e4062.png → 21fbbe96-02bf-4835-aa04-068bc5cc6ca3.png} +0 -0
- /kaa/sprites/{3b4dc708-1d34-4a88-9fe3-d8de2ec1d5c8.png → 24be7d90-7944-4a0a-a60c-67c9737b322c.png} +0 -0
- /kaa/sprites/{b59c0e9b-1f20-4194-ab37-286f505fa656.png → 24d6a47c-2099-45e2-9a67-b37767f459fc.png} +0 -0
- /kaa/sprites/{023b8f4c-15ab-4845-b141-446c861ad475.png → 2568d3d3-b642-4ea4-b929-4dee0b09738a.png} +0 -0
- /kaa/sprites/{7d7df15f-707e-4e27-826f-21e42af1dae0.png → 263b1037-fb51-4eb1-8c71-5232b03235d2.png} +0 -0
- /kaa/sprites/{f0aef696-2106-46a4-8b7f-9f16b6c89d3f.png → 27dbd535-7f95-4698-8fea-2bed67dd6968.png} +0 -0
- /kaa/sprites/{81686816-c723-47d1-9824-a68d9ebe1bd4.png → 286801f7-3af5-4cd0-9c25-46c12c2cd8f8.png} +0 -0
- /kaa/sprites/{dc97fea3-898f-4135-9c40-ad41570ab4ae.png → 298182ae-747a-44e3-8511-a64d3532b8ac.png} +0 -0
- /kaa/sprites/{8e019262-ad23-4cbb-84da-86b34775a91e.png → 2d3470f8-a714-4175-a8fe-71eef80921b6.png} +0 -0
- /kaa/sprites/{01247ebe-8d63-4573-90f4-d8dc2b7ca14c.png → 2e3b2982-d14b-4b49-bb64-da8178311d75.png} +0 -0
- /kaa/sprites/{fcc72120-2a77-4c26-a27e-e1027c6088c0.png → 2e41df89-a8d7-4e7e-96cb-7f551414823b.png} +0 -0
- /kaa/sprites/{31f2de0a-567b-425a-9be6-536e4532d813.png → 31e02e56-f266-47b5-8b10-fe79fe06d614.png} +0 -0
- /kaa/sprites/{7daaca55-e3fd-4e12-bf31-872105ceb726.png → 3314dc6c-868f-4045-9f60-1f3a17fed324.png} +0 -0
- /kaa/sprites/{fdf0da06-f088-424f-9941-8c883fea3db3.png → 358f1561-c16f-45a0-842d-d62fc735dc80.png} +0 -0
- /kaa/sprites/{51b95c81-4ff9-434c-ade2-3518e63337cb.png → 3782897a-f1c2-4f05-a02d-4c760672f52a.png} +0 -0
- /kaa/sprites/{847eb5c0-0350-4b7c-9c9c-43c796709795.png → 385e60df-2063-4caf-b1ea-e6ac909bc49d.png} +0 -0
- /kaa/sprites/{8e4d8a0f-4a9d-4562-9234-63806b11d85f.png → 39450419-26b5-4fbd-a5d4-1bab369ced30.png} +0 -0
- /kaa/sprites/{424a0ef5-102d-4734-a731-2b3b3c7c9682.png → 397c0e24-f35a-48c9-a576-aa1fcfc517b5.png} +0 -0
- /kaa/sprites/{23b9cda9-8be8-438e-8e54-57d91a4bd875.png → 3adef8f4-629d-4cb7-b54a-dadabfea155e.png} +0 -0
- /kaa/sprites/{2234f709-1703-4589-905c-175f4db09b1b.png → 3b86b4ac-aa29-4309-82da-f47a174d88cc.png} +0 -0
- /kaa/sprites/{e933cd55-e47a-4327-89d7-b25995cb4a3f.png → 3c6bbcea-488d-4df8-ab40-21e263aa0b16.png} +0 -0
- /kaa/sprites/{49bde219-f9a3-41b5-84b8-e417160a0f40.png → 3db54e0b-672d-4dfd-8a9b-5db37a08be74.png} +0 -0
- /kaa/sprites/{2204967a-a0ee-4dd3-aecb-4d531e8e954c.png → 402d430d-b507-4aa6-b3e1-db66b38c71b4.png} +0 -0
- /kaa/sprites/{70768479-5d7a-4941-8774-ad556c47bee2.png → 414140a2-de67-4c7f-a7f6-c8b30a6c8d6a.png} +0 -0
- /kaa/sprites/{dd7bd6cd-90f1-4773-9b68-5df7f2f84da5.png → 4147514f-4f3f-4dd5-952b-0f2cf5f62181.png} +0 -0
- /kaa/sprites/{0562f69f-0300-4a2b-8252-63f3e7180e4c.png → 43e53b71-9d69-4f4f-b217-a1abeea8991e.png} +0 -0
- /kaa/sprites/{55c3af20-58dc-4407-a383-312a57417c39.png → 44fab632-3920-4cd8-9967-f7a8a1ee29a0.png} +0 -0
- /kaa/sprites/{645909d7-b960-46c7-b208-db44b6b7feec.png → 45f705f9-58fb-4729-ae55-ee10848678d6.png} +0 -0
- /kaa/sprites/{da48db0d-09d9-47c3-9e08-8b69ad547be6.png → 4678a5fa-5b1c-4fdc-b7c4-e0b820039546.png} +0 -0
- /kaa/sprites/{37215a56-f8e1-4f22-a148-9894136f6ab1.png → 4738974e-60b8-4583-8548-94211c164291.png} +0 -0
- /kaa/sprites/{338d7e71-98ce-4cd1-9954-bf7155150780.png → 474c1678-9c36-495b-aef2-cadbb47b237d.png} +0 -0
- /kaa/sprites/{01256311-237c-476f-96ce-4136dc4bfbd3.png → 47783412-9cc7-4ba0-904d-8cd300222889.png} +0 -0
- /kaa/sprites/{9f7150bc-c0b8-48d6-862c-456aaf518b2b.png → 47ed66a4-9e7e-4646-b554-469dc86322db.png} +0 -0
- /kaa/sprites/{5930140e-effe-4bcf-b0be-c20d3990d833.png → 4d0074ad-6db4-4060-b71a-05c0e36e57a6.png} +0 -0
- /kaa/sprites/{22dc4cfe-8c66-4461-8660-e2d11bbe6154.png → 4f2f8328-a698-40d3-a40f-1f1ae77dc843.png} +0 -0
- /kaa/sprites/{694879e8-ecca-45e2-8ea4-1b447fd43ace.png → 52d0ff68-7a55-4d53-bc20-a1fa05cfe876.png} +0 -0
- /kaa/sprites/{962aa0b9-1dd3-4260-a4fb-c069c26e5a84.png → 52d737a7-5b0b-4ce0-ae3f-5d4048060f12.png} +0 -0
- /kaa/sprites/{87f3c1ae-5117-4871-a7d6-3f5ff0c9f9fb.png → 54a9cae1-62e5-4546-a46a-a5157f51e8b4.png} +0 -0
- /kaa/sprites/{e7f2734f-9fdc-4521-8d7e-8b0fe270a223.png → 56d35e14-ada9-4bfa-a48f-e4601054e7eb.png} +0 -0
- /kaa/sprites/{3b4f90c9-6de7-4ac3-8e41-5f8757bf3f3e.png → 575784c1-7c4a-4484-9f38-aa3c280ce56e.png} +0 -0
- /kaa/sprites/{57c81080-7b53-4286-8fa5-848ad63e4774.png → 577417ee-6635-4cb4-9f28-d1e1b47ae2cd.png} +0 -0
- /kaa/sprites/{72634cb3-4c76-4ca2-8898-ebb837ec19e3.png → 58358122-984b-4c31-91d7-eaf5c8c9353d.png} +0 -0
- /kaa/sprites/{179c0fff-ebd2-4a16-8db2-297552cca218.png → 5a06a662-ffa9-49a9-a86d-136e5983abdd.png} +0 -0
- /kaa/sprites/{2b6d2eb0-bcf7-4bea-b037-6293d9c6d728.png → 5c8eebc5-6d5e-445e-a3d1-66dce2bb6338.png} +0 -0
- /kaa/sprites/{2a8626df-056c-46a2-aaf3-0060a5aef6a3.png → 5d2b03a2-acb6-4bd2-86e8-1b203d1aeaec.png} +0 -0
- /kaa/sprites/{0af1d573-1dc7-427e-997d-173308ea3649.png → 5f02656f-1314-44d0-ae31-a176c24d758c.png} +0 -0
- /kaa/sprites/{84cabff2-7a1b-4018-b74b-46f4db06304f.png → 608c12e2-95dd-4efa-93b2-e648e9583062.png} +0 -0
- /kaa/sprites/{8f7b55d8-0143-4d27-bef8-560d4d510500.png → 647bb09a-13f8-4d54-a8ac-5b534f1a8d87.png} +0 -0
- /kaa/sprites/{1cf03f98-63e9-467c-804d-c74dd97b69bd.png → 6483c406-26cc-44ee-ad12-2a30ec47aedb.png} +0 -0
- /kaa/sprites/{889a4153-b713-49cb-a4d5-e302bcdd002d.png → 67d6a201-dfb9-4c88-b42b-d968cf9a034c.png} +0 -0
- /kaa/sprites/{ea430652-e263-4a15-bb6f-8a8807be6c8f.png → 6a93b483-0848-45e4-a937-51850f296c3d.png} +0 -0
- /kaa/sprites/{e4dc3b35-195c-415f-9484-c2459bd8675a.png → 6b4e4351-b370-48cd-8e8f-ca663d44aa0c.png} +0 -0
- /kaa/sprites/{f6b042a8-a91e-4811-99f9-18bbb5197468.png → 6c961dee-87f3-42f1-acef-9fe7d6be4df1.png} +0 -0
- /kaa/sprites/{ab237c6d-c4d8-4716-8ef7-99b8e995c9a7.png → 6d22b7ee-6e0f-4f5d-96a4-d4cba26a4d04.png} +0 -0
- /kaa/sprites/{d7750f81-de10-4d6f-9cc7-35223bda9d70.png → 6d5a3e08-257c-4394-96a6-e0719a66e5ae.png} +0 -0
- /kaa/sprites/{847226a3-b7d2-4156-b732-9215a3e14f3a.png → 71d0d086-50f1-4f50-bb24-a0190827bd08.png} +0 -0
- /kaa/sprites/{2cec1d6a-9e8c-49b3-b885-0b0d7c4b95ee.png → 71f87e1c-77f1-45c7-bb9c-16f14498682b.png} +0 -0
- /kaa/sprites/{30e12bf1-8fa5-4de1-8d7b-28fa0fec0cb6.png → 737570a7-b8f9-4cd7-b5bd-f40cd51b49f8.png} +0 -0
- /kaa/sprites/{ae1e70bc-f735-4749-8c23-95735b91897a.png → 745ee069-0f22-4b99-9327-513f365eb922.png} +0 -0
- /kaa/sprites/{8bd22fe1-b544-4d2e-b74a-34f3cf0eb512.png → 7601152e-a216-4bf8-92a6-4e3e6ea01d3d.png} +0 -0
- /kaa/sprites/{bfdc9b53-2fe5-43f1-8588-7ab71217d31c.png → 7a23d548-4395-40cc-ac19-4497fa3d9fe2.png} +0 -0
- /kaa/sprites/{96704aa3-b5ad-4e34-bb88-fad766415362.png → 7a7871dd-fd07-4234-bd01-c3c9e41bad45.png} +0 -0
- /kaa/sprites/{43a367e1-91dd-495e-8c30-41903f75a99a.png → 7d3c3a12-8d0f-48a7-9fd4-66db5e58488f.png} +0 -0
- /kaa/sprites/{756f4ca7-acac-48e1-8bcd-1c5cd8937e3a.png → 7d9f8ea3-1fdf-4675-8ddf-38393e235746.png} +0 -0
- /kaa/sprites/{31e3ac2b-ecd4-4c37-88bc-985ef32e73a3.png → 83f258af-35b8-4918-a971-80ea938a854e.png} +0 -0
- /kaa/sprites/{91b30f5e-31b2-4756-a3f7-f0f82a335442.png → 848a6c94-97a5-44f7-b84b-2f3283dc446b.png} +0 -0
- /kaa/sprites/{8ed51be4-815c-4a3d-805e-030fdfa341e2.png → 86a56df9-47ff-4741-822d-5b7e024d1598.png} +0 -0
- /kaa/sprites/{f0462447-5226-4819-a39b-19ab90583f83.png → 8b04d1a8-6cd6-4d2e-91e7-bdc58c46d939.png} +0 -0
- /kaa/sprites/{4a081370-b0a1-4067-8470-e3007cc68a12.png → 8b60ce9f-09c0-48a0-93f0-d51e0aa16afb.png} +0 -0
- /kaa/sprites/{91a50322-52d9-4516-9e46-bc121f20667d.png → 8c59d3ca-baff-4260-aa0a-6cedac1c2771.png} +0 -0
- /kaa/sprites/{f635499a-943d-47da-952a-1feb58daa25b.png → 8d7b4761-2555-4398-bb74-b70de3b75e22.png} +0 -0
- /kaa/sprites/{13cb0309-b713-4725-b10b-26afe46eb9c0.png → 901a2e7a-37f3-4dda-a58b-5a7644ead6b9.png} +0 -0
- /kaa/sprites/{cd0e8663-2ea1-436a-b9fb-3caa0c3ed9e8.png → 9cc77f5e-e7d0-4de4-aeb8-587ab8cb212a.png} +0 -0
- /kaa/sprites/{9991b19c-7330-42c4-9d7d-db3cb00103b7.png → 9e45adeb-4637-4b8b-a687-f1d2cd8c6c18.png} +0 -0
- /kaa/sprites/{5734e48a-1e58-42de-be7b-b7db67db4a01.png → a006054e-61fb-4d2b-a98e-45ce3c663662.png} +0 -0
- /kaa/sprites/{d1ea0ea6-4a6a-4036-b140-922c95a648b5.png → a0f98517-e4cf-422c-b29f-395a55939772.png} +0 -0
- /kaa/sprites/{3aed50a2-d640-4178-9b8a-4dd7973eebf1.png → a94d76ef-db70-45a9-aeca-ba16344cc572.png} +0 -0
- /kaa/sprites/{978873bb-e4d0-451b-9126-6977144f5395.png → afe7f086-723e-4999-a7aa-3342a797d828.png} +0 -0
- /kaa/sprites/{dce410ee-fa56-41c4-b75e-e1bff79cd94f.png → b2036053-36fb-4aa7-8348-e31942731a93.png} +0 -0
- /kaa/sprites/{ad94041c-f30b-40b9-b11a-1a26e9962274.png → b6da02bf-3f43-4ed0-9b13-f15becb42ce9.png} +0 -0
- /kaa/sprites/{a5694c76-3c5d-462e-81d5-1e0e6cef0ec9.png → ba2fd21c-6228-4e2d-b2db-a6d085cb38a6.png} +0 -0
- /kaa/sprites/{cba0646d-dffe-4c5b-a44d-1f8d827624a6.png → bb224de8-828e-4bc5-a986-632c72fc9157.png} +0 -0
- /kaa/sprites/{5bf2a814-df85-4d0a-b4b5-8883ac2ee434.png → bcc6ee72-ad5a-4d5c-b6c7-1b3fdfc5fa81.png} +0 -0
- /kaa/sprites/{edcec31d-d5de-4f22-b666-3e3c656e06d8.png → bebf9f6d-7cca-44c5-9b9f-fa36e29e97b3.png} +0 -0
- /kaa/sprites/{9008fbb2-f23f-424f-9be7-5bae6a3697ab.png → c4d0b0c9-ffbe-4b6c-9bf3-b05919e1a07c.png} +0 -0
- /kaa/sprites/{f32a41a2-c482-41ba-b718-28f048f5148c.png → c893e762-f328-4ef6-b862-5da8eb049f9c.png} +0 -0
- /kaa/sprites/{2d0e9d49-365a-4bcb-a416-38b87defaa3c.png → c944d298-a46b-4799-aea3-eec22fc7d4ac.png} +0 -0
- /kaa/sprites/{5c310fe5-7e92-4167-9eba-6e8e14a2863a.png → d28a18db-0f66-45a6-b3cd-69173ecdd790.png} +0 -0
- /kaa/sprites/{464b1dd8-ca2e-41e9-a5b5-90545c584db7.png → d8d5019c-52e6-4767-a9aa-d8da6ffcbd00.png} +0 -0
- /kaa/sprites/{dd873ac0-ffba-4335-9cf2-2162c6835ed8.png → d9cb2f43-2786-48d8-90f8-8cf1929f6172.png} +0 -0
- /kaa/sprites/{e13fc34b-accc-4986-865d-f8d8410b45e9.png → dbc5db78-81f5-41e6-bdc4-dafaa9173320.png} +0 -0
- /kaa/sprites/{e9310e38-a418-4561-bf33-eb3e6dccf477.png → e2ac106f-edeb-4375-af8c-45f33e9bfae6.png} +0 -0
- /kaa/sprites/{d81b1325-e57a-4f22-93e1-6ad4baa28935.png → e8a33d3f-a4fb-4851-b47a-b5f3d85e882f.png} +0 -0
- /kaa/sprites/{2289d38f-dc98-4310-9f34-4cf5023f8545.png → f7facb3a-1b41-4409-b128-d4ad03245845.png} +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/WHEEL +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11.post1.dist-info}/licenses/LICENSE +0 -0
- {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.
|
|
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
|