ksaa 2025.6.23.0__py3-none-any.whl → 2025.7.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kotonebot/backend/context/context.py +0 -2
- kotonebot/client/__init__.py +1 -2
- kotonebot/client/device.py +155 -4
- kotonebot/client/host/adb_common.py +94 -0
- kotonebot/client/host/custom.py +27 -21
- kotonebot/client/host/leidian_host.py +14 -23
- kotonebot/client/host/mumu12_host.py +70 -24
- kotonebot/client/host/protocol.py +4 -1
- kotonebot/client/host/windows_common.py +55 -0
- kotonebot/client/implements/__init__.py +2 -1
- kotonebot/client/implements/adb.py +1 -44
- kotonebot/client/implements/adb_raw.py +2 -9
- kotonebot/client/implements/nemu_ipc/__init__.py +8 -0
- kotonebot/client/implements/nemu_ipc/external_renderer_ipc.py +280 -0
- kotonebot/client/implements/nemu_ipc/nemu_ipc.py +327 -0
- kotonebot/client/implements/remote_windows.py +8 -14
- kotonebot/client/implements/uiautomator2.py +5 -16
- kotonebot/client/implements/windows.py +5 -36
- kotonebot/client/registration.py +2 -67
- kotonebot/config/base_config.py +4 -2
- kotonebot/debug_entry.py +4 -2
- kotonebot/errors.py +7 -0
- kotonebot/kaa/common.py +18 -0
- kotonebot/kaa/main/dmm_host.py +13 -32
- kotonebot/kaa/main/gr.py +373 -33
- kotonebot/kaa/main/kaa.py +30 -3
- kotonebot/kaa/metadata.py +42 -0
- kotonebot/kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
- kotonebot/kaa/resources/game.db +0 -0
- kotonebot/kaa/resources/game_ver.txt +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hmsz-3-005_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hmsz-3-005_1.png +0 -0
- kotonebot/kaa/tasks/R.py +132 -132
- {ksaa-2025.6.23.0.dist-info → ksaa-2025.7.3.0.dist-info}/METADATA +4 -1
- {ksaa-2025.6.23.0.dist-info → ksaa-2025.7.3.0.dist-info}/RECORD +172 -165
- /kotonebot/kaa/sprites/{c5ea3dfd-6761-466e-b44c-86592ef05323.png → 01ce8957-465d-4278-b297-f58b36c73285.png} +0 -0
- /kotonebot/kaa/sprites/{84bb4986-0295-4a45-9486-86e31fcdf1f1.png → 02048c24-3002-4122-b24b-15a2c2fb502f.png} +0 -0
- /kotonebot/kaa/sprites/{b01c25d2-21bf-4db9-b5b2-ec35817f1b04.png → 02de663b-a039-4530-b10b-fd5aea9f600e.png} +0 -0
- /kotonebot/kaa/sprites/{e1e0d751-9006-4fa4-a933-4c0dc5e1f3d2.png → 047454d6-9cbb-432d-b670-bde2d5f5fc9a.png} +0 -0
- /kotonebot/kaa/sprites/{920a3974-4875-4d2b-bbac-caa175c03ce0.png → 081ca89e-0f95-45e5-a855-5b7e49295af5.png} +0 -0
- /kotonebot/kaa/sprites/{0235ae3d-1741-4a81-8053-f60bc395ee85.png → 0a0dfcba-7ae4-415a-9361-7f3c4ec16ef9.png} +0 -0
- /kotonebot/kaa/sprites/{9c7f1bcc-0bc8-454b-95fb-56a803030771.png → 0a586241-e005-45a6-b12f-eed8089d8fd8.png} +0 -0
- /kotonebot/kaa/sprites/{5152e3fa-079c-4592-8df7-656101694df8.png → 0ad61c60-5458-400d-9788-437edb32608a.png} +0 -0
- /kotonebot/kaa/sprites/{f611bbd9-c062-4989-96a4-65ff6c59673c.png → 0b452661-3720-4fa3-9e52-6fdc69517396.png} +0 -0
- /kotonebot/kaa/sprites/{bed9575d-ccad-4f4e-825e-47b2a9cb0925.png → 0db398fd-3551-4a15-b734-ca5a7b54150f.png} +0 -0
- /kotonebot/kaa/sprites/{0d4b669e-5e43-4458-b65a-5565797335ae.png → 0e0686c7-9fe8-4f82-9d05-7922e55fc1a9.png} +0 -0
- /kotonebot/kaa/sprites/{264e056f-3bcc-4b16-94d4-f767c78ab6f5.png → 109ff896-1f96-465a-ad6f-ef410789e140.png} +0 -0
- /kotonebot/kaa/sprites/{b65724b4-ec8f-48a9-9ab2-e7ce5b8f35b2.png → 1140cce1-90e4-44cd-9acc-c2491841fbd4.png} +0 -0
- /kotonebot/kaa/sprites/{7f6cb60e-6ab3-4db4-86e1-8558250062a4.png → 124fb25f-47ac-468d-97af-f90c9604f1c5.png} +0 -0
- /kotonebot/kaa/sprites/{5868ebfb-5e61-4ac6-b270-acb1e89b738f.png → 1470cd16-3340-4a0a-854f-3acf9b882cb1.png} +0 -0
- /kotonebot/kaa/sprites/{1aaceb21-dc5c-4a58-96d3-d2c66b2fb357.png → 156d67bb-562c-42df-b55a-aea0b6ad71dd.png} +0 -0
- /kotonebot/kaa/sprites/{abcc709c-1f4d-4832-a063-eafbad94ac31.png → 17608ef8-fe7c-4fc7-b811-a6c05e838881.png} +0 -0
- /kotonebot/kaa/sprites/{dbd537c7-d1d3-4d64-9ccd-43dd4519bedd.png → 1a4c5291-70a9-4923-aadf-f7e6a28c7aa5.png} +0 -0
- /kotonebot/kaa/sprites/{d4c47cc7-5b3e-4c3e-8e80-78cb94e7eed9.png → 1db583b2-c82a-4576-9ca9-b7409bc1ca95.png} +0 -0
- /kotonebot/kaa/sprites/{7cabdf91-2f15-4991-b165-eb9cdd557af6.png → 1fc998a7-cfa2-4485-9742-1ae87306a9fc.png} +0 -0
- /kotonebot/kaa/sprites/{dde03640-6c3a-4b13-a783-f672816bfec4.png → 24cdb395-915e-4816-9406-efd1aafa70c1.png} +0 -0
- /kotonebot/kaa/sprites/{94433cf2-dd04-4b74-ae14-e5e3d945f579.png → 25151748-2eb2-4f08-94f1-f1be2fbea3da.png} +0 -0
- /kotonebot/kaa/sprites/{cdbbb5ba-5117-488a-8172-48cfc92c14c6.png → 25598023-8999-4737-9f3c-9da71bb88748.png} +0 -0
- /kotonebot/kaa/sprites/{d3e6e2e9-c5b5-463f-98f4-de72c9320d9d.png → 26b9efc1-51be-4784-bf78-2b929abac650.png} +0 -0
- /kotonebot/kaa/sprites/{e394ff91-09d3-41e1-bbf5-bc42a71a623b.png → 276522a3-d8f0-4b0f-8ee5-dce3f2cb87a5.png} +0 -0
- /kotonebot/kaa/sprites/{dfb14c98-f672-4906-80bd-d2a18bdd62cd.png → 277035b5-7eee-4ca8-80dd-f73d78e7531f.png} +0 -0
- /kotonebot/kaa/sprites/{15465879-eb84-4ca6-ae0f-d3c5ac71e723.png → 28ea2cc9-e9f2-4573-968a-0c88562c696a.png} +0 -0
- /kotonebot/kaa/sprites/{aa3b717f-67f8-445f-a6bf-b89f7200d95b.png → 28f44641-894d-4047-bc56-b932ac5a32a0.png} +0 -0
- /kotonebot/kaa/sprites/{4a310bdd-0a7d-4669-9d57-6ae69bc8f022.png → 2a0e9656-26ba-4d7a-a414-6045e521b92c.png} +0 -0
- /kotonebot/kaa/sprites/{bfec58df-2628-454f-92aa-769cad186448.png → 2a2770d2-7fd8-4bb0-89a7-c507046fc892.png} +0 -0
- /kotonebot/kaa/sprites/{cf66ae12-48bc-4512-a988-0e5de337c76d.png → 2b9fb35b-4a3b-440d-bcac-1eb1fdfe0e21.png} +0 -0
- /kotonebot/kaa/sprites/{c3ec61aa-f62e-46fd-b359-48864ea7a150.png → 2fc3fa82-cc3d-4164-839f-d0bd7f8a32f5.png} +0 -0
- /kotonebot/kaa/sprites/{1aae0ab3-f619-47e0-8bf6-3d3791f7d445.png → 2fd135e1-8010-4a53-90a3-2a950c5a43bf.png} +0 -0
- /kotonebot/kaa/sprites/{d1699baa-467b-46d1-9276-aae78fe8f589.png → 3037118b-4a82-4cfc-ad95-db8a03f779d5.png} +0 -0
- /kotonebot/kaa/sprites/{1d5f7454-672d-4e87-a368-ec4bb32f9b1f.png → 33aaec9e-dccc-441a-b91a-4784f1eb4498.png} +0 -0
- /kotonebot/kaa/sprites/{a8b3fdce-9e4a-495c-839e-0142f67fee69.png → 359e43b3-6b85-4f8c-86a1-4d4c1ae75779.png} +0 -0
- /kotonebot/kaa/sprites/{09fb5e41-6caa-4246-a415-8317b12d8d81.png → 3a4e2e77-c49b-4f69-bfd1-19fbe4f5c9a5.png} +0 -0
- /kotonebot/kaa/sprites/{038c69e6-7cb0-4c8d-99da-b537e48a86b7.png → 3bf0a104-739e-4bef-9304-4aa77e5e18ea.png} +0 -0
- /kotonebot/kaa/sprites/{cb24b3df-1ec3-4ffd-95f1-ca4b0dd5b7da.png → 3ea8a020-5605-47ce-8d3a-d812d0583058.png} +0 -0
- /kotonebot/kaa/sprites/{42d8b5dc-ef27-4411-b8b5-d981e562990b.png → 404c6271-1af4-4f63-be02-e82b318eb072.png} +0 -0
- /kotonebot/kaa/sprites/{8e48af2b-c083-4480-a27c-c59c31a7ede1.png → 43550662-cd46-4312-b18b-949cba98d173.png} +0 -0
- /kotonebot/kaa/sprites/{52f7c8b1-af88-43c5-a999-de4da3caa03a.png → 441c2df2-43ac-4ff3-814e-6230c510bce6.png} +0 -0
- /kotonebot/kaa/sprites/{58a5f51d-d1a3-480b-8dde-ecead34d9f02.png → 44430184-c35e-4bb8-8858-ed5cec580c36.png} +0 -0
- /kotonebot/kaa/sprites/{a4075991-98da-4d06-bcde-28054cd124d2.png → 4466c3fe-a5ad-4960-a137-0d735441b12e.png} +0 -0
- /kotonebot/kaa/sprites/{efb28e1d-7b52-4e20-aec5-117c798b7fbe.png → 46debd92-df4c-49d6-a3f6-c83a4c72be70.png} +0 -0
- /kotonebot/kaa/sprites/{448ea37d-a10d-4102-ac9f-a58403ee8914.png → 49e46cda-a6ac-44c8-8901-60956ca5151d.png} +0 -0
- /kotonebot/kaa/sprites/{faf360e8-7845-4fcf-b0a6-0f5f93c050f1.png → 4cca8c07-b33f-4f57-8c2b-3fff8cb4424a.png} +0 -0
- /kotonebot/kaa/sprites/{a1bba683-a740-4eaf-8c37-3b1042b963b0.png → 4fe4fbf2-4dbf-44d2-8dd6-a3f3c9f0d1b7.png} +0 -0
- /kotonebot/kaa/sprites/{7516c9a1-87ec-4d2f-ac5e-40d1aec27104.png → 501eaf11-021e-4764-93ed-0be6ea0ed5df.png} +0 -0
- /kotonebot/kaa/sprites/{5ee8e9a8-b133-4ab7-a52c-e7e4e1d1ce7b.png → 525b6f3a-acc8-4bd8-be4b-cc1f44fb377a.png} +0 -0
- /kotonebot/kaa/sprites/{6114d53e-dd69-4cee-82a7-7e43b338ff8d.png → 540547f7-5633-440c-b7ad-b54529436479.png} +0 -0
- /kotonebot/kaa/sprites/{c5e16f75-9b5a-4853-a144-275f3d20c186.png → 540a0d73-7158-4872-808f-abcb11ba1aef.png} +0 -0
- /kotonebot/kaa/sprites/{a3b15425-0bfd-4668-a3a9-2ab64da8505f.png → 559485ee-a27f-4824-ad7a-e57d0c613ed5.png} +0 -0
- /kotonebot/kaa/sprites/{8f1e5644-1079-44b1-9d44-97bae3817bc5.png → 56a7aed8-6367-40dd-a6a1-fc8a840abd9b.png} +0 -0
- /kotonebot/kaa/sprites/{2e00ac54-d23a-4d51-82f2-829c012552a6.png → 5d8bbe9f-4732-495a-8d27-80cfd2ea12f5.png} +0 -0
- /kotonebot/kaa/sprites/{4eaa5db2-d624-4df4-b2e4-01f72755f1a4.png → 612d508d-e77c-492e-854d-30141733bd27.png} +0 -0
- /kotonebot/kaa/sprites/{d5d854fc-1b87-43d4-b32d-66eccb66fa41.png → 62031705-40e0-4b74-b7b9-07f1fffd122f.png} +0 -0
- /kotonebot/kaa/sprites/{0a6c6b1e-7a80-428e-a483-1858bfb8ac59.png → 62a4c9fd-35e6-4982-b9f4-e3a5685eac13.png} +0 -0
- /kotonebot/kaa/sprites/{68838f92-5916-424e-a37e-47e0b3834eb3.png → 685fb958-ec13-4826-8e78-3575ff42df27.png} +0 -0
- /kotonebot/kaa/sprites/{b1e7f24e-f246-406e-9073-58e2f3e4e819.png → 689aa894-304a-48d2-8b6e-794dc967b1f6.png} +0 -0
- /kotonebot/kaa/sprites/{1b6be6dd-2711-441a-9fa6-3281a6ad10c7.png → 69266fc9-c8fe-48ea-8d68-8ace8c606049.png} +0 -0
- /kotonebot/kaa/sprites/{1ccdcacf-4f7d-442c-8e2f-09aa7fe14e56.png → 699df701-37a2-4e17-afae-5b49ab826926.png} +0 -0
- /kotonebot/kaa/sprites/{ba759205-ce99-4417-8cab-d32fe55dff4c.png → 6a7eacf1-f14e-45cf-8ef7-7f933d4fa664.png} +0 -0
- /kotonebot/kaa/sprites/{969eb98c-f761-4007-b8bd-2b3fb8d1f08c.png → 6af19ba1-ca74-473b-8788-61132e5fc084.png} +0 -0
- /kotonebot/kaa/sprites/{3cc9685d-6347-4114-9d39-7683c2dc9df6.png → 6be05914-aa45-4e55-a0bb-7ec16e76d7b1.png} +0 -0
- /kotonebot/kaa/sprites/{534d1310-3503-46d3-8ecd-426d9bcf183e.png → 6f342de5-b179-4120-ab6d-404c3eee5caa.png} +0 -0
- /kotonebot/kaa/sprites/{60be53a6-98e9-4fc6-9285-85506dc0e335.png → 6fc5543e-9d09-4f06-8331-64ee62bd73c3.png} +0 -0
- /kotonebot/kaa/sprites/{0fbcb3f6-9ca0-43c7-975b-e7c15c26c897.png → 7036c80b-28fd-4a54-a8f9-06a23d89e861.png} +0 -0
- /kotonebot/kaa/sprites/{b8aada91-eedd-4c53-99f3-f903d547235e.png → 71fe9437-3d7a-4321-9e5c-d6b81d954002.png} +0 -0
- /kotonebot/kaa/sprites/{a1cf80ee-64bf-4d54-a7db-ffadf3c97026.png → 7344f9d8-fccb-44e3-ab43-a180cfce2217.png} +0 -0
- /kotonebot/kaa/sprites/{90def878-cd6e-46e5-9dc4-9c92dd904b80.png → 74e207b4-a13e-47cc-bf23-dbf77089ea3c.png} +0 -0
- /kotonebot/kaa/sprites/{faf069e1-f623-47c1-b879-cfa246fbc7df.png → 76aca556-0042-4f84-a29a-30e6a631aa72.png} +0 -0
- /kotonebot/kaa/sprites/{e5eeb9af-8003-4981-bf56-2e32e76cec5d.png → 7aa7c3dc-02e8-4d70-a026-d1afb34f37f9.png} +0 -0
- /kotonebot/kaa/sprites/{9cd7e1f1-13c4-471e-abee-223ffd9126cb.png → 7d4d40cf-a6db-41ef-90fd-2fb0a6f5087d.png} +0 -0
- /kotonebot/kaa/sprites/{17a8b0a5-5b71-4612-8a68-16c51f03c71b.png → 7d7ccd61-8d92-49b4-aa7e-b1e73906371e.png} +0 -0
- /kotonebot/kaa/sprites/{e5259dfb-3a49-4cfc-9f89-b42958ce6eec.png → 807904aa-30fd-4a9b-8acb-ca4b235281bc.png} +0 -0
- /kotonebot/kaa/sprites/{8b9c115b-d4ce-492e-88cb-08bd01c43570.png → 81a6e258-670c-4646-90ef-a76846cf5d37.png} +0 -0
- /kotonebot/kaa/sprites/{5dd0cc39-4102-4f0f-8ad3-342bbf825977.png → 81bf65f2-9cc3-4613-9611-e7b5ec14c31c.png} +0 -0
- /kotonebot/kaa/sprites/{b5d4265c-82e0-470d-a48e-8aa4edbdef5a.png → 84af97ac-7e73-4ae8-88a6-9b3a18c81fbe.png} +0 -0
- /kotonebot/kaa/sprites/{aefdec38-e3b6-4762-aed8-33107686ddac.png → 85347bb8-c28d-4a40-bd55-386c530727c2.png} +0 -0
- /kotonebot/kaa/sprites/{4b20b364-5f5f-4b34-960e-b0cfd08b1662.png → 884a25c2-7b98-4a33-a975-6f918a8301aa.png} +0 -0
- /kotonebot/kaa/sprites/{29cb7b0f-5684-4516-8fae-4439f7f28e08.png → 88ed3d25-070a-411d-b4fb-8a9df068b091.png} +0 -0
- /kotonebot/kaa/sprites/{1bb00a74-2fdc-4973-84ae-dc1edee15f81.png → 94b8429e-64d9-49da-945c-d2d3dcccb587.png} +0 -0
- /kotonebot/kaa/sprites/{df97421e-4b74-430e-b3d1-ed9bac6918a7.png → 95e591bb-f0e6-457e-83e3-0909cb5c8877.png} +0 -0
- /kotonebot/kaa/sprites/{9aef1aa8-41e1-42a7-83ad-b4e212ee3976.png → 982d2e5d-4493-44a5-b922-e71649fd6bc5.png} +0 -0
- /kotonebot/kaa/sprites/{302fde7d-de85-44c7-ba57-fe4b5f6db5fa.png → 99ae067f-72f2-4d13-a2de-f78ce13ec5a3.png} +0 -0
- /kotonebot/kaa/sprites/{66678caa-7b25-4ff7-8c3a-017f67279349.png → 9b425fee-9118-4015-9242-29bf1150e704.png} +0 -0
- /kotonebot/kaa/sprites/{83f17b06-2792-4035-bc90-1800279ae131.png → 9bf5d8a8-30c1-4ce7-9888-bcada63d48e6.png} +0 -0
- /kotonebot/kaa/sprites/{c25c7ce5-ad8d-4b2c-83eb-ae6d4871a6c3.png → 9fb0b19e-ae0c-4c9e-8ec8-b126113b6091.png} +0 -0
- /kotonebot/kaa/sprites/{0ad2f603-a3ad-4a92-a398-c411145fd8e9.png → a241cff0-d803-4c8f-bcd0-22bda2adc8a7.png} +0 -0
- /kotonebot/kaa/sprites/{83acbca8-3567-4262-a1e7-50f158348d45.png → a26dc021-2a28-4f79-bd11-48c4a1261f0d.png} +0 -0
- /kotonebot/kaa/sprites/{ca2adfb8-1e88-4a31-b3cc-1f70568ce4a3.png → a2ab29ef-ddc7-4885-9f88-850858b0c995.png} +0 -0
- /kotonebot/kaa/sprites/{17414e9e-b046-49e0-9596-cad1f4673a9e.png → a388f87d-9a69-4189-b80a-e230d7d7b964.png} +0 -0
- /kotonebot/kaa/sprites/{83cf48ba-d1af-4674-a52e-6bb80a626db7.png → a53820f6-1572-413a-b7b1-2bc08690884f.png} +0 -0
- /kotonebot/kaa/sprites/{a1853223-d6b9-4660-af4e-91e59bdddc3c.png → a5bd802e-d10c-4e95-9b62-1ffd92aca4ab.png} +0 -0
- /kotonebot/kaa/sprites/{f12c2b0b-8273-4197-a8c6-2a8ef2788a9b.png → a6d63930-bb09-443c-95ae-47ad6a9f9cc4.png} +0 -0
- /kotonebot/kaa/sprites/{9d5dd50c-3341-41a4-a3dd-ccc00edcf201.png → ab4cd19c-ad2b-4ed7-baeb-eef6a12939b2.png} +0 -0
- /kotonebot/kaa/sprites/{080b3cf5-ce35-4382-9bfa-d6a12efb09b3.png → abd7bfbf-5f08-452a-b216-22fb0af4e955.png} +0 -0
- /kotonebot/kaa/sprites/{e9c45a73-2011-4584-87b7-c4e566eba87f.png → ac4579ad-2000-4283-8e13-53fe525725bf.png} +0 -0
- /kotonebot/kaa/sprites/{dad4ff8c-07f4-4b07-abd3-5d02bbcc4562.png → ada79928-ea1a-4537-89e7-a02877dc6e7d.png} +0 -0
- /kotonebot/kaa/sprites/{1f2981d8-5eb6-4332-aa9b-17f4db2d4163.png → af4b7a1d-4cb2-432c-8dbb-c333950c58c2.png} +0 -0
- /kotonebot/kaa/sprites/{7aa2435c-da90-4d52-b831-88dbec57dde9.png → b5d02984-ec1f-48f5-8593-0bc0e4babc1f.png} +0 -0
- /kotonebot/kaa/sprites/{25910d8e-d57f-409f-b0be-ee68c5af4920.png → bba69e83-b9f4-4a24-a95b-190c985c5b22.png} +0 -0
- /kotonebot/kaa/sprites/{1639278d-67e0-4452-a2b5-ec4cf4011f42.png → bc10fc41-960e-4151-aad2-325367b20895.png} +0 -0
- /kotonebot/kaa/sprites/{66172bc0-3869-4a48-a26d-0dc3fa404ab8.png → bc94b664-bbcf-4b59-8e4b-7dbf03997309.png} +0 -0
- /kotonebot/kaa/sprites/{bb0ae68d-44d5-47c6-91dd-a529bc34225b.png → bf44c221-0af9-497e-a2e8-cdc497348257.png} +0 -0
- /kotonebot/kaa/sprites/{2dd34393-ee6f-4b19-8a9c-76556d1bd7d7.png → bff85e9a-df48-429f-a82e-ceff41f8527b.png} +0 -0
- /kotonebot/kaa/sprites/{ed6d3e3d-0f04-4fa4-b0f9-fdbf324649f6.png → c4985caa-1e42-4980-9a76-a660a7b12c67.png} +0 -0
- /kotonebot/kaa/sprites/{f8eec9b2-55ca-4195-b098-a5393d02a98a.png → c5447438-3b41-465e-b438-157f5e61c764.png} +0 -0
- /kotonebot/kaa/sprites/{ad172750-d1a6-4a25-8ce8-9483f4b5affb.png → c696843a-1e17-4c0d-a92c-eb54f9356daf.png} +0 -0
- /kotonebot/kaa/sprites/{c571e1c0-ff85-4b2e-97ed-97d33b8d92e3.png → cc959ce4-8619-4bd7-8a85-02f97cf6cc51.png} +0 -0
- /kotonebot/kaa/sprites/{65d2a5e5-48aa-4390-bb87-bfd8e044e4f6.png → ce0df3fa-5d88-4b20-9cf1-6b4abac4c110.png} +0 -0
- /kotonebot/kaa/sprites/{26580772-ff20-4dcf-8496-f939e0f2890d.png → d2a8f04f-38c1-4a67-8c57-43e0334887ef.png} +0 -0
- /kotonebot/kaa/sprites/{2f74b04f-1992-4584-8dc6-e789b081ddc3.png → db375f07-c682-4aae-880a-a2cf13d0dac0.png} +0 -0
- /kotonebot/kaa/sprites/{d60a395b-d907-416a-b091-36bfee4948b3.png → dd4c523c-1286-4f68-89f5-371464aa138c.png} +0 -0
- /kotonebot/kaa/sprites/{694d3a07-9697-4bda-984d-967779d530f7.png → e2d3a8c0-3998-4643-b084-c21b2304843c.png} +0 -0
- /kotonebot/kaa/sprites/{6156116e-56dd-4b41-a6de-ccec55dab7c8.png → e3c1f79a-0077-43db-bd00-ba04d7ca8d3b.png} +0 -0
- /kotonebot/kaa/sprites/{2d145ade-b926-4276-b872-baec4ef78308.png → e47acec2-3466-419a-acad-30618239aab9.png} +0 -0
- /kotonebot/kaa/sprites/{f72bd3d6-850d-4190-9775-938f474d263c.png → e671d7bd-cf40-425f-b941-3e1adf4624e8.png} +0 -0
- /kotonebot/kaa/sprites/{9f99b0e9-8cc0-4877-8f8a-d26257ef5386.png → e703f139-9612-4e4a-be30-db32423d57d9.png} +0 -0
- /kotonebot/kaa/sprites/{4e8f3e59-edfa-4523-939d-bc46988fc909.png → e89906b2-7354-4724-80ef-7c7fe5cd3ef5.png} +0 -0
- /kotonebot/kaa/sprites/{6aa34982-e7ab-4001-808f-8c5cf370d087.png → ea0440b1-a7a5-4db0-828a-f907b0531cd5.png} +0 -0
- /kotonebot/kaa/sprites/{7b7dad18-a838-4267-b3c7-6ab43b8361f0.png → ecdf7c70-d50e-41f4-a2ee-c4f6dd5a2617.png} +0 -0
- /kotonebot/kaa/sprites/{5d3d61e9-bf13-4668-b0c7-fed730ea2ed6.png → ed331876-f724-4a9f-a494-7823be883a76.png} +0 -0
- /kotonebot/kaa/sprites/{a7da51c2-8444-4770-a16b-b6543e40197f.png → ee7f4e24-6cbc-41ed-9327-d6843ac6a820.png} +0 -0
- /kotonebot/kaa/sprites/{f6bfbf6a-6e53-4563-9345-3f3756d6ea9a.png → f1758956-6b88-49f7-9ecf-44db49d1e6fe.png} +0 -0
- /kotonebot/kaa/sprites/{f025027f-daa0-4943-8395-5d7d44cc7f15.png → f6063ed7-f59e-4c37-93e2-026c805826ea.png} +0 -0
- /kotonebot/kaa/sprites/{69b022a8-e42f-4985-bd16-b4a530ad8a20.png → f699ed29-e7aa-4c53-8320-3df785078ec3.png} +0 -0
- /kotonebot/kaa/sprites/{eae83523-e58c-4db9-a356-4335a5da3dc8.png → f897b52f-b9d8-4d94-9d98-1ed6bf7b6c76.png} +0 -0
- /kotonebot/kaa/sprites/{f528ea0e-1e55-4e41-844f-bb1db9185ef8.png → f92f9af7-77ef-4814-a64b-ce8f340a9cf9.png} +0 -0
- /kotonebot/kaa/sprites/{c484ca57-6b19-46b5-a107-1805a7488d48.png → fccea764-f5db-45c6-ace1-140844e0d0f0.png} +0 -0
- /kotonebot/kaa/sprites/{97adee05-1586-4589-93e6-c6c3a9cdae9d.png → feb8f473-8a2e-40a5-b6e0-dffafd35edc1.png} +0 -0
- /kotonebot/kaa/{clear_logs.py → tasks/clear_logs.py} +0 -0
- {ksaa-2025.6.23.0.dist-info → ksaa-2025.7.3.0.dist-info}/WHEEL +0 -0
- {ksaa-2025.6.23.0.dist-info → ksaa-2025.7.3.0.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.6.23.0.dist-info → ksaa-2025.7.3.0.dist-info}/licenses/LICENSE +0 -0
- {ksaa-2025.6.23.0.dist-info → ksaa-2025.7.3.0.dist-info}/top_level.txt +0 -0
kotonebot/kaa/main/dmm_host.py
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
from importlib import resources
|
|
2
1
|
from typing_extensions import override
|
|
3
2
|
|
|
4
|
-
from kotonebot.client import Device
|
|
5
|
-
from kotonebot.client.registration import create_device
|
|
6
|
-
from kotonebot.client.implements.windows import WindowsImplConfig
|
|
7
|
-
from kotonebot.client.implements.remote_windows import RemoteWindowsImplConfig
|
|
3
|
+
from kotonebot.client import Device
|
|
8
4
|
from kotonebot.client.host import HostProtocol, Instance
|
|
9
|
-
from kotonebot.client.host.
|
|
5
|
+
from kotonebot.client.host.windows_common import WindowsRecipes, WindowsHostConfigs, CommonWindowsCreateDeviceMixin
|
|
10
6
|
|
|
11
7
|
|
|
12
|
-
DmmHostConfigs =
|
|
8
|
+
DmmHostConfigs = WindowsHostConfigs
|
|
9
|
+
DmmRecipes = WindowsRecipes
|
|
13
10
|
|
|
14
11
|
# TODO: 可能应该把 start_game 和 end_game 里对启停的操作移动到这里来
|
|
15
|
-
class DmmInstance(Instance[DmmHostConfigs]):
|
|
12
|
+
class DmmInstance(CommonWindowsCreateDeviceMixin, Instance[DmmHostConfigs]):
|
|
16
13
|
def __init__(self):
|
|
17
14
|
super().__init__('dmm', 'gakumas')
|
|
18
15
|
|
|
@@ -37,31 +34,11 @@ class DmmInstance(Instance[DmmHostConfigs]):
|
|
|
37
34
|
raise NotImplementedError()
|
|
38
35
|
|
|
39
36
|
@override
|
|
40
|
-
def create_device(self, impl:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
win_config = WindowsImplConfig(
|
|
44
|
-
window_title=host_config.window_title,
|
|
45
|
-
ahk_exe_path=host_config.ahk_exe_path
|
|
46
|
-
)
|
|
47
|
-
return create_device(impl, win_config)
|
|
37
|
+
def create_device(self, impl: DmmRecipes, host_config: DmmHostConfigs) -> Device:
|
|
38
|
+
"""为 DMM 实例创建 Device。"""
|
|
39
|
+
return super().create_device(impl, host_config)
|
|
48
40
|
|
|
49
|
-
|
|
50
|
-
assert isinstance(host_config, RemoteWindowsHostConfig)
|
|
51
|
-
config = RemoteWindowsImplConfig(
|
|
52
|
-
windows_impl_config=WindowsImplConfig(
|
|
53
|
-
window_title=host_config.windows_host_config.window_title,
|
|
54
|
-
ahk_exe_path=host_config.windows_host_config.ahk_exe_path
|
|
55
|
-
),
|
|
56
|
-
host=host_config.host,
|
|
57
|
-
port=host_config.port
|
|
58
|
-
)
|
|
59
|
-
return create_device(impl, config)
|
|
60
|
-
|
|
61
|
-
else:
|
|
62
|
-
raise ValueError(f'Unsupported impl for DMM: {impl}')
|
|
63
|
-
|
|
64
|
-
class DmmHost(HostProtocol):
|
|
41
|
+
class DmmHost(HostProtocol[DmmRecipes]):
|
|
65
42
|
instance = DmmInstance()
|
|
66
43
|
"""DmmInstance 单例。"""
|
|
67
44
|
|
|
@@ -77,3 +54,7 @@ class DmmHost(HostProtocol):
|
|
|
77
54
|
@staticmethod
|
|
78
55
|
def query(*, id: str) -> Instance | None:
|
|
79
56
|
raise NotImplementedError()
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def recipes() -> 'list[DmmRecipes]':
|
|
60
|
+
return ['windows', 'remote_windows']
|
kotonebot/kaa/main/gr.py
CHANGED
|
@@ -2,6 +2,10 @@ import os
|
|
|
2
2
|
import traceback
|
|
3
3
|
import zipfile
|
|
4
4
|
import logging
|
|
5
|
+
import copy
|
|
6
|
+
import sys
|
|
7
|
+
import subprocess
|
|
8
|
+
import json
|
|
5
9
|
from functools import partial
|
|
6
10
|
from itertools import chain
|
|
7
11
|
from datetime import datetime, timedelta
|
|
@@ -21,7 +25,7 @@ from kotonebot.kaa.common import (
|
|
|
21
25
|
BaseConfig, APShopItems, CapsuleToysConfig, ClubRewardConfig, PurchaseConfig, ActivityFundsConfig,
|
|
22
26
|
PresentsConfig, AssignmentConfig, ContestConfig, ProduceConfig,
|
|
23
27
|
MissionRewardConfig, DailyMoneyShopItems, ProduceAction,
|
|
24
|
-
RecommendCardDetectionMode, TraceConfig, StartGameConfig, EndGameConfig, UpgradeSupportCardConfig,
|
|
28
|
+
RecommendCardDetectionMode, TraceConfig, StartGameConfig, EndGameConfig, UpgradeSupportCardConfig, MiscConfig,
|
|
25
29
|
)
|
|
26
30
|
|
|
27
31
|
logger = logging.getLogger(__name__)
|
|
@@ -33,6 +37,7 @@ ConfigKey = Literal[
|
|
|
33
37
|
'check_emulator', 'emulator_path',
|
|
34
38
|
'adb_emulator_name', 'emulator_args',
|
|
35
39
|
'_mumu_index', '_leidian_index',
|
|
40
|
+
'mumu_background_mode',
|
|
36
41
|
|
|
37
42
|
# purchase
|
|
38
43
|
'purchase_enabled',
|
|
@@ -86,6 +91,9 @@ ConfigKey = Literal[
|
|
|
86
91
|
'presents_enabled',
|
|
87
92
|
'trace_recommend_card_detection',
|
|
88
93
|
|
|
94
|
+
# misc
|
|
95
|
+
'check_update', 'auto_install_update',
|
|
96
|
+
|
|
89
97
|
'_selected_backend_index'
|
|
90
98
|
|
|
91
99
|
]
|
|
@@ -94,17 +102,30 @@ ConfigSetFunction = Callable[[BaseConfig, Dict[ConfigKey, Any]], None]
|
|
|
94
102
|
ConfigBuilderReturnValue = Tuple[ConfigSetFunction, Dict[ConfigKey, GradioInput]]
|
|
95
103
|
|
|
96
104
|
def _save_bug_report(
|
|
105
|
+
title: str,
|
|
106
|
+
description: str,
|
|
97
107
|
version: str,
|
|
108
|
+
upload: bool,
|
|
98
109
|
path: str | None = None
|
|
99
110
|
) -> Generator[str, None, str]:
|
|
100
111
|
"""
|
|
101
112
|
保存报告
|
|
102
113
|
|
|
103
|
-
:param
|
|
114
|
+
:param title: 标题
|
|
115
|
+
:param description: 描述
|
|
116
|
+
:param version: 版本号
|
|
117
|
+
:param upload: 是否上传
|
|
118
|
+
:param path: 保存的路径。若为 `None`,则保存到 `./reports/bug-YY-MM-DD HH-MM-SS_标题.zip`。
|
|
104
119
|
:return: 保存的路径
|
|
105
120
|
"""
|
|
106
121
|
from kotonebot import device
|
|
107
122
|
from kotonebot.backend.context import ContextStackVars
|
|
123
|
+
import re
|
|
124
|
+
|
|
125
|
+
# 过滤标题中的非法文件名字符
|
|
126
|
+
def sanitize_filename(s: str) -> str:
|
|
127
|
+
# 替换 \/:*?"<>| 为空或下划线
|
|
128
|
+
return re.sub(r'[\\/:*?"<>|]', '_', s)
|
|
108
129
|
|
|
109
130
|
# 确保目录存在
|
|
110
131
|
os.makedirs('logs', exist_ok=True)
|
|
@@ -112,8 +133,18 @@ def _save_bug_report(
|
|
|
112
133
|
|
|
113
134
|
error = ""
|
|
114
135
|
if path is None:
|
|
115
|
-
|
|
136
|
+
safe_title = sanitize_filename(title)[:30] or "无标题"
|
|
137
|
+
timestamp = datetime.now().strftime("%y-%m-%d-%H-%M-%S")
|
|
138
|
+
path = f'./reports/bug_{timestamp}_{safe_title}.zip'
|
|
116
139
|
with zipfile.ZipFile(path, 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zipf:
|
|
140
|
+
# 打包描述文件
|
|
141
|
+
yield "### 打包描述文件..."
|
|
142
|
+
try:
|
|
143
|
+
description_content = f"标题:{title}\n类型:bug\n内容:\n{description}"
|
|
144
|
+
zipf.writestr('description.txt', description_content.encode('utf-8'))
|
|
145
|
+
except Exception as e:
|
|
146
|
+
error += f"保存描述文件失败:{str(e)}\n"
|
|
147
|
+
|
|
117
148
|
# 打包截图
|
|
118
149
|
yield "### 打包上次截图..."
|
|
119
150
|
try:
|
|
@@ -158,12 +189,16 @@ def _save_bug_report(
|
|
|
158
189
|
# 写出版本号
|
|
159
190
|
zipf.writestr('version.txt', version)
|
|
160
191
|
|
|
192
|
+
if not upload:
|
|
193
|
+
yield f"### 报告已保存至 {os.path.abspath(path)}"
|
|
194
|
+
return path
|
|
195
|
+
|
|
161
196
|
# 上传报告
|
|
162
|
-
from kotonebot.ui.file_host.sensio import upload
|
|
197
|
+
from kotonebot.ui.file_host.sensio import upload as upload_file
|
|
163
198
|
yield "### 上传报告..."
|
|
164
199
|
url = ''
|
|
165
200
|
try:
|
|
166
|
-
url =
|
|
201
|
+
url = upload_file(path)
|
|
167
202
|
except Exception as e:
|
|
168
203
|
yield f"### 上传报告失败:{str(e)}\n\n"
|
|
169
204
|
return ''
|
|
@@ -371,9 +406,41 @@ class KotoneBotUI:
|
|
|
371
406
|
assert key in CONFIG_KEY_VALUE, f"未知的配置项:{key}"
|
|
372
407
|
key = cast(ConfigKey, key)
|
|
373
408
|
data[key] = value
|
|
374
|
-
|
|
409
|
+
|
|
410
|
+
# 先设置options
|
|
375
411
|
for (set_func, _) in return_values:
|
|
376
412
|
set_func(options, data)
|
|
413
|
+
|
|
414
|
+
# 验证规则1:截图方法验证
|
|
415
|
+
screenshot_method = self.current_config.backend.screenshot_impl
|
|
416
|
+
backend_type = self.current_config.backend.type
|
|
417
|
+
|
|
418
|
+
valid_screenshot_methods = {
|
|
419
|
+
'mumu12': ['adb', 'adb_raw', 'uiautomator2', 'nemu_ipc'],
|
|
420
|
+
'leidian': ['adb', 'adb_raw', 'uiautomator2'],
|
|
421
|
+
'custom': ['adb', 'adb_raw', 'uiautomator2'],
|
|
422
|
+
'dmm': ['remote_windows', 'windows']
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if screenshot_method not in valid_screenshot_methods.get(backend_type, []):
|
|
426
|
+
gr.Warning(f"截图方法 '{screenshot_method}' 不适用于当前选择的模拟器类型,配置未保存。")
|
|
427
|
+
return ""
|
|
428
|
+
|
|
429
|
+
# 验证规则2:若启用培育,那么培育偶像不能为空
|
|
430
|
+
if options.produce.enabled and not options.produce.idols:
|
|
431
|
+
gr.Warning("启用培育时,培育偶像不能为空,配置未保存。")
|
|
432
|
+
return ""
|
|
433
|
+
|
|
434
|
+
# 验证规则3:若启用AP/金币购买,对应的商品不能为空
|
|
435
|
+
if options.purchase.ap_enabled and not options.purchase.ap_items:
|
|
436
|
+
gr.Warning("启用AP购买时,AP商店购买物品不能为空,配置未保存。")
|
|
437
|
+
return ""
|
|
438
|
+
|
|
439
|
+
if options.purchase.money_enabled and not options.purchase.money_items:
|
|
440
|
+
gr.Warning("启用金币购买时,金币商店购买物品不能为空,配置未保存。")
|
|
441
|
+
return ""
|
|
442
|
+
|
|
443
|
+
# 验证通过,保存配置
|
|
377
444
|
self.current_config.options = options
|
|
378
445
|
try:
|
|
379
446
|
save_config(self.config, "config.json")
|
|
@@ -393,7 +460,14 @@ class KotoneBotUI:
|
|
|
393
460
|
if self._kaa.upgrade_msg:
|
|
394
461
|
gr.Markdown('### 配置升级报告')
|
|
395
462
|
gr.Markdown(self._kaa.upgrade_msg)
|
|
396
|
-
gr.Markdown('
|
|
463
|
+
gr.Markdown('脚本报错或者卡住?前往"反馈"选项卡可以快速导出报告!')
|
|
464
|
+
|
|
465
|
+
# 添加调试模式警告
|
|
466
|
+
if self.current_config.keep_screenshots:
|
|
467
|
+
gr.Markdown(
|
|
468
|
+
'<div style="color: red; font-size: larger;">当前启用了调试功能「保留截图数据」,调试结束后正常使用时建议关闭此选项!</div>',
|
|
469
|
+
elem_classes=["debug-warning"]
|
|
470
|
+
)
|
|
397
471
|
|
|
398
472
|
task_status = gr.Dataframe(
|
|
399
473
|
headers=["任务", "状态"],
|
|
@@ -555,7 +629,9 @@ class KotoneBotUI:
|
|
|
555
629
|
# choices = ['windows', 'remote_windows']
|
|
556
630
|
# else: # Mumu, Leidian, Custom
|
|
557
631
|
# choices = ['adb', 'adb_raw', 'uiautomator2']
|
|
558
|
-
|
|
632
|
+
# else:
|
|
633
|
+
# raise ValueError(f'Unsupported backend type: {type_in_config}')
|
|
634
|
+
choices = ['adb', 'adb_raw', 'uiautomator2', 'windows', 'remote_windows', 'nemu_ipc']
|
|
559
635
|
if impl_value not in choices:
|
|
560
636
|
new_value = choices[0]
|
|
561
637
|
else:
|
|
@@ -576,13 +652,21 @@ class KotoneBotUI:
|
|
|
576
652
|
choices=[(i.name, i.id) for i in instances],
|
|
577
653
|
interactive=True
|
|
578
654
|
)
|
|
655
|
+
mumu_background_mode = gr.Checkbox(
|
|
656
|
+
label="MuMu12 模拟器后台保活模式",
|
|
657
|
+
value=self.current_config.backend.mumu_background_mode,
|
|
658
|
+
info=BackendConfig.model_fields['mumu_background_mode'].description,
|
|
659
|
+
interactive=True
|
|
660
|
+
)
|
|
579
661
|
except: # noqa: E722
|
|
580
662
|
logger.exception('Failed to list installed MuMu12')
|
|
581
663
|
gr.Markdown('获取 MuMu12 模拟器列表失败,请升级模拟器到最新版本。若问题依旧,前往 QQ 群、QQ 频道或 Github 反馈 bug。')
|
|
582
664
|
mumu_instance = gr.Dropdown(visible=False)
|
|
665
|
+
mumu_background_mode = gr.Checkbox(visible=False)
|
|
583
666
|
else:
|
|
584
667
|
# 为了让 return 收集组件时不报错
|
|
585
668
|
mumu_instance = gr.Dropdown(visible=False)
|
|
669
|
+
mumu_background_mode = gr.Checkbox(visible=False)
|
|
586
670
|
|
|
587
671
|
with gr.Tab("雷电", interactive=has_leidian, id="leidian") as tab_leidian:
|
|
588
672
|
gr.Markdown("已选中雷电模拟器")
|
|
@@ -661,7 +745,7 @@ class KotoneBotUI:
|
|
|
661
745
|
# choices = ['adb', 'adb_raw', 'uiautomator2']
|
|
662
746
|
# else:
|
|
663
747
|
# raise ValueError(f'Unsupported backend type: {type_in_config}')
|
|
664
|
-
choices = ['adb', 'adb_raw', 'uiautomator2', 'windows', 'remote_windows']
|
|
748
|
+
choices = ['adb', 'adb_raw', 'uiautomator2', 'windows', 'remote_windows', 'nemu_ipc']
|
|
665
749
|
screenshot_impl = gr.Dropdown(
|
|
666
750
|
choices=choices,
|
|
667
751
|
value=self.current_config.backend.screenshot_impl,
|
|
@@ -711,6 +795,7 @@ class KotoneBotUI:
|
|
|
711
795
|
if current_tab == 0: # Mumu
|
|
712
796
|
self.current_config.backend.type = 'mumu12'
|
|
713
797
|
self.current_config.backend.instance_id = data['_mumu_index']
|
|
798
|
+
self.current_config.backend.mumu_background_mode = data['mumu_background_mode']
|
|
714
799
|
elif current_tab == 1: # Leidian
|
|
715
800
|
self.current_config.backend.type = 'leidian'
|
|
716
801
|
self.current_config.backend.instance_id = data['_leidian_index']
|
|
@@ -741,7 +826,8 @@ class KotoneBotUI:
|
|
|
741
826
|
'adb_emulator_name': adb_emulator_name,
|
|
742
827
|
'emulator_args': emulator_args,
|
|
743
828
|
'_mumu_index': mumu_instance,
|
|
744
|
-
'_leidian_index': leidian_instance
|
|
829
|
+
'_leidian_index': leidian_instance,
|
|
830
|
+
'mumu_background_mode': mumu_background_mode
|
|
745
831
|
}
|
|
746
832
|
|
|
747
833
|
def _create_purchase_settings(self) -> ConfigBuilderReturnValue:
|
|
@@ -1389,6 +1475,35 @@ class KotoneBotUI:
|
|
|
1389
1475
|
'trace_recommend_card_detection': trace_recommend_card_detection
|
|
1390
1476
|
}
|
|
1391
1477
|
|
|
1478
|
+
def _create_misc_settings(self) -> ConfigBuilderReturnValue:
|
|
1479
|
+
with gr.Column():
|
|
1480
|
+
gr.Markdown("### 杂项设置")
|
|
1481
|
+
check_update = gr.Dropdown(
|
|
1482
|
+
choices=[
|
|
1483
|
+
("启动时检查更新", "startup"),
|
|
1484
|
+
("从不检查更新", "never")
|
|
1485
|
+
],
|
|
1486
|
+
value=self.current_config.options.misc.check_update,
|
|
1487
|
+
label="检查更新时机",
|
|
1488
|
+
info=MiscConfig.model_fields['check_update'].description,
|
|
1489
|
+
interactive=True
|
|
1490
|
+
)
|
|
1491
|
+
auto_install_update = gr.Checkbox(
|
|
1492
|
+
label="自动安装更新",
|
|
1493
|
+
value=self.current_config.options.misc.auto_install_update,
|
|
1494
|
+
info=MiscConfig.model_fields['auto_install_update'].description,
|
|
1495
|
+
interactive=True
|
|
1496
|
+
)
|
|
1497
|
+
|
|
1498
|
+
def set_config(config: BaseConfig, data: dict[ConfigKey, Any]) -> None:
|
|
1499
|
+
config.misc.check_update = data['check_update']
|
|
1500
|
+
config.misc.auto_install_update = data['auto_install_update']
|
|
1501
|
+
|
|
1502
|
+
return set_config, {
|
|
1503
|
+
'check_update': check_update,
|
|
1504
|
+
'auto_install_update': auto_install_update
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1392
1507
|
def _create_settings_tab(self) -> None:
|
|
1393
1508
|
with gr.Tab("设置"):
|
|
1394
1509
|
gr.Markdown("## 设置")
|
|
@@ -1426,6 +1541,9 @@ class KotoneBotUI:
|
|
|
1426
1541
|
# 跟踪设置
|
|
1427
1542
|
trace_settings = self._create_trace_settings()
|
|
1428
1543
|
|
|
1544
|
+
# 杂项设置
|
|
1545
|
+
misc_settings = self._create_misc_settings()
|
|
1546
|
+
|
|
1429
1547
|
# 启动游戏设置
|
|
1430
1548
|
start_game_settings = self._create_start_game_settings()
|
|
1431
1549
|
|
|
@@ -1449,7 +1567,8 @@ class KotoneBotUI:
|
|
|
1449
1567
|
capsule_toys_settings,
|
|
1450
1568
|
start_game_settings,
|
|
1451
1569
|
end_game_settings,
|
|
1452
|
-
trace_settings
|
|
1570
|
+
trace_settings,
|
|
1571
|
+
misc_settings
|
|
1453
1572
|
] # list of (set_func, { 'key': component, ... })
|
|
1454
1573
|
all_components = [list(ret[1].values()) for ret in all_return_values] # [[c1, c2], [c3], ...]
|
|
1455
1574
|
all_components = list(chain(*all_components)) # [c1, c2, c3, ...]
|
|
@@ -1460,39 +1579,260 @@ class KotoneBotUI:
|
|
|
1460
1579
|
)
|
|
1461
1580
|
|
|
1462
1581
|
def _create_log_tab(self) -> None:
|
|
1463
|
-
with gr.Tab("
|
|
1464
|
-
gr.Markdown("##
|
|
1465
|
-
|
|
1582
|
+
with gr.Tab("反馈"):
|
|
1583
|
+
gr.Markdown("## 反馈")
|
|
1584
|
+
gr.Markdown('脚本报错或者卡住?在这里填写信息可以快速反馈!')
|
|
1466
1585
|
with gr.Column():
|
|
1586
|
+
report_title = gr.Textbox(label="标题", placeholder="用一句话概括问题")
|
|
1587
|
+
report_type = gr.Dropdown(label="反馈类型", choices=["bug"], value="bug", interactive=False)
|
|
1588
|
+
report_description = gr.Textbox(label="描述", lines=5, placeholder="详细描述问题。例如:什么时候出错、是否每次都出错、出错时的步骤是什么")
|
|
1467
1589
|
with gr.Row():
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
save_report_btn = gr.Button("一键导出报告")
|
|
1590
|
+
upload_report_btn = gr.Button("上传")
|
|
1591
|
+
save_local_report_btn = gr.Button("保存至本地")
|
|
1592
|
+
|
|
1472
1593
|
result_text = gr.Markdown("等待操作\n\n\n")
|
|
1473
1594
|
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
)
|
|
1478
|
-
|
|
1479
|
-
|
|
1595
|
+
def on_upload_click(title: str, description: str):
|
|
1596
|
+
yield from _save_bug_report(title, description, self._kaa.version, upload=True)
|
|
1597
|
+
|
|
1598
|
+
def on_save_local_click(title: str, description: str):
|
|
1599
|
+
yield from _save_bug_report(title, description, self._kaa.version, upload=False)
|
|
1600
|
+
|
|
1601
|
+
upload_report_btn.click(
|
|
1602
|
+
fn=on_upload_click,
|
|
1603
|
+
inputs=[report_title, report_description],
|
|
1480
1604
|
outputs=[result_text]
|
|
1481
1605
|
)
|
|
1482
|
-
|
|
1483
|
-
fn=
|
|
1606
|
+
save_local_report_btn.click(
|
|
1607
|
+
fn=on_save_local_click,
|
|
1608
|
+
inputs=[report_title, report_description],
|
|
1484
1609
|
outputs=[result_text]
|
|
1485
1610
|
)
|
|
1486
1611
|
|
|
1487
1612
|
def _create_whats_new_tab(self) -> None:
|
|
1488
|
-
"""
|
|
1489
|
-
with gr.Tab("
|
|
1490
|
-
|
|
1491
|
-
|
|
1613
|
+
"""创建更新标签页"""
|
|
1614
|
+
with gr.Tab("更新"):
|
|
1615
|
+
gr.Markdown("## 版本管理")
|
|
1616
|
+
|
|
1617
|
+
# 更新日志
|
|
1618
|
+
with gr.Accordion("更新日志", open=False):
|
|
1619
|
+
from kotonebot.kaa.metadata import WHATS_NEW
|
|
1620
|
+
gr.Markdown(WHATS_NEW)
|
|
1621
|
+
|
|
1622
|
+
# 载入信息按钮
|
|
1623
|
+
load_info_btn = gr.Button("载入信息", variant="primary")
|
|
1624
|
+
|
|
1625
|
+
# 状态信息
|
|
1626
|
+
status_text = gr.Markdown("")
|
|
1627
|
+
|
|
1628
|
+
# 版本选择下拉框(用于安装)
|
|
1629
|
+
version_dropdown = gr.Dropdown(
|
|
1630
|
+
label="选择要安装的版本",
|
|
1631
|
+
choices=[],
|
|
1632
|
+
value=None,
|
|
1633
|
+
visible=False,
|
|
1634
|
+
interactive=True
|
|
1635
|
+
)
|
|
1636
|
+
|
|
1637
|
+
# 安装选定版本按钮
|
|
1638
|
+
install_selected_btn = gr.Button("安装选定版本", visible=False)
|
|
1639
|
+
|
|
1640
|
+
def list_all_versions():
|
|
1641
|
+
"""列出所有可用版本"""
|
|
1642
|
+
import logging
|
|
1643
|
+
logger = logging.getLogger(__name__)
|
|
1644
|
+
|
|
1645
|
+
try:
|
|
1646
|
+
# 构建命令,使用清华镜像源
|
|
1647
|
+
cmd = [
|
|
1648
|
+
sys.executable, "-m", "pip", "index", "versions", "ksaa", "--json",
|
|
1649
|
+
"--index-url", "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple",
|
|
1650
|
+
"--trusted-host", "mirrors.tuna.tsinghua.edu.cn"
|
|
1651
|
+
]
|
|
1652
|
+
logger.info(f"执行命令: {' '.join(cmd)}")
|
|
1653
|
+
|
|
1654
|
+
# 使用 pip index versions --json 来获取版本信息
|
|
1655
|
+
result = subprocess.run(
|
|
1656
|
+
cmd,
|
|
1657
|
+
capture_output=True,
|
|
1658
|
+
text=True,
|
|
1659
|
+
timeout=30
|
|
1660
|
+
)
|
|
1661
|
+
|
|
1662
|
+
logger.info(f"命令返回码: {result.returncode}")
|
|
1663
|
+
if result.stdout:
|
|
1664
|
+
logger.info(f"命令输出: {result.stdout[:500]}...") # 只记录前500字符
|
|
1665
|
+
if result.stderr:
|
|
1666
|
+
logger.warning(f"命令错误输出: {result.stderr}")
|
|
1667
|
+
|
|
1668
|
+
if result.returncode != 0:
|
|
1669
|
+
error_msg = f"获取版本列表失败: {result.stderr}"
|
|
1670
|
+
logger.error(error_msg)
|
|
1671
|
+
return (
|
|
1672
|
+
error_msg,
|
|
1673
|
+
gr.Button(value="载入信息", interactive=True),
|
|
1674
|
+
gr.Dropdown(visible=False),
|
|
1675
|
+
gr.Button(visible=False)
|
|
1676
|
+
)
|
|
1677
|
+
|
|
1678
|
+
# 解析 JSON 输出
|
|
1679
|
+
try:
|
|
1680
|
+
data = json.loads(result.stdout)
|
|
1681
|
+
versions = data.get("versions", [])
|
|
1682
|
+
latest_version = data.get("latest", "")
|
|
1683
|
+
installed_version = data.get("installed_version", "")
|
|
1684
|
+
|
|
1685
|
+
logger.info(f"解析到 {len(versions)} 个版本")
|
|
1686
|
+
logger.info(f"最新版本: {latest_version}")
|
|
1687
|
+
logger.info(f"已安装版本: {installed_version}")
|
|
1688
|
+
|
|
1689
|
+
except json.JSONDecodeError as e:
|
|
1690
|
+
error_msg = f"解析版本信息失败: {str(e)}"
|
|
1691
|
+
logger.error(error_msg)
|
|
1692
|
+
return (
|
|
1693
|
+
error_msg,
|
|
1694
|
+
gr.Button(value="载入信息", interactive=True),
|
|
1695
|
+
gr.Dropdown(visible=False),
|
|
1696
|
+
gr.Button(visible=False)
|
|
1697
|
+
)
|
|
1698
|
+
|
|
1699
|
+
if not versions:
|
|
1700
|
+
error_msg = "未找到可用版本"
|
|
1701
|
+
logger.warning(error_msg)
|
|
1702
|
+
return (
|
|
1703
|
+
error_msg,
|
|
1704
|
+
gr.Button(value="载入信息", interactive=True),
|
|
1705
|
+
gr.Dropdown(visible=False),
|
|
1706
|
+
gr.Button(visible=False)
|
|
1707
|
+
)
|
|
1708
|
+
|
|
1709
|
+
# 构建状态信息
|
|
1710
|
+
status_info = []
|
|
1711
|
+
if installed_version:
|
|
1712
|
+
status_info.append(f"**当前安装版本:** {installed_version}")
|
|
1713
|
+
if latest_version:
|
|
1714
|
+
status_info.append(f"**最新版本:** {latest_version}")
|
|
1715
|
+
status_info.append(f"**找到 {len(versions)} 个可用版本**")
|
|
1716
|
+
|
|
1717
|
+
status_message = "\n\n".join(status_info)
|
|
1718
|
+
logger.info(f"版本信息载入完成: {status_message}")
|
|
1719
|
+
|
|
1720
|
+
# 返回更新后的组件
|
|
1721
|
+
return (
|
|
1722
|
+
status_message,
|
|
1723
|
+
gr.Button(value="载入信息", interactive=True),
|
|
1724
|
+
gr.Dropdown(choices=versions, value=versions[0] if versions else None, visible=True, label="选择要安装的版本"),
|
|
1725
|
+
gr.Button(visible=True, value="安装选定版本")
|
|
1726
|
+
)
|
|
1727
|
+
|
|
1728
|
+
except subprocess.TimeoutExpired:
|
|
1729
|
+
error_msg = "获取版本列表超时"
|
|
1730
|
+
logger.error(error_msg)
|
|
1731
|
+
return (
|
|
1732
|
+
error_msg,
|
|
1733
|
+
gr.Button(value="载入信息", interactive=True),
|
|
1734
|
+
gr.Dropdown(visible=False),
|
|
1735
|
+
gr.Button(visible=False)
|
|
1736
|
+
)
|
|
1737
|
+
except Exception as e:
|
|
1738
|
+
error_msg = f"获取版本列表失败: {str(e)}"
|
|
1739
|
+
logger.error(error_msg)
|
|
1740
|
+
return (
|
|
1741
|
+
error_msg,
|
|
1742
|
+
gr.Button(value="载入信息", interactive=True),
|
|
1743
|
+
gr.Dropdown(visible=False),
|
|
1744
|
+
gr.Button(visible=False)
|
|
1745
|
+
)
|
|
1746
|
+
|
|
1747
|
+
def install_selected_version(selected_version: str):
|
|
1748
|
+
"""安装选定的版本"""
|
|
1749
|
+
import logging
|
|
1750
|
+
import threading
|
|
1751
|
+
import time
|
|
1752
|
+
logger = logging.getLogger(__name__)
|
|
1753
|
+
|
|
1754
|
+
if not selected_version:
|
|
1755
|
+
error_msg = "请先选择一个版本"
|
|
1756
|
+
logger.warning(error_msg)
|
|
1757
|
+
return error_msg
|
|
1758
|
+
|
|
1759
|
+
def install_and_exit():
|
|
1760
|
+
"""在后台线程中执行安装并退出程序"""
|
|
1761
|
+
try:
|
|
1762
|
+
# 等待一小段时间确保UI响应已返回
|
|
1763
|
+
time.sleep(1)
|
|
1764
|
+
|
|
1765
|
+
# 构建启动器命令
|
|
1766
|
+
bootstrap_path = os.path.join(os.getcwd(), "bootstrap.pyz")
|
|
1767
|
+
cmd = [sys.executable, bootstrap_path, f"--install-version={selected_version}"]
|
|
1768
|
+
logger.info(f"开始通过启动器安装版本 {selected_version}")
|
|
1769
|
+
logger.info(f"执行命令: {' '.join(cmd)}")
|
|
1770
|
+
|
|
1771
|
+
# 启动启动器进程(不等待完成)
|
|
1772
|
+
subprocess.Popen(
|
|
1773
|
+
cmd,
|
|
1774
|
+
cwd=os.getcwd(),
|
|
1775
|
+
creationflags=subprocess.CREATE_NEW_CONSOLE if os.name == 'nt' else 0
|
|
1776
|
+
)
|
|
1777
|
+
|
|
1778
|
+
# 等待一小段时间确保启动器启动
|
|
1779
|
+
time.sleep(2)
|
|
1780
|
+
|
|
1781
|
+
# 退出当前程序
|
|
1782
|
+
logger.info("安装即将开始,正在退出当前程序...")
|
|
1783
|
+
os._exit(0)
|
|
1784
|
+
|
|
1785
|
+
except Exception as e:
|
|
1786
|
+
raise
|
|
1787
|
+
|
|
1788
|
+
try:
|
|
1789
|
+
# 在后台线程中执行安装和退出
|
|
1790
|
+
install_thread = threading.Thread(target=install_and_exit, daemon=True)
|
|
1791
|
+
install_thread.start()
|
|
1792
|
+
|
|
1793
|
+
return f"正在启动器中安装版本 {selected_version},程序将自动重启..."
|
|
1794
|
+
|
|
1795
|
+
except Exception as e:
|
|
1796
|
+
error_msg = f"启动安装进程失败: {str(e)}"
|
|
1797
|
+
logger.error(error_msg)
|
|
1798
|
+
return error_msg
|
|
1799
|
+
|
|
1800
|
+
def load_info_with_button_state():
|
|
1801
|
+
"""载入信息并管理按钮状态"""
|
|
1802
|
+
import logging
|
|
1803
|
+
logger = logging.getLogger(__name__)
|
|
1804
|
+
|
|
1805
|
+
logger.info("开始载入版本信息")
|
|
1806
|
+
|
|
1807
|
+
# 先禁用按钮
|
|
1808
|
+
yield (
|
|
1809
|
+
"正在载入版本信息...",
|
|
1810
|
+
gr.Button(value="载入中...", interactive=False),
|
|
1811
|
+
gr.Dropdown(visible=False),
|
|
1812
|
+
gr.Button(visible=False)
|
|
1813
|
+
)
|
|
1814
|
+
|
|
1815
|
+
# 执行载入操作
|
|
1816
|
+
result = list_all_versions()
|
|
1817
|
+
logger.info("版本信息载入操作完成")
|
|
1818
|
+
yield result
|
|
1819
|
+
|
|
1820
|
+
# 绑定事件
|
|
1821
|
+
load_info_btn.click(
|
|
1822
|
+
fn=load_info_with_button_state,
|
|
1823
|
+
outputs=[status_text, load_info_btn, version_dropdown, install_selected_btn]
|
|
1824
|
+
)
|
|
1825
|
+
|
|
1826
|
+
install_selected_btn.click(
|
|
1827
|
+
fn=install_selected_version,
|
|
1828
|
+
inputs=[version_dropdown],
|
|
1829
|
+
outputs=[status_text]
|
|
1830
|
+
)
|
|
1492
1831
|
|
|
1493
1832
|
def _create_screen_tab(self) -> None:
|
|
1494
1833
|
with gr.Tab("画面"):
|
|
1495
1834
|
gr.Markdown("## 当前设备画面")
|
|
1835
|
+
refresh_btn = gr.Button("刷新画面", variant="primary")
|
|
1496
1836
|
WIDTH = 720 // 3
|
|
1497
1837
|
HEIGHT = 1280 // 3
|
|
1498
1838
|
last_update_text = gr.Markdown("上次更新时间:无数据")
|
|
@@ -1501,14 +1841,14 @@ class KotoneBotUI:
|
|
|
1501
1841
|
def update_screenshot():
|
|
1502
1842
|
ctx = ContextStackVars.current()
|
|
1503
1843
|
if ctx is None:
|
|
1504
|
-
return [None,
|
|
1844
|
+
return [None, "上次更新时间:无上下文数据"]
|
|
1505
1845
|
screenshot = ctx._screenshot
|
|
1506
1846
|
if screenshot is None:
|
|
1507
|
-
return [None,
|
|
1847
|
+
return [None, "上次更新时间:无截图数据"]
|
|
1508
1848
|
screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2RGB)
|
|
1509
1849
|
return screenshot, f"上次更新时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
|
|
1510
1850
|
|
|
1511
|
-
|
|
1851
|
+
refresh_btn.click(
|
|
1512
1852
|
fn=update_screenshot,
|
|
1513
1853
|
outputs=[screenshot_display, last_update_text]
|
|
1514
1854
|
)
|