ksaa 2025.9b3__py3-none-any.whl → 2025.9b5__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/debug_entry.py +42 -0
- kaa/errors.py +7 -0
- kaa/game_ui/drinks_overview.py +14 -6
- kaa/main/gr.py +331 -44
- kaa/main/kaa.py +9 -0
- kaa/metadata.py +55 -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_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-amao-3-014_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-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-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-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-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/skill_cards/img_general_skillcard_ido-3_147.png +0 -0
- kaa/resources/skill_cards/img_general_skillcard_ido-3_149.png +0 -0
- kaa/sprites/7b5c8883-a1f9-4ce9-bd84-26668577dfc6.png +0 -0
- kaa/sprites/8fbd1aa8-d243-40b5-95e6-d9a4ecc107f2.png +0 -0
- kaa/tasks/R.py +134 -132
- kaa/tasks/daily/purchase.py +0 -2
- kaa/tasks/produce/cards.py +2 -2
- kaa/tasks/produce/produce.py +3 -0
- kaa/tasks/start_game.py +9 -3
- {ksaa-2025.9b3.dist-info → ksaa-2025.9b5.dist-info}/METADATA +8 -5
- {ksaa-2025.9b3.dist-info → ksaa-2025.9b5.dist-info}/RECORD +173 -147
- kaa/sprites/93133c4d-39e6-4ead-a6ce-3ea6303066b0.png +0 -0
- /kaa/sprites/{42c2b7b0-1d6f-420e-abfc-076763638275.png → 015bfe23-ce2c-460e-aa37-28b3d7560e1d.png} +0 -0
- /kaa/sprites/{5bf12674-852b-4d9c-b065-886b8a29b3b8.png → 01e47e1f-f724-423b-ba70-d856234c229d.png} +0 -0
- /kaa/sprites/{f659d1b8-f2e2-43c2-9421-7af3b2cae001.png → 05684027-1c3a-4a79-a3b8-324dc30b4c52.png} +0 -0
- /kaa/sprites/{783ebf90-f6d7-419b-81e2-19787425682e.png → 05caaf0f-28fd-4a05-aab1-7307bcf78747.png} +0 -0
- /kaa/sprites/{99276e06-774a-4ddb-b6a1-4fa827ae1997.png → 0717934b-7411-42e2-908d-f9ad5f1d233e.png} +0 -0
- /kaa/sprites/{2ae53e6d-f9e1-4d14-b6bf-637a36ab9fc7.png → 07d7ad36-3cf2-4c4f-905c-6eba7b97db4d.png} +0 -0
- /kaa/sprites/{fc044ce0-8456-401f-ace2-6c91b6e60b19.png → 110ed4b4-15ac-40ef-9852-e178b527d39f.png} +0 -0
- /kaa/sprites/{4f020d14-f2b0-4d6b-b6f7-4be27932517e.png → 11aaa80d-1c11-4077-a9ff-2a8ffc045117.png} +0 -0
- /kaa/sprites/{9e86ada7-3094-49a2-9704-86af78aaeaa8.png → 11d27619-0dd4-4681-acd6-a4bcc30f1530.png} +0 -0
- /kaa/sprites/{dfb9a168-a243-4752-a76c-8c52afaa9c4b.png → 1814758c-8f7f-4564-bbe2-6c7f87f9b449.png} +0 -0
- /kaa/sprites/{897358a6-6569-4643-8b60-77047287577d.png → 1a57efbe-f6d1-4bfb-9d58-cafc09158ba9.png} +0 -0
- /kaa/sprites/{a6a411ed-fbb0-4814-808d-5719cccd93bf.png → 1a73afa3-ccce-4525-b076-b0a6ad4000aa.png} +0 -0
- /kaa/sprites/{44f1d955-dbe5-48ff-887a-c720578a39e7.png → 1b16c4d5-7b9e-4ae2-bb0d-2990f96dfd25.png} +0 -0
- /kaa/sprites/{03a4f7be-8eea-4506-b8ba-19cef95612af.png → 1bc0ade2-ea41-4af4-b694-720eefeb546c.png} +0 -0
- /kaa/sprites/{19b610df-ac4a-463c-afdb-88a67dc7bc27.png → 1be9d3dc-9cc2-4742-83dd-cc405ee5e5e7.png} +0 -0
- /kaa/sprites/{5aa3920c-12ae-4678-8509-da660b4173de.png → 272eadd8-10fa-4dee-9547-a37dacce2187.png} +0 -0
- /kaa/sprites/{bb7cab97-c1bc-498d-af71-535769f1f4b0.png → 2c8fd695-3878-4eb9-988e-5a53e4c39bf6.png} +0 -0
- /kaa/sprites/{e5a018d1-1def-4511-97fd-55f6bc10a60c.png → 2e335072-f4e7-4ba5-83c8-355c43691557.png} +0 -0
- /kaa/sprites/{97a1cef5-7240-4456-a1c7-09a7c8edd8fd.png → 2fb54c0c-586e-4e6b-b5cd-bfb15fc73510.png} +0 -0
- /kaa/sprites/{67664fe3-0300-4b56-844c-1bbf0bfac3da.png → 2fd7b950-1f8f-40be-afce-ca576d512ca2.png} +0 -0
- /kaa/sprites/{d3a6ddfd-5bb3-47ef-a022-1024d5c3ecf2.png → 314e3b63-2a80-4a47-898f-647423257e50.png} +0 -0
- /kaa/sprites/{68b0d741-f1c2-4c29-bd06-85468ed4ff87.png → 31f02509-385c-4137-9a2a-87dcc0c9d858.png} +0 -0
- /kaa/sprites/{e7bc9fce-8b1a-4ce8-a812-0211c4d5558f.png → 35bd28b2-91f2-43d0-a744-31af6bbc588a.png} +0 -0
- /kaa/sprites/{4484618e-b4e4-4f8d-9c10-d32c4809c528.png → 3762c3be-3232-4f1b-8310-cef9b31f06a4.png} +0 -0
- /kaa/sprites/{6f499758-a73a-476f-93b5-d422dbc965c3.png → 391ea57b-172d-4d6c-a97b-46549417b2c1.png} +0 -0
- /kaa/sprites/{2ee4c3a8-c412-4734-ab52-88521e751f9a.png → 3996af24-d8fb-4397-98bd-cad4d6cbbd96.png} +0 -0
- /kaa/sprites/{9b12235d-baf7-4a76-9fd3-c9a5da9e9dc7.png → 3ba6d2cd-8583-4e90-b36e-8b2e47b3d2b6.png} +0 -0
- /kaa/sprites/{de80639f-e431-426b-b37d-306045f49fa9.png → 3e6c9eb8-5843-4a5c-9654-d652dcc3fb1a.png} +0 -0
- /kaa/sprites/{1d3b859a-f9ea-489d-82da-ec42a273b2a1.png → 402c40ed-c0bd-4475-b594-4a34c52e2300.png} +0 -0
- /kaa/sprites/{ce279078-fd78-4551-9aef-551bf0bcd012.png → 435b7728-f920-43b0-bc4c-83b84c4a0e84.png} +0 -0
- /kaa/sprites/{11ecc94a-6fd2-476e-8910-0fea18678068.png → 438080ea-284c-4556-b45c-bb1b374c6931.png} +0 -0
- /kaa/sprites/{512a1801-f3ff-4204-9ccb-90af00c90ff1.png → 45b0b8a2-0f5e-433a-b210-c731f8d626bb.png} +0 -0
- /kaa/sprites/{4ab6a7b3-fb00-42e6-8535-e2be8bc6f92b.png → 4a4d0977-3c18-4c95-a5d7-d9fb9512eddc.png} +0 -0
- /kaa/sprites/{f2248e03-41fb-486c-9d87-97b3acc0089a.png → 4ac65e10-4b99-4e0f-a204-b923bf16dfb1.png} +0 -0
- /kaa/sprites/{e8ca45b5-262b-40b7-8d2e-69e1e4d5c5a7.png → 4d95933e-a5e4-4a52-b132-7667b8ae8917.png} +0 -0
- /kaa/sprites/{d73318df-f20e-4a3f-b63a-af4abdc33c9f.png → 500f489c-37bd-430a-81b4-e79310d55fd8.png} +0 -0
- /kaa/sprites/{65291397-50c3-4b7b-8630-ab530f445bdb.png → 502cbbee-3211-4981-8090-a435933a2cd3.png} +0 -0
- /kaa/sprites/{1a0ee299-39f0-494f-864c-62253020b670.png → 50c87fa8-0e34-4220-9989-7f2367758058.png} +0 -0
- /kaa/sprites/{5a0f1984-2dad-424c-aa7d-a83c7d8c3c8d.png → 513ed0ac-22f5-4c61-a5b8-6ff55aaa1194.png} +0 -0
- /kaa/sprites/{b4576ed5-6e78-430d-b977-82f9030b70bd.png → 521317ee-26f2-419a-af95-b1e22cb7c923.png} +0 -0
- /kaa/sprites/{99023408-1bb5-43ad-8c70-3a10761d9956.png → 53104f5d-1cd3-486c-a4f0-00fc3bc62d2b.png} +0 -0
- /kaa/sprites/{dcc75592-c284-4e22-a229-600c1b30aa68.png → 56a0a713-bcb3-459e-bc8c-2da22c114107.png} +0 -0
- /kaa/sprites/{b74a9b0a-daad-4d2e-920e-5a6f2b15e67e.png → 573e5961-218c-46ba-95e9-321b5093ae25.png} +0 -0
- /kaa/sprites/{21c9b731-8bfd-47a7-8933-175dc47e642f.png → 59888d84-409f-479d-a338-9b7649f8b7e3.png} +0 -0
- /kaa/sprites/{e4084dd2-3db9-4a16-893b-d18bb0b60b26.png → 5a4f4fed-744a-475a-a251-dac04cf31084.png} +0 -0
- /kaa/sprites/{f9135063-fa0d-4ff0-8b37-d4c09dc28f18.png → 5a6c9933-e29f-41e0-9d16-36caca895c8e.png} +0 -0
- /kaa/sprites/{d60da1fc-f6cb-4d60-8eee-cb51284b6051.png → 5aa8d676-9900-4060-ae1b-f93f0f6c0e92.png} +0 -0
- /kaa/sprites/{c614fecb-c6b6-492c-8c58-9e8ba05f43cb.png → 5b213adc-07a8-4b61-8625-d80d255115a7.png} +0 -0
- /kaa/sprites/{273b2d25-da0f-41f5-995c-b8d5533008fe.png → 5d34161f-d768-4a72-8892-9c33e60ed32c.png} +0 -0
- /kaa/sprites/{b1b0f042-0e4b-42c9-ab6f-b5e9ab3afcaf.png → 609e6429-1652-4a32-a55b-52de362ed8b6.png} +0 -0
- /kaa/sprites/{08d4f0d1-43d5-44f8-814f-eba273f96903.png → 6809c6c0-bf4c-454b-90e9-9714e466d9de.png} +0 -0
- /kaa/sprites/{518b81e0-0ba6-4b63-a73f-07dccb3b5cc6.png → 681e68bb-9c31-4ddc-bc92-f25f5cd1d230.png} +0 -0
- /kaa/sprites/{f9baa6dd-506a-4c2b-a3b7-a4dbff4f53ae.png → 693cfb2b-c167-434e-bd24-ec48c2aa5aba.png} +0 -0
- /kaa/sprites/{ea9ff1a6-f8ae-4af3-bf12-5078fc51d87f.png → 69ea86ad-6624-4d6d-bfad-5a48d5a716a8.png} +0 -0
- /kaa/sprites/{ec613742-5f1f-4001-82d3-26f8c3e25314.png → 6b9092c3-712f-44dd-9b07-ba6d6e8f7190.png} +0 -0
- /kaa/sprites/{c1788160-27ba-4faa-9fb3-3d07e07bad82.png → 6c7e7ae3-7565-46ee-88bc-1be28fdafebb.png} +0 -0
- /kaa/sprites/{4e83a559-b52d-4369-8def-e2af428a8638.png → 6e5aad88-8c39-4b23-9809-103f16ea2033.png} +0 -0
- /kaa/sprites/{6fd65854-70c0-4ef7-ad6d-5f576c2ce0d2.png → 758b4d93-3594-452b-82db-c1e214916595.png} +0 -0
- /kaa/sprites/{56e88b0b-d73e-4304-ab7d-6865feb66dd3.png → 76962167-9afb-4518-948c-5436c8d23be5.png} +0 -0
- /kaa/sprites/{ab8a2dfe-01e8-408b-896a-b948823bbc03.png → 78348d18-4abe-40af-b7a2-d1a7b3a2990a.png} +0 -0
- /kaa/sprites/{ac9e9295-1063-4c39-aa8a-4b033c89dd3c.png → 79945bc4-fed5-49c3-b09d-84044d6f2e01.png} +0 -0
- /kaa/sprites/{d8e422b6-830e-47a7-a2db-b63e17a21d51.png → 7acefede-7dda-4cd0-80a9-ebcdc02835b4.png} +0 -0
- /kaa/sprites/{6d6b7b99-ad18-4e5d-bdc3-dac225752eb7.png → 7d14a6f1-51d3-43d3-b6d8-ce40f7f07870.png} +0 -0
- /kaa/sprites/{3ae23a66-efd4-4c21-83f7-aa0b2f045a50.png → 7fbf97e9-2045-4fed-8ca3-8a35964deb28.png} +0 -0
- /kaa/sprites/{69412d23-7c85-4717-a0c6-1f7826d9cbb2.png → 80297f84-00ec-40f4-b9ac-4a49d9bfaf27.png} +0 -0
- /kaa/sprites/{372bf1ba-8a61-4893-9ec1-336826d78464.png → 8346fa88-c20a-4c17-8c74-3bf2385749e8.png} +0 -0
- /kaa/sprites/{5d8f949c-e68d-44e6-a798-43b3f7f76db6.png → 838154d8-9062-433b-9f10-13827a01f615.png} +0 -0
- /kaa/sprites/{8780a0c9-d947-4ce3-924a-59d378b2d08a.png → 88647fc6-e670-478f-808b-0afc9905cf02.png} +0 -0
- /kaa/sprites/{c2cf69b5-f4e5-4f7f-a406-880ff11e5f4d.png → 889783ec-222d-4cf3-989a-edd19d5932f8.png} +0 -0
- /kaa/sprites/{7373803b-3557-4c6b-9b9b-fdb191af3286.png → 88ef007e-18f1-4d38-ac89-e70202957f6e.png} +0 -0
- /kaa/sprites/{291c1c6e-9e3c-440d-98f9-dfe2c27ce751.png → 8a0b3148-a21a-45d8-b95f-11d0fd87f442.png} +0 -0
- /kaa/sprites/{662dadc7-04d2-48be-824e-c7b1d3719676.png → 8a5864a5-6438-48d3-b11a-77f6841e38b8.png} +0 -0
- /kaa/sprites/{037ce002-5d67-412f-928a-5fcc3cd3df0f.png → 8aac14d1-cba9-4fd5-9082-a82e1459faf8.png} +0 -0
- /kaa/sprites/{b9f51636-7f8e-4297-991f-b686d105c97b.png → 8ec60800-ca3a-4744-b09a-c121ac03ad75.png} +0 -0
- /kaa/sprites/{8357bf4e-80aa-4a33-a874-3d7c1b47d452.png → 8f1ae6f0-4de7-4b4f-90ad-a623faa06318.png} +0 -0
- /kaa/sprites/{2f39035d-7e56-43ce-ade1-000ac6632cd7.png → 8f53d345-c3b3-48cd-8c8a-0f6d0935ceec.png} +0 -0
- /kaa/sprites/{4d6d0a7e-d006-4233-b4de-9024c4b08ce8.png → 91f9bfff-f5ff-469c-bbac-e665ebcb2e40.png} +0 -0
- /kaa/sprites/{42d5c5fb-2600-41e5-9480-2796b6d631d6.png → 920a4801-060b-43e5-9700-f360cdda4f18.png} +0 -0
- /kaa/sprites/{7ed170b5-d1ec-47ed-b4e1-000c7da241a3.png → 93aaddcc-67c6-4d11-adef-26f29a51e69d.png} +0 -0
- /kaa/sprites/{75684858-63a9-4b26-a175-67c6648d9bbe.png → 9858dcde-51bb-4357-841e-86c2234c051c.png} +0 -0
- /kaa/sprites/{1b675788-acb2-46c0-9ffc-c50ed770ae37.png → 99532e97-930f-45e1-aea1-2aaedeebe51a.png} +0 -0
- /kaa/sprites/{a1fec50c-8fcc-4fe2-8968-9253489d90db.png → 9b5e5a82-2718-481d-a74c-13cc5c4ba03e.png} +0 -0
- /kaa/sprites/{031cd28e-a1e6-469f-b6af-c68cc4b2dc2e.png → 9c9540c9-3c57-4eba-b97b-6ccc6c07bc4d.png} +0 -0
- /kaa/sprites/{a92a8ca8-b166-45c7-9508-d9e2955305ee.png → 9e284692-4817-437c-9d87-7208e5caf777.png} +0 -0
- /kaa/sprites/{4a43008e-f6ff-4302-99f6-77b9e082e64d.png → a03fec79-53b7-462d-a383-3496790e1285.png} +0 -0
- /kaa/sprites/{4c99205c-6787-463f-ae4d-bb1951c79686.png → a0e0fb8d-d196-45dc-b395-6c63ce4a10c4.png} +0 -0
- /kaa/sprites/{ca42efda-8bd8-416e-9f0c-d54c6af990bf.png → a1481be8-dd35-45aa-a5a0-2d3afe6fc2e4.png} +0 -0
- /kaa/sprites/{46049707-af5d-4dcd-9620-6a20eb8748e7.png → a15ea6da-7692-47cc-b808-d08c06eee4ef.png} +0 -0
- /kaa/sprites/{d0befb58-59f3-4956-af23-bacd9395f161.png → a612a68c-0c84-4528-8396-3e03e2c93844.png} +0 -0
- /kaa/sprites/{608f1b36-9c20-4c25-9881-7ef3579cabaa.png → aaff6d7b-047f-49a3-9e1a-b238d17d6bca.png} +0 -0
- /kaa/sprites/{89b14f97-894e-45b2-968c-97f28b833c73.png → ab21e45a-60b2-4097-9c56-559f1e7116b2.png} +0 -0
- /kaa/sprites/{f42771a1-460b-4636-b8e1-e38472bdda8b.png → ac5d3547-1687-4a8b-b61e-b668fc1119c1.png} +0 -0
- /kaa/sprites/{5fa8ba1e-5c58-4a39-b389-4c0d3d60c313.png → afe5014f-11d6-4b05-8e26-55ed94a29133.png} +0 -0
- /kaa/sprites/{ef5fdf85-d2cc-42e6-bd14-c29042bcf72c.png → b1119377-955b-4f24-9c9d-1df1eead0038.png} +0 -0
- /kaa/sprites/{d2eb65a1-738c-4e3b-bc61-78ec078632fe.png → b20036cf-4106-49b6-ab48-c85590b255fd.png} +0 -0
- /kaa/sprites/{dd9108fb-d251-4cc1-a0e7-3dae7362b7f6.png → b523b4b7-07a5-4d10-bb9f-fffa592a2598.png} +0 -0
- /kaa/sprites/{bb384d8c-4b92-402a-a89e-ec5e1b9203ea.png → b88c6cc4-e416-4e00-a8c2-15af0e2c1dba.png} +0 -0
- /kaa/sprites/{4c84d3da-5086-43a1-b820-53c19a90c533.png → bacba5c4-ec4a-4eb5-96c7-423059879668.png} +0 -0
- /kaa/sprites/{97b1f9c2-3899-49a7-b23d-8e422beaf0ca.png → bc8f690f-1db3-44d6-a1bf-ebd23418a822.png} +0 -0
- /kaa/sprites/{3fba6323-e557-4920-9548-f26b75a351c5.png → bff5a450-6790-4462-be0b-d6a1beff68e0.png} +0 -0
- /kaa/sprites/{830691ea-cf58-4429-ab54-32414583a4ee.png → c0e89ee7-0815-4e60-8c7b-972d093f1d0d.png} +0 -0
- /kaa/sprites/{33e3097a-50ed-4b1f-a806-f765eefba6e8.png → c22b8b54-4ddc-41fe-ad53-62a89d8d350e.png} +0 -0
- /kaa/sprites/{a9fbfe75-ee6f-46a4-81a5-81bf465d4bb0.png → c3fbd35f-3c70-4dad-9302-67e817b69052.png} +0 -0
- /kaa/sprites/{579de834-fb1d-4cb9-801c-6885de92a290.png → c6f7ef85-2514-4aa6-ac5f-49d579418606.png} +0 -0
- /kaa/sprites/{d605f177-46dc-43e2-9e3f-dc5ceb4bd729.png → caa21e62-1bca-4ed1-9db3-8cba2e640b13.png} +0 -0
- /kaa/sprites/{c7ed0a32-b15d-4fdd-a0a4-4be756619c78.png → cbe6dd1f-ca7f-4a5e-842a-2d8d8e4ccb2b.png} +0 -0
- /kaa/sprites/{f7051f86-9e8a-4a01-8e3e-23f8c092aa0d.png → cf28583c-09c0-43ef-b4d0-9c6fdd7f65cd.png} +0 -0
- /kaa/sprites/{b1ac9ebe-d393-4c8a-9282-e1334f2835f6.png → d09a11b5-78bb-4512-8a38-4adbfd61e84f.png} +0 -0
- /kaa/sprites/{bb3b7c29-f31e-42c1-8f1a-6ec95e766592.png → d1cdd520-854d-476c-818e-10990169f374.png} +0 -0
- /kaa/sprites/{484ba2a3-3a4b-42c1-bde1-8f0631017e73.png → d238c9ff-51d4-4328-a85e-75c36b3c2066.png} +0 -0
- /kaa/sprites/{9b5a6710-1a7b-44b0-ad36-7f1d1b62c014.png → d3dcd6fc-cfb8-4f05-ae55-99d88982f93d.png} +0 -0
- /kaa/sprites/{05eeb26a-2ecb-4804-ae68-85221fcdbe00.png → d8eafb6b-28ee-4be9-963b-da9831271df8.png} +0 -0
- /kaa/sprites/{5011f0a8-bb49-44ec-be4e-afbf7c4d5431.png → da474a58-eafb-4ada-af5c-d505f972c59e.png} +0 -0
- /kaa/sprites/{3f838a2c-a020-4a3e-a9c0-551132d057a2.png → db28a5b0-fc58-49cb-96bf-f991a9a0a288.png} +0 -0
- /kaa/sprites/{59c4ab1b-494e-4ac1-b21a-c6364bf7ae8a.png → ded9a710-6fe0-43a2-a56c-48fec91e386c.png} +0 -0
- /kaa/sprites/{92ed005c-291c-425e-ab0f-455be98ef149.png → e6e6494b-eb22-4651-b67c-be67afe3ff37.png} +0 -0
- /kaa/sprites/{1f96ddc2-c429-4806-9bc1-802136d37a6f.png → e89d6cb9-4ca7-4c8a-a77a-843fec97d710.png} +0 -0
- /kaa/sprites/{ee9ad821-991c-43d2-8947-f46016e2f534.png → e8e118e3-53a3-40c1-a852-1789089578b2.png} +0 -0
- /kaa/sprites/{42e2b5df-19dd-493d-8739-4c2ad596331b.png → ea9616c5-dd56-4619-a362-75f5730a1f9d.png} +0 -0
- /kaa/sprites/{e62a2b06-9aa5-43a3-8c5b-9de75957ad59.png → ebbc9a2b-70fc-48df-8e4e-0b107fc9aeb2.png} +0 -0
- /kaa/sprites/{febc5122-b2d3-4e63-a054-28de0e3eba05.png → edfc3ed9-fecc-413e-bbb4-8bcfd8e106cd.png} +0 -0
- /kaa/sprites/{cfd5b23c-f823-4551-8986-385a6d08ac4f.png → efca65f0-62e9-4006-91ed-06583170cba8.png} +0 -0
- /kaa/sprites/{3823cd03-e50a-45ee-bd9f-627d5d41ae82.png → f0638571-d6e1-49bb-a201-039c2846f884.png} +0 -0
- /kaa/sprites/{336cd0be-5f48-4286-b6e4-820ef8ba55dd.png → f07608fd-90f2-401f-a3ca-ac2c07d25da2.png} +0 -0
- /kaa/sprites/{6dffeb89-24ff-4d56-a059-367cd0a16a48.png → f15a6f61-7a41-455f-96b8-ee20c50bc0c7.png} +0 -0
- /kaa/sprites/{9a34ecf2-75f6-4fc6-9214-e27bb7be4b89.png → fb93db81-7804-4175-a758-4da50bbfb24b.png} +0 -0
- /kaa/sprites/{f8e38b5e-6820-423c-937c-27aff9cd528c.png → ff2106af-052c-4976-904b-749c4f1b5d3e.png} +0 -0
- {ksaa-2025.9b3.dist-info → ksaa-2025.9b5.dist-info}/WHEEL +0 -0
- {ksaa-2025.9b3.dist-info → ksaa-2025.9b5.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.9b3.dist-info → ksaa-2025.9b5.dist-info}/licenses/LICENSE +0 -0
- {ksaa-2025.9b3.dist-info → ksaa-2025.9b5.dist-info}/top_level.txt +0 -0
kaa/debug_entry.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import runpy
|
|
3
|
+
import logging
|
|
4
|
+
import argparse
|
|
5
|
+
|
|
6
|
+
from kaa.common import BaseConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def run_script(script_path: str) -> None:
|
|
10
|
+
"""
|
|
11
|
+
使用 runpy 运行指定的 Python 脚本
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
script_path: Python 脚本的路径
|
|
15
|
+
"""
|
|
16
|
+
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(levelname)s] [%(name)s] [%(funcName)s] [%(lineno)d] %(message)s')
|
|
17
|
+
# 获取模块名
|
|
18
|
+
module_name = script_path.strip('.py').lstrip('projects/').replace('\\', '/').strip('/').replace('/', '.')
|
|
19
|
+
|
|
20
|
+
print(f"正在运行脚本: {script_path}")
|
|
21
|
+
# 运行脚本
|
|
22
|
+
from kotonebot.backend.context import init_context, manual_context
|
|
23
|
+
from kaa.main.kaa import Kaa
|
|
24
|
+
logging.getLogger('kotonebot').setLevel(logging.DEBUG)
|
|
25
|
+
logging.getLogger('kaa').setLevel(logging.DEBUG)
|
|
26
|
+
config_path = './config.json'
|
|
27
|
+
kaa_instance = Kaa(config_path)
|
|
28
|
+
init_context(config_type=BaseConfig, target_device=kaa_instance._on_create_device())
|
|
29
|
+
kaa_instance._on_after_init_context()
|
|
30
|
+
manual_context().begin()
|
|
31
|
+
runpy.run_module(module_name, run_name="__main__")
|
|
32
|
+
|
|
33
|
+
def main():
|
|
34
|
+
parser = argparse.ArgumentParser(description='运行指定的 Python 脚本')
|
|
35
|
+
parser.add_argument('script_path', help='要运行的 Python 脚本路径')
|
|
36
|
+
|
|
37
|
+
args = parser.parse_args()
|
|
38
|
+
run_script(args.script_path)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if __name__ == '__main__':
|
|
42
|
+
main()
|
kaa/errors.py
CHANGED
|
@@ -56,4 +56,11 @@ class ElevationRequiredError(KaaUserFriendlyError):
|
|
|
56
56
|
super().__init__(
|
|
57
57
|
'请以管理员身份运行 kaa。',
|
|
58
58
|
'https://www.kdocs.cn/l/cetCY8mGKHLj?linkname=qOqulS4KeX'
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
class GameUpdateNeededError(KaaUserFriendlyError):
|
|
62
|
+
def __init__(self):
|
|
63
|
+
super().__init__(
|
|
64
|
+
'游戏本体需要更新。kaa 暂不支持自动更新,请前往 Play Store 手动更新游戏。',
|
|
65
|
+
'https://www.baidu.com/s?wd=%E5%BF%AB%E5%8E%BB%E6%9B%B4%E6%96%B0%E6%B8%B8%E6%88%8F%E5%95%8A%EF%BC%8C%E8%BF%98%E7%82%B9%E4%BB%80%E4%B9%88%E6%89%93%E5%BC%80%E5%B8%AE%E5%8A%A9'
|
|
59
66
|
)
|
kaa/game_ui/drinks_overview.py
CHANGED
|
@@ -21,7 +21,9 @@ def preprocess_drink_slot_img(img: MatLike) -> MatLike:
|
|
|
21
21
|
:param img: 输入的饮品槽图像,大小 68x68 (BGR)
|
|
22
22
|
:return: 处理后的图像,大小 68x68,其中会出现更大量的纯白色,便于识别
|
|
23
23
|
"""
|
|
24
|
-
|
|
24
|
+
BLUE_THRESHOLD = 255
|
|
25
|
+
FLOOD_BLUE_THRESHOLD = 240
|
|
26
|
+
FLOOD_COLOR_THRESHOLD = 230
|
|
25
27
|
|
|
26
28
|
assert img.shape[2] == 3
|
|
27
29
|
h, w, _ = img.shape
|
|
@@ -30,7 +32,7 @@ def preprocess_drink_slot_img(img: MatLike) -> MatLike:
|
|
|
30
32
|
b, g, r = cv2.split(img)
|
|
31
33
|
|
|
32
34
|
# 把 b==255 的像素修正为纯白
|
|
33
|
-
mask = (b >=
|
|
35
|
+
mask = (b >= BLUE_THRESHOLD)
|
|
34
36
|
g[mask] = 255
|
|
35
37
|
b[mask] = 255
|
|
36
38
|
r[mask] = 255
|
|
@@ -66,7 +68,7 @@ def preprocess_drink_slot_img(img: MatLike) -> MatLike:
|
|
|
66
68
|
# 四邻域扩展
|
|
67
69
|
for dy, dx in [(-1,0), (1,0), (0,-1), (0,1)]:
|
|
68
70
|
ny, nx = y + dy, x + dx
|
|
69
|
-
if 0 <= nx < w and 0 <= ny < h and not (nx > right_top_x and ny < right_top_y) and not visited[ny, nx] and not np.all(img[ny, nx] >=
|
|
71
|
+
if 0 <= nx < w and 0 <= ny < h and not (nx > right_top_x and ny < right_top_y) and not visited[ny, nx] and not np.all(img[ny, nx] >= FLOOD_COLOR_THRESHOLD) and not (img[ny, nx][0] >= FLOOD_BLUE_THRESHOLD):
|
|
70
72
|
q.append((ny, nx))
|
|
71
73
|
|
|
72
74
|
return img
|
|
@@ -89,7 +91,12 @@ def match_first_drinks(img: MatLike, delta_threshold: float = 0.7) -> Drink | No
|
|
|
89
91
|
:return: 若匹配成功,则返回 饮品的信息 和 前1~3个匹配饮品的数据库查询结果(用于更详细的日志输出);否则返回 None。
|
|
90
92
|
"""
|
|
91
93
|
|
|
94
|
+
|
|
95
|
+
# cv2.imshow("img", img)
|
|
92
96
|
img = preprocess_drink_slot_img(img)
|
|
97
|
+
# cv2.imshow("img1", img)
|
|
98
|
+
# cv2.waitKey(0)
|
|
99
|
+
# cv2.destroyAllWindows()
|
|
93
100
|
|
|
94
101
|
db = drinks_db()
|
|
95
102
|
matches = db.match_all(img, threshold=114514)
|
|
@@ -157,10 +164,11 @@ if __name__ == '__main__':
|
|
|
157
164
|
from logging import getLogger
|
|
158
165
|
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s')
|
|
159
166
|
|
|
160
|
-
img = R.InPurodyuusu.Screenshot5Cards.data
|
|
161
|
-
# img = R.InPurodyuusu.ScreenshotSenseiTipConsult.data
|
|
162
|
-
# img = R.InPurodyuusu.Screenshot1Cards.data
|
|
167
|
+
# img = R.InPurodyuusu.Screenshot5Cards.data # len = 2
|
|
168
|
+
# img = R.InPurodyuusu.ScreenshotSenseiTipConsult.data # len = 3
|
|
169
|
+
# img = R.InPurodyuusu.Screenshot1Cards.data # len = 2
|
|
163
170
|
# img = R.InPurodyuusu.ScreenshotDrinkTest.data # len = 2
|
|
164
171
|
# img = R.InPurodyuusu.Screenshot4Cards.data # len = 0
|
|
172
|
+
img = R.InPurodyuusu.ScreenshotDrinkTest3.data # len = 1
|
|
165
173
|
results = locate_all_drinks_in_3_drink_slots(img)
|
|
166
174
|
print(len(results), ":", results)
|
kaa/main/gr.py
CHANGED
|
@@ -20,6 +20,7 @@ from kaa.db import IdolCard
|
|
|
20
20
|
from kotonebot.backend.context.context import vars
|
|
21
21
|
from kotonebot.errors import ContextNotInitializedError
|
|
22
22
|
from kotonebot.client.host import Mumu12Host, LeidianHost
|
|
23
|
+
from kotonebot.client.host.mumu12_host import Mumu12V5Host
|
|
23
24
|
from kotonebot.config.manager import load_config, save_config
|
|
24
25
|
from kotonebot.config.base_config import UserConfig, BackendConfig
|
|
25
26
|
from kotonebot.backend.context import task_registry, ContextStackVars
|
|
@@ -42,7 +43,7 @@ ConfigKey = Literal[
|
|
|
42
43
|
'screenshot_method', 'keep_screenshots',
|
|
43
44
|
'check_emulator', 'emulator_path',
|
|
44
45
|
'adb_emulator_name', 'emulator_args',
|
|
45
|
-
'_mumu_index', '_leidian_index',
|
|
46
|
+
'_mumu_index', '_mumu12v5_index', '_leidian_index',
|
|
46
47
|
'mumu_background_mode', 'target_screenshot_interval',
|
|
47
48
|
|
|
48
49
|
# purchase
|
|
@@ -482,6 +483,7 @@ class KotoneBotUI:
|
|
|
482
483
|
|
|
483
484
|
valid_screenshot_methods = {
|
|
484
485
|
'mumu12': ['adb', 'adb_raw', 'uiautomator2', 'nemu_ipc'],
|
|
486
|
+
'mumu12v5': ['adb', 'adb_raw', 'uiautomator2', 'nemu_ipc'],
|
|
485
487
|
'leidian': ['adb', 'adb_raw', 'uiautomator2'],
|
|
486
488
|
'custom': ['adb', 'adb_raw', 'uiautomator2'],
|
|
487
489
|
'dmm': ['remote_windows', 'windows']
|
|
@@ -854,46 +856,78 @@ class KotoneBotUI:
|
|
|
854
856
|
with gr.Tab("任务"):
|
|
855
857
|
gr.Markdown("## 执行任务")
|
|
856
858
|
|
|
857
|
-
#
|
|
858
|
-
task_choices = [task.name for task in task_registry.values()]
|
|
859
|
-
task_dropdown = gr.Dropdown(
|
|
860
|
-
choices=task_choices,
|
|
861
|
-
label="选择要执行的任务",
|
|
862
|
-
info="选择一个要单独执行的任务",
|
|
863
|
-
type="value",
|
|
864
|
-
value=None
|
|
865
|
-
)
|
|
866
|
-
|
|
867
|
-
# 创建执行按钮和暂停按钮
|
|
859
|
+
# 第一行:统一的停止和暂停按钮
|
|
868
860
|
with gr.Row():
|
|
869
|
-
|
|
861
|
+
stop_all_btn = gr.Button("停止任务", variant="stop", scale=1)
|
|
870
862
|
pause_btn = gr.Button("暂停", scale=1)
|
|
863
|
+
|
|
871
864
|
task_result = gr.Markdown("")
|
|
872
865
|
|
|
873
|
-
|
|
866
|
+
# 获取所有任务并创建列表布局
|
|
867
|
+
tasks = list(task_registry.values())
|
|
868
|
+
task_buttons = [] # 存储所有任务按钮的引用
|
|
869
|
+
|
|
870
|
+
# 为每个任务创建一行:左侧启动按钮,右侧任务名
|
|
871
|
+
for task in tasks:
|
|
872
|
+
with gr.Row():
|
|
873
|
+
with gr.Column(scale=1, min_width=50):
|
|
874
|
+
task_btn = gr.Button("启动", variant="primary", size="sm")
|
|
875
|
+
task_buttons.append((task_btn, task.name))
|
|
876
|
+
with gr.Column(scale=7):
|
|
877
|
+
gr.Markdown(f"{task.name}")
|
|
878
|
+
|
|
879
|
+
# 事件处理函数
|
|
880
|
+
def start_single_task_by_name(task_name: str):
|
|
881
|
+
"""启动指定任务并返回状态信息及所有按钮的更新状态"""
|
|
874
882
|
if self.single_task_running:
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
883
|
+
return ["已有任务正在运行"] + [gr.Button(interactive=False) for _ in task_buttons]
|
|
884
|
+
|
|
885
|
+
# 启动任务
|
|
886
|
+
result = self.start_single_task(task_name)
|
|
887
|
+
status_msg = result[1]
|
|
888
|
+
|
|
889
|
+
# 如果成功启动,禁用所有任务按钮
|
|
890
|
+
if self.single_task_running:
|
|
891
|
+
disabled_buttons = [gr.Button(value="运行中", interactive=False) for _ in task_buttons]
|
|
892
|
+
else:
|
|
893
|
+
disabled_buttons = [gr.Button(value="启动", interactive=True) for _ in task_buttons]
|
|
894
|
+
|
|
895
|
+
return [status_msg] + disabled_buttons
|
|
878
896
|
|
|
879
|
-
|
|
880
|
-
|
|
897
|
+
def stop_all_tasks():
|
|
898
|
+
"""停止所有任务并重置按钮状态"""
|
|
899
|
+
if not self.single_task_running:
|
|
900
|
+
return ["没有正在运行的任务"] + [gr.Button(value="启动", interactive=True) for _ in task_buttons]
|
|
901
|
+
|
|
902
|
+
# 停止任务
|
|
903
|
+
result = self.stop_single_task()
|
|
904
|
+
status_msg = result[1]
|
|
905
|
+
|
|
906
|
+
# 如果正在停止中,显示停止中状态
|
|
907
|
+
if self.is_single_task_stopping:
|
|
908
|
+
disabled_buttons = [gr.Button(value="停止中", interactive=False) for _ in task_buttons]
|
|
881
909
|
else:
|
|
882
|
-
|
|
883
|
-
|
|
910
|
+
disabled_buttons = [gr.Button(value="启动", interactive=True) for _ in task_buttons]
|
|
911
|
+
|
|
912
|
+
return [status_msg] + disabled_buttons
|
|
884
913
|
|
|
885
|
-
def
|
|
914
|
+
def get_task_buttons_status() -> List[gr.Button]:
|
|
915
|
+
"""获取所有任务按钮的状态"""
|
|
886
916
|
if not hasattr(self, 'run_status') or not self.run_status.running:
|
|
887
917
|
self.single_task_running = False
|
|
888
|
-
self.is_single_task_stopping = False
|
|
889
|
-
return gr.Button(value="
|
|
918
|
+
self.is_single_task_stopping = False
|
|
919
|
+
return [gr.Button(value="启动", interactive=True) for _ in task_buttons]
|
|
890
920
|
|
|
891
921
|
if self.is_single_task_stopping:
|
|
892
|
-
return gr.Button(value="
|
|
922
|
+
return [gr.Button(value="停止中", interactive=False) for _ in task_buttons]
|
|
923
|
+
|
|
924
|
+
if self.single_task_running:
|
|
925
|
+
return [gr.Button(value="运行中", interactive=False) for _ in task_buttons]
|
|
893
926
|
|
|
894
|
-
return gr.Button(value="
|
|
927
|
+
return [gr.Button(value="启动", interactive=True) for _ in task_buttons]
|
|
895
928
|
|
|
896
929
|
def get_single_task_status() -> str:
|
|
930
|
+
"""获取任务状态信息"""
|
|
897
931
|
if not hasattr(self, 'run_status'):
|
|
898
932
|
return ""
|
|
899
933
|
|
|
@@ -924,15 +958,29 @@ class KotoneBotUI:
|
|
|
924
958
|
|
|
925
959
|
return ""
|
|
926
960
|
|
|
927
|
-
def on_pause_click(
|
|
961
|
+
def on_pause_click() -> str:
|
|
928
962
|
return self.toggle_pause()
|
|
929
963
|
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
964
|
+
# 绑定事件 - 为每个任务按钮绑定点击事件
|
|
965
|
+
def create_task_handler(task_name: str):
|
|
966
|
+
"""创建任务处理函数,避免闭包问题"""
|
|
967
|
+
def handler():
|
|
968
|
+
return start_single_task_by_name(task_name)
|
|
969
|
+
return handler
|
|
970
|
+
|
|
971
|
+
for task_btn, task_name in task_buttons:
|
|
972
|
+
task_btn.click(
|
|
973
|
+
fn=create_task_handler(task_name),
|
|
974
|
+
outputs=[task_result] + [btn for btn, _ in task_buttons]
|
|
975
|
+
)
|
|
976
|
+
|
|
977
|
+
# 绑定停止按钮事件
|
|
978
|
+
stop_all_btn.click(
|
|
979
|
+
fn=stop_all_tasks,
|
|
980
|
+
outputs=[task_result] + [btn for btn, _ in task_buttons]
|
|
934
981
|
)
|
|
935
982
|
|
|
983
|
+
# 绑定暂停按钮事件
|
|
936
984
|
pause_btn.click(
|
|
937
985
|
fn=on_pause_click,
|
|
938
986
|
outputs=[pause_btn]
|
|
@@ -940,8 +988,8 @@ class KotoneBotUI:
|
|
|
940
988
|
|
|
941
989
|
# 添加定时器更新按钮状态和任务状态
|
|
942
990
|
gr.Timer(1.0).tick(
|
|
943
|
-
fn=
|
|
944
|
-
outputs=[
|
|
991
|
+
fn=get_task_buttons_status,
|
|
992
|
+
outputs=[btn for btn, _ in task_buttons]
|
|
945
993
|
)
|
|
946
994
|
gr.Timer(1.0).tick(
|
|
947
995
|
fn=self.get_pause_button_with_interactive,
|
|
@@ -967,8 +1015,8 @@ class KotoneBotUI:
|
|
|
967
1015
|
return new_value
|
|
968
1016
|
|
|
969
1017
|
with gr.Tabs(selected=self.current_config.backend.type):
|
|
970
|
-
with gr.Tab("MuMu 12", id="mumu12") as tab_mumu12:
|
|
971
|
-
gr.Markdown("已选中 MuMu 12 模拟器")
|
|
1018
|
+
with gr.Tab("MuMu 12 v4.x", id="mumu12") as tab_mumu12:
|
|
1019
|
+
gr.Markdown("已选中 MuMu 12 v4.x 模拟器")
|
|
972
1020
|
mumu_refresh_message = gr.Markdown("<div style='color: red;'>点击下方「刷新」按钮载入信息</div>", visible=True)
|
|
973
1021
|
mumu_instance = gr.Dropdown(
|
|
974
1022
|
label="选择多开实例",
|
|
@@ -1012,6 +1060,51 @@ class KotoneBotUI:
|
|
|
1012
1060
|
interactive=True
|
|
1013
1061
|
)
|
|
1014
1062
|
|
|
1063
|
+
with gr.Tab("MuMu 12 v5.x", id="mumu12v5") as tab_mumu12v5:
|
|
1064
|
+
gr.Markdown("已选中 MuMu 12 v5.x 模拟器")
|
|
1065
|
+
mumu_refresh_message = gr.Markdown("<div style='color: red;'>点击下方「刷新」按钮载入信息</div>", visible=True)
|
|
1066
|
+
mumu_instance12v5 = gr.Dropdown(
|
|
1067
|
+
label="选择多开实例",
|
|
1068
|
+
choices=[],
|
|
1069
|
+
interactive=True
|
|
1070
|
+
)
|
|
1071
|
+
mumu_refresh_btn = gr.Button("刷新")
|
|
1072
|
+
|
|
1073
|
+
def refresh_mumu12v5_instances():
|
|
1074
|
+
try:
|
|
1075
|
+
instances = Mumu12V5Host.list()
|
|
1076
|
+
is_mumu12v5 = self.current_config.backend.type == 'mumu12v5'
|
|
1077
|
+
current_id = self.current_config.backend.instance_id if is_mumu12v5 else None
|
|
1078
|
+
choices = [(i.name, i.id) for i in instances]
|
|
1079
|
+
return gr.Dropdown(choices=choices, value=current_id, interactive=True), gr.Markdown(visible=False)
|
|
1080
|
+
except Exception as e:
|
|
1081
|
+
logger.exception('Failed to list installed MuMu12v5')
|
|
1082
|
+
gr.Error("获取 MuMu12 模拟器列表失败,请升级模拟器到最新版本。若问题依旧,前往 QQ 群、QQ 频道或 Github 反馈 bug。")
|
|
1083
|
+
return gr.Dropdown(choices=[], interactive=True), gr.Markdown(visible=True)
|
|
1084
|
+
|
|
1085
|
+
mumu_refresh_btn.click(
|
|
1086
|
+
fn=refresh_mumu12v5_instances,
|
|
1087
|
+
outputs=[mumu_instance12v5, mumu_refresh_message]
|
|
1088
|
+
)
|
|
1089
|
+
|
|
1090
|
+
# 如果当前是 MuMu 模拟器且有配置的 instance_id,立即加载实例列表
|
|
1091
|
+
if self.current_config.backend.type == 'mumu12v5' and self.current_config.backend.instance_id:
|
|
1092
|
+
try:
|
|
1093
|
+
instances = Mumu12V5Host.list()
|
|
1094
|
+
choices = [(i.name, i.id) for i in instances]
|
|
1095
|
+
mumu_instance12v5.choices = choices
|
|
1096
|
+
mumu_instance12v5.value = self.current_config.backend.instance_id
|
|
1097
|
+
mumu_refresh_message.visible = False
|
|
1098
|
+
except Exception as e:
|
|
1099
|
+
logger.exception('Failed to auto-load MuMu12v5 instances')
|
|
1100
|
+
|
|
1101
|
+
mumu_background_mode = gr.Checkbox(
|
|
1102
|
+
label="MuMu12v5 模拟器后台保活模式",
|
|
1103
|
+
value=self.current_config.backend.mumu_background_mode,
|
|
1104
|
+
info=BackendConfig.model_fields['mumu_background_mode'].description,
|
|
1105
|
+
interactive=True
|
|
1106
|
+
)
|
|
1107
|
+
|
|
1015
1108
|
with gr.Tab("雷电", id="leidian") as tab_leidian:
|
|
1016
1109
|
gr.Markdown("已选中雷电模拟器")
|
|
1017
1110
|
leidian_refresh_message = gr.Markdown("<div style='color: red;'>点击下方「刷新」按钮载入信息</div>", visible=True)
|
|
@@ -1101,6 +1194,7 @@ class KotoneBotUI:
|
|
|
1101
1194
|
|
|
1102
1195
|
with gr.Tab("DMM", id="dmm") as tab_dmm:
|
|
1103
1196
|
gr.Markdown("已选中 DMM")
|
|
1197
|
+
gr.Markdown("**暂停快捷键 <kbd>Ctrl</kbd> + <kbd>F4</kbd>,停止快捷键 <kbd>Ctrl</kbd> + <kbd>F3</kbd>**")
|
|
1104
1198
|
|
|
1105
1199
|
choices = ['adb', 'adb_raw', 'uiautomator2', 'windows', 'remote_windows', 'nemu_ipc']
|
|
1106
1200
|
screenshot_impl = gr.Dropdown(
|
|
@@ -1122,6 +1216,7 @@ class KotoneBotUI:
|
|
|
1122
1216
|
)
|
|
1123
1217
|
|
|
1124
1218
|
tab_mumu12.select(fn=partial(_update_emulator_tab_options, selected_index=0), inputs=[screenshot_impl], outputs=[screenshot_impl])
|
|
1219
|
+
tab_mumu12v5.select(fn=partial(_update_emulator_tab_options, selected_index=1), inputs=[screenshot_impl], outputs=[screenshot_impl])
|
|
1125
1220
|
tab_leidian.select(fn=partial(_update_emulator_tab_options, selected_index=1), inputs=[screenshot_impl], outputs=[screenshot_impl])
|
|
1126
1221
|
tab_custom.select(fn=partial(_update_emulator_tab_options, selected_index=2), inputs=[screenshot_impl], outputs=[screenshot_impl])
|
|
1127
1222
|
tab_dmm.select(fn=partial(_update_emulator_tab_options, selected_index=3), inputs=[screenshot_impl], outputs=[screenshot_impl])
|
|
@@ -1132,21 +1227,26 @@ class KotoneBotUI:
|
|
|
1132
1227
|
impl_value=self.current_config.backend.screenshot_impl,
|
|
1133
1228
|
selected_index=0
|
|
1134
1229
|
)
|
|
1135
|
-
elif self.current_config.backend.type == '
|
|
1230
|
+
elif self.current_config.backend.type == 'mumu12v5':
|
|
1136
1231
|
_update_emulator_tab_options(
|
|
1137
1232
|
impl_value=self.current_config.backend.screenshot_impl,
|
|
1138
1233
|
selected_index=1
|
|
1139
1234
|
)
|
|
1140
|
-
elif self.current_config.backend.type == '
|
|
1235
|
+
elif self.current_config.backend.type == 'leidian':
|
|
1141
1236
|
_update_emulator_tab_options(
|
|
1142
1237
|
impl_value=self.current_config.backend.screenshot_impl,
|
|
1143
1238
|
selected_index=2
|
|
1144
1239
|
)
|
|
1145
|
-
elif self.current_config.backend.type == '
|
|
1240
|
+
elif self.current_config.backend.type == 'custom':
|
|
1146
1241
|
_update_emulator_tab_options(
|
|
1147
1242
|
impl_value=self.current_config.backend.screenshot_impl,
|
|
1148
1243
|
selected_index=3
|
|
1149
1244
|
)
|
|
1245
|
+
elif self.current_config.backend.type == 'dmm':
|
|
1246
|
+
_update_emulator_tab_options(
|
|
1247
|
+
impl_value=self.current_config.backend.screenshot_impl,
|
|
1248
|
+
selected_index=4
|
|
1249
|
+
)
|
|
1150
1250
|
else:
|
|
1151
1251
|
gr.Warning(f"未知的模拟器类型:{self.current_config.backend.type}")
|
|
1152
1252
|
|
|
@@ -1156,10 +1256,15 @@ class KotoneBotUI:
|
|
|
1156
1256
|
self.current_config.backend.type = 'mumu12'
|
|
1157
1257
|
self.current_config.backend.instance_id = data['_mumu_index']
|
|
1158
1258
|
self.current_config.backend.mumu_background_mode = data['mumu_background_mode']
|
|
1159
|
-
elif current_tab == 1: #
|
|
1259
|
+
elif current_tab == 1: # Mumu12v5
|
|
1260
|
+
# TODO: 由于 backend 类型放在了 Kotonebot 里,现在无法扩展,后续需要移出来
|
|
1261
|
+
self.current_config.backend.type = 'mumu12v5'
|
|
1262
|
+
self.current_config.backend.instance_id = data['_mumu12v5_index']
|
|
1263
|
+
self.current_config.backend.mumu_background_mode = data['mumu_background_mode']
|
|
1264
|
+
elif current_tab == 2: # Leidian
|
|
1160
1265
|
self.current_config.backend.type = 'leidian'
|
|
1161
1266
|
self.current_config.backend.instance_id = data['_leidian_index']
|
|
1162
|
-
elif current_tab ==
|
|
1267
|
+
elif current_tab == 3: # Custom
|
|
1163
1268
|
self.current_config.backend.type = 'custom'
|
|
1164
1269
|
self.current_config.backend.instance_id = None
|
|
1165
1270
|
self.current_config.backend.adb_ip = data['adb_ip']
|
|
@@ -1168,7 +1273,7 @@ class KotoneBotUI:
|
|
|
1168
1273
|
self.current_config.backend.check_emulator = data['check_emulator']
|
|
1169
1274
|
self.current_config.backend.emulator_path = data['emulator_path']
|
|
1170
1275
|
self.current_config.backend.emulator_args = data['emulator_args']
|
|
1171
|
-
elif current_tab ==
|
|
1276
|
+
elif current_tab == 4: # DMM
|
|
1172
1277
|
self.current_config.backend.type = 'dmm'
|
|
1173
1278
|
self.current_config.backend.instance_id = None # DMM doesn't use instance_id here
|
|
1174
1279
|
|
|
@@ -1187,6 +1292,7 @@ class KotoneBotUI:
|
|
|
1187
1292
|
'emulator_args': emulator_args,
|
|
1188
1293
|
'_mumu_index': mumu_instance,
|
|
1189
1294
|
'_leidian_index': leidian_instance,
|
|
1295
|
+
'_mumu12v5_index': mumu_instance12v5,
|
|
1190
1296
|
'mumu_background_mode': mumu_background_mode
|
|
1191
1297
|
}
|
|
1192
1298
|
|
|
@@ -2570,7 +2676,63 @@ class KotoneBotUI:
|
|
|
2570
2676
|
def list_all_versions():
|
|
2571
2677
|
"""列出所有可用版本"""
|
|
2572
2678
|
import logging
|
|
2679
|
+
import re
|
|
2573
2680
|
logger = logging.getLogger(__name__)
|
|
2681
|
+
|
|
2682
|
+
# 检查启动器版本
|
|
2683
|
+
def check_launcher_version():
|
|
2684
|
+
"""通过读取bootstrap.pyz/meta.py获取启动器版本"""
|
|
2685
|
+
import zipfile
|
|
2686
|
+
try:
|
|
2687
|
+
bootstrap_path = os.path.join(os.getcwd(), "bootstrap.pyz")
|
|
2688
|
+
if not os.path.exists(bootstrap_path):
|
|
2689
|
+
logger.warning("启动器文件不存在")
|
|
2690
|
+
gr.Warning("启动器文件不存在")
|
|
2691
|
+
return None
|
|
2692
|
+
|
|
2693
|
+
# 尝试从bootstrap.pyz中读取meta.py
|
|
2694
|
+
try:
|
|
2695
|
+
with zipfile.ZipFile(bootstrap_path, 'r') as zip_file:
|
|
2696
|
+
if 'meta.py' in zip_file.namelist():
|
|
2697
|
+
# 读取meta.py内容
|
|
2698
|
+
meta_content = zip_file.read('meta.py').decode('utf-8')
|
|
2699
|
+
|
|
2700
|
+
# 创建一个安全的执行环境
|
|
2701
|
+
exec_globals = {}
|
|
2702
|
+
exec_locals = {}
|
|
2703
|
+
|
|
2704
|
+
# 执行meta.py内容
|
|
2705
|
+
exec(meta_content, exec_globals, exec_locals)
|
|
2706
|
+
|
|
2707
|
+
# 获取VERSION变量
|
|
2708
|
+
if 'VERSION' in exec_locals:
|
|
2709
|
+
version = exec_locals['VERSION']
|
|
2710
|
+
# 移除v前缀(如果有)
|
|
2711
|
+
if isinstance(version, str) and version.startswith('v'):
|
|
2712
|
+
version = version[1:]
|
|
2713
|
+
logger.info(f"从meta.py读取到启动器版本: {version}")
|
|
2714
|
+
return str(version)
|
|
2715
|
+
else:
|
|
2716
|
+
logger.warning("meta.py中未找到VERSION变量")
|
|
2717
|
+
gr.Warning("meta.py中未找到VERSION变量")
|
|
2718
|
+
return None
|
|
2719
|
+
else:
|
|
2720
|
+
logger.warning("bootstrap.pyz中未找到meta.py文件")
|
|
2721
|
+
gr.Warning("bootstrap.pyz中未找到meta.py文件")
|
|
2722
|
+
return None
|
|
2723
|
+
except zipfile.BadZipFile:
|
|
2724
|
+
# 不是有效的zip文件,可能是旧版本启动器
|
|
2725
|
+
logger.info("bootstrap.pyz不是有效的zip文件,判断为旧版本启动器")
|
|
2726
|
+
return "0.4.x"
|
|
2727
|
+
except Exception as e:
|
|
2728
|
+
logger.warning(f"读取bootstrap.pyz失败: {str(e)}")
|
|
2729
|
+
gr.Warning(f"读取bootstrap.pyz失败: {str(e)}")
|
|
2730
|
+
return None
|
|
2731
|
+
|
|
2732
|
+
except Exception as e:
|
|
2733
|
+
logger.warning(f"检查启动器版本失败: {str(e)}")
|
|
2734
|
+
gr.Warning(f"检查启动器版本失败: {str(e)}")
|
|
2735
|
+
return None
|
|
2574
2736
|
|
|
2575
2737
|
try:
|
|
2576
2738
|
# 构建命令,使用清华镜像源
|
|
@@ -2636,12 +2798,22 @@ class KotoneBotUI:
|
|
|
2636
2798
|
gr.Button(visible=False)
|
|
2637
2799
|
)
|
|
2638
2800
|
|
|
2801
|
+
# 检查启动器版本
|
|
2802
|
+
launcher_version = check_launcher_version()
|
|
2803
|
+
|
|
2639
2804
|
# 构建状态信息
|
|
2640
2805
|
status_info = []
|
|
2641
2806
|
if installed_version:
|
|
2642
2807
|
status_info.append(f"**当前安装版本:** {installed_version}")
|
|
2643
2808
|
if latest_version:
|
|
2644
2809
|
status_info.append(f"**最新版本:** {latest_version}")
|
|
2810
|
+
if launcher_version:
|
|
2811
|
+
if launcher_version == "0.4.x":
|
|
2812
|
+
status_info.append(f"**启动器版本:** < v0.5.0 (旧版本)")
|
|
2813
|
+
else:
|
|
2814
|
+
status_info.append(f"**启动器版本:** v{launcher_version}")
|
|
2815
|
+
else:
|
|
2816
|
+
status_info.append(f"**启动器版本:** 未知")
|
|
2645
2817
|
status_info.append(f"**找到 {len(versions)} 个可用版本**")
|
|
2646
2818
|
|
|
2647
2819
|
status_message = "\n\n".join(status_info)
|
|
@@ -2679,12 +2851,130 @@ class KotoneBotUI:
|
|
|
2679
2851
|
import logging
|
|
2680
2852
|
import threading
|
|
2681
2853
|
import time
|
|
2854
|
+
import re
|
|
2682
2855
|
logger = logging.getLogger(__name__)
|
|
2683
2856
|
|
|
2684
2857
|
if not selected_version:
|
|
2685
2858
|
error_msg = "请先选择一个版本"
|
|
2686
2859
|
logger.warning(error_msg)
|
|
2687
2860
|
return error_msg
|
|
2861
|
+
|
|
2862
|
+
|
|
2863
|
+
def compare_version(version1: str, version2: str) -> int:
|
|
2864
|
+
"""比较版本号,返回-1(v1<v2), 0(v1==v2), 1(v1>v2)"""
|
|
2865
|
+
# 处理特殊标记
|
|
2866
|
+
if version1 == "0.4.x":
|
|
2867
|
+
version1 = "0.4.0"
|
|
2868
|
+
|
|
2869
|
+
def parse_version(v):
|
|
2870
|
+
# 移除v前缀并解析版本号和预发布标识
|
|
2871
|
+
v = v.lstrip('v')
|
|
2872
|
+
if 'b' in v:
|
|
2873
|
+
base, beta = v.split('b', 1)
|
|
2874
|
+
return tuple(map(int, base.split('.'))) + (-1, int(beta))
|
|
2875
|
+
elif 'a' in v:
|
|
2876
|
+
base, alpha = v.split('a', 1)
|
|
2877
|
+
return tuple(map(int, base.split('.'))) + (-2, int(alpha))
|
|
2878
|
+
elif 'rc' in v:
|
|
2879
|
+
base, rc = v.split('rc', 1)
|
|
2880
|
+
return tuple(map(int, base.split('.'))) + (-0.5, int(rc))
|
|
2881
|
+
else:
|
|
2882
|
+
return tuple(map(int, v.split('.'))) + (0, 0)
|
|
2883
|
+
|
|
2884
|
+
v1_parsed = parse_version(version1)
|
|
2885
|
+
v2_parsed = parse_version(version2)
|
|
2886
|
+
|
|
2887
|
+
if v1_parsed < v2_parsed:
|
|
2888
|
+
return -1
|
|
2889
|
+
elif v1_parsed > v2_parsed:
|
|
2890
|
+
return 1
|
|
2891
|
+
else:
|
|
2892
|
+
return 0
|
|
2893
|
+
|
|
2894
|
+
# 检查启动器版本进行兼容性验证
|
|
2895
|
+
def check_launcher_version_simple():
|
|
2896
|
+
"""通过读取bootstrap.pyz/meta.py获取启动器版本"""
|
|
2897
|
+
import zipfile
|
|
2898
|
+
try:
|
|
2899
|
+
bootstrap_path = os.path.join(os.getcwd(), "bootstrap.pyz")
|
|
2900
|
+
if not os.path.exists(bootstrap_path):
|
|
2901
|
+
logger.warning("启动器文件不存在")
|
|
2902
|
+
gr.Warning("启动器文件不存在")
|
|
2903
|
+
return None
|
|
2904
|
+
|
|
2905
|
+
# 尝试从bootstrap.pyz中读取meta.py
|
|
2906
|
+
try:
|
|
2907
|
+
with zipfile.ZipFile(bootstrap_path, 'r') as zip_file:
|
|
2908
|
+
if 'meta.py' in zip_file.namelist():
|
|
2909
|
+
# 读取meta.py内容
|
|
2910
|
+
meta_content = zip_file.read('meta.py').decode('utf-8')
|
|
2911
|
+
|
|
2912
|
+
# 创建一个安全的执行环境
|
|
2913
|
+
exec_globals = {}
|
|
2914
|
+
exec_locals = {}
|
|
2915
|
+
|
|
2916
|
+
# 执行meta.py内容
|
|
2917
|
+
exec(meta_content, exec_globals, exec_locals)
|
|
2918
|
+
|
|
2919
|
+
# 获取VERSION变量
|
|
2920
|
+
if 'VERSION' in exec_locals:
|
|
2921
|
+
version = exec_locals['VERSION']
|
|
2922
|
+
# 移除v前缀(如果有)
|
|
2923
|
+
if isinstance(version, str) and version.startswith('v'):
|
|
2924
|
+
version = version[1:]
|
|
2925
|
+
logger.info(f"从meta.py读取到启动器版本: {version}")
|
|
2926
|
+
return str(version)
|
|
2927
|
+
else:
|
|
2928
|
+
logger.warning("meta.py中未找到VERSION变量")
|
|
2929
|
+
gr.Warning("meta.py中未找到VERSION变量")
|
|
2930
|
+
return None
|
|
2931
|
+
else:
|
|
2932
|
+
logger.warning("bootstrap.pyz中未找到meta.py文件")
|
|
2933
|
+
gr.Warning("bootstrap.pyz中未找到meta.py文件")
|
|
2934
|
+
return None
|
|
2935
|
+
except zipfile.BadZipFile:
|
|
2936
|
+
# 不是有效的zip文件,可能是旧版本启动器
|
|
2937
|
+
logger.info("bootstrap.pyz不是有效的zip文件,判断为旧版本启动器")
|
|
2938
|
+
return "0.4.x"
|
|
2939
|
+
except Exception as e:
|
|
2940
|
+
logger.warning(f"读取bootstrap.pyz失败: {str(e)}")
|
|
2941
|
+
gr.Warning(f"读取bootstrap.pyz失败: {str(e)}")
|
|
2942
|
+
return None
|
|
2943
|
+
|
|
2944
|
+
except Exception as e:
|
|
2945
|
+
logger.warning(f"检查启动器版本失败: {str(e)}")
|
|
2946
|
+
gr.Warning(f"检查启动器版本失败: {str(e)}")
|
|
2947
|
+
return None
|
|
2948
|
+
|
|
2949
|
+
# 执行启动器版本检查
|
|
2950
|
+
launcher_version = check_launcher_version_simple()
|
|
2951
|
+
logger.info(f"检测到启动器版本: {launcher_version}")
|
|
2952
|
+
|
|
2953
|
+
# 版本兼容性检查
|
|
2954
|
+
if launcher_version:
|
|
2955
|
+
if compare_version(launcher_version, "0.5.0") < 0:
|
|
2956
|
+
# 启动器版本低于0.5.0
|
|
2957
|
+
logger.warning(f"启动器版本 {launcher_version} 低于 v0.5.0")
|
|
2958
|
+
|
|
2959
|
+
# 检查要安装的版本是否 >= v2025.9b1
|
|
2960
|
+
if compare_version(selected_version, "2025.9b1") >= 0:
|
|
2961
|
+
error_msg = (
|
|
2962
|
+
f"❌ 版本兼容性错误\n\n"
|
|
2963
|
+
f"启动器版本: {launcher_version}\n"
|
|
2964
|
+
f"要安装的版本: {selected_version}\n\n"
|
|
2965
|
+
f"v2025.9b1 及以上版本需要**启动器 v0.5.0*** 或更高版本支持。\n"
|
|
2966
|
+
f"请先升级启动器到 v0.5.0 以上版本。[查看帮助](https://www.kdocs.cn/l/cetCY8mGKHLj?linkname=UhPH1itaSv)"
|
|
2967
|
+
)
|
|
2968
|
+
logger.error(error_msg)
|
|
2969
|
+
return error_msg
|
|
2970
|
+
else:
|
|
2971
|
+
# 版本兼容,但给出警告
|
|
2972
|
+
logger.warning(f"启动器版本较低,建议升级到 v0.5.0 以上")
|
|
2973
|
+
gr.Warning("启动器版本较低,建议升级到 v0.5.0 以上")
|
|
2974
|
+
else:
|
|
2975
|
+
# 无法获取启动器版本,给出警告但继续
|
|
2976
|
+
logger.warning("无法获取启动器版本,可以继续安装但可能存在兼容性问题")
|
|
2977
|
+
gr.Warning("无法获取启动器版本,可以继续安装但可能存在兼容性问题")
|
|
2688
2978
|
|
|
2689
2979
|
def install_and_exit():
|
|
2690
2980
|
"""在后台线程中执行安装并退出程序"""
|
|
@@ -2705,9 +2995,6 @@ class KotoneBotUI:
|
|
|
2705
2995
|
creationflags=subprocess.CREATE_NEW_CONSOLE if os.name == 'nt' else 0
|
|
2706
2996
|
)
|
|
2707
2997
|
|
|
2708
|
-
# 等待一小段时间确保启动器启动
|
|
2709
|
-
time.sleep(2)
|
|
2710
|
-
|
|
2711
2998
|
# 退出当前程序
|
|
2712
2999
|
logger.info("安装即将开始,正在退出当前程序...")
|
|
2713
3000
|
os._exit(0)
|