ksaa 2025.4.17.2__py3-none-any.whl → 2025.4.26.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 +18 -3
- kotonebot/client/factory.py +16 -1
- kotonebot/client/implements/remote_windows.py +197 -0
- kotonebot/config/base_config.py +4 -2
- kotonebot/tasks/R.py +156 -138
- kotonebot/tasks/common.py +53 -16
- kotonebot/tasks/end_game.py +94 -0
- kotonebot/tasks/main/cli.py +19 -0
- kotonebot/tasks/main/gr.py +189 -73
- kotonebot/tasks/metadata.py +18 -0
- kotonebot/tasks/produce/in_purodyuusu.py +103 -65
- kotonebot/tasks/produce/non_lesson_actions.py +93 -20
- kotonebot/tasks/produce/produce.py +29 -15
- kotonebot/tasks/resources/__pycache__/__init__.cpython-310.pyc +0 -0
- kotonebot/tasks/resources/game.db +0 -0
- kotonebot/tasks/resources/game_ver.txt +0 -0
- kotonebot/tasks/sprites/208463e9-cbe8-45a7-b721-d72b34ef59db.png +0 -0
- kotonebot/tasks/sprites/23d88465-65d9-4718-8725-8dbf0a98a5a4.png +0 -0
- kotonebot/tasks/sprites/25f00ee3-8dfe-42d1-a67e-191fa5c3df4b.png +0 -0
- kotonebot/tasks/sprites/3c8b477a-8eda-407e-9e9f-7540c8808f89.png +0 -0
- kotonebot/tasks/sprites/4096cffa-a889-4622-852e-760fc7022d93.png +0 -0
- kotonebot/tasks/sprites/772adec4-a38c-4b3d-b2eb-35c50168783f.png +0 -0
- kotonebot/tasks/sprites/9fd0753f-c607-4d49-82d1-40bda27e014f.png +0 -0
- kotonebot/tasks/sprites/d83f338d-dde3-494b-9bea-cae511e3517c.png +0 -0
- kotonebot/tasks/start_game.py +5 -2
- kotonebot/util.py +1 -0
- {ksaa-2025.4.17.2.dist-info → ksaa-2025.4.26.0.dist-info}/METADATA +1 -1
- {ksaa-2025.4.17.2.dist-info → ksaa-2025.4.26.0.dist-info}/RECORD +162 -152
- {ksaa-2025.4.17.2.dist-info → ksaa-2025.4.26.0.dist-info}/WHEEL +1 -1
- /kotonebot/tasks/sprites/{05d78c7e-0c5f-4710-9285-8c95fe73b88b.png → 056a629e-242e-4bfc-9bd5-bb974a9fb4ef.png} +0 -0
- /kotonebot/tasks/sprites/{7253d078-05b4-4518-af0c-ce0d84445a76.png → 0c188f78-d5b3-4fe1-b486-69cb975aeeb4.png} +0 -0
- /kotonebot/tasks/sprites/{a9c4a376-33bc-43ec-a153-a4733d32cd26.png → 0c5b29d4-9595-4739-928a-289ac670727d.png} +0 -0
- /kotonebot/tasks/sprites/{68863cef-f992-4458-94c2-e1d428840585.png → 0cbbd1eb-86c4-4155-9101-1dc8bc295c00.png} +0 -0
- /kotonebot/tasks/sprites/{e3304287-a0ee-4eff-8ddb-8f0a697188fc.png → 152b54dd-3b06-487e-821a-cc2348cb1113.png} +0 -0
- /kotonebot/tasks/sprites/{034e0502-00d2-4e9d-9be3-205b8055f74c.png → 15a9e393-8e42-482c-8706-6b95d419ecf5.png} +0 -0
- /kotonebot/tasks/sprites/{84276f4c-50ca-47fc-b5f3-66364abb1b0e.png → 165f585c-1d26-4a3a-baa0-eb1fac8f88f4.png} +0 -0
- /kotonebot/tasks/sprites/{b3d90f5c-ded1-4d7c-aeda-0ed252e4fdbe.png → 17bf6042-b4b0-4fa0-89c8-9da8c9569457.png} +0 -0
- /kotonebot/tasks/sprites/{d0fe95f8-ebec-4a4e-8132-39500ef0c76e.png → 17efa369-de88-44a7-9fe4-00da62ceaf72.png} +0 -0
- /kotonebot/tasks/sprites/{25693c38-d638-47f2-8c02-17a67c101d55.png → 17f53690-ee3c-4479-8014-149775733979.png} +0 -0
- /kotonebot/tasks/sprites/{6d30c494-bf10-4a26-b026-11b15682ce03.png → 1a6f4158-d50f-4d3b-b608-f947c4dde26b.png} +0 -0
- /kotonebot/tasks/sprites/{c17aab08-bd50-45ec-bfd4-72fd3e3b9e5b.png → 1a6fe30b-bd69-4c46-af93-f93842b0dcd9.png} +0 -0
- /kotonebot/tasks/sprites/{24ee9323-9476-48da-aac0-eb9a3da47ce5.png → 1b0e8f53-6fc6-4341-92d8-3e2f4a662676.png} +0 -0
- /kotonebot/tasks/sprites/{0b74125e-03dd-46cb-9e6b-41b15334e613.png → 1ce57116-fbad-450d-aa9a-1e59dfe83698.png} +0 -0
- /kotonebot/tasks/sprites/{5b9e73f0-9deb-4a59-8907-0aab694e71b4.png → 1d8d20e8-7037-4c80-b2a0-a87597ed25de.png} +0 -0
- /kotonebot/tasks/sprites/{bb5f128a-2bf3-42a6-af1f-62643340dece.png → 241f635c-d479-4508-bfcc-e555d4820ccb.png} +0 -0
- /kotonebot/tasks/sprites/{27ec16e8-1e39-4694-9c06-5d67d72afb09.png → 258ceabd-efb9-441b-8474-2d64cd8ae229.png} +0 -0
- /kotonebot/tasks/sprites/{83f18e1a-90f3-40c4-a01b-eadd21f4a135.png → 262d7636-389e-48b3-94c0-50cd4b9ab3ec.png} +0 -0
- /kotonebot/tasks/sprites/{68276791-c4c1-41c5-bf13-eb3e2c708ad0.png → 2658cf2a-ef0d-4849-9309-b35d5c0173f5.png} +0 -0
- /kotonebot/tasks/sprites/{f145cdff-2eb0-4429-bdf7-a2701640f4cb.png → 27036a5b-6604-4244-8dd4-57b3f27eecdc.png} +0 -0
- /kotonebot/tasks/sprites/{82193e69-a777-48a7-bcf5-fe9b0920db93.png → 2b363bc8-0a17-42f7-8caa-d03ccdf0e15f.png} +0 -0
- /kotonebot/tasks/sprites/{9f44c556-c481-4f0b-835b-41091e196141.png → 2c505b36-3c6c-4914-9cd6-dafdfc9cc01c.png} +0 -0
- /kotonebot/tasks/sprites/{dc515ece-409b-45e9-8dad-77e09a1cea8c.png → 2ead898a-112c-49e9-a689-14d526144931.png} +0 -0
- /kotonebot/tasks/sprites/{18db3c71-061e-4ccb-8fda-ca06a530b64b.png → 2f9cc1c9-915c-405a-8f9d-2b56c822de63.png} +0 -0
- /kotonebot/tasks/sprites/{79ce2616-39bb-4143-8d07-253709951185.png → 30e3df65-9bf8-4178-88c1-538e763e47cf.png} +0 -0
- /kotonebot/tasks/sprites/{f6171a54-bd80-4207-a61d-4a2ffd3fc5d8.png → 3384166f-5462-41bc-ace1-bf60f2aa19a3.png} +0 -0
- /kotonebot/tasks/sprites/{be7a1734-9b8d-4714-96d4-9ce6907906fb.png → 33f831fb-43e7-485f-a4a8-d643126c7837.png} +0 -0
- /kotonebot/tasks/sprites/{bcc98e91-1c21-4f5b-9e9a-039af3f8f34f.png → 349698bd-f5ee-497f-ba93-f6baed5b44b4.png} +0 -0
- /kotonebot/tasks/sprites/{fad894d2-73a8-49cb-97ac-64c5167d236e.png → 3522aa93-a1aa-4674-a70a-e51a23700413.png} +0 -0
- /kotonebot/tasks/sprites/{f5d72cb3-a3c3-41fd-ae61-c65bbe9fa12c.png → 35cea915-cfe5-4d94-88c7-ffba843292d1.png} +0 -0
- /kotonebot/tasks/sprites/{2f3b9110-5ddf-4c2c-97ee-0292c3cbf6b6.png → 3bbf29aa-921d-4b7b-be17-881375d03c02.png} +0 -0
- /kotonebot/tasks/sprites/{0c4d5dc0-359b-4af4-963e-fd79d13a5a8a.png → 3c261188-de36-4a6b-8255-52bd089557c9.png} +0 -0
- /kotonebot/tasks/sprites/{7bafd109-da67-41ad-af00-710693162139.png → 3d6f64ea-95ae-4bce-9ca5-8627e05bd746.png} +0 -0
- /kotonebot/tasks/sprites/{b4fb066b-1f49-44d1-8755-e7acc9711afb.png → 3e233f05-c783-4790-aa21-aafc33914a96.png} +0 -0
- /kotonebot/tasks/sprites/{b92079f2-88cb-4a8d-bcbd-7248f28e438e.png → 40761930-a1f1-476c-aada-143969076651.png} +0 -0
- /kotonebot/tasks/sprites/{facacf54-4273-41d6-9033-aa5a5d133450.png → 40bba601-c36a-41bd-861c-fe13a0f0eb5e.png} +0 -0
- /kotonebot/tasks/sprites/{30c1db28-6202-420b-be91-11a433eb14f2.png → 41698ac4-0db8-4539-8876-c5c01cda43c0.png} +0 -0
- /kotonebot/tasks/sprites/{1b0dc6cf-62ba-4b99-862a-1ce764c70e26.png → 470b5761-0a7b-4a49-b1a9-4bf4a81371b8.png} +0 -0
- /kotonebot/tasks/sprites/{802bf373-cfcf-4d1e-afde-fc21ab00c2ed.png → 470d3807-c50b-46f0-aec5-19b3e55f8674.png} +0 -0
- /kotonebot/tasks/sprites/{f3c8afba-c230-4566-ba5a-2668f8b3c4cb.png → 50028cad-b460-4889-9b3f-a915b20aaee2.png} +0 -0
- /kotonebot/tasks/sprites/{63c3ac21-c9fd-4879-bd54-81c3f3550639.png → 52b5038f-c10f-4e01-a4f7-14479f51ca94.png} +0 -0
- /kotonebot/tasks/sprites/{2c518744-f00f-4a36-b8a5-cb4b8ca7dacc.png → 5732647f-2bf2-47aa-a214-0b883a741ec2.png} +0 -0
- /kotonebot/tasks/sprites/{cea6f17a-3269-485c-b507-d5bcace0da4f.png → 57ab058a-e791-4a8d-a811-e3a0c9c85785.png} +0 -0
- /kotonebot/tasks/sprites/{8dff2e43-537b-4eaa-860b-93053b52c31c.png → 57bcf309-a634-4a75-a554-1a942dae4a7e.png} +0 -0
- /kotonebot/tasks/sprites/{c8e4d52a-d21e-492e-9b7a-6543fd0d5a95.png → 59049d4d-af07-4a98-8be2-174efdca8177.png} +0 -0
- /kotonebot/tasks/sprites/{07b46a97-3ed4-48f9-881b-5228f4b3ada9.png → 590ea94a-92db-46c3-84e2-69f413bb16d1.png} +0 -0
- /kotonebot/tasks/sprites/{834356a9-b332-46fc-bd04-caea1d58b138.png → 59481a16-05ac-4c96-ac80-d39ee2861821.png} +0 -0
- /kotonebot/tasks/sprites/{11e195bb-7107-40b4-aea5-173441f1c9b2.png → 5b49aab0-67a5-4b04-b61f-8c2ef4b56c53.png} +0 -0
- /kotonebot/tasks/sprites/{6831a0ce-1803-4138-9e75-83ccaf095745.png → 5b6f1ada-b671-4037-a23a-9ca5556540b7.png} +0 -0
- /kotonebot/tasks/sprites/{2ec293e3-8e18-4ffe-ad5e-0d23eebac96d.png → 5cc327f5-ed47-44e7-94dc-ed0ae287f6ec.png} +0 -0
- /kotonebot/tasks/sprites/{43fab6cf-6330-4f0a-a560-3e060b1e79fa.png → 5e0b2e63-329c-4ca6-80f5-3a3c7bea3197.png} +0 -0
- /kotonebot/tasks/sprites/{3e7a9b6e-e469-41f7-9073-1709cfeaf6cf.png → 5e4838dc-e524-4350-b7d0-070e979b51d0.png} +0 -0
- /kotonebot/tasks/sprites/{19ebee01-0a40-4750-9fec-bc9bd1fc1cd4.png → 610d0228-77a8-4d40-8363-668d07852f0f.png} +0 -0
- /kotonebot/tasks/sprites/{f332ea63-a58b-41ee-8426-7245f5fd96c2.png → 616370a6-302f-47be-a71b-d1b253ef5d26.png} +0 -0
- /kotonebot/tasks/sprites/{e5bc55d2-d2ee-4be9-b068-ef0c1ce6a6ac.png → 64b8f151-f3bb-46a5-b66b-6364644e5c57.png} +0 -0
- /kotonebot/tasks/sprites/{db246a45-b3c7-4983-9f1f-db88f8126d38.png → 7298faf9-303d-4b17-b4ec-d72189620415.png} +0 -0
- /kotonebot/tasks/sprites/{c840a295-dc0e-4906-94ab-ee3ec24c7416.png → 73d633bf-87dc-4f00-8bab-1cee26bb57f4.png} +0 -0
- /kotonebot/tasks/sprites/{f34ccd13-7602-4490-a7a3-1a4bffd82c90.png → 73d6d47c-d47e-4bfa-b37d-94e4546294a7.png} +0 -0
- /kotonebot/tasks/sprites/{d0bf1d05-a48d-4895-b5dd-b2b1b9012d37.png → 74ea1223-aa62-4f27-862c-58cfac0f6f1b.png} +0 -0
- /kotonebot/tasks/sprites/{1455365d-c213-4476-864b-644d14ba0218.png → 74f05b71-468b-42a7-960d-aec2ee888314.png} +0 -0
- /kotonebot/tasks/sprites/{03e0fd71-8b2c-4b65-bbdf-363c5aa96bb7.png → 75b9f513-25ec-4e47-b71e-b9c86bb318d0.png} +0 -0
- /kotonebot/tasks/sprites/{903bab6b-e831-4b80-a087-3f213d5678e6.png → 75d35137-25f0-4cb1-b934-aad4b28013c1.png} +0 -0
- /kotonebot/tasks/sprites/{799d5bc5-9fe1-416b-ac3c-26d89d2f5ed2.png → 75e16c86-d0bd-42e0-8624-368a95f2b7fa.png} +0 -0
- /kotonebot/tasks/sprites/{14e6b7ae-3db6-4fd9-ba6a-fae4ec63064a.png → 76377a1e-92af-4d79-84ba-7d9060411336.png} +0 -0
- /kotonebot/tasks/sprites/{da113628-d106-43a0-9e74-99aa93a57aad.png → 77b359e6-7dc9-44cf-baa4-85a8abc40fc5.png} +0 -0
- /kotonebot/tasks/sprites/{dea50b1c-7005-4f9e-b188-bf94c157af15.png → 78512fc1-11b8-4a12-b06e-63b09604a27f.png} +0 -0
- /kotonebot/tasks/sprites/{a9582588-9809-45ff-9400-fde668480906.png → 7a4e2bc7-7f5e-482a-bbce-0d8a4801b502.png} +0 -0
- /kotonebot/tasks/sprites/{7cebfa84-fc03-4544-bdab-71d8940dfc72.png → 7a983ea5-c05f-42ee-95a9-9f1c6ef6deac.png} +0 -0
- /kotonebot/tasks/sprites/{373a5761-afaa-4763-9264-c38df17535ec.png → 7e2d836d-cd59-43a9-978b-3e333273712c.png} +0 -0
- /kotonebot/tasks/sprites/{dcba6a05-4720-4075-bbce-b76baa8c6ab4.png → 80d0e08b-7179-456f-8228-b9dcf6ccb6f1.png} +0 -0
- /kotonebot/tasks/sprites/{5fa367ec-6d48-4891-aa78-80762ec4e958.png → 811dd2d9-6e28-4bf3-97bf-537e068a3701.png} +0 -0
- /kotonebot/tasks/sprites/{a9276e58-5764-476b-925d-28854bf5db5f.png → 8520878d-15c6-4bcf-95c9-921666f23525.png} +0 -0
- /kotonebot/tasks/sprites/{3bfec2af-854e-4a3c-ad91-a272b0b9b413.png → 85e3c4ba-95ee-46c8-904a-cea3f8ad48db.png} +0 -0
- /kotonebot/tasks/sprites/{f872dcba-5174-472c-abda-c44696b4fa43.png → 88d94d19-d1b2-4e7e-a342-4f5c47832542.png} +0 -0
- /kotonebot/tasks/sprites/{60e90826-df0a-41d7-bf89-9e820577fc65.png → 8c4895ce-c87c-479d-9b6b-fa4da5e7eca6.png} +0 -0
- /kotonebot/tasks/sprites/{eeddb9f2-4f90-443f-8494-6c205ba2f48d.png → 8e3a8e95-b504-490a-9c85-65ce134e9d33.png} +0 -0
- /kotonebot/tasks/sprites/{25e5b8da-29c8-40e0-abb0-af288f5d5b3c.png → 8f6df3a3-7bad-4ad2-9f39-7cd2c8a92c68.png} +0 -0
- /kotonebot/tasks/sprites/{6e5c8c24-465b-4594-93ba-86558a37d42c.png → 918c27be-ab0e-42bd-b470-cb48907d229e.png} +0 -0
- /kotonebot/tasks/sprites/{ce61a356-d19c-4a89-a2d6-0cc1bff147b8.png → 93f973b7-f700-49ec-b484-b74a50fda5b2.png} +0 -0
- /kotonebot/tasks/sprites/{36c6e2ca-6ff7-4642-bb91-6847b743eba3.png → 966dafff-c26e-4043-9f7d-39133c860de6.png} +0 -0
- /kotonebot/tasks/sprites/{14a90b3a-49cb-4f53-a41b-3e26e0bbd480.png → 973e2f4d-5693-47b4-b555-f243ef2d86fe.png} +0 -0
- /kotonebot/tasks/sprites/{be7ba2ab-3405-45c6-86a9-87f5a8fb2335.png → 9ad18387-a834-46fa-ab85-b09fec60b89e.png} +0 -0
- /kotonebot/tasks/sprites/{0a619440-9d31-4a76-9dd5-ad4aafb0817e.png → 9b8604fb-6dfa-471a-aeb4-458d5d59f726.png} +0 -0
- /kotonebot/tasks/sprites/{51f2ce40-246d-45cf-8c61-00617118fb66.png → 9b86c2e6-2d97-4c49-9e00-27ed7dfe8cd5.png} +0 -0
- /kotonebot/tasks/sprites/{caeafb3e-34ee-4996-b22d-01043803023d.png → 9e35b9d0-dfde-41d0-ab10-0d95e7008d99.png} +0 -0
- /kotonebot/tasks/sprites/{108999f3-bf8e-4037-b85f-7c9a848d69fe.png → a23742d9-9199-43c1-922b-d7f286bccbde.png} +0 -0
- /kotonebot/tasks/sprites/{ff789de2-98d8-4b88-8f70-83d8ce15dc3e.png → a2dae26f-14a7-46d3-bfa6-2bec94cce843.png} +0 -0
- /kotonebot/tasks/sprites/{07a2184b-5240-4f60-811c-dd7dfa663e77.png → a3988fad-4f8f-46c8-a6ef-d64dccdfbe5d.png} +0 -0
- /kotonebot/tasks/sprites/{6898af97-010a-4640-92bc-853fe563fd31.png → a65bec5b-2875-4bd7-9c06-7c941946b00e.png} +0 -0
- /kotonebot/tasks/sprites/{304c44f5-384d-4c94-b801-25974e0071d4.png → a688ef42-79c2-4de5-88d1-4a6e0cb65829.png} +0 -0
- /kotonebot/tasks/sprites/{49acc597-207f-48b1-b8ac-2c4246b00585.png → a6895be9-f7c2-4889-88d4-8b3906ed80ff.png} +0 -0
- /kotonebot/tasks/sprites/{57ce1f5a-c2cf-4fb7-b066-244b4dcbba98.png → a9567e98-c2fa-42c3-896b-73a6aaeb5379.png} +0 -0
- /kotonebot/tasks/sprites/{3e48784d-8fef-4d80-9bc3-dededa66a24e.png → aa01cacc-cf11-488c-a315-3ab807bda741.png} +0 -0
- /kotonebot/tasks/sprites/{ad877757-251f-470b-947a-62b31982313c.png → ac238fb2-492d-4f8c-b8d8-5e6b5451aac0.png} +0 -0
- /kotonebot/tasks/sprites/{a3618dea-720a-4fa5-be7f-5b171331b027.png → ad0624ab-c9af-4224-8128-1306d63cbbfa.png} +0 -0
- /kotonebot/tasks/sprites/{dce05535-a13e-4409-96f9-10a9ab742e85.png → b18ead61-b3de-4a39-9ed0-664b64f45a6a.png} +0 -0
- /kotonebot/tasks/sprites/{be5f1221-2bc9-4512-b975-f204c9c28732.png → b210716c-6b40-4fba-887e-50e48a0d53ab.png} +0 -0
- /kotonebot/tasks/sprites/{0cfbc864-e698-44b3-9f89-6c1715bf55a8.png → b399e131-25b2-4f26-8757-533c1009dddc.png} +0 -0
- /kotonebot/tasks/sprites/{a565cca2-837d-479d-93e7-f3067013958a.png → b6c42310-592a-4cdd-a106-3f8bb0f3df30.png} +0 -0
- /kotonebot/tasks/sprites/{6ac60114-3f39-4965-b559-dcd85c072308.png → b8667106-89e4-41e7-b0f4-d13eb8e4ab54.png} +0 -0
- /kotonebot/tasks/sprites/{d9b77ac7-6708-4d2b-aef7-ecebb21df573.png → b96bbdef-93c9-4965-9ff4-805c953143d8.png} +0 -0
- /kotonebot/tasks/sprites/{913aa235-9ee7-4022-85e5-0611fed1fb08.png → bb46f878-7976-408d-a671-12854f7dcffb.png} +0 -0
- /kotonebot/tasks/sprites/{01162a01-9a9a-4cee-b607-7f3a67c47087.png → be4a9682-8828-42ef-88f2-e177dd8f0e01.png} +0 -0
- /kotonebot/tasks/sprites/{c46da919-190b-49ec-8b81-669f4f4e4de4.png → bfa4c9ec-f54c-4fbd-92b8-1bca9f2354e7.png} +0 -0
- /kotonebot/tasks/sprites/{abf4c9a1-d24f-4559-92d2-98dd30b3a5a2.png → bfbd85ee-5256-4a81-82b5-70da967a0004.png} +0 -0
- /kotonebot/tasks/sprites/{b74e708a-6497-4d9a-afdb-16bf2ce99af3.png → c4fded0c-8075-49a9-a56c-9591a004f4e3.png} +0 -0
- /kotonebot/tasks/sprites/{5082dc0d-3b59-4282-b714-89f11a0759a1.png → c6177849-daa3-4e1f-92de-2cc68b752e68.png} +0 -0
- /kotonebot/tasks/sprites/{587cba78-6af2-4913-8a02-da177c785ad2.png → c6d16470-3952-465d-8e7e-0e1e8c5a79a2.png} +0 -0
- /kotonebot/tasks/sprites/{82a2720d-7952-41a8-97e8-cb7986382e36.png → c7632864-0678-4ab1-8f22-414d8f1a1b1d.png} +0 -0
- /kotonebot/tasks/sprites/{5ec43604-92db-4256-8aec-f6966af73002.png → cb2c4421-5504-4a0c-b568-3e25a7a568ab.png} +0 -0
- /kotonebot/tasks/sprites/{d2d4df1f-d29b-479c-b0a6-5ca1e1de2b47.png → cb9b9cd7-36c1-4c26-9027-11b3ab709e01.png} +0 -0
- /kotonebot/tasks/sprites/{83e2ba4c-6a38-4de4-a545-9a5347931fbd.png → d2338793-6d96-4475-bfd5-a0dcaea6ea90.png} +0 -0
- /kotonebot/tasks/sprites/{86dcd997-50cd-4efc-8b0c-3e6a639e3316.png → d993723d-da01-494f-a37f-b9242feb1cf7.png} +0 -0
- /kotonebot/tasks/sprites/{b00e8013-9475-433d-929f-f16af552fe0d.png → ddc43151-a3ae-4c3f-95bb-ae9f72b8f875.png} +0 -0
- /kotonebot/tasks/sprites/{dabecc2b-7938-490b-8bba-a5d26d5b21c4.png → df5e43bb-b9bc-4bb9-a47c-d0077fec3b3c.png} +0 -0
- /kotonebot/tasks/sprites/{640f6f78-2e39-45c8-a71f-664eb302d9b5.png → e31acb36-85fc-4ec3-af99-c65e2b9bc35b.png} +0 -0
- /kotonebot/tasks/sprites/{77870708-86cd-45b0-b5ee-071bb375f660.png → e4af688e-fa37-4af7-b5d5-bb1784f204ed.png} +0 -0
- /kotonebot/tasks/sprites/{4ce0c0a5-2fae-45db-b986-a44e15e3f247.png → e748f660-ac56-4dac-b903-23fa508d8d5b.png} +0 -0
- /kotonebot/tasks/sprites/{6f01e188-f901-4d36-ba03-8419842c9b02.png → e949772f-f286-4394-ab9b-ae0620ab6095.png} +0 -0
- /kotonebot/tasks/sprites/{00cda413-7e30-44e3-8eed-7567f4cbdb13.png → e9e2db9c-7cee-4990-bcb3-ae8cad0da7dc.png} +0 -0
- /kotonebot/tasks/sprites/{7b731a67-d690-4068-939e-1e86496430d0.png → ea12ede1-88cd-4ff2-8997-2f4d0a950ace.png} +0 -0
- /kotonebot/tasks/sprites/{e0eeea93-b5c3-4f9e-a368-7080fc8d22b7.png → eae2eaf0-0f97-43f1-891e-0544d609140b.png} +0 -0
- /kotonebot/tasks/sprites/{eec6a6c0-b3fd-44f3-8745-7bdb60e63521.png → ec6790e4-2c43-41bc-ac25-b7179e604e04.png} +0 -0
- /kotonebot/tasks/sprites/{a40f00e3-f6a3-4f4d-91cd-b9c0f9b9d3f3.png → eec6e59b-e458-4a51-85da-31c9eb11543d.png} +0 -0
- /kotonebot/tasks/sprites/{04d9b790-2d53-4b1b-a7ea-08ed06b12046.png → f0ad28dc-568b-4436-962f-e6e024d46373.png} +0 -0
- /kotonebot/tasks/sprites/{817a5e76-64f0-4d51-a224-4f6a71f11f23.png → f414d470-3427-4752-a58f-4f2aff55b81c.png} +0 -0
- /kotonebot/tasks/sprites/{e8efd7a2-284b-406a-8467-7fb3a71333fd.png → f8cf065b-d071-412c-8f0f-8d8047a612e4.png} +0 -0
- /kotonebot/tasks/sprites/{0db7f069-8d5f-4a88-8d39-d36b57b8f8c9.png → f92a8682-acde-4f82-83c1-b2760fc2e915.png} +0 -0
- /kotonebot/tasks/sprites/{00e1c918-3c57-4a33-8c97-0b96ddfc3278.png → fa6eadbc-e462-4473-b681-1158c6cca82c.png} +0 -0
- /kotonebot/tasks/sprites/{a1ee66f3-25ad-4098-bff8-29ad02056634.png → fc9d1512-76ce-41b5-ad01-c393f2fa169d.png} +0 -0
- /kotonebot/tasks/sprites/{d0ebfbfa-fbef-48cb-a337-fa1cc6a1551f.png → fd092b4f-cf20-48e9-9c57-7d38367b893d.png} +0 -0
- {ksaa-2025.4.17.2.dist-info → ksaa-2025.4.26.0.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.4.17.2.dist-info → ksaa-2025.4.26.0.dist-info}/top_level.txt +0 -0
kotonebot/backend/bot.py
CHANGED
|
@@ -207,6 +207,7 @@ class KotoneBot:
|
|
|
207
207
|
"""
|
|
208
208
|
self.check_backend()
|
|
209
209
|
init_context(config_type=self.config_type)
|
|
210
|
+
vars.interrupted.clear()
|
|
210
211
|
|
|
211
212
|
if by_priority:
|
|
212
213
|
tasks = sorted(tasks, key=lambda x: x.priority, reverse=True)
|
|
@@ -249,7 +250,14 @@ class KotoneBot:
|
|
|
249
250
|
def run_all(self) -> None:
|
|
250
251
|
return self.run(list(task_registry.values()), by_priority=True)
|
|
251
252
|
|
|
252
|
-
def
|
|
253
|
+
def start(self, tasks: list[Task], *, by_priority: bool = True) -> RunStatus:
|
|
254
|
+
"""
|
|
255
|
+
在单独的线程中按优先级顺序运行指定的任务。
|
|
256
|
+
|
|
257
|
+
:param tasks: 要运行的任务列表
|
|
258
|
+
:param by_priority: 是否按优先级排序
|
|
259
|
+
:return: 运行状态对象
|
|
260
|
+
"""
|
|
253
261
|
run_status = RunStatus(running=True)
|
|
254
262
|
def _on_finished():
|
|
255
263
|
run_status.running = False
|
|
@@ -271,7 +279,14 @@ class KotoneBot:
|
|
|
271
279
|
|
|
272
280
|
self.events.task_status_changed += _on_task_status_changed
|
|
273
281
|
self.events.finished += _on_finished
|
|
274
|
-
thread = threading.Thread(target=self.
|
|
282
|
+
thread = threading.Thread(target=lambda: self.run(tasks, by_priority=by_priority))
|
|
275
283
|
thread.start()
|
|
276
284
|
return run_status
|
|
277
|
-
|
|
285
|
+
|
|
286
|
+
def start_all(self) -> RunStatus:
|
|
287
|
+
"""
|
|
288
|
+
在单独的线程中运行所有任务。
|
|
289
|
+
|
|
290
|
+
:return: 运行状态对象
|
|
291
|
+
"""
|
|
292
|
+
return self.start(list(task_registry.values()), by_priority=True)
|
kotonebot/client/factory.py
CHANGED
|
@@ -4,12 +4,13 @@ from typing import Literal
|
|
|
4
4
|
from .implements.adb import AdbImpl
|
|
5
5
|
from .implements.adb_raw import AdbRawImpl
|
|
6
6
|
from .implements.windows import WindowsImpl
|
|
7
|
+
from .implements.remote_windows import RemoteWindowsImpl
|
|
7
8
|
from .implements.uiautomator2 import UiAutomator2Impl
|
|
8
9
|
from .device import Device, AndroidDevice, WindowsDevice
|
|
9
10
|
|
|
10
11
|
from adbutils import adb
|
|
11
12
|
|
|
12
|
-
DeviceImpl = Literal['adb', 'adb_raw', 'uiautomator2', 'windows']
|
|
13
|
+
DeviceImpl = Literal['adb', 'adb_raw', 'uiautomator2', 'windows', 'remote_windows']
|
|
13
14
|
|
|
14
15
|
def create_device(
|
|
15
16
|
addr: str,
|
|
@@ -40,4 +41,18 @@ def create_device(
|
|
|
40
41
|
device = WindowsDevice()
|
|
41
42
|
device._touch = WindowsImpl(device)
|
|
42
43
|
device._screenshot = WindowsImpl(device)
|
|
44
|
+
elif impl == 'remote_windows':
|
|
45
|
+
# For remote_windows, addr should be in the format 'host:port'
|
|
46
|
+
if ':' not in addr:
|
|
47
|
+
raise ValueError(f"Invalid address format for remote_windows: {addr}. Expected format: 'host:port'")
|
|
48
|
+
host, port_str = addr.split(':', 1)
|
|
49
|
+
try:
|
|
50
|
+
port = int(port_str)
|
|
51
|
+
except ValueError:
|
|
52
|
+
raise ValueError(f"Invalid port in address: {port_str}")
|
|
53
|
+
|
|
54
|
+
device = WindowsDevice()
|
|
55
|
+
remote_impl = RemoteWindowsImpl(device, host, port)
|
|
56
|
+
device._touch = remote_impl
|
|
57
|
+
device._screenshot = remote_impl
|
|
43
58
|
return device
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Remote Windows implementation using XML-RPC.
|
|
3
|
+
|
|
4
|
+
This module provides:
|
|
5
|
+
1. RemoteWindowsImpl - Client implementation that connects to a remote Windows machine
|
|
6
|
+
2. RemoteWindowsServer - Server implementation that exposes a WindowsImpl instance via XML-RPC
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import io
|
|
10
|
+
import base64
|
|
11
|
+
import logging
|
|
12
|
+
import xmlrpc.client
|
|
13
|
+
import xmlrpc.server
|
|
14
|
+
from typing import Literal, cast, Any, Tuple
|
|
15
|
+
from functools import cached_property
|
|
16
|
+
from threading import Thread
|
|
17
|
+
|
|
18
|
+
import cv2
|
|
19
|
+
import numpy as np
|
|
20
|
+
from cv2.typing import MatLike
|
|
21
|
+
|
|
22
|
+
from kotonebot import logging
|
|
23
|
+
from ..device import Device, WindowsDevice
|
|
24
|
+
from ..protocol import Touchable, Screenshotable
|
|
25
|
+
from .windows import WindowsImpl
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
def _encode_image(image: MatLike) -> str:
|
|
30
|
+
"""Encode an image as a base64 string."""
|
|
31
|
+
success, buffer = cv2.imencode('.png', image)
|
|
32
|
+
if not success:
|
|
33
|
+
raise RuntimeError("Failed to encode image")
|
|
34
|
+
return base64.b64encode(buffer.tobytes()).decode('ascii')
|
|
35
|
+
|
|
36
|
+
def _decode_image(encoded_image: str) -> MatLike:
|
|
37
|
+
"""Decode a base64 string to an image."""
|
|
38
|
+
buffer = base64.b64decode(encoded_image)
|
|
39
|
+
image = cv2.imdecode(np.frombuffer(buffer, np.uint8), cv2.IMREAD_COLOR)
|
|
40
|
+
if image is None:
|
|
41
|
+
raise RuntimeError("Failed to decode image")
|
|
42
|
+
return image
|
|
43
|
+
|
|
44
|
+
class RemoteWindowsServer:
|
|
45
|
+
"""
|
|
46
|
+
XML-RPC server that exposes a WindowsImpl instance.
|
|
47
|
+
|
|
48
|
+
This class wraps a WindowsImpl instance and exposes its methods via XML-RPC.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, host="localhost", port=8000):
|
|
52
|
+
"""Initialize the server with the given host and port."""
|
|
53
|
+
self.host = host
|
|
54
|
+
self.port = port
|
|
55
|
+
self.server = None
|
|
56
|
+
self.device = WindowsDevice()
|
|
57
|
+
self.impl = WindowsImpl(self.device)
|
|
58
|
+
self.device._screenshot = self.impl
|
|
59
|
+
self.device._touch = self.impl
|
|
60
|
+
|
|
61
|
+
def start(self):
|
|
62
|
+
"""Start the XML-RPC server."""
|
|
63
|
+
self.server = xmlrpc.server.SimpleXMLRPCServer(
|
|
64
|
+
(self.host, self.port),
|
|
65
|
+
logRequests=True,
|
|
66
|
+
allow_none=True
|
|
67
|
+
)
|
|
68
|
+
self.server.register_instance(self)
|
|
69
|
+
logger.info(f"Starting RemoteWindowsServer on {self.host}:{self.port}")
|
|
70
|
+
self.server.serve_forever()
|
|
71
|
+
|
|
72
|
+
def start_in_thread(self):
|
|
73
|
+
"""Start the XML-RPC server in a separate thread."""
|
|
74
|
+
thread = Thread(target=self.start, daemon=True)
|
|
75
|
+
thread.start()
|
|
76
|
+
return thread
|
|
77
|
+
|
|
78
|
+
# Screenshotable methods
|
|
79
|
+
|
|
80
|
+
def screenshot(self) -> str:
|
|
81
|
+
"""Take a screenshot and return it as a base64-encoded string."""
|
|
82
|
+
try:
|
|
83
|
+
image = self.impl.screenshot()
|
|
84
|
+
return _encode_image(image)
|
|
85
|
+
except Exception as e:
|
|
86
|
+
logger.error(f"Error taking screenshot: {e}")
|
|
87
|
+
raise
|
|
88
|
+
|
|
89
|
+
def get_screen_size(self) -> tuple[int, int]:
|
|
90
|
+
"""Get the screen size."""
|
|
91
|
+
return self.impl.screen_size
|
|
92
|
+
|
|
93
|
+
def detect_orientation(self) -> str | None:
|
|
94
|
+
"""Detect the screen orientation."""
|
|
95
|
+
return self.impl.detect_orientation()
|
|
96
|
+
|
|
97
|
+
# Touchable methods
|
|
98
|
+
|
|
99
|
+
def click(self, x: int, y: int) -> bool:
|
|
100
|
+
"""Click at the given coordinates."""
|
|
101
|
+
try:
|
|
102
|
+
self.impl.click(x, y)
|
|
103
|
+
return True
|
|
104
|
+
except Exception as e:
|
|
105
|
+
logger.error(f"Error clicking at ({x}, {y}): {e}")
|
|
106
|
+
return False
|
|
107
|
+
|
|
108
|
+
def swipe(self, x1: int, y1: int, x2: int, y2: int, duration: float | None = None) -> bool:
|
|
109
|
+
"""Swipe from (x1, y1) to (x2, y2)."""
|
|
110
|
+
try:
|
|
111
|
+
self.impl.swipe(x1, y1, x2, y2, duration)
|
|
112
|
+
return True
|
|
113
|
+
except Exception as e:
|
|
114
|
+
logger.error(f"Error swiping from ({x1}, {y1}) to ({x2}, {y2}): {e}")
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
# Other methods
|
|
118
|
+
|
|
119
|
+
def get_scale_ratio(self) -> float:
|
|
120
|
+
"""Get the scale ratio."""
|
|
121
|
+
return self.impl.scale_ratio
|
|
122
|
+
|
|
123
|
+
def ping(self) -> bool:
|
|
124
|
+
"""Check if the server is alive."""
|
|
125
|
+
return True
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class RemoteWindowsImpl(Touchable, Screenshotable):
|
|
129
|
+
"""
|
|
130
|
+
Client implementation that connects to a remote Windows machine via XML-RPC.
|
|
131
|
+
|
|
132
|
+
This class implements the same interfaces as WindowsImpl but forwards all
|
|
133
|
+
method calls to a remote server.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
def __init__(self, device: Device, host="localhost", port=8000):
|
|
137
|
+
"""Initialize the client with the given device, host, and port."""
|
|
138
|
+
self.device = device
|
|
139
|
+
self.host = host
|
|
140
|
+
self.port = port
|
|
141
|
+
self.proxy = xmlrpc.client.ServerProxy(
|
|
142
|
+
f"http://{host}:{port}/",
|
|
143
|
+
allow_none=True
|
|
144
|
+
)
|
|
145
|
+
# Test connection
|
|
146
|
+
try:
|
|
147
|
+
if not self.proxy.ping():
|
|
148
|
+
raise ConnectionError(f"Failed to connect to RemoteWindowsServer at {host}:{port}")
|
|
149
|
+
logger.info(f"Connected to RemoteWindowsServer at {host}:{port}")
|
|
150
|
+
except Exception as e:
|
|
151
|
+
raise ConnectionError(f"Failed to connect to RemoteWindowsServer at {host}:{port}: {e}")
|
|
152
|
+
|
|
153
|
+
@cached_property
|
|
154
|
+
def scale_ratio(self) -> float:
|
|
155
|
+
"""Get the scale ratio from the remote server."""
|
|
156
|
+
return cast(float, self.proxy.get_scale_ratio())
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def screen_size(self) -> tuple[int, int]:
|
|
160
|
+
"""Get the screen size from the remote server."""
|
|
161
|
+
return cast(Tuple[int, int], self.proxy.get_screen_size())
|
|
162
|
+
|
|
163
|
+
def detect_orientation(self) -> None | Literal['portrait'] | Literal['landscape']:
|
|
164
|
+
"""Detect the screen orientation from the remote server."""
|
|
165
|
+
return cast(None | Literal['portrait'] | Literal['landscape'], self.proxy.detect_orientation())
|
|
166
|
+
|
|
167
|
+
def screenshot(self) -> MatLike:
|
|
168
|
+
"""Take a screenshot from the remote server."""
|
|
169
|
+
encoded_image = cast(str, self.proxy.screenshot())
|
|
170
|
+
return _decode_image(encoded_image)
|
|
171
|
+
|
|
172
|
+
def click(self, x: int, y: int) -> None:
|
|
173
|
+
"""Click at the given coordinates on the remote server."""
|
|
174
|
+
if not self.proxy.click(x, y):
|
|
175
|
+
raise RuntimeError(f"Failed to click at ({x}, {y})")
|
|
176
|
+
|
|
177
|
+
def swipe(self, x1: int, y1: int, x2: int, y2: int, duration: float | None = None) -> None:
|
|
178
|
+
"""Swipe from (x1, y1) to (x2, y2) on the remote server."""
|
|
179
|
+
if not self.proxy.swipe(x1, y1, x2, y2, duration):
|
|
180
|
+
raise RuntimeError(f"Failed to swipe from ({x1}, {y1}) to ({x2}, {y2})")
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
import argparse
|
|
185
|
+
|
|
186
|
+
parser = argparse.ArgumentParser(description="Remote Windows XML-RPC Server")
|
|
187
|
+
parser.add_argument("--host", default="0.0.0.0", help="Host to bind to")
|
|
188
|
+
parser.add_argument("--port", type=int, default=8000, help="Port to bind to")
|
|
189
|
+
args = parser.parse_args()
|
|
190
|
+
|
|
191
|
+
logging.basicConfig(level=logging.INFO)
|
|
192
|
+
|
|
193
|
+
server = RemoteWindowsServer(args.host, args.port)
|
|
194
|
+
try:
|
|
195
|
+
server.start()
|
|
196
|
+
except KeyboardInterrupt:
|
|
197
|
+
logger.info("Server stopped by user")
|
kotonebot/config/base_config.py
CHANGED
|
@@ -22,9 +22,11 @@ class BackendConfig(ConfigBaseModel):
|
|
|
22
22
|
雷电模拟器需要设置正确的模拟器名,否则 自动启动模拟器 功能将无法正常工作。
|
|
23
23
|
其他功能不受影响。
|
|
24
24
|
"""
|
|
25
|
-
screenshot_impl: Literal['adb', 'adb_raw', 'uiautomator2', 'windows'] = 'adb'
|
|
25
|
+
screenshot_impl: Literal['adb', 'adb_raw', 'uiautomator2', 'windows', 'remote_windows'] = 'adb'
|
|
26
26
|
"""
|
|
27
27
|
截图方法。暂时推荐使用【adb】截图方式。
|
|
28
|
+
|
|
29
|
+
如果使用 remote_windows,需要在 adb_ip 中填写远程 Windows 的 IP 地址,在 adb_port 中填写远程 Windows 的端口号。
|
|
28
30
|
"""
|
|
29
31
|
check_emulator: bool = False
|
|
30
32
|
"""
|
|
@@ -72,7 +74,7 @@ class UserConfig(ConfigBaseModel, Generic[T]):
|
|
|
72
74
|
|
|
73
75
|
|
|
74
76
|
class RootConfig(ConfigBaseModel, Generic[T]):
|
|
75
|
-
version: int =
|
|
77
|
+
version: int = 4
|
|
76
78
|
"""配置版本。"""
|
|
77
79
|
user_configs: list[UserConfig[T]] = []
|
|
78
80
|
"""用户配置。"""
|