ksaa 2025.6.8.0__py3-none-any.whl → 2025.6.28.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 +29 -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 -2
- kotonebot/client/device.py +178 -25
- kotonebot/client/host/__init__.py +2 -1
- kotonebot/client/host/adb_common.py +94 -0
- kotonebot/client/host/custom.py +33 -4
- kotonebot/client/host/leidian_host.py +17 -15
- kotonebot/client/host/mumu12_host.py +79 -11
- kotonebot/client/host/protocol.py +44 -19
- kotonebot/client/host/windows_common.py +55 -0
- kotonebot/client/implements/__init__.py +7 -0
- kotonebot/client/implements/adb.py +24 -7
- kotonebot/client/implements/adb_raw.py +3 -3
- 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 +17 -21
- kotonebot/client/implements/uiautomator2.py +5 -8
- kotonebot/client/implements/windows.py +28 -36
- kotonebot/client/protocol.py +13 -0
- kotonebot/client/registration.py +24 -0
- kotonebot/config/base_config.py +8 -2
- kotonebot/debug_entry.py +11 -4
- kotonebot/errors.py +7 -0
- 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 +15 -8
- kotonebot/kaa/main/gr.py +114 -27
- kotonebot/kaa/main/kaa.py +140 -41
- kotonebot/kaa/metadata.py +47 -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/{clear_logs.py → tasks/clear_logs.py} +0 -3
- 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.28.0.dist-info}/METADATA +4 -1
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.28.0.dist-info}/RECORD +201 -181
- kotonebot/client/factory.py +0 -92
- kotonebot/kaa/sprites/38b8f119-8de1-49bf-8a5f-a44371de4569.png +0 -0
- /kotonebot/kaa/sprites/{5ca50448-cc21-499a-a685-c5e1c4240c48.png → 019273c4-22ce-486f-8a7d-dbc78f13dcac.png} +0 -0
- /kotonebot/kaa/sprites/{afa0f85f-dcb7-48a1-a1ae-624456b9b65c.png → 03e34ef7-36b5-4ddc-9545-5b70a2eba72e.png} +0 -0
- /kotonebot/kaa/sprites/{a00fcf77-2800-4f7d-993d-4636b36045bb.png → 06ea773b-e2b3-40d4-82f6-b119ce9ca00b.png} +0 -0
- /kotonebot/kaa/sprites/{d58d9987-b1ca-4669-a9a6-9a0fd1847fa6.png → 0769f8f4-1c47-4bad-a783-bba5e20250bf.png} +0 -0
- /kotonebot/kaa/sprites/{82a5e224-a161-43d4-8e15-2946480336dd.png → 08946997-4e9e-4242-95e1-e988fa96b919.png} +0 -0
- /kotonebot/kaa/sprites/{fb927b92-7a82-4869-8c61-581d49cd7201.png → 0d60ce10-20ce-4980-8172-b6bac08d6258.png} +0 -0
- /kotonebot/kaa/sprites/{b1e88fda-434a-4d06-8891-883a7beafa12.png → 0f40352f-6443-406e-8e2c-c40d5cfc6c59.png} +0 -0
- /kotonebot/kaa/sprites/{c4f28132-4aba-40ba-be6c-b1a31d014635.png → 0f6d7f89-bdb2-4235-9b6b-e65cb73a4167.png} +0 -0
- /kotonebot/kaa/sprites/{e866d8b1-4f61-45bf-8170-5229f53c047a.png → 14d09c44-3897-4c81-b615-19c35d0f3793.png} +0 -0
- /kotonebot/kaa/sprites/{a105d17d-d44c-4798-aeff-70808c91cb47.png → 15191dec-7e33-4721-8068-15c11978e885.png} +0 -0
- /kotonebot/kaa/sprites/{869b1771-b2ce-4872-ab75-2157c47c5b13.png → 15f8f31e-65ce-408d-8556-b799bcefc9d4.png} +0 -0
- /kotonebot/kaa/sprites/{994aa6a6-0189-4a79-8125-56136973b581.png → 20b01af5-907b-4d49-9f5b-a3700ca9c0c3.png} +0 -0
- /kotonebot/kaa/sprites/{92b7d830-3db5-434e-b156-0ac855db480d.png → 242c088b-bc73-4d11-aa31-ee7c71477fb4.png} +0 -0
- /kotonebot/kaa/sprites/{9c1fa1d4-2ae5-4093-abaa-cebb51135721.png → 2f2a7951-a30a-4835-b9f6-3205cfdd2f05.png} +0 -0
- /kotonebot/kaa/sprites/{a33ae1c3-ac69-4783-977e-9f0f1b1a2f8d.png → 3031397e-3d12-4f23-8377-006eca5d2627.png} +0 -0
- /kotonebot/kaa/sprites/{e7022542-4317-4a61-8098-f3f733d8400e.png → 312dbd82-5457-474a-91ce-511f0e4e9c80.png} +0 -0
- /kotonebot/kaa/sprites/{cd8d3d55-f102-419e-a6fd-2ad5ecc4fd2e.png → 31851ad1-df39-4a4f-9ae7-19c1d1c6b51a.png} +0 -0
- /kotonebot/kaa/sprites/{826bf80a-112e-4356-9111-4b7e692ccc82.png → 338b699a-d556-4b80-a577-123442c3db45.png} +0 -0
- /kotonebot/kaa/sprites/{d8136469-6d73-4f82-a79c-fee83c3e93a8.png → 35319890-98e3-4f75-b969-6b8576ef668d.png} +0 -0
- /kotonebot/kaa/sprites/{96cf0633-6531-499b-b1cc-6670ab710293.png → 3536f829-70d3-48f9-8fd4-b65eab7502f3.png} +0 -0
- /kotonebot/kaa/sprites/{31a52dc8-b7fb-4ff6-a261-eb90a918603c.png → 35516b69-a4f4-4ad4-8af4-35043475ee90.png} +0 -0
- /kotonebot/kaa/sprites/{d747239f-7620-4f23-9ac7-cf2d34889266.png → 36d71d33-09c9-4be8-b184-ccf40f700333.png} +0 -0
- /kotonebot/kaa/sprites/{b44f5e5b-e999-4427-8a9f-f76c6485f4a5.png → 379d5084-637f-45e8-8bd8-789eaa919821.png} +0 -0
- /kotonebot/kaa/sprites/{0a430873-8c12-4ce2-a5de-ab9790c08344.png → 3851303a-e3a0-46eb-aa7e-b47fb41946f7.png} +0 -0
- /kotonebot/kaa/sprites/{ff77d221-8444-4d0f-8c93-0223a97e2a98.png → 3d1aa368-e198-478f-a47f-49818efbaec8.png} +0 -0
- /kotonebot/kaa/sprites/{333fe6d3-0be7-40fb-a2a3-364f98758f2a.png → 3f5907a9-7fe4-4f46-8e46-a96ac7fa3923.png} +0 -0
- /kotonebot/kaa/sprites/{0decaa6a-b9a9-4d9b-829a-0fc1f67538b4.png → 40c0f296-d29e-4e05-aaff-a212339b742e.png} +0 -0
- /kotonebot/kaa/sprites/{c1ad996a-925e-41b5-b26c-d48b8ded21d2.png → 43e72796-a644-4d9b-a817-8add011d9a75.png} +0 -0
- /kotonebot/kaa/sprites/{e2fae2a4-bb19-4f49-b382-47e504ec26d3.png → 469c2b41-4171-4902-acc5-da0c807886ab.png} +0 -0
- /kotonebot/kaa/sprites/{559df9b9-e74d-45af-a300-77d3424e69c6.png → 497e7930-f423-457a-8168-b1a1532bb1e9.png} +0 -0
- /kotonebot/kaa/sprites/{e41bb5df-164d-4760-9db6-d5d5d763bb5f.png → 49a43af3-17e3-4434-ba4d-519775ccaea9.png} +0 -0
- /kotonebot/kaa/sprites/{f9b2f64d-f829-4b13-9704-c5f00fb956be.png → 49b9a298-e847-4322-99a2-c0588c3542fe.png} +0 -0
- /kotonebot/kaa/sprites/{645744c4-3bbf-4ea2-8f46-4725fff874b3.png → 4a1902aa-01db-46bb-bea5-88ac62c82562.png} +0 -0
- /kotonebot/kaa/sprites/{c0fc7de5-b842-4c70-9cf2-89d833bfe7a6.png → 4a96a728-6303-4ae3-8e0c-9f1e8e5f86a7.png} +0 -0
- /kotonebot/kaa/sprites/{73f4204e-8281-47cc-9dce-6bb8280c4ce5.png → 4b7c4221-a679-47f6-929d-0ef514894b27.png} +0 -0
- /kotonebot/kaa/sprites/{c1b1125f-542b-4e63-9c86-5d2e35a89a10.png → 4d355e36-9169-43e4-bd58-2836ee3e56e0.png} +0 -0
- /kotonebot/kaa/sprites/{ad8ee599-88a8-429c-8982-99086e552dcc.png → 4eb97d68-cd47-4100-9c3b-35b5c86b4bdf.png} +0 -0
- /kotonebot/kaa/sprites/{7a479871-547e-4098-9cdd-6c9bb9f7449a.png → 515a2ff0-36b8-4f2f-9902-e6c1b9796586.png} +0 -0
- /kotonebot/kaa/sprites/{02e0aa0d-4094-4bdc-8625-1a063733615b.png → 51a3ed29-92b9-4429-9e50-783d1b8dc6a7.png} +0 -0
- /kotonebot/kaa/sprites/{22d5a7d5-59a0-4137-b02e-1a7af86d4250.png → 52d3438b-afae-4c7a-abe5-7ed530c7558c.png} +0 -0
- /kotonebot/kaa/sprites/{5bf00cba-9aab-4ffe-b20b-8f5e74279276.png → 540ee3b5-ca8f-4091-80a6-ce774d95e5f7.png} +0 -0
- /kotonebot/kaa/sprites/{05ff5efd-0f76-47ce-bc89-237266bc17c0.png → 54a15298-ecaf-4cc5-b8a2-5b0d8f8add41.png} +0 -0
- /kotonebot/kaa/sprites/{1f9165e6-77ee-403e-9b76-99c114527dbb.png → 554c0ff6-0a05-419d-85f9-5ced260d0d2e.png} +0 -0
- /kotonebot/kaa/sprites/{79bc56c5-eae6-4389-9116-4a9e182d6bf3.png → 55e4ef75-ba8e-4230-819c-450cf14b08cd.png} +0 -0
- /kotonebot/kaa/sprites/{cd4cbd7b-df80-45bb-a053-cc333a806934.png → 5824ef5f-6776-402c-b78c-ae79cc4cc878.png} +0 -0
- /kotonebot/kaa/sprites/{804a4b05-1ca3-4915-bf23-a66ccdc34404.png → 5a393483-c631-47fd-805c-c460c23b8f9e.png} +0 -0
- /kotonebot/kaa/sprites/{e5d15c50-45ee-4de9-8b97-4630cbd8f01a.png → 5b75cae4-a853-402c-acec-edbfef94342a.png} +0 -0
- /kotonebot/kaa/sprites/{1a3d18a4-7d91-4182-9e40-e60d73fed365.png → 5c9ae62c-488f-4109-a4d2-d2385c32043d.png} +0 -0
- /kotonebot/kaa/sprites/{7344e180-251b-465a-a8cf-974477f7ad44.png → 5cdd71be-c8cd-4310-b6f4-5e97ddbeb46e.png} +0 -0
- /kotonebot/kaa/sprites/{67a81c23-4ce4-45e3-bfa8-1136fb14b831.png → 5d5cb13b-c1fd-4808-b352-b21291a9ff0b.png} +0 -0
- /kotonebot/kaa/sprites/{4e21f02d-d5e1-49eb-946a-8edc74d0f1f7.png → 5d6c4462-3d7c-42eb-ab3e-195ebf845a09.png} +0 -0
- /kotonebot/kaa/sprites/{d7f604a6-c663-44db-b1d3-c9792eb3daa4.png → 5d94e628-82ff-4531-b70a-b13297491bea.png} +0 -0
- /kotonebot/kaa/sprites/{74521b6f-de5e-4ba8-a3c9-c6ba01070498.png → 5dc2dca3-48bd-4eee-af89-1a1d30593bd5.png} +0 -0
- /kotonebot/kaa/sprites/{b604e25d-680a-4e02-a012-2e593b5bc276.png → 5f0c2a57-efd0-4094-9f71-6f6fe97316f6.png} +0 -0
- /kotonebot/kaa/sprites/{fd610de1-b023-4747-8c1b-72f89b1c5647.png → 610348f2-6262-4cd1-8fc3-e7470f85580c.png} +0 -0
- /kotonebot/kaa/sprites/{5be4f6c7-2baa-42f3-a5a5-99ca0830cc30.png → 613e9b10-b2eb-44ea-b6d9-9310c0e1bdcf.png} +0 -0
- /kotonebot/kaa/sprites/{72c1804f-db8c-40fa-bc79-6533f2861a5d.png → 618b21ad-ab8b-436a-8eb8-bd320a198c9f.png} +0 -0
- /kotonebot/kaa/sprites/{572077d4-7ee2-449a-b4f0-66239b0d7aff.png → 61a09df6-7443-436c-9ef0-1d5a1cae1509.png} +0 -0
- /kotonebot/kaa/sprites/{321b54c8-c69b-4437-931d-655882dabeed.png → 64be274e-e8ad-4938-84c1-5d8aabcd10d8.png} +0 -0
- /kotonebot/kaa/sprites/{22ee3f1b-ddcb-48bf-85dd-8423f85e3199.png → 671b4a55-023a-434d-b29a-e844fe528e6b.png} +0 -0
- /kotonebot/kaa/sprites/{668002b6-805b-467b-a703-203fb75444f4.png → 6e5e9cf9-80b0-4241-a222-ff50dbd89a0c.png} +0 -0
- /kotonebot/kaa/sprites/{4bd66b38-78d3-4a27-816b-d315039a8bb6.png → 6ef59649-bbb3-42b6-a6b0-eac4f35a3da4.png} +0 -0
- /kotonebot/kaa/sprites/{7b3c6860-fbbe-48aa-aadf-8062fa88f1fe.png → 75a2093d-8743-427e-8d24-ae9a69fa14c1.png} +0 -0
- /kotonebot/kaa/sprites/{371a3192-101c-45ef-9da4-2ed389770c0f.png → 76bde19a-4b1b-4e52-86d9-f56be7529c71.png} +0 -0
- /kotonebot/kaa/sprites/{ef39804e-8d2d-40f6-8d13-bd2877d1353a.png → 77d06f4d-8214-4306-9dc5-035c720f7256.png} +0 -0
- /kotonebot/kaa/sprites/{24cd42fd-bb3b-4fc6-b40d-d3e3e36fe9f1.png → 78b642d3-9a2c-4c17-8872-3cc78211f4a0.png} +0 -0
- /kotonebot/kaa/sprites/{0bab7080-9a37-4c27-9821-8df36d49b678.png → 7a9d1c39-b306-4cb0-be2f-7a5963099949.png} +0 -0
- /kotonebot/kaa/sprites/{b1d1dfab-51f5-4ae9-b718-cdf46774c0ff.png → 7ddda828-c8b0-4331-864f-99b85b7c5557.png} +0 -0
- /kotonebot/kaa/sprites/{5edef075-4843-4dc9-840f-ae445cbe0730.png → 81399fd9-f254-4d0e-9775-ad451c237a4e.png} +0 -0
- /kotonebot/kaa/sprites/{705d9ecf-faf8-40f4-b701-637cec822c1e.png → 81526e97-1b8d-433f-a5c9-907e4e8c85cd.png} +0 -0
- /kotonebot/kaa/sprites/{ecd44a4a-e1ca-4a86-ae0d-2306a672613f.png → 818e2370-8fb9-4e6c-ab78-58e86d6525b5.png} +0 -0
- /kotonebot/kaa/sprites/{4f58031c-36b9-4baf-bccf-11c05d83bd19.png → 8431cc52-0041-4425-808c-dcd4d196506c.png} +0 -0
- /kotonebot/kaa/sprites/{13535ecd-bdf5-4ff7-aa2c-6ecb20fe9c06.png → 85a49ff3-6075-4797-8b7f-35851a843698.png} +0 -0
- /kotonebot/kaa/sprites/{d22ca9e0-001d-43d6-a557-1c76c5a27c81.png → 86062e91-d6c1-44cf-9f8c-26a8b9dd8686.png} +0 -0
- /kotonebot/kaa/sprites/{0bbfb5b0-f0f7-4ad9-86f7-a2adb01a6371.png → 860c3d98-e263-482f-95fb-4fc9c472e8b8.png} +0 -0
- /kotonebot/kaa/sprites/{ed5d2bf3-405c-4165-88d0-9f8a4be968c6.png → 8669ce44-dec7-47c2-aafd-3f2fbfd1d083.png} +0 -0
- /kotonebot/kaa/sprites/{f0786a26-81b5-4e76-b577-db70ab3fab50.png → 86b15801-c932-4034-bed8-fd76b0f65916.png} +0 -0
- /kotonebot/kaa/sprites/{80fb515c-4323-422d-a24c-80a3bf702f1d.png → 893b015d-6894-4e74-880e-d22859a25662.png} +0 -0
- /kotonebot/kaa/sprites/{fdfecda8-2fe0-487e-b5fe-6358274bb9ff.png → 8c0fa5fa-cebb-4ae7-bd1c-b542c9cbf694.png} +0 -0
- /kotonebot/kaa/sprites/{73af305f-840f-4325-abae-b3519fba672a.png → 913a1d17-54fe-4c8f-ac50-ef7f39600b86.png} +0 -0
- /kotonebot/kaa/sprites/{c2667677-cbff-4dd4-a401-e0963e7224f4.png → 964c6b90-f526-4199-9523-d8124373a56b.png} +0 -0
- /kotonebot/kaa/sprites/{db94ffb7-a09d-4a51-b420-b930851c9db4.png → 97c281a9-ebb0-4f54-b644-b7ed7dd65f81.png} +0 -0
- /kotonebot/kaa/sprites/{48c257f8-3583-49f7-b01a-ba7d251086ac.png → 998fc84a-af71-4fa5-8aa4-e0bfeb9c53ea.png} +0 -0
- /kotonebot/kaa/sprites/{469006bc-a011-46e4-bcde-992be888456e.png → 9cbf7f6e-fe77-463b-9c60-495dc823510a.png} +0 -0
- /kotonebot/kaa/sprites/{4d6c198a-0e34-4c80-86d1-7789b2082d64.png → 9ce7d48e-295d-47b2-96eb-f3ce697c1b37.png} +0 -0
- /kotonebot/kaa/sprites/{a3c12040-2b11-4038-b830-215fb7b6f359.png → 9dcca89b-c92b-4708-8f19-facd40d09a65.png} +0 -0
- /kotonebot/kaa/sprites/{fbd816df-7ae6-40a4-b4d4-5708f5ba4a7c.png → 9e369992-ea8c-4c15-88d3-1344319978b0.png} +0 -0
- /kotonebot/kaa/sprites/{54bb5fcf-be61-4af8-bb19-a3c5113cf9e1.png → 9f9003ba-468f-406f-a82f-1b7a23ef347c.png} +0 -0
- /kotonebot/kaa/sprites/{309105d4-073a-47c9-8c5c-d593aa497723.png → a2bf4e11-fbc3-4172-bc0b-b16f8f59e68c.png} +0 -0
- /kotonebot/kaa/sprites/{111a03e6-e401-4ad5-b5dc-d5124e8f1ab0.png → a546e254-0490-43df-a291-a9a5c2b4c34a.png} +0 -0
- /kotonebot/kaa/sprites/{7736a171-9221-4cda-8288-908997abeff2.png → aacd229c-d307-4a20-a388-84d8f4afb4a5.png} +0 -0
- /kotonebot/kaa/sprites/{1bfce48a-b151-406e-a6f5-863cb68cbbf2.png → b003bef5-53db-4032-b1bd-d5075de365a8.png} +0 -0
- /kotonebot/kaa/sprites/{b2f7a430-5777-4861-8435-5419394e5ee8.png → b641a122-4734-43e1-b22f-468464a0cff1.png} +0 -0
- /kotonebot/kaa/sprites/{a82e06fb-a02e-4be5-a7b4-4d2758914fcf.png → bc7303f3-43e9-4ece-9206-5f9c779b813b.png} +0 -0
- /kotonebot/kaa/sprites/{f74fc514-61f1-4068-bdf4-754fcaf8ac89.png → bd7a6754-fffc-4315-987f-5ba32d95b697.png} +0 -0
- /kotonebot/kaa/sprites/{c7aa3f89-8a5e-4685-9297-4fc892bfdd81.png → c39f2006-442b-4ab7-99bb-3dfa0673f05d.png} +0 -0
- /kotonebot/kaa/sprites/{6bf5556a-8f4e-41d7-8ab5-d683ad1b47a8.png → c70f4634-6821-4480-a615-b5f9cdc578c1.png} +0 -0
- /kotonebot/kaa/sprites/{89c0e675-3fd4-456a-8ae7-3bfb248b7281.png → c774098e-d782-455c-80a9-5bad3713129d.png} +0 -0
- /kotonebot/kaa/sprites/{09433024-3dfe-4fcb-9d67-cf442b58f31b.png → c7e3736a-0e0f-474a-9386-f58292a45b92.png} +0 -0
- /kotonebot/kaa/sprites/{48d2f007-8c1b-43fc-bd3f-f0b10d2a0c88.png → c90b582c-8570-48b4-98c0-62d5b067ca2c.png} +0 -0
- /kotonebot/kaa/sprites/{9bb1a400-935a-4c5e-838b-fca502c49aba.png → c9d3699b-c8b1-4294-9b48-103df4ab6c65.png} +0 -0
- /kotonebot/kaa/sprites/{157dd58d-e319-4e0c-a37a-638e1a31c60b.png → cc9483c3-c895-4dcc-b3f2-0934ba1ad42e.png} +0 -0
- /kotonebot/kaa/sprites/{43d65b3f-bbae-4e29-a7bf-539379c1b072.png → cec49286-3d48-4fe0-8911-6a1b17d1ac20.png} +0 -0
- /kotonebot/kaa/sprites/{56a8c0ca-4659-4de2-9bce-55ce86a40d75.png → cef78712-d9ae-4d6e-8d7d-d047d48fbb98.png} +0 -0
- /kotonebot/kaa/sprites/{12e8d3f1-494a-46f5-908f-f621a0c57ec6.png → d06fd859-4678-4593-b096-c86b38810cb7.png} +0 -0
- /kotonebot/kaa/sprites/{ba955365-1328-4018-83a2-bfe818f8f172.png → d19c37ff-d5c1-4316-8424-e69ccb5c2523.png} +0 -0
- /kotonebot/kaa/sprites/{695f8d57-b2c9-4a6d-9ae9-1b49ee3eb22a.png → d26b60f7-d15c-4563-bedc-dd6e7e4078b2.png} +0 -0
- /kotonebot/kaa/sprites/{910d307b-6461-4950-badb-509975d0b797.png → d26bf52c-cb1b-4ebf-9c03-ff3f2d245959.png} +0 -0
- /kotonebot/kaa/sprites/{7e8164f6-a9e4-4600-b776-77b35a490933.png → d5fd6c73-4ad8-47b5-89be-c7b137a9950f.png} +0 -0
- /kotonebot/kaa/sprites/{05bfd235-2077-479a-8c43-11fb49316000.png → d696062b-9b58-4af1-835e-2cf5a0a0fbeb.png} +0 -0
- /kotonebot/kaa/sprites/{03458cf9-8ab0-4908-9a56-9c5c7e06bc9b.png → da7a329e-339e-4ee7-8775-bca505a1980d.png} +0 -0
- /kotonebot/kaa/sprites/{2f81e70a-f2af-420f-9b6b-6338c391911f.png → dedb8499-5881-4add-914f-ff0049285dae.png} +0 -0
- /kotonebot/kaa/sprites/{b3d1f8d4-1393-4206-b78e-a5495d8fb930.png → dedea21b-f21d-4621-a213-70ad03faec58.png} +0 -0
- /kotonebot/kaa/sprites/{f65a4495-f044-44de-bf0d-c869e637d5d3.png → dff74cce-ba2d-44aa-b924-183259080a32.png} +0 -0
- /kotonebot/kaa/sprites/{b3e72de2-e103-49a3-b0f2-8593cff87c4e.png → e0246b0d-f0cf-49d4-8423-7da46e75a575.png} +0 -0
- /kotonebot/kaa/sprites/{624555b9-31e3-46a3-8078-55619eaa40b9.png → e1b6b32b-c797-4f1d-aa2b-e7320083a9a6.png} +0 -0
- /kotonebot/kaa/sprites/{90a9c819-ee6b-4b3e-a0e4-ce484c6e413d.png → e23e3f19-03f6-4507-9128-115191272b90.png} +0 -0
- /kotonebot/kaa/sprites/{cc829886-23e8-4d47-b4c4-37ca20381180.png → e2eb3bae-6451-40b9-bbff-90f11dca1904.png} +0 -0
- /kotonebot/kaa/sprites/{6a7d061e-682b-42c1-97d5-121c52921e8b.png → e46e1b6d-6702-46bf-a07e-aec8d183453f.png} +0 -0
- /kotonebot/kaa/sprites/{de709296-e411-465f-86fc-5daf5ca83cef.png → e5297036-9934-44a4-a761-a6a49ae06e3e.png} +0 -0
- /kotonebot/kaa/sprites/{52620946-b92c-42c7-9fcc-0ff13388fd0d.png → e7da5988-0e83-44ad-888b-246365473f9e.png} +0 -0
- /kotonebot/kaa/sprites/{05f8f996-a38a-45d9-8ff9-720b6c4fd599.png → eb8d208a-dbcc-43ca-a8ac-098e1005ebfa.png} +0 -0
- /kotonebot/kaa/sprites/{8e8a0b57-0231-4ed6-958e-3196f7c9ca7b.png → ebe4ce64-98a9-40f2-9fde-3d5cdae673c7.png} +0 -0
- /kotonebot/kaa/sprites/{4a235eaa-46f1-4f71-b54d-ada0ade44572.png → ef2ad3df-3f89-4a48-8fc3-c70a8adc1044.png} +0 -0
- /kotonebot/kaa/sprites/{f8cbb089-a63e-4e40-9238-26d14da2c459.png → f05e410d-15b8-4831-bcc1-4cd8af07c882.png} +0 -0
- /kotonebot/kaa/sprites/{550fc45d-22c0-4a7c-a324-2c4ff107ab39.png → f1fac13a-84f3-42bd-9b52-e0ba90bc5255.png} +0 -0
- /kotonebot/kaa/sprites/{ad784a29-f0e2-4037-976b-45143db8441c.png → f7c34ab6-c165-48b7-ad5a-0b60613ce1bc.png} +0 -0
- /kotonebot/kaa/sprites/{0439399f-5fca-43f9-a105-99342ff04d2e.png → fa80b14e-953f-44bd-a4ad-99aefd276fd7.png} +0 -0
- /kotonebot/kaa/sprites/{7cea265a-fca5-43d0-b2da-067c8fff4d72.png → fe35655e-701b-4081-8df8-c17a7252acef.png} +0 -0
- /kotonebot/kaa/sprites/{da3e7cee-d77b-4e62-b703-ed257706dd39.png → fe853ac7-934e-4b4a-bcc7-b986e057dfcf.png} +0 -0
- /kotonebot/kaa/sprites/{1f8f8c46-43ec-4449-be9f-2e96da11da1e.png → ffda716c-2903-4ec7-8c59-aab5b8ad10bb.png} +0 -0
- /kotonebot/kaa/sprites/{4c72f39e-1182-4479-867f-8207744ee4fd.png → fff33200-c947-49f2-ab86-3ac98937fa36.png} +0 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.28.0.dist-info}/WHEEL +0 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.28.0.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.28.0.dist-info}/licenses/LICENSE +0 -0
- {ksaa-2025.6.8.0.dist-info → ksaa-2025.6.28.0.dist-info}/top_level.txt +0 -0
|
@@ -25,7 +25,7 @@ from typing_extensions import deprecated
|
|
|
25
25
|
import cv2
|
|
26
26
|
from cv2.typing import MatLike
|
|
27
27
|
|
|
28
|
-
from kotonebot.client.device import Device
|
|
28
|
+
from kotonebot.client.device import Device, AndroidDevice, WindowsDevice
|
|
29
29
|
from kotonebot.backend.flow_controller import FlowController
|
|
30
30
|
import kotonebot.backend.image as raw_image
|
|
31
31
|
from kotonebot.backend.image import (
|
|
@@ -46,12 +46,10 @@ from kotonebot.backend.color import (
|
|
|
46
46
|
from kotonebot.backend.ocr import (
|
|
47
47
|
Ocr, OcrResult, OcrResultList, jp, en, StringMatchFunction
|
|
48
48
|
)
|
|
49
|
-
from kotonebot.client.factory import create_device
|
|
50
49
|
from kotonebot.config.manager import load_config, save_config
|
|
51
50
|
from kotonebot.config.base_config import UserConfig
|
|
52
51
|
from kotonebot.backend.core import Image, HintBox
|
|
53
52
|
from kotonebot.errors import KotonebotWarning
|
|
54
|
-
from kotonebot.client.factory import DeviceImpl
|
|
55
53
|
from kotonebot.backend.preprocessor import PreprocessorProtocol
|
|
56
54
|
from kotonebot.primitives import Rect
|
|
57
55
|
|
|
@@ -717,9 +715,10 @@ class Forwarded:
|
|
|
717
715
|
raise ValueError(f"Forwarded object {self._FORWARD_name} called before initialization.")
|
|
718
716
|
setattr(self._FORWARD_getter(), name, value)
|
|
719
717
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
718
|
+
|
|
719
|
+
T_Device = TypeVar('T_Device', bound=Device)
|
|
720
|
+
class ContextDevice(Generic[T_Device], Device):
|
|
721
|
+
def __init__(self, device: T_Device):
|
|
723
722
|
self._device = device
|
|
724
723
|
|
|
725
724
|
def screenshot(self, *, force: bool = False):
|
|
@@ -746,26 +745,42 @@ class ContextDevice(Device):
|
|
|
746
745
|
current._screenshot = img
|
|
747
746
|
return img
|
|
748
747
|
|
|
749
|
-
def __getattribute__(self, name: str)
|
|
750
|
-
if name in ['_device', 'screenshot']:
|
|
748
|
+
def __getattribute__(self, name: str):
|
|
749
|
+
if name in ['_device', 'screenshot', 'of_android', 'of_windows']:
|
|
751
750
|
return object.__getattribute__(self, name)
|
|
752
751
|
else:
|
|
753
752
|
return getattr(self._device, name)
|
|
754
753
|
|
|
755
754
|
def __setattr__(self, name: str, value: Any):
|
|
756
|
-
if name in ['_device', 'screenshot']:
|
|
755
|
+
if name in ['_device', 'screenshot', 'of_android', 'of_windows']:
|
|
757
756
|
return object.__setattr__(self, name, value)
|
|
758
757
|
else:
|
|
759
758
|
return setattr(self._device, name, value)
|
|
760
759
|
|
|
760
|
+
def of_android(self) -> 'ContextDevice | AndroidDevice':
|
|
761
|
+
"""
|
|
762
|
+
确保此 ContextDevice 底层为 Android 平台。
|
|
763
|
+
同时通过返回的对象可以调用 Android 平台特有的方法。
|
|
764
|
+
"""
|
|
765
|
+
if not isinstance(self._device, AndroidDevice):
|
|
766
|
+
raise ValueError("Device is not AndroidDevice")
|
|
767
|
+
return self
|
|
768
|
+
|
|
769
|
+
def of_windows(self) -> 'ContextDevice | WindowsDevice':
|
|
770
|
+
"""
|
|
771
|
+
确保此 ContextDevice 底层为 Windows 平台。
|
|
772
|
+
同时通过返回的对象可以调用 Windows 平台特有的方法。
|
|
773
|
+
"""
|
|
774
|
+
if not isinstance(self._device, WindowsDevice):
|
|
775
|
+
raise ValueError("Device is not WindowsDevice")
|
|
776
|
+
return self
|
|
761
777
|
|
|
762
778
|
class Context(Generic[T]):
|
|
763
779
|
def __init__(
|
|
764
780
|
self,
|
|
765
781
|
config_path: str,
|
|
766
782
|
config_type: Type[T],
|
|
767
|
-
|
|
768
|
-
device: Optional[Device] = None
|
|
783
|
+
device: Device
|
|
769
784
|
):
|
|
770
785
|
self.__ocr = ContextOcr(self)
|
|
771
786
|
self.__image = ContextImage(self)
|
|
@@ -773,14 +788,7 @@ class Context(Generic[T]):
|
|
|
773
788
|
self.__vars = ContextGlobalVars()
|
|
774
789
|
self.__debug = ContextDebug(self)
|
|
775
790
|
self.__config = ContextConfig[T](self, config_path, config_type)
|
|
776
|
-
|
|
777
|
-
ip = self.config.current.backend.adb_ip
|
|
778
|
-
port = self.config.current.backend.adb_port
|
|
779
|
-
# TODO: 处理链接失败情况
|
|
780
|
-
if screenshot_impl is None:
|
|
781
|
-
screenshot_impl = self.config.current.backend.screenshot_impl
|
|
782
|
-
logger.info(f'Using "{screenshot_impl}" as screenshot implementation')
|
|
783
|
-
self.__device = ContextDevice(device or create_device(f'{ip}:{port}', screenshot_impl))
|
|
791
|
+
self.__device = ContextDevice(device)
|
|
784
792
|
|
|
785
793
|
def inject(
|
|
786
794
|
self,
|
|
@@ -891,8 +899,7 @@ def init_context(
|
|
|
891
899
|
config_path: str = 'config.json',
|
|
892
900
|
config_type: Type[T] = dict[str, Any],
|
|
893
901
|
force: bool = False,
|
|
894
|
-
|
|
895
|
-
target_device: Device | None = None,
|
|
902
|
+
target_device: Device,
|
|
896
903
|
):
|
|
897
904
|
"""
|
|
898
905
|
初始化 Context 模块。
|
|
@@ -903,8 +910,6 @@ def init_context(
|
|
|
903
910
|
默认为 `dict[str, Any]`,即普通的 JSON 数据,不包含任何类型信息。
|
|
904
911
|
:param force: 是否强制重新初始化。
|
|
905
912
|
若为 `True`,则忽略已存在的 Context 实例,并重新创建一个新的实例。
|
|
906
|
-
:param screenshot_impl: 截图实现。
|
|
907
|
-
若为 `None`,则使用默认配置文件中指定的截图实现。
|
|
908
913
|
:param target_device: 目标设备
|
|
909
914
|
"""
|
|
910
915
|
global _c, device, ocr, image, color, vars, debug, config
|
|
@@ -913,8 +918,7 @@ def init_context(
|
|
|
913
918
|
_c = Context(
|
|
914
919
|
config_path=config_path,
|
|
915
920
|
config_type=config_type,
|
|
916
|
-
|
|
917
|
-
device=target_device
|
|
921
|
+
device=target_device,
|
|
918
922
|
)
|
|
919
923
|
device._FORWARD_getter = lambda: _c.device # type: ignore
|
|
920
924
|
ocr._FORWARD_getter = lambda: _c.ocr # type: ignore
|
|
@@ -216,8 +216,6 @@ def wait_message_all_done():
|
|
|
216
216
|
threading.Thread(target=_wait, daemon=True).start()
|
|
217
217
|
|
|
218
218
|
if __name__ == "__main__":
|
|
219
|
-
from kotonebot.backend.context import init_context
|
|
220
|
-
init_context()
|
|
221
219
|
debug_vars.debug.hide_server_log = False
|
|
222
220
|
process = subprocess.Popen(["pylsp", "--port", "5479", "--ws"])
|
|
223
221
|
print("LSP started. PID=", process.pid)
|
kotonebot/backend/dispatch.py
CHANGED
|
@@ -328,20 +328,4 @@ class SimpleDispatcher:
|
|
|
328
328
|
self.result = self.timeout_result
|
|
329
329
|
break
|
|
330
330
|
device.screenshot()
|
|
331
|
-
return self.result
|
|
332
|
-
|
|
333
|
-
if __name__ == '__main__':
|
|
334
|
-
from .context.task_action import action
|
|
335
|
-
from .context import init_context
|
|
336
|
-
init_context()
|
|
337
|
-
@action('inner', dispatcher=True)
|
|
338
|
-
def inner(ctx: DispatcherContext):
|
|
339
|
-
print('inner')
|
|
340
|
-
ctx.finish()
|
|
341
|
-
|
|
342
|
-
@action('test', dispatcher=True)
|
|
343
|
-
def test(ctx: DispatcherContext):
|
|
344
|
-
print('test')
|
|
345
|
-
inner()
|
|
346
|
-
ctx.finish()
|
|
347
|
-
test()
|
|
331
|
+
return self.result
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from functools import lru_cache, partial
|
|
3
|
+
from typing import Callable, Any, overload, Literal, Generic, TypeVar, cast, get_args, get_origin
|
|
4
|
+
|
|
5
|
+
from cv2.typing import MatLike
|
|
6
|
+
|
|
7
|
+
from kotonebot.util import Interval
|
|
8
|
+
from kotonebot import device, image, ocr
|
|
9
|
+
from kotonebot.backend.core import Image
|
|
10
|
+
from kotonebot.backend.ocr import TextComparator
|
|
11
|
+
from kotonebot.client.protocol import ClickableObjectProtocol
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LoopAction:
|
|
15
|
+
def __init__(self, loop: 'Loop', func: Callable[[], ClickableObjectProtocol | None]):
|
|
16
|
+
self.loop = loop
|
|
17
|
+
self.func = func
|
|
18
|
+
self.result: ClickableObjectProtocol | None = None
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def found(self):
|
|
22
|
+
"""
|
|
23
|
+
是否找到结果。若父 Loop 未在运行中,则返回 False。
|
|
24
|
+
"""
|
|
25
|
+
if not self.loop.running:
|
|
26
|
+
return False
|
|
27
|
+
return bool(self.result)
|
|
28
|
+
|
|
29
|
+
def __bool__(self):
|
|
30
|
+
return self.found
|
|
31
|
+
|
|
32
|
+
def reset(self):
|
|
33
|
+
"""
|
|
34
|
+
重置 LoopAction,以复用此对象。
|
|
35
|
+
"""
|
|
36
|
+
self.result = None
|
|
37
|
+
|
|
38
|
+
def do(self):
|
|
39
|
+
"""
|
|
40
|
+
执行 LoopAction。
|
|
41
|
+
:return: 执行结果。
|
|
42
|
+
"""
|
|
43
|
+
if not self.loop.running:
|
|
44
|
+
return
|
|
45
|
+
if self.loop.found_anything:
|
|
46
|
+
# 本轮循环已执行任意操作,因此不需要再继续检测
|
|
47
|
+
return
|
|
48
|
+
self.result = self.func()
|
|
49
|
+
if self.result:
|
|
50
|
+
self.loop.found_anything = True
|
|
51
|
+
|
|
52
|
+
def click(self, *, at: tuple[int, int] | None = None):
|
|
53
|
+
"""
|
|
54
|
+
点击寻找结果。若结果为空,会跳过执行。
|
|
55
|
+
|
|
56
|
+
:return:
|
|
57
|
+
"""
|
|
58
|
+
if self.result:
|
|
59
|
+
if at is not None:
|
|
60
|
+
device.click(*at)
|
|
61
|
+
else:
|
|
62
|
+
device.click(self.result)
|
|
63
|
+
|
|
64
|
+
def call(self, func: Callable[[ClickableObjectProtocol], Any]):
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Loop:
|
|
69
|
+
def __init__(
|
|
70
|
+
self,
|
|
71
|
+
*,
|
|
72
|
+
timeout: float = 300,
|
|
73
|
+
interval: float = 0.3,
|
|
74
|
+
auto_screenshot: bool = True
|
|
75
|
+
):
|
|
76
|
+
self.running = True
|
|
77
|
+
self.found_anything = False
|
|
78
|
+
self.auto_screenshot = auto_screenshot
|
|
79
|
+
"""
|
|
80
|
+
是否在每次循环开始时(Loop.tick() 被调用时)截图。
|
|
81
|
+
"""
|
|
82
|
+
self.__last_loop: float = -1
|
|
83
|
+
self.__interval = Interval(interval)
|
|
84
|
+
self.screenshot: MatLike | None = None
|
|
85
|
+
"""上次截图时的图像数据。"""
|
|
86
|
+
|
|
87
|
+
def __iter__(self):
|
|
88
|
+
self.__interval.reset()
|
|
89
|
+
return self
|
|
90
|
+
|
|
91
|
+
def __next__(self):
|
|
92
|
+
if not self.running:
|
|
93
|
+
raise StopIteration
|
|
94
|
+
self.found_anything = False
|
|
95
|
+
self.__last_loop = time.time()
|
|
96
|
+
return self.tick()
|
|
97
|
+
|
|
98
|
+
def tick(self):
|
|
99
|
+
self.__interval.wait()
|
|
100
|
+
if self.auto_screenshot:
|
|
101
|
+
self.screenshot = device.screenshot()
|
|
102
|
+
self.__last_loop = time.time()
|
|
103
|
+
self.found_anything = False
|
|
104
|
+
return self
|
|
105
|
+
|
|
106
|
+
def exit(self):
|
|
107
|
+
"""
|
|
108
|
+
结束循环。
|
|
109
|
+
"""
|
|
110
|
+
self.running = False
|
|
111
|
+
|
|
112
|
+
@overload
|
|
113
|
+
def when(self, condition: Image) -> LoopAction:
|
|
114
|
+
...
|
|
115
|
+
|
|
116
|
+
@overload
|
|
117
|
+
def when(self, condition: TextComparator) -> LoopAction:
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
def when(self, condition: Any):
|
|
121
|
+
"""
|
|
122
|
+
判断某个条件是否成立。
|
|
123
|
+
|
|
124
|
+
:param condition:
|
|
125
|
+
:return:
|
|
126
|
+
"""
|
|
127
|
+
if isinstance(condition, Image):
|
|
128
|
+
func = partial(image.find, condition)
|
|
129
|
+
elif isinstance(condition, TextComparator):
|
|
130
|
+
func = partial(ocr.find, condition)
|
|
131
|
+
else:
|
|
132
|
+
raise ValueError('Invalid condition type.')
|
|
133
|
+
la = LoopAction(self, func)
|
|
134
|
+
la.reset()
|
|
135
|
+
la.do()
|
|
136
|
+
return la
|
|
137
|
+
|
|
138
|
+
def until(self, condition: Any):
|
|
139
|
+
"""
|
|
140
|
+
当满足指定条件时,结束循环。
|
|
141
|
+
|
|
142
|
+
等价于 ``loop.when(...).call(lambda _: loop.exit())``
|
|
143
|
+
"""
|
|
144
|
+
return self.when(condition).call(lambda _: self.exit())
|
|
145
|
+
|
|
146
|
+
def click_if(self, condition: Any, *, at: tuple[int, int] | None = None):
|
|
147
|
+
"""
|
|
148
|
+
检测指定对象是否出现,若出现,点击该对象或指定位置。
|
|
149
|
+
|
|
150
|
+
``click_if()`` 等价于 ``loop.when(...).click(...)``。
|
|
151
|
+
|
|
152
|
+
:param condition: 检测目标。
|
|
153
|
+
:param at: 点击位置。若为 None,表示点击找到的目标。
|
|
154
|
+
"""
|
|
155
|
+
return self.when(condition).click(at=at)
|
|
156
|
+
|
|
157
|
+
StateType = TypeVar('StateType')
|
|
158
|
+
class StatedLoop(Loop, Generic[StateType]):
|
|
159
|
+
def __init__(
|
|
160
|
+
self,
|
|
161
|
+
states: list[Any] | None = None,
|
|
162
|
+
initial_state: StateType | None = None,
|
|
163
|
+
*,
|
|
164
|
+
timeout: float = 300,
|
|
165
|
+
interval: float = 0.3,
|
|
166
|
+
auto_screenshot: bool = True
|
|
167
|
+
):
|
|
168
|
+
self.__tmp_states = states
|
|
169
|
+
self.__tmp_initial_state = initial_state
|
|
170
|
+
self.state: StateType
|
|
171
|
+
super().__init__(timeout=timeout, interval=interval, auto_screenshot=auto_screenshot)
|
|
172
|
+
|
|
173
|
+
def __iter__(self):
|
|
174
|
+
# __retrive_state_values() 只能在非 __init__ 中调用
|
|
175
|
+
self.__retrive_state_values()
|
|
176
|
+
return super().__iter__()
|
|
177
|
+
|
|
178
|
+
def __retrive_state_values(self):
|
|
179
|
+
# HACK: __orig_class__ 是 undocumented 属性
|
|
180
|
+
if not hasattr(self, '__orig_class__'):
|
|
181
|
+
# 如果 Foo 不是以参数化泛型的方式实例化的,可能没有 __orig_class__
|
|
182
|
+
if self.state is None:
|
|
183
|
+
raise ValueError('Either specify `states` or use StatedLoop[Literal[...]] syntax.')
|
|
184
|
+
else:
|
|
185
|
+
generic_type_args = get_args(self.__orig_class__) # type: ignore
|
|
186
|
+
if len(generic_type_args) != 1:
|
|
187
|
+
raise ValueError('StatedLoop must have exactly one generic type argument.')
|
|
188
|
+
state_values = get_args(generic_type_args[0])
|
|
189
|
+
if not state_values:
|
|
190
|
+
raise ValueError('StatedLoop must have at least one state value.')
|
|
191
|
+
self.states = cast(tuple[StateType, ...], state_values)
|
|
192
|
+
self.state = self.__tmp_initial_state or self.states[0]
|
|
193
|
+
return state_values
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def StatedLoop2(states: StateType) -> StatedLoop[StateType]:
|
|
197
|
+
state_values = get_args(states)
|
|
198
|
+
return cast(StatedLoop[StateType], Loop())
|
|
199
|
+
|
|
200
|
+
if __name__ == '__main__':
|
|
201
|
+
from kotonebot.kaa.tasks import R
|
|
202
|
+
from kotonebot.backend.ocr import contains
|
|
203
|
+
from kotonebot.backend.context import manual_context, init_context
|
|
204
|
+
|
|
205
|
+
# T = TypeVar('T')
|
|
206
|
+
# class Foo(Generic[T]):
|
|
207
|
+
# def get_literal_params(self) -> list | None:
|
|
208
|
+
# """
|
|
209
|
+
# 尝试获取泛型参数 T (如果它是 Literal 类型) 的参数列表。
|
|
210
|
+
# """
|
|
211
|
+
# # self.__orig_class__ 会是 Foo 的具体参数化类型,
|
|
212
|
+
# # 例如 Foo[Literal['p0', 'p1', 'p2', 'p3', 'ap']]
|
|
213
|
+
# if not hasattr(self, '__orig_class__'):
|
|
214
|
+
# # 如果 Foo 不是以参数化泛型的方式实例化的,可能没有 __orig_class__
|
|
215
|
+
# return None
|
|
216
|
+
#
|
|
217
|
+
# # generic_type_args 是传递给 Foo 的类型参数元组
|
|
218
|
+
# # 例如 (Literal['p0', 'p1', 'p2', 'p3', 'ap'],)
|
|
219
|
+
# generic_type_args = get_args(self.__orig_class__)
|
|
220
|
+
#
|
|
221
|
+
# if not generic_type_args:
|
|
222
|
+
# # Foo 没有类型参数
|
|
223
|
+
# return None
|
|
224
|
+
#
|
|
225
|
+
# # T_type 是 Foo 的第一个类型参数
|
|
226
|
+
# # 例如 Literal['p0', 'p1', 'p2', 'p3', 'ap']
|
|
227
|
+
# t_type = generic_type_args[0]
|
|
228
|
+
#
|
|
229
|
+
# # 检查 T_type 是否是 Literal 类型
|
|
230
|
+
# if get_origin(t_type) is Literal:
|
|
231
|
+
# # literal_args 是 Literal 类型的参数元组
|
|
232
|
+
# # 例如 ('p0', 'p1', 'p2', 'p3', 'ap')
|
|
233
|
+
# literal_args = get_args(t_type)
|
|
234
|
+
# return list(literal_args)
|
|
235
|
+
# else:
|
|
236
|
+
# # T 不是 Literal 类型
|
|
237
|
+
# return None
|
|
238
|
+
# f = Foo[Literal['p0', 'p1', 'p2', 'p3', 'ap']]()
|
|
239
|
+
# values = f.get_literal_params()
|
|
240
|
+
# 1
|
|
241
|
+
|
|
242
|
+
from typing_extensions import reveal_type
|
|
243
|
+
slp = StatedLoop[Literal['p0', 'p1', 'p2', 'p3', 'ap']]()
|
|
244
|
+
for l in slp:
|
|
245
|
+
reveal_type(l.states)
|
|
246
|
+
|
|
247
|
+
# init_context()
|
|
248
|
+
# manual_context().begin()
|
|
249
|
+
# for l in Loop():
|
|
250
|
+
# l.when(R.Produce.ButtonUse).click()
|
|
251
|
+
# l.when(R.Produce.ButtonRefillAP).click()
|
|
252
|
+
# l.when(contains("123")).click()
|
|
253
|
+
# l.click_if(contains("!23"), at=(1, 2))
|
|
254
|
+
|
|
255
|
+
# State = Literal['p0', 'p1', 'p2', 'p3', 'ap']
|
|
256
|
+
# for sl in StatedLoop[State]():
|
|
257
|
+
# match sl.state:
|
|
258
|
+
# case 'p0':
|
|
259
|
+
# sl.click_if(R.Produce.ButtonProduce)
|
|
260
|
+
# sl.click_if(contains('master'))
|
|
261
|
+
# sl.when(R.Produce.ButtonPIdolOverview).goto('p1')
|
|
262
|
+
# # AP 不足
|
|
263
|
+
# sl.when(R.Produce.TextAPInsufficient).goto('ap')
|
|
264
|
+
# case 'ap':
|
|
265
|
+
# pass
|
|
266
|
+
# # p1: 选择偶像
|
|
267
|
+
# case 'p1':
|
|
268
|
+
# sl.call(lambda _: select_idol(idol_skin_id), once=True)
|
|
269
|
+
# sl.when(R.Produce.TextAnotherIdolAvailableDialog).call(dialog.no)
|
|
270
|
+
# sl.click_if(R.Common.ButtonNextNoIcon)
|
|
271
|
+
# sl.until(R.Produce.TextStepIndicator2).goto('p2')
|
|
272
|
+
# case 'p2':
|
|
273
|
+
# sl.when(contains("123")).click()
|
|
274
|
+
# case 'p3':
|
|
275
|
+
# sl.click_if(contains("!23"), at=(1, 2))
|
|
276
|
+
# case _:
|
|
277
|
+
# assert_never(sl.state)
|
kotonebot/client/__init__.py
CHANGED