ksaa 2025.6.8.0__py3-none-any.whl → 2025.6.23.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 +31 -25
- kotonebot/backend/debug/server.py +0 -2
- kotonebot/backend/dispatch.py +1 -17
- kotonebot/backend/loop.py +277 -0
- kotonebot/client/__init__.py +4 -1
- kotonebot/client/device.py +23 -21
- kotonebot/client/host/__init__.py +2 -1
- kotonebot/client/host/custom.py +26 -3
- kotonebot/client/host/leidian_host.py +22 -11
- kotonebot/client/host/mumu12_host.py +25 -3
- kotonebot/client/host/protocol.py +40 -18
- kotonebot/client/implements/__init__.py +6 -0
- kotonebot/client/implements/adb.py +67 -7
- kotonebot/client/implements/adb_raw.py +12 -5
- kotonebot/client/implements/remote_windows.py +20 -18
- kotonebot/client/implements/uiautomator2.py +8 -0
- kotonebot/client/implements/windows.py +38 -15
- kotonebot/client/protocol.py +13 -0
- kotonebot/client/registration.py +89 -0
- kotonebot/config/base_config.py +5 -1
- kotonebot/debug_entry.py +7 -2
- kotonebot/kaa/clear_logs.py +0 -3
- kotonebot/kaa/game_ui/common.py +4 -7
- kotonebot/kaa/game_ui/dialog.py +24 -4
- kotonebot/kaa/game_ui/idols_overview.py +28 -12
- kotonebot/kaa/game_ui/primary_button.py +55 -0
- kotonebot/kaa/game_ui/scrollable.py +0 -5
- kotonebot/kaa/main/cli.py +9 -4
- kotonebot/kaa/main/dmm_host.py +33 -7
- kotonebot/kaa/main/kaa.py +113 -41
- kotonebot/kaa/metadata.py +15 -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-kllj-3-012_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-kllj-3-012_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-ssmk-3-012_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-ssmk-3-012_1.png +0 -0
- kotonebot/kaa/sprites/24e99232-9434-457f-a9a0-69dd7ecf675f.png +0 -0
- kotonebot/kaa/sprites/2ededcf5-1d80-4e2a-9c83-2a31998331ce.png +0 -0
- kotonebot/kaa/sprites/3b473fe6-e147-477f-b088-9b8fb042a4f6.png +0 -0
- kotonebot/kaa/sprites/55f7db71-0a18-4b3d-b847-57959b8d2e32.png +0 -0
- kotonebot/kaa/sprites/6cd80be8-c9b3-4ba5-bf17-3ffc9b000743.png +0 -0
- kotonebot/kaa/sprites/74ec3510-583d-4a76-ac69-38480fbf1387.png +0 -0
- kotonebot/kaa/sprites/a0bd6a5f-784d-4f0a-9d66-10f4b80c8d3e.png +0 -0
- kotonebot/kaa/sprites/d3424d31-0502-4623-996e-f0194e5085ce.png +0 -0
- kotonebot/kaa/sprites/e6b45405-cd9f-4c6e-a9f1-6ec953747c65.png +0 -0
- kotonebot/kaa/sprites/f5c16d2f-ebc5-4617-9b96-971696af7c52.png +0 -0
- kotonebot/kaa/tasks/R.py +157 -135
- kotonebot/kaa/tasks/produce/in_purodyuusu.py +0 -4
- kotonebot/kaa/tasks/produce/non_lesson_actions.py +0 -3
- kotonebot/kaa/tasks/produce/produce.py +119 -70
- kotonebot/kaa/tasks/start_game.py +7 -6
- kotonebot/kaa/util/paths.py +6 -1
- kotonebot/tools/mirror.py +23 -13
- kotonebot/util.py +32 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.23.0.dist-info}/METADATA +1 -1
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.23.0.dist-info}/RECORD +194 -179
- kotonebot/client/factory.py +0 -92
- kotonebot/kaa/sprites/38b8f119-8de1-49bf-8a5f-a44371de4569.png +0 -0
- /kotonebot/kaa/sprites/{321b54c8-c69b-4437-931d-655882dabeed.png → 0235ae3d-1741-4a81-8053-f60bc395ee85.png} +0 -0
- /kotonebot/kaa/sprites/{4d6c198a-0e34-4c80-86d1-7789b2082d64.png → 038c69e6-7cb0-4c8d-99da-b537e48a86b7.png} +0 -0
- /kotonebot/kaa/sprites/{4bd66b38-78d3-4a27-816b-d315039a8bb6.png → 080b3cf5-ce35-4382-9bfa-d6a12efb09b3.png} +0 -0
- /kotonebot/kaa/sprites/{ecd44a4a-e1ca-4a86-ae0d-2306a672613f.png → 09fb5e41-6caa-4246-a415-8317b12d8d81.png} +0 -0
- /kotonebot/kaa/sprites/{4f58031c-36b9-4baf-bccf-11c05d83bd19.png → 0a6c6b1e-7a80-428e-a483-1858bfb8ac59.png} +0 -0
- /kotonebot/kaa/sprites/{e41bb5df-164d-4760-9db6-d5d5d763bb5f.png → 0ad2f603-a3ad-4a92-a398-c411145fd8e9.png} +0 -0
- /kotonebot/kaa/sprites/{c1b1125f-542b-4e63-9c86-5d2e35a89a10.png → 0d4b669e-5e43-4458-b65a-5565797335ae.png} +0 -0
- /kotonebot/kaa/sprites/{74521b6f-de5e-4ba8-a3c9-c6ba01070498.png → 0fbcb3f6-9ca0-43c7-975b-e7c15c26c897.png} +0 -0
- /kotonebot/kaa/sprites/{7b3c6860-fbbe-48aa-aadf-8062fa88f1fe.png → 15465879-eb84-4ca6-ae0f-d3c5ac71e723.png} +0 -0
- /kotonebot/kaa/sprites/{309105d4-073a-47c9-8c5c-d593aa497723.png → 1639278d-67e0-4452-a2b5-ec4cf4011f42.png} +0 -0
- /kotonebot/kaa/sprites/{157dd58d-e319-4e0c-a37a-638e1a31c60b.png → 17414e9e-b046-49e0-9596-cad1f4673a9e.png} +0 -0
- /kotonebot/kaa/sprites/{05ff5efd-0f76-47ce-bc89-237266bc17c0.png → 17a8b0a5-5b71-4612-8a68-16c51f03c71b.png} +0 -0
- /kotonebot/kaa/sprites/{54bb5fcf-be61-4af8-bb19-a3c5113cf9e1.png → 1aaceb21-dc5c-4a58-96d3-d2c66b2fb357.png} +0 -0
- /kotonebot/kaa/sprites/{1f8f8c46-43ec-4449-be9f-2e96da11da1e.png → 1aae0ab3-f619-47e0-8bf6-3d3791f7d445.png} +0 -0
- /kotonebot/kaa/sprites/{b1e88fda-434a-4d06-8891-883a7beafa12.png → 1b6be6dd-2711-441a-9fa6-3281a6ad10c7.png} +0 -0
- /kotonebot/kaa/sprites/{ef39804e-8d2d-40f6-8d13-bd2877d1353a.png → 1bb00a74-2fdc-4973-84ae-dc1edee15f81.png} +0 -0
- /kotonebot/kaa/sprites/{804a4b05-1ca3-4915-bf23-a66ccdc34404.png → 1ccdcacf-4f7d-442c-8e2f-09aa7fe14e56.png} +0 -0
- /kotonebot/kaa/sprites/{6a7d061e-682b-42c1-97d5-121c52921e8b.png → 1d5f7454-672d-4e87-a368-ec4bb32f9b1f.png} +0 -0
- /kotonebot/kaa/sprites/{624555b9-31e3-46a3-8078-55619eaa40b9.png → 1f2981d8-5eb6-4332-aa9b-17f4db2d4163.png} +0 -0
- /kotonebot/kaa/sprites/{ff77d221-8444-4d0f-8c93-0223a97e2a98.png → 25910d8e-d57f-409f-b0be-ee68c5af4920.png} +0 -0
- /kotonebot/kaa/sprites/{fbd816df-7ae6-40a4-b4d4-5708f5ba4a7c.png → 264e056f-3bcc-4b16-94d4-f767c78ab6f5.png} +0 -0
- /kotonebot/kaa/sprites/{0bbfb5b0-f0f7-4ad9-86f7-a2adb01a6371.png → 26580772-ff20-4dcf-8496-f939e0f2890d.png} +0 -0
- /kotonebot/kaa/sprites/{0a430873-8c12-4ce2-a5de-ab9790c08344.png → 29cb7b0f-5684-4516-8fae-4439f7f28e08.png} +0 -0
- /kotonebot/kaa/sprites/{52620946-b92c-42c7-9fcc-0ff13388fd0d.png → 2d145ade-b926-4276-b872-baec4ef78308.png} +0 -0
- /kotonebot/kaa/sprites/{7e8164f6-a9e4-4600-b776-77b35a490933.png → 2dd34393-ee6f-4b19-8a9c-76556d1bd7d7.png} +0 -0
- /kotonebot/kaa/sprites/{550fc45d-22c0-4a7c-a324-2c4ff107ab39.png → 2e00ac54-d23a-4d51-82f2-829c012552a6.png} +0 -0
- /kotonebot/kaa/sprites/{d58d9987-b1ca-4669-a9a6-9a0fd1847fa6.png → 2f74b04f-1992-4584-8dc6-e789b081ddc3.png} +0 -0
- /kotonebot/kaa/sprites/{668002b6-805b-467b-a703-203fb75444f4.png → 302fde7d-de85-44c7-ba57-fe4b5f6db5fa.png} +0 -0
- /kotonebot/kaa/sprites/{80fb515c-4323-422d-a24c-80a3bf702f1d.png → 3cc9685d-6347-4114-9d39-7683c2dc9df6.png} +0 -0
- /kotonebot/kaa/sprites/{869b1771-b2ce-4872-ab75-2157c47c5b13.png → 42d8b5dc-ef27-4411-b8b5-d981e562990b.png} +0 -0
- /kotonebot/kaa/sprites/{ba955365-1328-4018-83a2-bfe818f8f172.png → 448ea37d-a10d-4102-ac9f-a58403ee8914.png} +0 -0
- /kotonebot/kaa/sprites/{111a03e6-e401-4ad5-b5dc-d5124e8f1ab0.png → 4a310bdd-0a7d-4669-9d57-6ae69bc8f022.png} +0 -0
- /kotonebot/kaa/sprites/{05bfd235-2077-479a-8c43-11fb49316000.png → 4b20b364-5f5f-4b34-960e-b0cfd08b1662.png} +0 -0
- /kotonebot/kaa/sprites/{cd4cbd7b-df80-45bb-a053-cc333a806934.png → 4e8f3e59-edfa-4523-939d-bc46988fc909.png} +0 -0
- /kotonebot/kaa/sprites/{67a81c23-4ce4-45e3-bfa8-1136fb14b831.png → 4eaa5db2-d624-4df4-b2e4-01f72755f1a4.png} +0 -0
- /kotonebot/kaa/sprites/{705d9ecf-faf8-40f4-b701-637cec822c1e.png → 5152e3fa-079c-4592-8df7-656101694df8.png} +0 -0
- /kotonebot/kaa/sprites/{4e21f02d-d5e1-49eb-946a-8edc74d0f1f7.png → 52f7c8b1-af88-43c5-a999-de4da3caa03a.png} +0 -0
- /kotonebot/kaa/sprites/{f74fc514-61f1-4068-bdf4-754fcaf8ac89.png → 534d1310-3503-46d3-8ecd-426d9bcf183e.png} +0 -0
- /kotonebot/kaa/sprites/{9bb1a400-935a-4c5e-838b-fca502c49aba.png → 5868ebfb-5e61-4ac6-b270-acb1e89b738f.png} +0 -0
- /kotonebot/kaa/sprites/{82a5e224-a161-43d4-8e15-2946480336dd.png → 58a5f51d-d1a3-480b-8dde-ecead34d9f02.png} +0 -0
- /kotonebot/kaa/sprites/{c1ad996a-925e-41b5-b26c-d48b8ded21d2.png → 5d3d61e9-bf13-4668-b0c7-fed730ea2ed6.png} +0 -0
- /kotonebot/kaa/sprites/{ad784a29-f0e2-4037-976b-45143db8441c.png → 5dd0cc39-4102-4f0f-8ad3-342bbf825977.png} +0 -0
- /kotonebot/kaa/sprites/{4a235eaa-46f1-4f71-b54d-ada0ade44572.png → 5ee8e9a8-b133-4ab7-a52c-e7e4e1d1ce7b.png} +0 -0
- /kotonebot/kaa/sprites/{09433024-3dfe-4fcb-9d67-cf442b58f31b.png → 60be53a6-98e9-4fc6-9285-85506dc0e335.png} +0 -0
- /kotonebot/kaa/sprites/{90a9c819-ee6b-4b3e-a0e4-ce484c6e413d.png → 6114d53e-dd69-4cee-82a7-7e43b338ff8d.png} +0 -0
- /kotonebot/kaa/sprites/{4c72f39e-1182-4479-867f-8207744ee4fd.png → 6156116e-56dd-4b41-a6de-ccec55dab7c8.png} +0 -0
- /kotonebot/kaa/sprites/{559df9b9-e74d-45af-a300-77d3424e69c6.png → 65d2a5e5-48aa-4390-bb87-bfd8e044e4f6.png} +0 -0
- /kotonebot/kaa/sprites/{c0fc7de5-b842-4c70-9cf2-89d833bfe7a6.png → 66172bc0-3869-4a48-a26d-0dc3fa404ab8.png} +0 -0
- /kotonebot/kaa/sprites/{fdfecda8-2fe0-487e-b5fe-6358274bb9ff.png → 66678caa-7b25-4ff7-8c3a-017f67279349.png} +0 -0
- /kotonebot/kaa/sprites/{f8cbb089-a63e-4e40-9238-26d14da2c459.png → 68838f92-5916-424e-a37e-47e0b3834eb3.png} +0 -0
- /kotonebot/kaa/sprites/{fb927b92-7a82-4869-8c61-581d49cd7201.png → 694d3a07-9697-4bda-984d-967779d530f7.png} +0 -0
- /kotonebot/kaa/sprites/{db94ffb7-a09d-4a51-b420-b930851c9db4.png → 69b022a8-e42f-4985-bd16-b4a530ad8a20.png} +0 -0
- /kotonebot/kaa/sprites/{13535ecd-bdf5-4ff7-aa2c-6ecb20fe9c06.png → 6aa34982-e7ab-4001-808f-8c5cf370d087.png} +0 -0
- /kotonebot/kaa/sprites/{572077d4-7ee2-449a-b4f0-66239b0d7aff.png → 7516c9a1-87ec-4d2f-ac5e-40d1aec27104.png} +0 -0
- /kotonebot/kaa/sprites/{d7f604a6-c663-44db-b1d3-c9792eb3daa4.png → 7aa2435c-da90-4d52-b831-88dbec57dde9.png} +0 -0
- /kotonebot/kaa/sprites/{56a8c0ca-4659-4de2-9bce-55ce86a40d75.png → 7b7dad18-a838-4267-b3c7-6ab43b8361f0.png} +0 -0
- /kotonebot/kaa/sprites/{1f9165e6-77ee-403e-9b76-99c114527dbb.png → 7cabdf91-2f15-4991-b165-eb9cdd557af6.png} +0 -0
- /kotonebot/kaa/sprites/{5ca50448-cc21-499a-a685-c5e1c4240c48.png → 7f6cb60e-6ab3-4db4-86e1-8558250062a4.png} +0 -0
- /kotonebot/kaa/sprites/{a82e06fb-a02e-4be5-a7b4-4d2758914fcf.png → 83acbca8-3567-4262-a1e7-50f158348d45.png} +0 -0
- /kotonebot/kaa/sprites/{b3d1f8d4-1393-4206-b78e-a5495d8fb930.png → 83cf48ba-d1af-4674-a52e-6bb80a626db7.png} +0 -0
- /kotonebot/kaa/sprites/{22d5a7d5-59a0-4137-b02e-1a7af86d4250.png → 83f17b06-2792-4035-bc90-1800279ae131.png} +0 -0
- /kotonebot/kaa/sprites/{1bfce48a-b151-406e-a6f5-863cb68cbbf2.png → 84bb4986-0295-4a45-9486-86e31fcdf1f1.png} +0 -0
- /kotonebot/kaa/sprites/{73f4204e-8281-47cc-9dce-6bb8280c4ce5.png → 8b9c115b-d4ce-492e-88cb-08bd01c43570.png} +0 -0
- /kotonebot/kaa/sprites/{f0786a26-81b5-4e76-b577-db70ab3fab50.png → 8e48af2b-c083-4480-a27c-c59c31a7ede1.png} +0 -0
- /kotonebot/kaa/sprites/{c7aa3f89-8a5e-4685-9297-4fc892bfdd81.png → 8f1e5644-1079-44b1-9d44-97bae3817bc5.png} +0 -0
- /kotonebot/kaa/sprites/{cc829886-23e8-4d47-b4c4-37ca20381180.png → 90def878-cd6e-46e5-9dc4-9c92dd904b80.png} +0 -0
- /kotonebot/kaa/sprites/{d8136469-6d73-4f82-a79c-fee83c3e93a8.png → 920a3974-4875-4d2b-bbac-caa175c03ce0.png} +0 -0
- /kotonebot/kaa/sprites/{c4f28132-4aba-40ba-be6c-b1a31d014635.png → 94433cf2-dd04-4b74-ae14-e5e3d945f579.png} +0 -0
- /kotonebot/kaa/sprites/{ad8ee599-88a8-429c-8982-99086e552dcc.png → 969eb98c-f761-4007-b8bd-2b3fb8d1f08c.png} +0 -0
- /kotonebot/kaa/sprites/{31a52dc8-b7fb-4ff6-a261-eb90a918603c.png → 97adee05-1586-4589-93e6-c6c3a9cdae9d.png} +0 -0
- /kotonebot/kaa/sprites/{02e0aa0d-4094-4bdc-8625-1a063733615b.png → 9aef1aa8-41e1-42a7-83ad-b4e212ee3976.png} +0 -0
- /kotonebot/kaa/sprites/{e2fae2a4-bb19-4f49-b382-47e504ec26d3.png → 9c7f1bcc-0bc8-454b-95fb-56a803030771.png} +0 -0
- /kotonebot/kaa/sprites/{8e8a0b57-0231-4ed6-958e-3196f7c9ca7b.png → 9cd7e1f1-13c4-471e-abee-223ffd9126cb.png} +0 -0
- /kotonebot/kaa/sprites/{5bf00cba-9aab-4ffe-b20b-8f5e74279276.png → 9d5dd50c-3341-41a4-a3dd-ccc00edcf201.png} +0 -0
- /kotonebot/kaa/sprites/{e866d8b1-4f61-45bf-8170-5229f53c047a.png → 9f99b0e9-8cc0-4877-8f8a-d26257ef5386.png} +0 -0
- /kotonebot/kaa/sprites/{1a3d18a4-7d91-4182-9e40-e60d73fed365.png → a1853223-d6b9-4660-af4e-91e59bdddc3c.png} +0 -0
- /kotonebot/kaa/sprites/{ed5d2bf3-405c-4165-88d0-9f8a4be968c6.png → a1bba683-a740-4eaf-8c37-3b1042b963b0.png} +0 -0
- /kotonebot/kaa/sprites/{910d307b-6461-4950-badb-509975d0b797.png → a1cf80ee-64bf-4d54-a7db-ffadf3c97026.png} +0 -0
- /kotonebot/kaa/sprites/{645744c4-3bbf-4ea2-8f46-4725fff874b3.png → a3b15425-0bfd-4668-a3a9-2ab64da8505f.png} +0 -0
- /kotonebot/kaa/sprites/{7cea265a-fca5-43d0-b2da-067c8fff4d72.png → a4075991-98da-4d06-bcde-28054cd124d2.png} +0 -0
- /kotonebot/kaa/sprites/{89c0e675-3fd4-456a-8ae7-3bfb248b7281.png → a7da51c2-8444-4770-a16b-b6543e40197f.png} +0 -0
- /kotonebot/kaa/sprites/{5be4f6c7-2baa-42f3-a5a5-99ca0830cc30.png → a8b3fdce-9e4a-495c-839e-0142f67fee69.png} +0 -0
- /kotonebot/kaa/sprites/{72c1804f-db8c-40fa-bc79-6533f2861a5d.png → aa3b717f-67f8-445f-a6bf-b89f7200d95b.png} +0 -0
- /kotonebot/kaa/sprites/{7736a171-9221-4cda-8288-908997abeff2.png → abcc709c-1f4d-4832-a063-eafbad94ac31.png} +0 -0
- /kotonebot/kaa/sprites/{12e8d3f1-494a-46f5-908f-f621a0c57ec6.png → ad172750-d1a6-4a25-8ce8-9483f4b5affb.png} +0 -0
- /kotonebot/kaa/sprites/{a33ae1c3-ac69-4783-977e-9f0f1b1a2f8d.png → aefdec38-e3b6-4762-aed8-33107686ddac.png} +0 -0
- /kotonebot/kaa/sprites/{22ee3f1b-ddcb-48bf-85dd-8423f85e3199.png → b01c25d2-21bf-4db9-b5b2-ec35817f1b04.png} +0 -0
- /kotonebot/kaa/sprites/{5edef075-4843-4dc9-840f-ae445cbe0730.png → b1e7f24e-f246-406e-9073-58e2f3e4e819.png} +0 -0
- /kotonebot/kaa/sprites/{a105d17d-d44c-4798-aeff-70808c91cb47.png → b5d4265c-82e0-470d-a48e-8aa4edbdef5a.png} +0 -0
- /kotonebot/kaa/sprites/{48c257f8-3583-49f7-b01a-ba7d251086ac.png → b65724b4-ec8f-48a9-9ab2-e7ce5b8f35b2.png} +0 -0
- /kotonebot/kaa/sprites/{469006bc-a011-46e4-bcde-992be888456e.png → b8aada91-eedd-4c53-99f3-f903d547235e.png} +0 -0
- /kotonebot/kaa/sprites/{e5d15c50-45ee-4de9-8b97-4630cbd8f01a.png → ba759205-ce99-4417-8cab-d32fe55dff4c.png} +0 -0
- /kotonebot/kaa/sprites/{afa0f85f-dcb7-48a1-a1ae-624456b9b65c.png → bb0ae68d-44d5-47c6-91dd-a529bc34225b.png} +0 -0
- /kotonebot/kaa/sprites/{79bc56c5-eae6-4389-9116-4a9e182d6bf3.png → bed9575d-ccad-4f4e-825e-47b2a9cb0925.png} +0 -0
- /kotonebot/kaa/sprites/{f9b2f64d-f829-4b13-9704-c5f00fb956be.png → bfec58df-2628-454f-92aa-769cad186448.png} +0 -0
- /kotonebot/kaa/sprites/{9c1fa1d4-2ae5-4093-abaa-cebb51135721.png → c25c7ce5-ad8d-4b2c-83eb-ae6d4871a6c3.png} +0 -0
- /kotonebot/kaa/sprites/{05f8f996-a38a-45d9-8ff9-720b6c4fd599.png → c3ec61aa-f62e-46fd-b359-48864ea7a150.png} +0 -0
- /kotonebot/kaa/sprites/{826bf80a-112e-4356-9111-4b7e692ccc82.png → c484ca57-6b19-46b5-a107-1805a7488d48.png} +0 -0
- /kotonebot/kaa/sprites/{cd8d3d55-f102-419e-a6fd-2ad5ecc4fd2e.png → c571e1c0-ff85-4b2e-97ed-97d33b8d92e3.png} +0 -0
- /kotonebot/kaa/sprites/{0decaa6a-b9a9-4d9b-829a-0fc1f67538b4.png → c5e16f75-9b5a-4853-a144-275f3d20c186.png} +0 -0
- /kotonebot/kaa/sprites/{d747239f-7620-4f23-9ac7-cf2d34889266.png → c5ea3dfd-6761-466e-b44c-86592ef05323.png} +0 -0
- /kotonebot/kaa/sprites/{695f8d57-b2c9-4a6d-9ae9-1b49ee3eb22a.png → ca2adfb8-1e88-4a31-b3cc-1f70568ce4a3.png} +0 -0
- /kotonebot/kaa/sprites/{333fe6d3-0be7-40fb-a2a3-364f98758f2a.png → cb24b3df-1ec3-4ffd-95f1-ca4b0dd5b7da.png} +0 -0
- /kotonebot/kaa/sprites/{0bab7080-9a37-4c27-9821-8df36d49b678.png → cdbbb5ba-5117-488a-8172-48cfc92c14c6.png} +0 -0
- /kotonebot/kaa/sprites/{a3c12040-2b11-4038-b830-215fb7b6f359.png → cf66ae12-48bc-4512-a988-0e5de337c76d.png} +0 -0
- /kotonebot/kaa/sprites/{994aa6a6-0189-4a79-8125-56136973b581.png → d1699baa-467b-46d1-9276-aae78fe8f589.png} +0 -0
- /kotonebot/kaa/sprites/{48d2f007-8c1b-43fc-bd3f-f0b10d2a0c88.png → d3e6e2e9-c5b5-463f-98f4-de72c9320d9d.png} +0 -0
- /kotonebot/kaa/sprites/{b2f7a430-5777-4861-8435-5419394e5ee8.png → d4c47cc7-5b3e-4c3e-8e80-78cb94e7eed9.png} +0 -0
- /kotonebot/kaa/sprites/{fd610de1-b023-4747-8c1b-72f89b1c5647.png → d5d854fc-1b87-43d4-b32d-66eccb66fa41.png} +0 -0
- /kotonebot/kaa/sprites/{c2667677-cbff-4dd4-a401-e0963e7224f4.png → d60a395b-d907-416a-b091-36bfee4948b3.png} +0 -0
- /kotonebot/kaa/sprites/{43d65b3f-bbae-4e29-a7bf-539379c1b072.png → dad4ff8c-07f4-4b07-abd3-5d02bbcc4562.png} +0 -0
- /kotonebot/kaa/sprites/{b44f5e5b-e999-4427-8a9f-f76c6485f4a5.png → dbd537c7-d1d3-4d64-9ccd-43dd4519bedd.png} +0 -0
- /kotonebot/kaa/sprites/{2f81e70a-f2af-420f-9b6b-6338c391911f.png → dde03640-6c3a-4b13-a783-f672816bfec4.png} +0 -0
- /kotonebot/kaa/sprites/{da3e7cee-d77b-4e62-b703-ed257706dd39.png → df97421e-4b74-430e-b3d1-ed9bac6918a7.png} +0 -0
- /kotonebot/kaa/sprites/{0439399f-5fca-43f9-a105-99342ff04d2e.png → dfb14c98-f672-4906-80bd-d2a18bdd62cd.png} +0 -0
- /kotonebot/kaa/sprites/{03458cf9-8ab0-4908-9a56-9c5c7e06bc9b.png → e1e0d751-9006-4fa4-a933-4c0dc5e1f3d2.png} +0 -0
- /kotonebot/kaa/sprites/{f65a4495-f044-44de-bf0d-c869e637d5d3.png → e394ff91-09d3-41e1-bbf5-bc42a71a623b.png} +0 -0
- /kotonebot/kaa/sprites/{de709296-e411-465f-86fc-5daf5ca83cef.png → e5259dfb-3a49-4cfc-9f89-b42958ce6eec.png} +0 -0
- /kotonebot/kaa/sprites/{371a3192-101c-45ef-9da4-2ed389770c0f.png → e5eeb9af-8003-4981-bf56-2e32e76cec5d.png} +0 -0
- /kotonebot/kaa/sprites/{73af305f-840f-4325-abae-b3519fba672a.png → e9c45a73-2011-4584-87b7-c4e566eba87f.png} +0 -0
- /kotonebot/kaa/sprites/{7a479871-547e-4098-9cdd-6c9bb9f7449a.png → eae83523-e58c-4db9-a356-4335a5da3dc8.png} +0 -0
- /kotonebot/kaa/sprites/{e7022542-4317-4a61-8098-f3f733d8400e.png → ed6d3e3d-0f04-4fa4-b0f9-fdbf324649f6.png} +0 -0
- /kotonebot/kaa/sprites/{24cd42fd-bb3b-4fc6-b40d-d3e3e36fe9f1.png → efb28e1d-7b52-4e20-aec5-117c798b7fbe.png} +0 -0
- /kotonebot/kaa/sprites/{6bf5556a-8f4e-41d7-8ab5-d683ad1b47a8.png → f025027f-daa0-4943-8395-5d7d44cc7f15.png} +0 -0
- /kotonebot/kaa/sprites/{b3e72de2-e103-49a3-b0f2-8593cff87c4e.png → f12c2b0b-8273-4197-a8c6-2a8ef2788a9b.png} +0 -0
- /kotonebot/kaa/sprites/{d22ca9e0-001d-43d6-a557-1c76c5a27c81.png → f528ea0e-1e55-4e41-844f-bb1db9185ef8.png} +0 -0
- /kotonebot/kaa/sprites/{b604e25d-680a-4e02-a012-2e593b5bc276.png → f611bbd9-c062-4989-96a4-65ff6c59673c.png} +0 -0
- /kotonebot/kaa/sprites/{b1d1dfab-51f5-4ae9-b718-cdf46774c0ff.png → f6bfbf6a-6e53-4563-9345-3f3756d6ea9a.png} +0 -0
- /kotonebot/kaa/sprites/{7344e180-251b-465a-a8cf-974477f7ad44.png → f72bd3d6-850d-4190-9775-938f474d263c.png} +0 -0
- /kotonebot/kaa/sprites/{96cf0633-6531-499b-b1cc-6670ab710293.png → f8eec9b2-55ca-4195-b098-a5393d02a98a.png} +0 -0
- /kotonebot/kaa/sprites/{92b7d830-3db5-434e-b156-0ac855db480d.png → faf069e1-f623-47c1-b879-cfa246fbc7df.png} +0 -0
- /kotonebot/kaa/sprites/{a00fcf77-2800-4f7d-993d-4636b36045bb.png → faf360e8-7845-4fcf-b0a6-0f5f93c050f1.png} +0 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.23.0.dist-info}/WHEEL +0 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.23.0.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.23.0.dist-info}/licenses/LICENSE +0 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.23.0.dist-info}/top_level.txt +0 -0
kotonebot/kaa/game_ui/common.py
CHANGED
|
@@ -2,10 +2,10 @@ import cv2
|
|
|
2
2
|
import numpy as np
|
|
3
3
|
from cv2.typing import MatLike
|
|
4
4
|
|
|
5
|
-
from kotonebot import
|
|
6
|
-
from kotonebot.backend.color import HsvColor
|
|
7
|
-
from kotonebot.primitives import RectTuple, Rect
|
|
5
|
+
from kotonebot.primitives import Rect
|
|
8
6
|
from kotonebot.backend.core import Image
|
|
7
|
+
from kotonebot.backend.color import HsvColor
|
|
8
|
+
from kotonebot import action, color, image, device
|
|
9
9
|
from kotonebot.backend.preprocessor import HsvColorFilter
|
|
10
10
|
|
|
11
11
|
|
|
@@ -88,7 +88,4 @@ class WhiteFilter(HsvColorFilter):
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
if __name__ == '__main__':
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
init_context()
|
|
94
|
-
manual_context().begin()
|
|
91
|
+
pass
|
kotonebot/kaa/game_ui/dialog.py
CHANGED
|
@@ -1,45 +1,65 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
1
3
|
from kotonebot.kaa.tasks import R
|
|
2
4
|
from kotonebot import device, image
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
def expect_yes(*, msg: str | None = None):
|
|
5
9
|
"""
|
|
6
10
|
点击对话框上的✔️按钮。若不存在,会等待其出现,直至超时异常。
|
|
7
11
|
|
|
8
12
|
前置条件:当前打开了任意对话框\n
|
|
9
13
|
结束状态:点击了肯定意义按钮(✔️图标,橙色背景)后瞬间
|
|
14
|
+
|
|
15
|
+
:param msg: 成功点击后输出的日志信息。信息中的动词建议使用过去式。
|
|
10
16
|
"""
|
|
11
17
|
device.click(image.expect(R.Common.IconButtonCheck))
|
|
18
|
+
if msg is not None:
|
|
19
|
+
logger.debug(msg)
|
|
12
20
|
|
|
13
|
-
def yes() -> bool:
|
|
21
|
+
def yes(*, msg: str | None = None) -> bool:
|
|
14
22
|
"""
|
|
15
23
|
点击对话框上的✔️按钮。
|
|
16
24
|
|
|
17
25
|
前置条件:当前打开了任意对话框\n
|
|
18
26
|
结束状态:点击了肯定意义按钮(✔️图标,橙色背景)后瞬间
|
|
27
|
+
|
|
28
|
+
:param msg: 成功点击后输出的日志信息。信息中的动词建议使用过去式。
|
|
19
29
|
"""
|
|
20
30
|
if image.find(R.Common.IconButtonCheck):
|
|
21
31
|
device.click()
|
|
32
|
+
if msg is not None:
|
|
33
|
+
logger.debug(msg)
|
|
22
34
|
return True
|
|
23
35
|
return False
|
|
24
36
|
|
|
25
|
-
def expect_no():
|
|
37
|
+
def expect_no(*, msg: str | None = None):
|
|
26
38
|
"""
|
|
27
39
|
点击对话框上的✖️按钮。若不存在,会等待其出现,直至超时异常。
|
|
28
40
|
|
|
29
41
|
前置条件:当前打开了任意对话框\n
|
|
30
42
|
结束状态:点击了否定意义按钮(✖️图标,白色背景)后瞬间
|
|
43
|
+
|
|
44
|
+
:param msg: 成功点击后输出的日志信息。信息中的动词建议使用过去式。
|
|
31
45
|
"""
|
|
32
46
|
device.click(image.expect(R.Common.IconButtonCross))
|
|
47
|
+
if msg is not None:
|
|
48
|
+
logger.debug(msg)
|
|
33
49
|
|
|
34
|
-
def no():
|
|
50
|
+
def no(*, msg: str | None = None):
|
|
35
51
|
"""
|
|
36
52
|
点击对话框上的✖️按钮。
|
|
37
53
|
|
|
38
54
|
前置条件:当前打开了任意对话框\n
|
|
39
55
|
结束状态:点击了否定意义按钮(✖️图标,白色背景)后瞬间
|
|
56
|
+
|
|
57
|
+
:param msg: 成功点击后输出的日志信息。信息中的动词建议使用过去式。
|
|
40
58
|
"""
|
|
41
59
|
if image.find(R.Common.IconButtonCross):
|
|
42
60
|
device.click()
|
|
61
|
+
if msg is not None:
|
|
62
|
+
logger.debug(msg)
|
|
43
63
|
return True
|
|
44
64
|
return False
|
|
45
65
|
|
|
@@ -10,7 +10,8 @@ from kotonebot.kaa.util import paths
|
|
|
10
10
|
from kotonebot.primitives import RectTuple, Rect
|
|
11
11
|
from kotonebot.kaa.game_ui import Scrollable
|
|
12
12
|
from kotonebot import device, action
|
|
13
|
-
from kotonebot.
|
|
13
|
+
from kotonebot.util import cv2_imread
|
|
14
|
+
from kotonebot.kaa.image_db import ImageDatabase, HistDescriptor, FileDataSource, DatabaseQueryResult
|
|
14
15
|
from kotonebot.backend.preprocessor import HsvColorsRemover
|
|
15
16
|
|
|
16
17
|
logger = logging.getLogger(__name__)
|
|
@@ -106,8 +107,32 @@ def idols_db() -> ImageDatabase:
|
|
|
106
107
|
_db = ImageDatabase(FileDataSource(str(path)), db_path, HistDescriptor(8), name='idols')
|
|
107
108
|
return _db
|
|
108
109
|
|
|
110
|
+
def match_idol(skin_id: str, idol_img: MatLike) -> DatabaseQueryResult | None:
|
|
111
|
+
"""
|
|
112
|
+
将给定图像与指定偶像 ID 进行匹配。
|
|
113
|
+
|
|
114
|
+
:param skin_id: 偶像 ID。
|
|
115
|
+
:param idol_img: 待匹配偶像图像。
|
|
116
|
+
:return: 若匹配成功,则返回匹配结果,否则返回 None。
|
|
117
|
+
"""
|
|
118
|
+
db = idols_db()
|
|
119
|
+
match = db.match(idol_img, 20)
|
|
120
|
+
if match and match.key.startswith(skin_id):
|
|
121
|
+
return match
|
|
122
|
+
else:
|
|
123
|
+
return None
|
|
124
|
+
|
|
109
125
|
@action('定位偶像', screenshot_mode='manual-inherit')
|
|
110
|
-
def locate_idol(skin_id: str):
|
|
126
|
+
def locate_idol(skin_id: str) -> Rect | None:
|
|
127
|
+
"""
|
|
128
|
+
定位并选中指定偶像。
|
|
129
|
+
|
|
130
|
+
前置条件:位于偶像总览界面。\n
|
|
131
|
+
结束状态:位于偶像总览界面。
|
|
132
|
+
|
|
133
|
+
:param skin_id: 目标偶像的 Skin ID
|
|
134
|
+
:return: 若成功,返回目标偶像的范围 (x, y, w, h),否则返回 None。
|
|
135
|
+
"""
|
|
111
136
|
device.screenshot()
|
|
112
137
|
logger.info('Locating idol %s', skin_id)
|
|
113
138
|
x, y, w, h = R.Produce.BoxIdolOverviewIdols.xywh
|
|
@@ -146,15 +171,6 @@ def locate_idol(skin_id: str):
|
|
|
146
171
|
|
|
147
172
|
# # 使用新函数绘制预览图
|
|
148
173
|
# preview_img = draw_idol_preview(img, rects, db, path)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
def test():
|
|
152
|
-
from kotonebot.backend.context import init_context, manual_context
|
|
153
|
-
init_context()
|
|
154
|
-
manual_context().begin()
|
|
155
|
-
locate_idol('i_card-skin-fktn-3-006')
|
|
156
174
|
|
|
157
175
|
if __name__ == '__main__':
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
test()
|
|
176
|
+
locate_idol('i_card-skin-fktn-3-006')
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import cv2
|
|
2
|
+
import numpy as np
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from cv2.typing import MatLike
|
|
5
|
+
|
|
6
|
+
from kotonebot import action, image, device
|
|
7
|
+
from kotonebot.backend.core import Image
|
|
8
|
+
from kotonebot.backend.image import TemplateMatchResult
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def primary_button_state(img: MatLike) -> Optional[bool]:
|
|
12
|
+
"""
|
|
13
|
+
分析按钮图像并根据红色通道直方图返回按钮状态
|
|
14
|
+
|
|
15
|
+
:param img: 输入的按钮图像 (BGR格式)
|
|
16
|
+
:return: True - 启用状态
|
|
17
|
+
False - 禁用状态
|
|
18
|
+
None - 未知状态或输入无效
|
|
19
|
+
"""
|
|
20
|
+
# 确保图像有效
|
|
21
|
+
if img is None or img.size == 0:
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
# 计算红色通道直方图(五箱)
|
|
25
|
+
_, _, r = cv2.split(img)
|
|
26
|
+
hist = cv2.calcHist([r], [0], None, [5], [0, 256])
|
|
27
|
+
# 归一化并找出红色集中在哪一箱
|
|
28
|
+
hist = hist.ravel() / hist.sum()
|
|
29
|
+
max_idx = np.argmax(hist)
|
|
30
|
+
|
|
31
|
+
if max_idx == 3:
|
|
32
|
+
return False
|
|
33
|
+
elif max_idx == 4:
|
|
34
|
+
return True
|
|
35
|
+
else:
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
@action('寻找按钮', screenshot_mode='manual-inherit')
|
|
39
|
+
def find_button(template: MatLike | Image, state: Optional[bool] = None) -> Optional[bool]:
|
|
40
|
+
"""
|
|
41
|
+
在图像中寻找按钮并返回其状态
|
|
42
|
+
|
|
43
|
+
:param template: 按钮模板图像 (BGR格式)
|
|
44
|
+
:param state: 按钮状态 (True - 启用, False - 禁用, None - 任意)
|
|
45
|
+
:return: True - 启用状态
|
|
46
|
+
False - 禁用状态
|
|
47
|
+
None - 未找到按钮或状态未知
|
|
48
|
+
"""
|
|
49
|
+
img = device.screenshot()
|
|
50
|
+
result = image.find(template)
|
|
51
|
+
if result is None:
|
|
52
|
+
return None
|
|
53
|
+
x, y, w, h = result.rect.xywh
|
|
54
|
+
button_img = img[y:y+h, x:x+w]
|
|
55
|
+
return primary_button_state(button_img)
|
|
@@ -327,12 +327,7 @@ class Scrollable:
|
|
|
327
327
|
return ScrollableIterator(self, int(self.track_height * step), start, end, skip_first)
|
|
328
328
|
|
|
329
329
|
if __name__ == '__main__':
|
|
330
|
-
from kotonebot.backend.context import init_context, manual_context, device
|
|
331
|
-
init_context()
|
|
332
|
-
manual_context().begin()
|
|
333
|
-
from kotonebot import device
|
|
334
330
|
import cv2
|
|
335
|
-
from kotonebot.util import cv2_imread
|
|
336
331
|
import time
|
|
337
332
|
logger.setLevel(logging.DEBUG)
|
|
338
333
|
|
kotonebot/kaa/main/cli.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import sys
|
|
3
|
-
import runpy
|
|
4
3
|
import logging
|
|
5
4
|
import argparse
|
|
6
5
|
import importlib.metadata
|
|
7
6
|
from datetime import datetime
|
|
8
7
|
|
|
9
8
|
from .kaa import Kaa
|
|
9
|
+
from ..util.paths import get_ahk_path
|
|
10
|
+
from kotonebot.client.implements.windows import WindowsImplConfig
|
|
10
11
|
from kotonebot.backend.context import tasks_from_id, task_registry
|
|
12
|
+
from kotonebot.client.implements.remote_windows import RemoteWindowsServer
|
|
11
13
|
|
|
12
14
|
version = importlib.metadata.version('ksaa')
|
|
13
15
|
|
|
@@ -90,9 +92,12 @@ def task_list() -> int:
|
|
|
90
92
|
def remote_server() -> int:
|
|
91
93
|
args = psr.parse_args()
|
|
92
94
|
try:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
ahk_path = get_ahk_path()
|
|
96
|
+
server = RemoteWindowsServer(WindowsImplConfig(window_title='gakumas', ahk_exe_path=ahk_path), args.host, args.port)
|
|
97
|
+
server.start()
|
|
98
|
+
return 0
|
|
99
|
+
except KeyboardInterrupt:
|
|
100
|
+
print("Server stopped by user")
|
|
96
101
|
return 0
|
|
97
102
|
except Exception as e:
|
|
98
103
|
print(f'Error starting remote server: {e}')
|
kotonebot/kaa/main/dmm_host.py
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
|
+
from importlib import resources
|
|
1
2
|
from typing_extensions import override
|
|
2
3
|
|
|
3
|
-
from kotonebot.client import Device,
|
|
4
|
-
from kotonebot.client import
|
|
4
|
+
from kotonebot.client import Device, DeviceImpl
|
|
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
|
|
5
8
|
from kotonebot.client.host import HostProtocol, Instance
|
|
9
|
+
from kotonebot.client.host.protocol import WindowsHostConfig, RemoteWindowsHostConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
DmmHostConfigs = WindowsHostConfig | RemoteWindowsHostConfig
|
|
6
13
|
|
|
7
14
|
# TODO: 可能应该把 start_game 和 end_game 里对启停的操作移动到这里来
|
|
8
|
-
class DmmInstance(Instance):
|
|
15
|
+
class DmmInstance(Instance[DmmHostConfigs]):
|
|
9
16
|
def __init__(self):
|
|
10
17
|
super().__init__('dmm', 'gakumas')
|
|
11
18
|
|
|
@@ -30,10 +37,29 @@ class DmmInstance(Instance):
|
|
|
30
37
|
raise NotImplementedError()
|
|
31
38
|
|
|
32
39
|
@override
|
|
33
|
-
def create_device(self, impl: DeviceImpl,
|
|
34
|
-
if impl
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
def create_device(self, impl: DeviceImpl, host_config: DmmHostConfigs) -> Device:
|
|
41
|
+
if impl == 'windows':
|
|
42
|
+
assert isinstance(host_config, WindowsHostConfig)
|
|
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)
|
|
48
|
+
|
|
49
|
+
elif impl == 'remote_windows':
|
|
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}')
|
|
37
63
|
|
|
38
64
|
class DmmHost(HostProtocol):
|
|
39
65
|
instance = DmmInstance()
|
kotonebot/kaa/main/kaa.py
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import os
|
|
3
|
+
import zipfile
|
|
3
4
|
import logging
|
|
4
|
-
import importlib.metadata
|
|
5
5
|
import traceback
|
|
6
|
-
import
|
|
6
|
+
import importlib.metadata
|
|
7
7
|
from datetime import datetime
|
|
8
|
+
from typing_extensions import override
|
|
8
9
|
|
|
9
10
|
import cv2
|
|
10
|
-
from typing_extensions import override
|
|
11
11
|
|
|
12
|
-
from .dmm_host import DmmHost
|
|
13
12
|
from ...client import Device
|
|
14
13
|
from kotonebot.ui import user
|
|
15
14
|
from kotonebot import KotoneBot
|
|
15
|
+
from ..util.paths import get_ahk_path
|
|
16
16
|
from ..kaa_context import _set_instance
|
|
17
|
+
from .dmm_host import DmmHost, DmmInstance
|
|
17
18
|
from ..common import BaseConfig, upgrade_config
|
|
18
|
-
from kotonebot.
|
|
19
|
+
from kotonebot.config.base_config import UserConfig
|
|
20
|
+
from kotonebot.client.host import (
|
|
21
|
+
Mumu12Host, LeidianHost, Mumu12Instance,
|
|
22
|
+
LeidianInstance, CustomInstance
|
|
23
|
+
)
|
|
24
|
+
from kotonebot.client.host.protocol import (
|
|
25
|
+
Instance, AdbHostConfig, WindowsHostConfig,
|
|
26
|
+
RemoteWindowsHostConfig
|
|
27
|
+
)
|
|
19
28
|
|
|
20
29
|
# 初始化日志
|
|
21
30
|
log_formatter = logging.Formatter('[%(asctime)s][%(levelname)s][%(name)s] %(message)s')
|
|
@@ -104,23 +113,27 @@ class Kaa(KotoneBot):
|
|
|
104
113
|
raise ValueError('Backend instance is not set.')
|
|
105
114
|
_set_instance(self.backend_instance)
|
|
106
115
|
|
|
107
|
-
|
|
108
|
-
|
|
116
|
+
def __get_backend_instance(self, config: UserConfig) -> Instance:
|
|
117
|
+
"""
|
|
118
|
+
根据配置获取或创建 Instance。
|
|
119
|
+
|
|
120
|
+
:param config: 用户配置对象
|
|
121
|
+
:return: 后端实例
|
|
122
|
+
"""
|
|
109
123
|
from kotonebot.client.host import create_custom
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
config = config.user_configs[0]
|
|
114
|
-
logger.info('Checking backend...')
|
|
124
|
+
|
|
125
|
+
logger.info(f'Querying for backend: {config.backend.type}')
|
|
126
|
+
|
|
115
127
|
if config.backend.type == 'custom':
|
|
116
128
|
exe = config.backend.emulator_path
|
|
117
|
-
|
|
129
|
+
instance = create_custom(
|
|
118
130
|
adb_ip=config.backend.adb_ip,
|
|
119
131
|
adb_port=config.backend.adb_port,
|
|
120
132
|
adb_name=config.backend.adb_emulator_name,
|
|
121
133
|
exe_path=exe,
|
|
122
134
|
emulator_args=config.backend.emulator_args
|
|
123
135
|
)
|
|
136
|
+
# 对于 custom 类型,需要额外验证模拟器路径
|
|
124
137
|
if config.backend.check_emulator:
|
|
125
138
|
if exe is None:
|
|
126
139
|
user.error('「检查并启动模拟器」已开启但未配置「模拟器 exe 文件路径」。')
|
|
@@ -128,42 +141,101 @@ class Kaa(KotoneBot):
|
|
|
128
141
|
if not os.path.exists(exe):
|
|
129
142
|
user.error('「模拟器 exe 文件路径」对应的文件不存在!请检查路径是否正确。')
|
|
130
143
|
raise FileNotFoundError(f'Emulator executable not found: {exe}')
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
self.backend_instance.start()
|
|
134
|
-
logger.info('Waiting for custom backend to be available...')
|
|
135
|
-
self.backend_instance.wait_available()
|
|
136
|
-
else:
|
|
137
|
-
logger.info('Custom backend "%s" already running.', self.backend_instance)
|
|
144
|
+
return instance
|
|
145
|
+
|
|
138
146
|
elif config.backend.type == 'mumu12':
|
|
139
147
|
if config.backend.instance_id is None:
|
|
140
148
|
raise ValueError('MuMu12 instance ID is not set.')
|
|
141
|
-
|
|
142
|
-
if
|
|
149
|
+
instance = Mumu12Host.query(id=config.backend.instance_id)
|
|
150
|
+
if instance is None:
|
|
143
151
|
raise ValueError(f'MuMu12 instance not found: {config.backend.instance_id}')
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
self.backend_instance.start()
|
|
147
|
-
logger.info('Waiting for MuMu12 backend to be available...')
|
|
148
|
-
self.backend_instance.wait_available()
|
|
149
|
-
else:
|
|
150
|
-
logger.info('MuMu12 backend "%s" already running.', self.backend_instance)
|
|
152
|
+
return instance
|
|
153
|
+
|
|
151
154
|
elif config.backend.type == 'leidian':
|
|
152
155
|
if config.backend.instance_id is None:
|
|
153
156
|
raise ValueError('Leidian instance ID is not set.')
|
|
154
|
-
|
|
155
|
-
if
|
|
157
|
+
instance = LeidianHost.query(id=config.backend.instance_id)
|
|
158
|
+
if instance is None:
|
|
156
159
|
raise ValueError(f'Leidian instance not found: {config.backend.instance_id}')
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
self.backend_instance.start()
|
|
160
|
-
logger.info('Waiting for Leidian backend to be available...')
|
|
161
|
-
self.backend_instance.wait_available()
|
|
162
|
-
else:
|
|
163
|
-
logger.info('Leidian backend "%s" already running.', self.backend_instance)
|
|
160
|
+
return instance
|
|
161
|
+
|
|
164
162
|
elif config.backend.type == 'dmm':
|
|
165
|
-
|
|
163
|
+
return DmmHost.instance
|
|
164
|
+
|
|
166
165
|
else:
|
|
167
166
|
raise ValueError(f'Unsupported backend type: {config.backend.type}')
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
|
|
168
|
+
def __ensure_instance_running(self, instance: Instance, config: UserConfig):
|
|
169
|
+
"""
|
|
170
|
+
确保 Instance 正在运行。
|
|
171
|
+
|
|
172
|
+
:param instance: 后端实例
|
|
173
|
+
:param config: 用户配置对象
|
|
174
|
+
"""
|
|
175
|
+
# DMM 实例不需要启动,直接返回
|
|
176
|
+
if isinstance(instance, DmmInstance):
|
|
177
|
+
logger.info('DMM backend does not require startup.')
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
# 对所有需要启动的后端(custom, mumu, leidian)使用统一逻辑
|
|
181
|
+
if config.backend.check_emulator and not instance.running():
|
|
182
|
+
logger.info(f'Starting backend "{instance}"...')
|
|
183
|
+
instance.start()
|
|
184
|
+
logger.info(f'Waiting for backend "{instance}" to be available...')
|
|
185
|
+
instance.wait_available()
|
|
186
|
+
else:
|
|
187
|
+
logger.info(f'Backend "{instance}" already running or check is disabled.')
|
|
188
|
+
|
|
189
|
+
@override
|
|
190
|
+
def _on_create_device(self) -> Device:
|
|
191
|
+
"""
|
|
192
|
+
创建设备。
|
|
193
|
+
"""
|
|
194
|
+
from kotonebot.config.manager import load_config
|
|
195
|
+
|
|
196
|
+
# 步骤1:加载配置
|
|
197
|
+
config = load_config(self.config_path, type=self.config_type)
|
|
198
|
+
user_config = config.user_configs[0] # HACK: 硬编码
|
|
199
|
+
|
|
200
|
+
# 步骤2:获取实例
|
|
201
|
+
self.backend_instance = self.__get_backend_instance(user_config)
|
|
202
|
+
if self.backend_instance is None:
|
|
203
|
+
raise RuntimeError(f"Failed to find instance for backend '{user_config.backend.type}'")
|
|
204
|
+
|
|
205
|
+
# 步骤3:确保实例运行
|
|
206
|
+
self.__ensure_instance_running(self.backend_instance, user_config)
|
|
207
|
+
|
|
208
|
+
# 步骤4:准备 HostConfig 并创建 Device
|
|
209
|
+
impl_name = user_config.backend.screenshot_impl
|
|
210
|
+
|
|
211
|
+
if isinstance(self.backend_instance, DmmInstance):
|
|
212
|
+
if impl_name == 'windows':
|
|
213
|
+
ahk_path = get_ahk_path()
|
|
214
|
+
host_conf = WindowsHostConfig(
|
|
215
|
+
window_title='gakumas',
|
|
216
|
+
ahk_exe_path=ahk_path
|
|
217
|
+
)
|
|
218
|
+
elif impl_name == 'remote_windows':
|
|
219
|
+
ahk_path = get_ahk_path()
|
|
220
|
+
host_conf = RemoteWindowsHostConfig(
|
|
221
|
+
windows_host_config=WindowsHostConfig(
|
|
222
|
+
window_title='gakumas',
|
|
223
|
+
ahk_exe_path=ahk_path
|
|
224
|
+
),
|
|
225
|
+
host=user_config.backend.adb_ip,
|
|
226
|
+
port=user_config.backend.adb_port
|
|
227
|
+
)
|
|
228
|
+
else:
|
|
229
|
+
raise ValueError(f"Impl of '{impl_name}' is not supported on DMM.")
|
|
230
|
+
return self.backend_instance.create_device(impl_name, host_conf)
|
|
231
|
+
|
|
232
|
+
# 统一处理所有基于 ADB 的后端
|
|
233
|
+
elif isinstance(self.backend_instance, (CustomInstance, Mumu12Instance, LeidianInstance)):
|
|
234
|
+
if impl_name in ['adb', 'adb_raw', 'uiautomator2']:
|
|
235
|
+
host_conf = AdbHostConfig(timeout=180)
|
|
236
|
+
return self.backend_instance.create_device(impl_name, host_conf)
|
|
237
|
+
else:
|
|
238
|
+
raise ValueError(f"{user_config.backend.type} backend does not support implementation '{impl_name}'")
|
|
239
|
+
|
|
240
|
+
else:
|
|
241
|
+
raise TypeError(f"Unknown instance type: {type(self.backend_instance)}")
|
kotonebot/kaa/metadata.py
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
WHATS_NEW = """
|
|
2
2
|
# 更新日志
|
|
3
3
|
## kaa
|
|
4
|
+
### v2025.6.23.0
|
|
5
|
+
脚本:
|
|
6
|
+
* [新增] 优化了培育开始的逻辑,修复若干 bug(#86313ec)
|
|
7
|
+
|
|
8
|
+
框架:
|
|
9
|
+
* [修复] 修复由于分离 AndroidDevice 方法导致的 typing 问题(#4d76e1a)
|
|
10
|
+
* [重构] 将 Commandable 分离为 WindowsCommandable 与 AndroidCommandable(#16a267d)
|
|
11
|
+
* [重构] 将启动 remote_server 的逻辑移动到 kaa cli 中(#b8b5ba8)
|
|
12
|
+
* [重构] 提取三个 adb-based 截图方法的工厂函数的共同部分(#bd57dc4)
|
|
13
|
+
* [重构] 将创建设备的逻辑从 init_context 中移除(#f2599e6)
|
|
14
|
+
* [重构] 重构 Device 与 Impl 的创建方式(#2fc9ad5)
|
|
15
|
+
|
|
16
|
+
其他:
|
|
17
|
+
* [其他] 更新上游 submodules(#810c341)
|
|
18
|
+
|
|
4
19
|
### v2025.6.8.0
|
|
5
20
|
脚本:
|
|
6
21
|
* [新增] 新增支持自动禁用与恢复 Gakumasu Localify 汉化插件(#264dac2)
|
|
Binary file
|
kotonebot/kaa/resources/game.db
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|