ksaa 2025.5.23.2__py3-none-any.whl → 2025.6.8.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/bot.py +3 -3
- kotonebot/backend/context/context.py +21 -11
- kotonebot/backend/debug/server.py +3 -3
- kotonebot/backend/flow_controller.py +195 -0
- kotonebot/client/implements/windows.py +18 -13
- kotonebot/kaa/common.py +21 -0
- kotonebot/kaa/main/gr.py +184 -28
- kotonebot/kaa/metadata.py +22 -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-amao-3-012_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-amao-3-012_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-fktn-3-014_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-fktn-3-014_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hrnm-3-012_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hrnm-3-012_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hski-3-013_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hski-3-013_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hume-3-013_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-hume-3-013_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-jsna-3-012_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-jsna-3-012_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-kcna-3-012_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-kcna-3-012_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-shro-3-013_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-shro-3-013_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-ssmk-3-013_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-ssmk-3-013_1.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-ttmr-3-013_0.png +0 -0
- kotonebot/kaa/resources/idol_cards/i_card-skin-ttmr-3-013_1.png +0 -0
- kotonebot/kaa/tasks/R.py +133 -133
- kotonebot/kaa/tasks/end_game.py +14 -0
- kotonebot/kaa/tasks/produce/common.py +1 -0
- kotonebot/kaa/tasks/produce/in_purodyuusu.py +21 -6
- kotonebot/kaa/tasks/produce/non_lesson_actions.py +1 -1
- kotonebot/kaa/tasks/start_game.py +49 -1
- {ksaa-2025.5.23.2.dist-info → ksaa-2025.6.8.0.dist-info}/METADATA +38 -1
- {ksaa-2025.5.23.2.dist-info → ksaa-2025.6.8.0.dist-info}/RECORD +176 -154
- {ksaa-2025.5.23.2.dist-info → ksaa-2025.6.8.0.dist-info}/WHEEL +1 -1
- ksaa-2025.6.8.0.dist-info/licenses/LICENSE +674 -0
- /kotonebot/kaa/sprites/{207c9bc9-d89f-4fa5-8b9a-5dd084708c1f.png → 02e0aa0d-4094-4bdc-8625-1a063733615b.png} +0 -0
- /kotonebot/kaa/sprites/{3a267e0c-d644-410d-a889-cea60ab5e206.png → 03458cf9-8ab0-4908-9a56-9c5c7e06bc9b.png} +0 -0
- /kotonebot/kaa/sprites/{26c544a9-8e09-454d-8ddf-9358f83354e0.png → 0439399f-5fca-43f9-a105-99342ff04d2e.png} +0 -0
- /kotonebot/kaa/sprites/{6624e6af-81d0-47aa-be7c-b03fa1ebed71.png → 05bfd235-2077-479a-8c43-11fb49316000.png} +0 -0
- /kotonebot/kaa/sprites/{824ee5ae-b3c0-4839-b277-f6be5a968f30.png → 05f8f996-a38a-45d9-8ff9-720b6c4fd599.png} +0 -0
- /kotonebot/kaa/sprites/{5d86c075-3156-48c8-8cb2-66be1e32d97b.png → 05ff5efd-0f76-47ce-bc89-237266bc17c0.png} +0 -0
- /kotonebot/kaa/sprites/{4281236e-1fee-48ca-9a5a-70dbd5971801.png → 09433024-3dfe-4fcb-9d67-cf442b58f31b.png} +0 -0
- /kotonebot/kaa/sprites/{69a0d1e3-4a97-494a-a1fe-cf85d1412ccb.png → 0a430873-8c12-4ce2-a5de-ab9790c08344.png} +0 -0
- /kotonebot/kaa/sprites/{ea291981-d7ac-433a-8703-2e7cc6ad5303.png → 0bab7080-9a37-4c27-9821-8df36d49b678.png} +0 -0
- /kotonebot/kaa/sprites/{9255b257-16b6-4c2e-ad93-3fc0ef5aac32.png → 0bbfb5b0-f0f7-4ad9-86f7-a2adb01a6371.png} +0 -0
- /kotonebot/kaa/sprites/{637f8470-1780-4f74-8a4c-d2fdb1fe5b9b.png → 0decaa6a-b9a9-4d9b-829a-0fc1f67538b4.png} +0 -0
- /kotonebot/kaa/sprites/{3436165b-94cb-4fe4-929f-51f3dbe4b7c8.png → 111a03e6-e401-4ad5-b5dc-d5124e8f1ab0.png} +0 -0
- /kotonebot/kaa/sprites/{1630ce5d-cdb1-42b5-9dcb-57aaeabcd46f.png → 12e8d3f1-494a-46f5-908f-f621a0c57ec6.png} +0 -0
- /kotonebot/kaa/sprites/{d7916e81-7de3-49d5-91a7-2ecbba93835e.png → 13535ecd-bdf5-4ff7-aa2c-6ecb20fe9c06.png} +0 -0
- /kotonebot/kaa/sprites/{8314ad8f-1ac4-4ce6-86b5-4d3f11b9ed87.png → 157dd58d-e319-4e0c-a37a-638e1a31c60b.png} +0 -0
- /kotonebot/kaa/sprites/{701f9931-d33f-4443-9b31-24e9553f5133.png → 1a3d18a4-7d91-4182-9e40-e60d73fed365.png} +0 -0
- /kotonebot/kaa/sprites/{2e173b48-333e-44e6-a29f-28f1e8ca450d.png → 1bfce48a-b151-406e-a6f5-863cb68cbbf2.png} +0 -0
- /kotonebot/kaa/sprites/{03f46f59-a90e-4d78-b218-474473e4ec6e.png → 1f8f8c46-43ec-4449-be9f-2e96da11da1e.png} +0 -0
- /kotonebot/kaa/sprites/{0b0ee4bd-78f6-42cd-ae40-ad232bf6e33c.png → 1f9165e6-77ee-403e-9b76-99c114527dbb.png} +0 -0
- /kotonebot/kaa/sprites/{43b335ee-9c0f-4b70-8d22-e1aa209a384c.png → 22d5a7d5-59a0-4137-b02e-1a7af86d4250.png} +0 -0
- /kotonebot/kaa/sprites/{61ed91d6-b4d9-4e82-9155-da706b700ce7.png → 22ee3f1b-ddcb-48bf-85dd-8423f85e3199.png} +0 -0
- /kotonebot/kaa/sprites/{426dcc3e-2556-45b6-9ca9-b9acce8b0222.png → 24cd42fd-bb3b-4fc6-b40d-d3e3e36fe9f1.png} +0 -0
- /kotonebot/kaa/sprites/{9ff6e594-b4c6-4aae-a412-52c83fc5bc3c.png → 2f81e70a-f2af-420f-9b6b-6338c391911f.png} +0 -0
- /kotonebot/kaa/sprites/{99a48c79-ab3a-4688-bed6-1d4c35e720fc.png → 309105d4-073a-47c9-8c5c-d593aa497723.png} +0 -0
- /kotonebot/kaa/sprites/{c96f3076-918f-4dd2-bb01-e74e07086812.png → 31a52dc8-b7fb-4ff6-a261-eb90a918603c.png} +0 -0
- /kotonebot/kaa/sprites/{a26ca6a4-2a8d-4472-86d7-990cc5df01de.png → 321b54c8-c69b-4437-931d-655882dabeed.png} +0 -0
- /kotonebot/kaa/sprites/{d21d3557-6238-4ceb-a53d-3f9147421e80.png → 333fe6d3-0be7-40fb-a2a3-364f98758f2a.png} +0 -0
- /kotonebot/kaa/sprites/{a6e18008-0caa-42d5-ae04-6f015f04a6df.png → 371a3192-101c-45ef-9da4-2ed389770c0f.png} +0 -0
- /kotonebot/kaa/sprites/{3c75ffa8-c197-4e88-949e-75b48621ae20.png → 38b8f119-8de1-49bf-8a5f-a44371de4569.png} +0 -0
- /kotonebot/kaa/sprites/{9d2b4c3f-aa77-4aec-8f78-b25bbd650d5b.png → 43d65b3f-bbae-4e29-a7bf-539379c1b072.png} +0 -0
- /kotonebot/kaa/sprites/{6f4cd73b-dc7d-4671-9481-793d12c606bb.png → 469006bc-a011-46e4-bcde-992be888456e.png} +0 -0
- /kotonebot/kaa/sprites/{71ef7bee-9b67-4968-80a8-f5b658458651.png → 48c257f8-3583-49f7-b01a-ba7d251086ac.png} +0 -0
- /kotonebot/kaa/sprites/{27b26162-2eb6-4513-aa8b-72d1baefd5f7.png → 48d2f007-8c1b-43fc-bd3f-f0b10d2a0c88.png} +0 -0
- /kotonebot/kaa/sprites/{50d923e8-d647-4741-a81d-7ad8ac67a79f.png → 4a235eaa-46f1-4f71-b54d-ada0ade44572.png} +0 -0
- /kotonebot/kaa/sprites/{9b4ea9ad-0d0a-4f0c-8018-da8a24fe4e5f.png → 4bd66b38-78d3-4a27-816b-d315039a8bb6.png} +0 -0
- /kotonebot/kaa/sprites/{95a5c724-2f9f-4d6f-ad44-b5b5d29b9c89.png → 4c72f39e-1182-4479-867f-8207744ee4fd.png} +0 -0
- /kotonebot/kaa/sprites/{fdf42d81-645a-41b5-868e-0a733f32992e.png → 4d6c198a-0e34-4c80-86d1-7789b2082d64.png} +0 -0
- /kotonebot/kaa/sprites/{2888b46f-ab47-4f57-9342-74f3d434a585.png → 4e21f02d-d5e1-49eb-946a-8edc74d0f1f7.png} +0 -0
- /kotonebot/kaa/sprites/{eaa079be-6b26-4e25-ac63-328d6f400c35.png → 4f58031c-36b9-4baf-bccf-11c05d83bd19.png} +0 -0
- /kotonebot/kaa/sprites/{e58f5357-dd17-4498-8643-0c15c433d23e.png → 52620946-b92c-42c7-9fcc-0ff13388fd0d.png} +0 -0
- /kotonebot/kaa/sprites/{32a92eb3-8bc8-4021-ade4-d633deabb8b9.png → 54bb5fcf-be61-4af8-bb19-a3c5113cf9e1.png} +0 -0
- /kotonebot/kaa/sprites/{26159619-42da-42d6-af30-c3d07e6a4a7b.png → 550fc45d-22c0-4a7c-a324-2c4ff107ab39.png} +0 -0
- /kotonebot/kaa/sprites/{f32d9ece-4fef-48a8-9be0-55f23acc5e6b.png → 559df9b9-e74d-45af-a300-77d3424e69c6.png} +0 -0
- /kotonebot/kaa/sprites/{1c18153e-8207-4dc6-a057-ad06c626003d.png → 56a8c0ca-4659-4de2-9bce-55ce86a40d75.png} +0 -0
- /kotonebot/kaa/sprites/{09f7e1c8-9ba3-40fb-b135-b3908956cb63.png → 572077d4-7ee2-449a-b4f0-66239b0d7aff.png} +0 -0
- /kotonebot/kaa/sprites/{c952a585-1004-48d7-b870-e144a60626b5.png → 5be4f6c7-2baa-42f3-a5a5-99ca0830cc30.png} +0 -0
- /kotonebot/kaa/sprites/{c158004f-7e76-4f8d-95e8-deea12251cbe.png → 5bf00cba-9aab-4ffe-b20b-8f5e74279276.png} +0 -0
- /kotonebot/kaa/sprites/{f220b5c7-432d-4fd0-abde-ec0a3a569489.png → 5ca50448-cc21-499a-a685-c5e1c4240c48.png} +0 -0
- /kotonebot/kaa/sprites/{bbc002f3-4c6c-40b1-bfbc-891d8a407412.png → 5edef075-4843-4dc9-840f-ae445cbe0730.png} +0 -0
- /kotonebot/kaa/sprites/{112db090-fb51-413f-8f7b-6859b98bc1eb.png → 624555b9-31e3-46a3-8078-55619eaa40b9.png} +0 -0
- /kotonebot/kaa/sprites/{38030889-3d17-4648-8f37-572da43944cf.png → 645744c4-3bbf-4ea2-8f46-4725fff874b3.png} +0 -0
- /kotonebot/kaa/sprites/{fb2be5fb-f70f-4bfc-8ef9-d08440fafcab.png → 668002b6-805b-467b-a703-203fb75444f4.png} +0 -0
- /kotonebot/kaa/sprites/{b5931274-f987-4bc5-bd00-2296a9be6f68.png → 67a81c23-4ce4-45e3-bfa8-1136fb14b831.png} +0 -0
- /kotonebot/kaa/sprites/{31c249b7-05ef-4e2a-b157-91976f564bef.png → 695f8d57-b2c9-4a6d-9ae9-1b49ee3eb22a.png} +0 -0
- /kotonebot/kaa/sprites/{fc146a5c-c154-4b44-b690-23470d9662e3.png → 6a7d061e-682b-42c1-97d5-121c52921e8b.png} +0 -0
- /kotonebot/kaa/sprites/{b6660670-834a-499d-85c8-a51d8ac2f951.png → 6bf5556a-8f4e-41d7-8ab5-d683ad1b47a8.png} +0 -0
- /kotonebot/kaa/sprites/{bbb5b48b-ba98-4fa3-bd6d-f079c42acabf.png → 705d9ecf-faf8-40f4-b701-637cec822c1e.png} +0 -0
- /kotonebot/kaa/sprites/{685e377b-3108-44a3-a384-1b527fb4c980.png → 72c1804f-db8c-40fa-bc79-6533f2861a5d.png} +0 -0
- /kotonebot/kaa/sprites/{a885df26-00d6-4e4c-8bb2-626f68ea06ad.png → 7344e180-251b-465a-a8cf-974477f7ad44.png} +0 -0
- /kotonebot/kaa/sprites/{0673f22f-a766-4f05-a32e-6ae92d9ebd6f.png → 73af305f-840f-4325-abae-b3519fba672a.png} +0 -0
- /kotonebot/kaa/sprites/{99090cad-ca7e-4bd3-b38f-1f8ed6f01ed4.png → 73f4204e-8281-47cc-9dce-6bb8280c4ce5.png} +0 -0
- /kotonebot/kaa/sprites/{654e8eaf-e83c-41a4-a55e-6c4cdd0d8fdc.png → 74521b6f-de5e-4ba8-a3c9-c6ba01070498.png} +0 -0
- /kotonebot/kaa/sprites/{c5c16303-3858-4d5c-bc3c-18b7196ba030.png → 7736a171-9221-4cda-8288-908997abeff2.png} +0 -0
- /kotonebot/kaa/sprites/{86538a9c-d267-48d8-935f-ae9ec05073e3.png → 79bc56c5-eae6-4389-9116-4a9e182d6bf3.png} +0 -0
- /kotonebot/kaa/sprites/{bdca0571-b1be-4c97-a59d-016512f412b1.png → 7a479871-547e-4098-9cdd-6c9bb9f7449a.png} +0 -0
- /kotonebot/kaa/sprites/{7ce714eb-7380-4069-bacb-25d68b9aa895.png → 7b3c6860-fbbe-48aa-aadf-8062fa88f1fe.png} +0 -0
- /kotonebot/kaa/sprites/{e4c6780b-798d-4298-bf6a-5e33c9ca1e8f.png → 7cea265a-fca5-43d0-b2da-067c8fff4d72.png} +0 -0
- /kotonebot/kaa/sprites/{37690104-f535-4a19-8640-bf310e4b6a52.png → 7e8164f6-a9e4-4600-b776-77b35a490933.png} +0 -0
- /kotonebot/kaa/sprites/{db9f5641-1afb-4b02-89e8-222390c4cfca.png → 804a4b05-1ca3-4915-bf23-a66ccdc34404.png} +0 -0
- /kotonebot/kaa/sprites/{edaf2b11-38e3-4d2b-b34f-2c01d23c2c35.png → 80fb515c-4323-422d-a24c-80a3bf702f1d.png} +0 -0
- /kotonebot/kaa/sprites/{50d91433-f3a0-4264-8719-289de3739c6c.png → 826bf80a-112e-4356-9111-4b7e692ccc82.png} +0 -0
- /kotonebot/kaa/sprites/{de71582f-4de3-450b-b4e8-dd9028b82f40.png → 82a5e224-a161-43d4-8e15-2946480336dd.png} +0 -0
- /kotonebot/kaa/sprites/{48dc8d02-ea41-49a2-b993-2af26979183c.png → 869b1771-b2ce-4872-ab75-2157c47c5b13.png} +0 -0
- /kotonebot/kaa/sprites/{8e3a97d3-d34a-4c78-a08b-2cacb4da42bc.png → 89c0e675-3fd4-456a-8ae7-3bfb248b7281.png} +0 -0
- /kotonebot/kaa/sprites/{2b9f424d-2c5e-4d84-900a-2646fc131527.png → 8e8a0b57-0231-4ed6-958e-3196f7c9ca7b.png} +0 -0
- /kotonebot/kaa/sprites/{329013cc-7bf0-45e3-bb24-a38cbcf0d2f9.png → 90a9c819-ee6b-4b3e-a0e4-ce484c6e413d.png} +0 -0
- /kotonebot/kaa/sprites/{94f21a05-154b-44a6-9f93-ca41dce3b5de.png → 910d307b-6461-4950-badb-509975d0b797.png} +0 -0
- /kotonebot/kaa/sprites/{99fee062-0d95-4d47-8266-d8649c3c3ff4.png → 92b7d830-3db5-434e-b156-0ac855db480d.png} +0 -0
- /kotonebot/kaa/sprites/{0e1150eb-e6cf-4ee1-a5e2-2610111bb460.png → 96cf0633-6531-499b-b1cc-6670ab710293.png} +0 -0
- /kotonebot/kaa/sprites/{ba583fe8-7334-47b3-8c19-6394bfeee16d.png → 994aa6a6-0189-4a79-8125-56136973b581.png} +0 -0
- /kotonebot/kaa/sprites/{e2809286-fbf5-40da-b442-ae8fae4babd3.png → 9bb1a400-935a-4c5e-838b-fca502c49aba.png} +0 -0
- /kotonebot/kaa/sprites/{39f36c02-8132-42d5-91fb-59dc57ceea70.png → 9c1fa1d4-2ae5-4093-abaa-cebb51135721.png} +0 -0
- /kotonebot/kaa/sprites/{cdd6e06c-741d-4341-a080-51ce89d34a5d.png → a00fcf77-2800-4f7d-993d-4636b36045bb.png} +0 -0
- /kotonebot/kaa/sprites/{c8ca0c53-a94d-4e7c-8bd8-bdd9912760e2.png → a105d17d-d44c-4798-aeff-70808c91cb47.png} +0 -0
- /kotonebot/kaa/sprites/{6e75aa68-7b5a-4e8a-9c11-778ea3a04acf.png → a33ae1c3-ac69-4783-977e-9f0f1b1a2f8d.png} +0 -0
- /kotonebot/kaa/sprites/{4a163f23-a48c-46eb-b03e-ab0b269d5216.png → a3c12040-2b11-4038-b830-215fb7b6f359.png} +0 -0
- /kotonebot/kaa/sprites/{fff0c75d-8819-48c6-adb5-97c79d2be401.png → a82e06fb-a02e-4be5-a7b4-4d2758914fcf.png} +0 -0
- /kotonebot/kaa/sprites/{aadb0941-88b4-4333-9571-7caf97782e75.png → ad784a29-f0e2-4037-976b-45143db8441c.png} +0 -0
- /kotonebot/kaa/sprites/{c02c9b66-cecb-4bcb-b016-654a891b0ef4.png → ad8ee599-88a8-429c-8982-99086e552dcc.png} +0 -0
- /kotonebot/kaa/sprites/{5931b4e7-abd4-414f-a27a-357916bf9999.png → afa0f85f-dcb7-48a1-a1ae-624456b9b65c.png} +0 -0
- /kotonebot/kaa/sprites/{d7481c1c-736a-41f5-afcf-e79bea74f881.png → b1d1dfab-51f5-4ae9-b718-cdf46774c0ff.png} +0 -0
- /kotonebot/kaa/sprites/{3d13cc4d-30d3-4044-bdc2-da932581fa4f.png → b1e88fda-434a-4d06-8891-883a7beafa12.png} +0 -0
- /kotonebot/kaa/sprites/{b2b36034-4f08-4826-835a-b97d7641529f.png → b2f7a430-5777-4861-8435-5419394e5ee8.png} +0 -0
- /kotonebot/kaa/sprites/{27b15f5e-e803-4bcc-bf55-2d5829df73ab.png → b3d1f8d4-1393-4206-b78e-a5495d8fb930.png} +0 -0
- /kotonebot/kaa/sprites/{1a1b970e-9cf0-49b6-a765-45170689f427.png → b3e72de2-e103-49a3-b0f2-8593cff87c4e.png} +0 -0
- /kotonebot/kaa/sprites/{82cc8881-1e3a-41a1-9845-135a40521558.png → b44f5e5b-e999-4427-8a9f-f76c6485f4a5.png} +0 -0
- /kotonebot/kaa/sprites/{0e7b4802-c445-4baa-bf38-f2589b39527b.png → b604e25d-680a-4e02-a012-2e593b5bc276.png} +0 -0
- /kotonebot/kaa/sprites/{655ffd1b-88bb-4174-9e98-82fc40ab86b6.png → ba955365-1328-4018-83a2-bfe818f8f172.png} +0 -0
- /kotonebot/kaa/sprites/{347c5a29-b1d2-40ab-a385-ff42a36e1ea7.png → c0fc7de5-b842-4c70-9cf2-89d833bfe7a6.png} +0 -0
- /kotonebot/kaa/sprites/{240152d2-fd3e-40f7-8023-5f105f215d5c.png → c1ad996a-925e-41b5-b26c-d48b8ded21d2.png} +0 -0
- /kotonebot/kaa/sprites/{d7167e88-c5b0-4aaf-a8f5-29977c3062aa.png → c1b1125f-542b-4e63-9c86-5d2e35a89a10.png} +0 -0
- /kotonebot/kaa/sprites/{593503e0-a673-4910-83a9-b7e4f7c43568.png → c2667677-cbff-4dd4-a401-e0963e7224f4.png} +0 -0
- /kotonebot/kaa/sprites/{b590b94b-8b76-466a-809d-0a16a37e2eb7.png → c4f28132-4aba-40ba-be6c-b1a31d014635.png} +0 -0
- /kotonebot/kaa/sprites/{e7683a0b-d4f7-4bcf-9b5d-ae73c41f0a78.png → c7aa3f89-8a5e-4685-9297-4fc892bfdd81.png} +0 -0
- /kotonebot/kaa/sprites/{fedc068b-148c-4e39-9f1f-6b4d6c055c66.png → cc829886-23e8-4d47-b4c4-37ca20381180.png} +0 -0
- /kotonebot/kaa/sprites/{097346ef-9951-4989-8df3-7b71459e2230.png → cd4cbd7b-df80-45bb-a053-cc333a806934.png} +0 -0
- /kotonebot/kaa/sprites/{ad6de3fd-8486-46e5-b2eb-27c5f73b146a.png → cd8d3d55-f102-419e-a6fd-2ad5ecc4fd2e.png} +0 -0
- /kotonebot/kaa/sprites/{fd2bdf99-47c0-4ac6-9495-6c6be084d9c7.png → d22ca9e0-001d-43d6-a557-1c76c5a27c81.png} +0 -0
- /kotonebot/kaa/sprites/{d43f13a4-6160-4acd-8732-d614e3150807.png → d58d9987-b1ca-4669-a9a6-9a0fd1847fa6.png} +0 -0
- /kotonebot/kaa/sprites/{c3540ea8-70e3-409e-ba83-9761d238ae14.png → d747239f-7620-4f23-9ac7-cf2d34889266.png} +0 -0
- /kotonebot/kaa/sprites/{6c332793-741c-49a1-bd60-a9533de744fc.png → d7f604a6-c663-44db-b1d3-c9792eb3daa4.png} +0 -0
- /kotonebot/kaa/sprites/{664ecf07-b3cf-4d61-9ea8-288b1b3bccb9.png → d8136469-6d73-4f82-a79c-fee83c3e93a8.png} +0 -0
- /kotonebot/kaa/sprites/{f220084e-939d-4505-b41a-f71d5ff89286.png → da3e7cee-d77b-4e62-b703-ed257706dd39.png} +0 -0
- /kotonebot/kaa/sprites/{f7c1ee7f-62cf-4654-b684-19995570aa8a.png → db94ffb7-a09d-4a51-b420-b930851c9db4.png} +0 -0
- /kotonebot/kaa/sprites/{0fe025ae-98be-48f0-9c23-e47ddc69d932.png → de709296-e411-465f-86fc-5daf5ca83cef.png} +0 -0
- /kotonebot/kaa/sprites/{1157e138-6b65-497d-8b51-0a37ebf77b91.png → e2fae2a4-bb19-4f49-b382-47e504ec26d3.png} +0 -0
- /kotonebot/kaa/sprites/{d6dede34-0b2f-4803-bb9b-4da8a9c10b68.png → e41bb5df-164d-4760-9db6-d5d5d763bb5f.png} +0 -0
- /kotonebot/kaa/sprites/{edd85973-ee6f-450f-85fa-102e78c806a5.png → e5d15c50-45ee-4de9-8b97-4630cbd8f01a.png} +0 -0
- /kotonebot/kaa/sprites/{e8d97522-852c-48d6-970b-fb60e23336e6.png → e7022542-4317-4a61-8098-f3f733d8400e.png} +0 -0
- /kotonebot/kaa/sprites/{38f9d826-4a3f-4bab-87fc-b55a49cbc2a1.png → e866d8b1-4f61-45bf-8170-5229f53c047a.png} +0 -0
- /kotonebot/kaa/sprites/{e91455c0-4b5a-49b0-b9e7-29ef5456ddc3.png → ecd44a4a-e1ca-4a86-ae0d-2306a672613f.png} +0 -0
- /kotonebot/kaa/sprites/{85aba299-2625-47e1-a016-b25298fbb688.png → ed5d2bf3-405c-4165-88d0-9f8a4be968c6.png} +0 -0
- /kotonebot/kaa/sprites/{4255d2b3-5ee5-46e5-a35c-515500199d50.png → ef39804e-8d2d-40f6-8d13-bd2877d1353a.png} +0 -0
- /kotonebot/kaa/sprites/{9229fe6b-f0bd-4502-be35-5818dfdbc732.png → f0786a26-81b5-4e76-b577-db70ab3fab50.png} +0 -0
- /kotonebot/kaa/sprites/{13b25df3-9bba-4195-8a49-3c41d6d1ef0d.png → f65a4495-f044-44de-bf0d-c869e637d5d3.png} +0 -0
- /kotonebot/kaa/sprites/{f8c87b1e-87b6-491e-b22e-0409b98bd165.png → f74fc514-61f1-4068-bdf4-754fcaf8ac89.png} +0 -0
- /kotonebot/kaa/sprites/{c9c09edf-312f-4776-80fd-2571052a8894.png → f8cbb089-a63e-4e40-9238-26d14da2c459.png} +0 -0
- /kotonebot/kaa/sprites/{5ece0028-7af2-4b13-bcbc-6a923a2149db.png → f9b2f64d-f829-4b13-9704-c5f00fb956be.png} +0 -0
- /kotonebot/kaa/sprites/{18a55200-aee1-4dfc-867b-8958137a1ecd.png → fb927b92-7a82-4869-8c61-581d49cd7201.png} +0 -0
- /kotonebot/kaa/sprites/{fe7d4d8b-03cf-4d73-8049-ab9e9a296b7f.png → fbd816df-7ae6-40a4-b4d4-5708f5ba4a7c.png} +0 -0
- /kotonebot/kaa/sprites/{0b49fc7d-fe42-44b9-9f2e-69e39cd1b267.png → fd610de1-b023-4747-8c1b-72f89b1c5647.png} +0 -0
- /kotonebot/kaa/sprites/{e1a156d6-874e-4a72-b5b1-05ea11bb1647.png → fdfecda8-2fe0-487e-b5fe-6358274bb9ff.png} +0 -0
- /kotonebot/kaa/sprites/{bb9fbfe9-f913-4220-8704-157095456f06.png → ff77d221-8444-4d0f-8c93-0223a97e2a98.png} +0 -0
- {ksaa-2025.5.23.2.dist-info → ksaa-2025.6.8.0.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.5.23.2.dist-info → ksaa-2025.6.8.0.dist-info}/top_level.txt +0 -0
kotonebot/backend/bot.py
CHANGED
|
@@ -32,7 +32,7 @@ class RunStatus:
|
|
|
32
32
|
callstack: list[Task | Action] = field(default_factory=list)
|
|
33
33
|
|
|
34
34
|
def interrupt(self):
|
|
35
|
-
vars.
|
|
35
|
+
vars.flow.request_interrupt()
|
|
36
36
|
|
|
37
37
|
# Modified from https://stackoverflow.com/questions/70982565/how-do-i-make-an-event-listener-with-decorators-in-python
|
|
38
38
|
Params = ParamSpec('Params')
|
|
@@ -158,7 +158,7 @@ class KotoneBot:
|
|
|
158
158
|
d = self._on_create_device()
|
|
159
159
|
init_context(config_path=self.config_path, config_type=self.config_type, target_device=d)
|
|
160
160
|
self._on_after_init_context()
|
|
161
|
-
vars.
|
|
161
|
+
vars.flow.clear_interrupt()
|
|
162
162
|
|
|
163
163
|
if by_priority:
|
|
164
164
|
tasks = sorted(tasks, key=lambda x: x.priority, reverse=True)
|
|
@@ -180,7 +180,7 @@ class KotoneBot:
|
|
|
180
180
|
logger.exception('Keyboard interrupt detected.')
|
|
181
181
|
for task1 in tasks[tasks.index(task):]:
|
|
182
182
|
self.events.task_status_changed.trigger(task1, 'cancelled')
|
|
183
|
-
vars.
|
|
183
|
+
vars.flow.clear_interrupt()
|
|
184
184
|
break
|
|
185
185
|
# 其他错误
|
|
186
186
|
except Exception as e:
|
|
@@ -3,6 +3,7 @@ import re
|
|
|
3
3
|
import time
|
|
4
4
|
import logging
|
|
5
5
|
import warnings
|
|
6
|
+
import threading
|
|
6
7
|
from datetime import datetime
|
|
7
8
|
from threading import Event
|
|
8
9
|
from typing import (
|
|
@@ -25,6 +26,7 @@ import cv2
|
|
|
25
26
|
from cv2.typing import MatLike
|
|
26
27
|
|
|
27
28
|
from kotonebot.client.device import Device
|
|
29
|
+
from kotonebot.backend.flow_controller import FlowController
|
|
28
30
|
import kotonebot.backend.image as raw_image
|
|
29
31
|
from kotonebot.backend.image import (
|
|
30
32
|
TemplateMatchResult,
|
|
@@ -126,8 +128,7 @@ def interruptible(func: Callable[P, T]) -> Callable[P, T]:
|
|
|
126
128
|
"""
|
|
127
129
|
def _decorator(*args: P.args, **kwargs: P.kwargs) -> T:
|
|
128
130
|
global vars
|
|
129
|
-
|
|
130
|
-
raise KeyboardInterrupt("User requested interrupt.")
|
|
131
|
+
vars.flow.check()
|
|
131
132
|
return func(*args, **kwargs)
|
|
132
133
|
return _decorator
|
|
133
134
|
|
|
@@ -145,15 +146,13 @@ def interruptible_class(cls: Type[T]) -> Type[T]:
|
|
|
145
146
|
|
|
146
147
|
def sleep(seconds: float, /):
|
|
147
148
|
"""
|
|
148
|
-
|
|
149
|
+
可中断和可暂停的 sleep 函数。
|
|
149
150
|
|
|
150
151
|
建议使用本函数代替 `time.sleep()`,
|
|
151
|
-
|
|
152
|
+
这样能以最快速度响应用户请求中断和暂停。
|
|
152
153
|
"""
|
|
153
154
|
global vars
|
|
154
|
-
vars.
|
|
155
|
-
if vars.interrupted.is_set():
|
|
156
|
-
raise KeyboardInterrupt("User requested interrupt.")
|
|
155
|
+
vars.flow.sleep(seconds)
|
|
157
156
|
|
|
158
157
|
def warn_manual_screenshot_mode(name: str, alternative: str):
|
|
159
158
|
"""
|
|
@@ -175,8 +174,8 @@ def is_manual_screenshot_mode() -> bool:
|
|
|
175
174
|
class ContextGlobalVars:
|
|
176
175
|
def __init__(self):
|
|
177
176
|
self.__vars = dict[str, Any]()
|
|
178
|
-
self.
|
|
179
|
-
"""
|
|
177
|
+
self.flow: FlowController = FlowController()
|
|
178
|
+
"""流程控制器,负责停止、暂停、恢复等操作"""
|
|
180
179
|
|
|
181
180
|
def __getitem__(self, key: str) -> Any:
|
|
182
181
|
return self.__vars[key]
|
|
@@ -198,6 +197,17 @@ class ContextGlobalVars:
|
|
|
198
197
|
|
|
199
198
|
def clear(self):
|
|
200
199
|
self.__vars.clear()
|
|
200
|
+
self.flow.reset() # 重置流程控制器
|
|
201
|
+
|
|
202
|
+
def check_flow_control():
|
|
203
|
+
"""
|
|
204
|
+
统一的流程控制检查函数。
|
|
205
|
+
|
|
206
|
+
检查用户是否请求中断或暂停,如果是则相应处理:
|
|
207
|
+
- 如果请求中断,抛出 KeyboardInterrupt 异常
|
|
208
|
+
- 如果请求暂停,等待直到恢复
|
|
209
|
+
"""
|
|
210
|
+
vars.flow.check()
|
|
201
211
|
|
|
202
212
|
class ContextStackVars:
|
|
203
213
|
stack: list['ContextStackVars'] = []
|
|
@@ -716,6 +726,7 @@ class ContextDevice(Device):
|
|
|
716
726
|
"""
|
|
717
727
|
截图。返回截图数据,同时更新当前上下文的截图数据。
|
|
718
728
|
"""
|
|
729
|
+
check_flow_control()
|
|
719
730
|
global next_wait, last_screenshot_time, next_wait_time
|
|
720
731
|
current = ContextStackVars.ensure_current()
|
|
721
732
|
if force:
|
|
@@ -950,5 +961,4 @@ def manual_context(screenshot_mode: ScreenshotMode = 'auto') -> ManualContextMan
|
|
|
950
961
|
默认情况下,Context* 类仅允许在 @task/@action 函数中使用。
|
|
951
962
|
如果想要在其他地方使用,使用此函数手动创建一个上下文。
|
|
952
963
|
"""
|
|
953
|
-
return ManualContextManager(screenshot_mode)
|
|
954
|
-
|
|
964
|
+
return ManualContextManager(screenshot_mode)
|
|
@@ -115,7 +115,7 @@ async def run_code(request: RunCodeRequest):
|
|
|
115
115
|
except KeyboardInterrupt as e:
|
|
116
116
|
result = {"status": "error", "result": stdout.getvalue(), "message": str(e), "traceback": traceback.format_exc()}
|
|
117
117
|
finally:
|
|
118
|
-
context_vars.
|
|
118
|
+
context_vars.flow.clear_interrupt()
|
|
119
119
|
event.set()
|
|
120
120
|
threading.Thread(target=_runner, daemon=True).start()
|
|
121
121
|
await event.wait()
|
|
@@ -124,8 +124,8 @@ async def run_code(request: RunCodeRequest):
|
|
|
124
124
|
@app.get("/api/code/stop")
|
|
125
125
|
async def stop_code():
|
|
126
126
|
from kotonebot.backend.context import vars
|
|
127
|
-
vars.
|
|
128
|
-
while vars.
|
|
127
|
+
vars.flow.request_interrupt()
|
|
128
|
+
while vars.flow.is_interrupted:
|
|
129
129
|
await asyncio.sleep(0.1)
|
|
130
130
|
return {"status": "ok"}
|
|
131
131
|
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import logging
|
|
3
|
+
import threading
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
class FlowController:
|
|
9
|
+
"""
|
|
10
|
+
一个用于控制任务执行流程(如停止、暂停、恢复)的类。
|
|
11
|
+
|
|
12
|
+
这个类是线程安全的,提供了以下功能:
|
|
13
|
+
|
|
14
|
+
* 停止任务执行(通过中断信号)
|
|
15
|
+
* 暂停/恢复任务执行
|
|
16
|
+
* 可中断和可暂停的 sleep 功能
|
|
17
|
+
* 流程状态检查
|
|
18
|
+
|
|
19
|
+
使用方法::
|
|
20
|
+
|
|
21
|
+
controller = FlowController()
|
|
22
|
+
|
|
23
|
+
# 在任务的关键路径上调用检查
|
|
24
|
+
controller.check()
|
|
25
|
+
|
|
26
|
+
# 使用可控制的 sleep
|
|
27
|
+
controller.sleep(1.0)
|
|
28
|
+
|
|
29
|
+
# 外部控制
|
|
30
|
+
controller.request_pause() # 暂停
|
|
31
|
+
controller.request_resume() # 恢复
|
|
32
|
+
controller.request_stop() # 停止
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self):
|
|
36
|
+
self.interrupt_event: threading.Event = threading.Event()
|
|
37
|
+
"""中断事件,用于停止任务"""
|
|
38
|
+
|
|
39
|
+
self.paused: bool = False
|
|
40
|
+
"""暂停标志"""
|
|
41
|
+
|
|
42
|
+
self.pause_condition: threading.Condition = threading.Condition()
|
|
43
|
+
"""暂停条件变量,用于线程间同步"""
|
|
44
|
+
|
|
45
|
+
def check(self) -> None:
|
|
46
|
+
"""
|
|
47
|
+
检查当前流程状态。
|
|
48
|
+
|
|
49
|
+
如果收到停止请求,则抛出 KeyboardInterrupt 异常。
|
|
50
|
+
如果收到暂停请求,则阻塞直到恢复。
|
|
51
|
+
|
|
52
|
+
这是核心的检查点方法,应在任务的关键路径上(如循环或等待前)调用。
|
|
53
|
+
|
|
54
|
+
:raises KeyboardInterrupt: 当收到停止请求时
|
|
55
|
+
"""
|
|
56
|
+
# 优先检查中断信号
|
|
57
|
+
if self.interrupt_event.is_set():
|
|
58
|
+
raise KeyboardInterrupt("User requested interrupt.")
|
|
59
|
+
|
|
60
|
+
# 检查暂停状态
|
|
61
|
+
with self.pause_condition:
|
|
62
|
+
while self.paused:
|
|
63
|
+
self.pause_condition.wait()
|
|
64
|
+
|
|
65
|
+
def sleep(self, seconds: float) -> None:
|
|
66
|
+
"""
|
|
67
|
+
一个可被中断和暂停的 sleep 方法。
|
|
68
|
+
|
|
69
|
+
与标准的 time.sleep() 不同,这个方法会响应停止和暂停请求。
|
|
70
|
+
在暂停状态下,计时器会暂停,恢复后继续计时。
|
|
71
|
+
|
|
72
|
+
:param seconds: 睡眠时间(秒)
|
|
73
|
+
:raises KeyboardInterrupt: 当收到停止请求时
|
|
74
|
+
"""
|
|
75
|
+
with self.pause_condition:
|
|
76
|
+
end_time = time.time() + seconds
|
|
77
|
+
while True:
|
|
78
|
+
self.check() # 每次循环都检查状态
|
|
79
|
+
remaining = end_time - time.time()
|
|
80
|
+
if remaining <= 0:
|
|
81
|
+
break
|
|
82
|
+
# 等待指定时间或直到被唤醒
|
|
83
|
+
self.pause_condition.wait(timeout=remaining)
|
|
84
|
+
|
|
85
|
+
# 结束后再次检查状态
|
|
86
|
+
self.check()
|
|
87
|
+
|
|
88
|
+
def request_interrupt(self) -> None:
|
|
89
|
+
"""
|
|
90
|
+
请求停止任务。
|
|
91
|
+
|
|
92
|
+
设置中断信号,所有正在执行的任务将在下一个检查点停止。
|
|
93
|
+
停止的优先级高于暂停。
|
|
94
|
+
"""
|
|
95
|
+
logger.info('Interrupt requested.')
|
|
96
|
+
self.interrupt_event.set()
|
|
97
|
+
|
|
98
|
+
def request_pause(self) -> None:
|
|
99
|
+
"""
|
|
100
|
+
请求暂停任务。
|
|
101
|
+
|
|
102
|
+
设置暂停标志,所有正在执行的任务将在下一个检查点暂停。
|
|
103
|
+
如果任务已经暂停,此操作无效果。
|
|
104
|
+
"""
|
|
105
|
+
with self.pause_condition:
|
|
106
|
+
if not self.paused:
|
|
107
|
+
logger.info('Pause requested.')
|
|
108
|
+
self.paused = True
|
|
109
|
+
|
|
110
|
+
def request_resume(self) -> None:
|
|
111
|
+
"""
|
|
112
|
+
请求恢复任务。
|
|
113
|
+
|
|
114
|
+
清除暂停标志并通知所有等待的线程恢复执行。
|
|
115
|
+
如果任务没有暂停,此操作无效果。
|
|
116
|
+
"""
|
|
117
|
+
with self.pause_condition:
|
|
118
|
+
if self.paused:
|
|
119
|
+
logger.info('Resume requested.')
|
|
120
|
+
self.paused = False
|
|
121
|
+
self.pause_condition.notify_all()
|
|
122
|
+
|
|
123
|
+
def toggle_pause(self) -> bool:
|
|
124
|
+
"""
|
|
125
|
+
切换暂停/恢复状态。
|
|
126
|
+
|
|
127
|
+
:returns: 操作后的暂停状态。True 表示已暂停,False 表示已恢复。
|
|
128
|
+
"""
|
|
129
|
+
with self.pause_condition:
|
|
130
|
+
logger.info('Pause toggled.')
|
|
131
|
+
if self.paused:
|
|
132
|
+
self.paused = False
|
|
133
|
+
self.pause_condition.notify_all()
|
|
134
|
+
return False
|
|
135
|
+
else:
|
|
136
|
+
self.paused = True
|
|
137
|
+
return True
|
|
138
|
+
|
|
139
|
+
def clear_interrupt(self) -> None:
|
|
140
|
+
"""
|
|
141
|
+
清除中断信号。
|
|
142
|
+
|
|
143
|
+
用于任务正常结束或重启时重置状态。
|
|
144
|
+
通常在开始新任务前调用。
|
|
145
|
+
"""
|
|
146
|
+
self.interrupt_event.clear()
|
|
147
|
+
logger.info('Interrupt cleared.')
|
|
148
|
+
|
|
149
|
+
def reset(self) -> None:
|
|
150
|
+
"""
|
|
151
|
+
重置流程控制器到初始状态。
|
|
152
|
+
|
|
153
|
+
清除所有信号和状态,相当于重新创建一个新的控制器。
|
|
154
|
+
"""
|
|
155
|
+
self.interrupt_event.clear()
|
|
156
|
+
with self.pause_condition:
|
|
157
|
+
if self.paused:
|
|
158
|
+
self.paused = False
|
|
159
|
+
self.pause_condition.notify_all()
|
|
160
|
+
logger.info('FlowController reset.')
|
|
161
|
+
|
|
162
|
+
@property
|
|
163
|
+
def is_interrupted(self) -> bool:
|
|
164
|
+
"""
|
|
165
|
+
检查是否收到中断请求。
|
|
166
|
+
|
|
167
|
+
:returns: True 表示已收到中断请求
|
|
168
|
+
"""
|
|
169
|
+
return self.interrupt_event.is_set()
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def is_paused(self) -> bool:
|
|
173
|
+
"""
|
|
174
|
+
检查是否处于暂停状态。
|
|
175
|
+
|
|
176
|
+
:returns: True 表示当前处于暂停状态
|
|
177
|
+
"""
|
|
178
|
+
return self.paused
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def status(self) -> Literal['running', 'paused', 'interrupted']:
|
|
182
|
+
"""
|
|
183
|
+
获取当前状态的字符串描述。
|
|
184
|
+
|
|
185
|
+
:returns: 状态描述,可能的值:'running', 'paused', 'interrupted'
|
|
186
|
+
"""
|
|
187
|
+
if self.is_interrupted:
|
|
188
|
+
return 'interrupted'
|
|
189
|
+
elif self.is_paused:
|
|
190
|
+
return 'paused'
|
|
191
|
+
else:
|
|
192
|
+
return 'running'
|
|
193
|
+
|
|
194
|
+
def __repr__(self) -> str:
|
|
195
|
+
return f"FlowController(status='{self.status}')"
|
|
@@ -7,7 +7,7 @@ import cv2
|
|
|
7
7
|
import win32ui
|
|
8
8
|
import win32gui
|
|
9
9
|
import numpy as np
|
|
10
|
-
from ahk import AHK
|
|
10
|
+
from ahk import AHK, MsgBoxIcon
|
|
11
11
|
from cv2.typing import MatLike
|
|
12
12
|
|
|
13
13
|
from ..device import Device
|
|
@@ -19,14 +19,26 @@ class WindowsImpl(Touchable, Screenshotable):
|
|
|
19
19
|
# TODO: 硬编码路径
|
|
20
20
|
self.ahk = AHK(executable_path=str(resources.files('kaa.res.bin') / 'AutoHotkey.exe'))
|
|
21
21
|
self.device = device
|
|
22
|
-
self.emergency = False
|
|
23
22
|
|
|
24
23
|
# 设置 DPI aware,否则高缩放显示器上返回的坐标会错误
|
|
25
24
|
windll.user32.SetProcessDPIAware()
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
# TODO: 这个应该移动到其他地方去
|
|
26
|
+
def _stop():
|
|
27
|
+
from kotonebot.backend.context.context import vars
|
|
28
|
+
vars.flow.request_interrupt()
|
|
29
|
+
self.ahk.msg_box('任务已停止。', title='琴音小助手', icon=MsgBoxIcon.EXCLAMATION)
|
|
30
|
+
|
|
31
|
+
def _toggle_pause():
|
|
32
|
+
from kotonebot.backend.context.context import vars
|
|
33
|
+
if vars.flow.is_paused:
|
|
34
|
+
self.ahk.msg_box('任务即将恢复。\n关闭此消息框后将会继续执行', title='琴音小助手', icon=MsgBoxIcon.EXCLAMATION)
|
|
35
|
+
vars.flow.request_resume()
|
|
36
|
+
else:
|
|
37
|
+
vars.flow.request_pause()
|
|
38
|
+
self.ahk.msg_box('任务已暂停。\n关闭此消息框后再按一次快捷键恢复执行。', title='琴音小助手', icon=MsgBoxIcon.EXCLAMATION)
|
|
39
|
+
|
|
40
|
+
self.ahk.add_hotkey('^F4', _toggle_pause) # Ctrl+F4 暂停/恢复
|
|
41
|
+
self.ahk.add_hotkey('^F3', _stop) # Ctrl+F3 停止
|
|
30
42
|
self.ahk.start_hotkeys()
|
|
31
43
|
# 将点击坐标设置为相对 Client
|
|
32
44
|
self.ahk.set_coord_mode('Mouse', 'Client')
|
|
@@ -60,11 +72,6 @@ class WindowsImpl(Touchable, Screenshotable):
|
|
|
60
72
|
"""将 Client 区域坐标转换为屏幕坐标"""
|
|
61
73
|
return win32gui.ClientToScreen(hwnd, (x, y))
|
|
62
74
|
|
|
63
|
-
def __wait_not_emergency(self):
|
|
64
|
-
from time import sleep # TODO: 改为 kotonebot.backend.context.sleep
|
|
65
|
-
while self.emergency:
|
|
66
|
-
sleep(0.2)
|
|
67
|
-
|
|
68
75
|
def screenshot(self) -> MatLike:
|
|
69
76
|
if not self.ahk.win_is_active('gakumas'):
|
|
70
77
|
self.ahk.win_activate('gakumas')
|
|
@@ -133,7 +140,6 @@ class WindowsImpl(Touchable, Screenshotable):
|
|
|
133
140
|
return 'portrait'
|
|
134
141
|
|
|
135
142
|
def click(self, x: int, y: int) -> None:
|
|
136
|
-
self.__wait_not_emergency()
|
|
137
143
|
# x, y = self.__client_to_screen(self.hwnd, x, y)
|
|
138
144
|
# (0, 0) 很可能会点到窗口边框上
|
|
139
145
|
if x == 0:
|
|
@@ -146,7 +152,6 @@ class WindowsImpl(Touchable, Screenshotable):
|
|
|
146
152
|
self.ahk.click(x, y)
|
|
147
153
|
|
|
148
154
|
def swipe(self, x1: int, y1: int, x2: int, y2: int, duration: float | None = None) -> None:
|
|
149
|
-
self.__wait_not_emergency()
|
|
150
155
|
if not self.ahk.win_is_active('gakumas'):
|
|
151
156
|
self.ahk.win_activate('gakumas')
|
|
152
157
|
x1, y1 = int(x1 / self.scale_ratio), int(y1 / self.scale_ratio)
|
kotonebot/kaa/common.py
CHANGED
|
@@ -425,6 +425,20 @@ class StartGameConfig(ConfigBaseModel):
|
|
|
425
425
|
|
|
426
426
|
kuyo_package_name: str = 'org.kuyo.game'
|
|
427
427
|
"""Kuyo包名"""
|
|
428
|
+
|
|
429
|
+
disable_gakumas_localify: bool = False
|
|
430
|
+
"""
|
|
431
|
+
自动检测并禁用 Gakumas Localify 汉化插件。
|
|
432
|
+
|
|
433
|
+
(目前仅对 DMM 版有效。)
|
|
434
|
+
"""
|
|
435
|
+
|
|
436
|
+
dmm_game_path: str | None = None
|
|
437
|
+
"""
|
|
438
|
+
DMM 版游戏路径。若不填写,会自动检测。
|
|
439
|
+
|
|
440
|
+
例:`F:\\Games\\gakumas\\gakumas.exe`
|
|
441
|
+
"""
|
|
428
442
|
|
|
429
443
|
class EndGameConfig(ConfigBaseModel):
|
|
430
444
|
exit_kaa: bool = False
|
|
@@ -439,6 +453,13 @@ class EndGameConfig(ConfigBaseModel):
|
|
|
439
453
|
"""关闭系统"""
|
|
440
454
|
hibernate: bool = False
|
|
441
455
|
"""休眠系统"""
|
|
456
|
+
restore_gakumas_localify: bool = False
|
|
457
|
+
"""
|
|
458
|
+
恢复 Gakumas Localify 汉化插件状态至启动前。通常与
|
|
459
|
+
`disable_gakumas_localify` 配对使用。
|
|
460
|
+
|
|
461
|
+
(目前仅对 DMM 版有效。)
|
|
462
|
+
"""
|
|
442
463
|
|
|
443
464
|
class BaseConfig(ConfigBaseModel):
|
|
444
465
|
purchase: PurchaseConfig = PurchaseConfig()
|