ksaa 2025.11b1__py3-none-any.whl → 2025.11b3__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.
- kaa/application/core/feedback_service.py +121 -0
- kaa/application/core/misc_core.py +4 -1
- kaa/application/core/update_service.py +208 -0
- kaa/config/schema.py +6 -0
- kaa/errors.py +60 -0
- kaa/main/gr.py +106 -516
- kaa/main/kaa.py +11 -3
- kaa/metadata.py +10 -0
- kaa/resources/__pycache__/__init__.cpython-310.pyc +0 -0
- kaa/resources/game.db +0 -0
- kaa/resources/game_ver.txt +0 -0
- kaa/resources/idol_cards/i_card-skin-amao-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-amao-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-1-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-1-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-2-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-2-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-3-000_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-atbm-3-000_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-fktn-3-016_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-fktn-3-016_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-003_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-003_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-013_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hmsz-3-013_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hrnm-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hrnm-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hski-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hski-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-hume-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-009_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-009_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-014_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-jsna-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kcna-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kllj-3-014_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-kllj-3-014_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-shro-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-shro-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ssmk-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ssmk-3-015_1.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ttmr-3-015_0.png +0 -0
- kaa/resources/idol_cards/i_card-skin-ttmr-3-015_1.png +0 -0
- kaa/sprites/19513e9f-2cbb-4f66-84b7-2ad2faed252d.png +0 -0
- kaa/sprites/1ef5fa52-b6e1-42d0-947a-ce970eba057d.png +0 -0
- kaa/sprites/318abb8a-5950-4d22-ac42-77219b5bc1a0.png +0 -0
- kaa/sprites/321b7040-87d7-4f87-9b44-ad2972584a11.png +0 -0
- kaa/sprites/3ae72684-1d40-43cf-9508-511c010de64f.png +0 -0
- kaa/sprites/3e669188-5933-4502-b039-38f4d4649664.png +0 -0
- kaa/sprites/4370013d-f052-4314-94ff-a342d70754c3.png +0 -0
- kaa/sprites/4fb1d36c-5fb6-4fe5-9ba3-07e056eb1dfc.png +0 -0
- kaa/sprites/5247b052-5b45-4e64-b7fc-d566f5d4bc82.png +0 -0
- kaa/sprites/545a9032-a676-4d9d-ac74-2b2c9b330d1a.png +0 -0
- kaa/sprites/57741798-65dd-47eb-b4b1-b3f0e3c3e318.png +0 -0
- kaa/sprites/5e2b4bb9-f200-4723-96ac-5f907e28eaaa.png +0 -0
- kaa/sprites/5f6fafd9-43aa-443e-994e-f2688af5e238.png +0 -0
- kaa/sprites/61229c71-303b-4dc9-ba4e-6a14e5ab161e.png +0 -0
- kaa/sprites/62f93327-5946-4a48-aff8-a203483b0562.png +0 -0
- kaa/sprites/64dfeb35-61ad-4e9b-9847-a18530f02584.png +0 -0
- kaa/sprites/64f8ef99-4766-471b-aeb0-b109704d9615.png +0 -0
- kaa/sprites/677933e9-1481-4f01-95b4-d55bea51db8c.png +0 -0
- kaa/sprites/67edcd91-d2c1-418b-987a-e60263626f56.png +0 -0
- kaa/sprites/6c032aa7-20e3-4e2e-b1a4-1585141ba22b.png +0 -0
- kaa/sprites/6fadb00b-e32e-4c45-a738-f21b8f48c139.png +0 -0
- kaa/sprites/719297ec-82be-4820-8ecf-8bf6322b81fe.png +0 -0
- kaa/sprites/76970b91-7864-4413-bfc7-79c04a48dce7.png +0 -0
- kaa/sprites/7c62081d-097a-4514-a69d-69e96201e816.png +0 -0
- kaa/sprites/7e16af89-bb51-4889-8a7e-25715ff5faa1.png +0 -0
- kaa/sprites/7efce7bc-12a5-4a53-9a0a-9fa755649ebd.png +0 -0
- kaa/sprites/803fb770-6982-4460-8fe0-f9ccd67367c2.png +0 -0
- kaa/sprites/82200c8c-0916-4601-839a-945f96cc4ebc.png +0 -0
- kaa/sprites/8299e3e2-cfd5-4380-adce-a46c93b1be4d.png +0 -0
- kaa/sprites/83c27159-36d2-4ccf-ace7-e5d2169e7e52.png +0 -0
- kaa/sprites/8661bc83-9b0a-4555-8b21-2258b31c7f57.png +0 -0
- kaa/sprites/89437aca-7339-4795-b848-ec529b1e5e8d.png +0 -0
- kaa/sprites/8a0260f5-b32e-430e-bc98-7b5a77cab6ab.png +0 -0
- kaa/sprites/8c3bc157-022a-4bb1-be74-af1ad254e67f.png +0 -0
- kaa/sprites/8d09178a-251e-4f74-b023-12233417621b.png +0 -0
- kaa/sprites/8fbee6fe-9409-407e-8f55-d2d36ab37f6a.png +0 -0
- kaa/sprites/8fdc102b-d8f3-4d16-b8ef-1d804f5aff07.png +0 -0
- kaa/sprites/93e91dd0-0050-48b4-8bf8-c732cd76f0e3.png +0 -0
- kaa/sprites/993a33ac-994b-4eb0-9c1e-b9412d499d67.png +0 -0
- kaa/sprites/99a27ff1-bc1c-48a2-9f9b-0803338d1bd8.png +0 -0
- kaa/sprites/9a9a1f40-d308-4aa5-8d91-60342bc6a4e0.png +0 -0
- kaa/sprites/9f573ac2-9d28-4d92-8e3f-1b78031220dd.png +0 -0
- kaa/sprites/__pycache__/__init__.cpython-310.pyc +0 -0
- kaa/sprites/a2545c5c-b5cc-4fd2-93c1-04c74c17ee16.png +0 -0
- kaa/sprites/a2dd125b-9868-4e01-9a46-3b552c2ebdc9.png +0 -0
- kaa/sprites/a7f25aeb-d91b-47e0-ba1a-0c6382380102.png +0 -0
- kaa/sprites/a888e87e-49fe-405d-b074-3dda30304808.png +0 -0
- kaa/sprites/a9ba2741-38da-4448-ab80-f0e5b3c3847f.png +0 -0
- kaa/sprites/a9c5aeb0-c0c9-47da-8793-ffe8d172bea0.png +0 -0
- kaa/sprites/aba47934-f264-49f9-a72c-6ed90b112701.png +0 -0
- kaa/sprites/abe2757f-84f3-4967-bd05-79c17cb1f32c.png +0 -0
- kaa/sprites/acd741da-d4ab-4b76-a6a3-4a2fd25870ef.png +0 -0
- kaa/sprites/ad17ae00-f6ce-4f32-9386-9a8073b5e79a.png +0 -0
- kaa/sprites/ae73d26b-2d47-4921-a6ec-5bbea32773a3.png +0 -0
- kaa/sprites/b10281ae-cfaf-4400-b2fb-c8c2b432c8e7.png +0 -0
- kaa/sprites/b40bebbf-2800-40fb-b7a2-1c2d5995e747.png +0 -0
- kaa/sprites/b76add75-2187-428c-9ede-fb43086bacb6.png +0 -0
- kaa/sprites/b77a7e97-dc59-493d-9d76-4ea9c2876978.png +0 -0
- kaa/sprites/b9770cd2-b55f-44dc-965f-f29686fba7da.png +0 -0
- kaa/sprites/ba8ee2cd-f662-440c-90b3-1e4bfe7bab6b.png +0 -0
- kaa/sprites/bb3990c8-4618-4d96-9365-a4d1213b59f7.png +0 -0
- kaa/sprites/bbe59f62-c3e7-404c-a313-b50db70de7b5.png +0 -0
- kaa/sprites/bdb1460e-c5db-494a-a58a-688f72b6bdba.png +0 -0
- kaa/sprites/bdb72f31-5808-4451-827f-fffc3b616083.png +0 -0
- kaa/sprites/bf3ff37e-d4fc-42ee-87d6-db1e2040aed5.png +0 -0
- kaa/sprites/bff753bb-b02e-441b-89e5-14845f18c6f6.png +0 -0
- kaa/sprites/c035ac76-39e9-466b-a606-28bc52bc73e8.png +0 -0
- kaa/sprites/c05a600a-d79e-432d-a49f-5b2443d67bd4.png +0 -0
- kaa/sprites/c0801be3-f07a-4afc-ab0d-7f5d3c4afbd3.png +0 -0
- kaa/sprites/c2100faf-1234-49db-b6d4-5a08a4b08272.png +0 -0
- kaa/sprites/c6b0f9ba-a976-474b-b22d-6fe4391d9373.png +0 -0
- kaa/sprites/c78fb143-18e3-4697-a0c1-6151514f2a7c.png +0 -0
- kaa/sprites/c8c17304-e949-4dfc-b07d-9e7133483e31.png +0 -0
- kaa/sprites/c91874f4-363f-4997-a38e-3e486dfd8043.png +0 -0
- kaa/sprites/c9245201-4d29-4088-a5e0-f4e93d4494b5.png +0 -0
- kaa/sprites/cb0bbf0f-a25b-4ec4-99bd-f5742270a062.png +0 -0
- kaa/sprites/ccfab3e2-7b6d-4ae3-998b-4e5c1863884a.png +0 -0
- kaa/sprites/cdf310f0-b917-4f92-95a9-893af76e3c3a.png +0 -0
- kaa/sprites/cea8f98d-ba68-498f-bd3d-cc10f0d4575b.png +0 -0
- kaa/sprites/cec36685-85a7-4e84-bbbc-4df70b4f7bac.png +0 -0
- kaa/sprites/cf49878d-a1c5-4b9f-9502-1e0d9eaadc49.png +0 -0
- kaa/sprites/d23a600a-7002-4268-96a4-18dc54928ec6.png +0 -0
- kaa/sprites/d57f792a-f086-4fbe-b4d9-5db629a78d42.png +0 -0
- kaa/sprites/d6dd92b3-310f-4f5d-a8ef-b941c3659c0c.png +0 -0
- kaa/sprites/d8967770-c64a-4609-a0a5-f46ba81edceb.png +0 -0
- kaa/sprites/d91483a2-83fa-4664-8eda-52498c0e77bc.png +0 -0
- kaa/sprites/d9a636be-a017-4ef5-a70c-c374827008a0.png +0 -0
- kaa/sprites/dae37bd7-6a34-4eb4-8cd0-3c0c03b4575a.png +0 -0
- kaa/sprites/dc51eccf-9470-495a-9e38-59d4481adbd4.png +0 -0
- kaa/sprites/dcea5aae-322e-4cd4-b218-0eac48690755.png +0 -0
- kaa/sprites/dcf465c6-ad64-48e7-9c3c-7bc7cfc13a44.png +0 -0
- kaa/sprites/ddb59f04-91a0-4fbd-8921-be13acdab291.png +0 -0
- kaa/sprites/de81f919-4d01-4a4e-bdc1-ffe6e23a5c22.png +0 -0
- kaa/sprites/e05f2c16-926f-48be-bdd0-16182e879394.png +0 -0
- kaa/sprites/e2a0c1a6-c0cf-400e-99be-1ed0d35c6ed8.png +0 -0
- kaa/sprites/e30922ed-a02f-4ede-9968-1656be5a05b2.png +0 -0
- kaa/sprites/e388db01-0870-412d-b8bc-5a512ec997c8.png +0 -0
- kaa/sprites/e392856d-ac59-4414-8fb8-df93a1a99be4.png +0 -0
- kaa/sprites/e57db8c2-c050-43fb-8205-339aeb5875e8.png +0 -0
- kaa/sprites/e687c2ba-2c30-4fc8-804f-fea5815f6765.png +0 -0
- kaa/sprites/e6e66204-8a2f-4377-8674-b7d663ff0081.png +0 -0
- kaa/sprites/e79a2a08-3b58-4ab0-8c2b-769f30cc8591.png +0 -0
- kaa/sprites/ebe22aea-0318-49d8-ab07-ce2eef34265f.png +0 -0
- kaa/sprites/ed6df33a-c7aa-4542-a87b-9cc9cae0465c.png +0 -0
- kaa/sprites/ed854df1-878c-4e0b-8138-9b28d314ede6.png +0 -0
- kaa/sprites/ed98a341-5dff-4af7-a194-d28232d481a4.png +0 -0
- kaa/sprites/f0ed1dd3-b227-48c1-8c8c-858dbd84fcc7.png +0 -0
- kaa/sprites/f1eb4089-8cd1-4830-b00e-40535ddcd116.png +0 -0
- kaa/sprites/f237d88e-92ac-4ebf-85e1-80a696b5203a.png +0 -0
- kaa/sprites/f2f818c9-b0cf-436d-9d3e-6544c5399063.png +0 -0
- kaa/sprites/f333118a-81c2-417f-b54f-64dc4e8df613.png +0 -0
- kaa/sprites/f34e8026-bdfc-47e6-a0ed-49e587ef0f40.png +0 -0
- kaa/sprites/f3a5992b-dabf-4c2b-83e9-4c91c3b7aac8.png +0 -0
- kaa/sprites/f4195ceb-586a-4a8c-9424-4962239d2120.png +0 -0
- kaa/sprites/f485db66-2159-4d31-ba53-0fbb726e7f64.png +0 -0
- kaa/sprites/f7264cee-fea6-47b5-9f9b-8f3f31c03ea0.png +0 -0
- kaa/sprites/f7e34403-a53c-4d3f-935b-25b4acb7f7a5.png +0 -0
- kaa/sprites/f8d8c943-1b36-4391-a7fc-2a49f8966d53.png +0 -0
- kaa/sprites/f9157db8-d70b-4d46-9800-5a833ce7eda8.png +0 -0
- kaa/sprites/f9a353b2-958d-4aae-ade4-66bdc6481e35.png +0 -0
- kaa/sprites/fa5b5b92-9c60-4811-a44c-8e897c9632c3.png +0 -0
- kaa/sprites/fac7b90a-1174-477b-803b-28798647c307.png +0 -0
- kaa/sprites/fbbb73f9-880e-4c7f-9ec9-276bdab4b394.png +0 -0
- kaa/sprites/fce4a481-e71c-4dab-aeac-59ff8b18201b.png +0 -0
- kaa/sprites/fd8a7a5d-f021-4bfd-83f7-a2dd33325837.png +0 -0
- kaa/sprites/fda4b3eb-e31a-448b-8cb3-9126e1ab7deb.png +0 -0
- kaa/sprites/fda78372-04b4-4d55-92b1-aedec20d0913.png +0 -0
- kaa/sprites/fe993a91-1a49-488e-b7ff-c1b05b8f2b5f.png +0 -0
- kaa/sprites/ff8efb8f-e1a4-4202-a6e1-680eb44f58da.png +0 -0
- kaa/tasks/R.py +128 -128
- kaa/tasks/common.py +5 -0
- kaa/tasks/daily/contest.py +2 -1
- kaa/tasks/produce/cards.py +5 -4
- kaa/tasks/produce/common.py +201 -105
- kaa/tasks/produce/in_purodyuusu.py +14 -10
- kaa/tasks/produce/non_lesson_actions.py +10 -33
- kaa/tasks/produce/p_drink.py +5 -1
- kaa/tasks/produce/produce.py +2 -1
- kaa/tasks/start_game.py +2 -1
- {ksaa-2025.11b1.dist-info → ksaa-2025.11b3.dist-info}/METADATA +9 -6
- {ksaa-2025.11b1.dist-info → ksaa-2025.11b3.dist-info}/RECORD +323 -177
- /kaa/sprites/{fdf0da06-f088-424f-9941-8c883fea3db3.png → 03d0acec-15fd-4c21-82ce-122764def185.png} +0 -0
- /kaa/sprites/{68d9f340-a3d2-4708-8eb1-c1ed857decda.png → 03d22cb3-0193-4dcb-8a0d-98b7ca9c2b4c.png} +0 -0
- /kaa/sprites/{dce410ee-fa56-41c4-b75e-e1bff79cd94f.png → 0455e229-75c9-44ba-8729-745799746979.png} +0 -0
- /kaa/sprites/{ad94041c-f30b-40b9-b11a-1a26e9962274.png → 049ecbf6-d434-46fa-a42c-a447475269bb.png} +0 -0
- /kaa/sprites/{f6b042a8-a91e-4811-99f9-18bbb5197468.png → 04ea8503-cdd5-4b3e-a33b-63893b92f6ba.png} +0 -0
- /kaa/sprites/{847226a3-b7d2-4156-b732-9215a3e14f3a.png → 05251a85-2883-4098-842e-6544391de919.png} +0 -0
- /kaa/sprites/{9008fbb2-f23f-424f-9be7-5bae6a3697ab.png → 054db45e-1434-4604-91ec-7ac586ca11b5.png} +0 -0
- /kaa/sprites/{ae1e70bc-f735-4749-8c23-95735b91897a.png → 06cf74aa-635f-48ab-b965-36981f2063d3.png} +0 -0
- /kaa/sprites/{3b4f90c9-6de7-4ac3-8e41-5f8757bf3f3e.png → 0814c0fd-6f89-47d3-8089-e8cfde569750.png} +0 -0
- /kaa/sprites/{2cec1d6a-9e8c-49b3-b885-0b0d7c4b95ee.png → 08bde3ff-7554-4bdb-a7f0-193323489d5b.png} +0 -0
- /kaa/sprites/{91b30f5e-31b2-4756-a3f7-f0f82a335442.png → 09222fb0-78a6-4663-8c1f-1d44e881513d.png} +0 -0
- /kaa/sprites/{5431dc38-c257-40b3-8f7b-8bceaa7fe587.png → 0b436edb-8f6a-429d-87b7-5d4250f651ac.png} +0 -0
- /kaa/sprites/{338d7e71-98ce-4cd1-9954-bf7155150780.png → 0c266b0e-de7a-49c1-9709-b01fb5086f75.png} +0 -0
- /kaa/sprites/{8e019262-ad23-4cbb-84da-86b34775a91e.png → 0db579bf-d555-4468-8104-c2d2e68d33b1.png} +0 -0
- /kaa/sprites/{8be81341-a74d-42c8-8231-5d1854bc08e7.png → 114730f6-eddd-4381-b723-aee18cde0d90.png} +0 -0
- /kaa/sprites/{31f2de0a-567b-425a-9be6-536e4532d813.png → 11870372-dc78-4a80-8320-15bb24da6f25.png} +0 -0
- /kaa/sprites/{3fa5f81c-9223-44ba-bf07-71932350e845.png → 11bc7d35-e58d-4301-a0b0-f557dbd73c7b.png} +0 -0
- /kaa/sprites/{92c3de1b-eed1-45b9-82e0-c9e97bb479e7.png → 12455dbd-7d70-4435-a3ba-f40654e75c37.png} +0 -0
- /kaa/sprites/{aa1624ff-88b0-447b-8e2b-8a50fd9e4062.png → 12f330a6-4eab-4015-b0e3-4e1a35a7b676.png} +0 -0
- /kaa/sprites/{9991b19c-7330-42c4-9d7d-db3cb00103b7.png → 14a697d4-0b58-4644-bb2d-8823d2fefcb8.png} +0 -0
- /kaa/sprites/{49bde219-f9a3-41b5-84b8-e417160a0f40.png → 15605f7a-2206-436c-8a71-011d9f95cf4e.png} +0 -0
- /kaa/sprites/{ea430652-e263-4a15-bb6f-8a8807be6c8f.png → 15dd89cc-53ed-4c77-a355-62e3bd7a15dd.png} +0 -0
- /kaa/sprites/{5c310fe5-7e92-4167-9eba-6e8e14a2863a.png → 18b13508-c46f-4134-b991-975c0a1b9a74.png} +0 -0
- /kaa/sprites/{cd00a2d7-af48-48b1-b2e1-5360ceed249f.png → 1a5c147b-e28e-42ad-893a-7430d8f4fc35.png} +0 -0
- /kaa/sprites/{94d54ba7-0ccf-4fd9-a5bf-488bac1364c8.png → 1b3c84c5-16d1-43a7-8513-719bd7a10450.png} +0 -0
- /kaa/sprites/{2289d38f-dc98-4310-9f34-4cf5023f8545.png → 1b847790-90e2-44f8-b6d9-4814812006bd.png} +0 -0
- /kaa/sprites/{6c926e92-9af9-402d-8512-6417ca116928.png → 1e57ab88-9962-4024-81df-746529a758f9.png} +0 -0
- /kaa/sprites/{30e12bf1-8fa5-4de1-8d7b-28fa0fec0cb6.png → 205e03de-46d9-4983-a2ea-a7f7500d508f.png} +0 -0
- /kaa/sprites/{e4dc3b35-195c-415f-9484-c2459bd8675a.png → 20bd834e-c99c-4e80-92db-0740e5bbe746.png} +0 -0
- /kaa/sprites/{68e20ebf-02fd-46a1-88d7-b4472824e7bc.png → 218a6ab3-93f6-4bb1-9848-8c97ff695945.png} +0 -0
- /kaa/sprites/{ec3cad5f-e0c9-4577-8499-79b50248344e.png → 22071c63-a1bc-4163-8d5a-973b3d579c76.png} +0 -0
- /kaa/sprites/{e933cd55-e47a-4327-89d7-b25995cb4a3f.png → 2460d0c9-50e2-451b-b609-ad466b574395.png} +0 -0
- /kaa/sprites/{0af1d573-1dc7-427e-997d-173308ea3649.png → 264d021a-b322-4472-8a7b-5f1322aba993.png} +0 -0
- /kaa/sprites/{57c81080-7b53-4286-8fa5-848ad63e4774.png → 28335ba3-9a0f-46cd-b66d-047781773264.png} +0 -0
- /kaa/sprites/{d7750f81-de10-4d6f-9cc7-35223bda9d70.png → 28df544b-72f2-4ed8-8bf3-609ff99633d9.png} +0 -0
- /kaa/sprites/{81686816-c723-47d1-9824-a68d9ebe1bd4.png → 2a82e2d6-0722-433a-87fa-f1752ce0b9b7.png} +0 -0
- /kaa/sprites/{5ffd3f29-db4f-4f66-b9ed-be5a70b7ebf9.png → 2abce6a4-111f-42bb-9255-f98d544108de.png} +0 -0
- /kaa/sprites/{23b9cda9-8be8-438e-8e54-57d91a4bd875.png → 2d8e6464-aceb-41fd-9e78-7523738d5720.png} +0 -0
- /kaa/sprites/{1ad89ee4-1bb1-41d2-a92c-79caf6baa38a.png → 2f9e2dbb-66a1-4b13-9b9e-d62e10efa6d3.png} +0 -0
- /kaa/sprites/{c69dcdcf-42a7-420e-aa8e-bb8639ea80b6.png → 307b58f0-20c1-41bd-9eaa-1337fd0e6563.png} +0 -0
- /kaa/sprites/{55c3af20-58dc-4407-a383-312a57417c39.png → 3192a62f-224d-44b1-a0b9-b1fc22de8ec1.png} +0 -0
- /kaa/sprites/{645909d7-b960-46c7-b208-db44b6b7feec.png → 31b4c370-696f-4dfc-a918-839495520266.png} +0 -0
- /kaa/sprites/{7daaca55-e3fd-4e12-bf31-872105ceb726.png → 330c2207-af32-453b-8db7-889cda83e7cc.png} +0 -0
- /kaa/sprites/{5734e48a-1e58-42de-be7b-b7db67db4a01.png → 38186efc-850c-4d83-97bc-9417f1494b94.png} +0 -0
- /kaa/sprites/{8ed51be4-815c-4a3d-805e-030fdfa341e2.png → 38426696-ff13-4f20-9f74-b05855990153.png} +0 -0
- /kaa/sprites/{cfe3563d-a24b-4197-a0cb-5628bd990c08.png → 3a211792-1243-496a-b41e-0e3fd121cd5b.png} +0 -0
- /kaa/sprites/{179c0fff-ebd2-4a16-8db2-297552cca218.png → 3a4e2d8a-deca-4980-b6c2-37bfc17d2720.png} +0 -0
- /kaa/sprites/{2d0e9d49-365a-4bcb-a416-38b87defaa3c.png → 3a4ec054-2c48-4359-afb9-fa5ea8191d16.png} +0 -0
- /kaa/sprites/{51b95c81-4ff9-434c-ade2-3518e63337cb.png → 3c490171-6810-44f0-b28d-c6b664347a3c.png} +0 -0
- /kaa/sprites/{35341839-4469-4ab6-aa40-33642fe43e82.png → 3cda578a-fa75-4bbd-9cff-be4bc4355a58.png} +0 -0
- /kaa/sprites/{72634cb3-4c76-4ca2-8898-ebb837ec19e3.png → 3ea03db7-4de9-45c4-a07b-a9bbc2c63e70.png} +0 -0
- /kaa/sprites/{da48db0d-09d9-47c3-9e08-8b69ad547be6.png → 3ea8e354-2684-46f3-9f5a-43f094717c95.png} +0 -0
- /kaa/sprites/{3e087b8d-420d-48ff-b526-29c4a65d8cbe.png → 3eb9b21b-abbe-49fd-a3a9-6e1c1a6e91d9.png} +0 -0
- /kaa/sprites/{2234f709-1703-4589-905c-175f4db09b1b.png → 3fb84a71-ed15-4989-9598-34e7342f38f5.png} +0 -0
- /kaa/sprites/{39f6d657-3b3e-40aa-849b-7ad87a0be1d0.png → 3ffd2992-fa55-499c-8c3b-193518ebbe07.png} +0 -0
- /kaa/sprites/{464b1dd8-ca2e-41e9-a5b5-90545c584db7.png → 41ff9641-d200-4caa-bcfa-d8389a3438eb.png} +0 -0
- /kaa/sprites/{70768479-5d7a-4941-8774-ad556c47bee2.png → 455dcf19-63f5-4b0a-99e6-b23d3876d199.png} +0 -0
- /kaa/sprites/{694879e8-ecca-45e2-8ea4-1b447fd43ace.png → 45f09e08-53ea-4e08-97dc-70f689bab002.png} +0 -0
- /kaa/sprites/{dd873ac0-ffba-4335-9cf2-2162c6835ed8.png → 4729b509-0f4a-4e96-b186-ec56c680c9e6.png} +0 -0
- /kaa/sprites/{7d7df15f-707e-4e27-826f-21e42af1dae0.png → 4eb665ef-7741-40f9-8174-7b6ca66d045b.png} +0 -0
- /kaa/sprites/{8e5e968b-edad-4c03-abc8-3f2a7e8879ae.png → 4f370ff6-61d1-405a-b29e-e6d0b3072194.png} +0 -0
- /kaa/sprites/{f0462447-5226-4819-a39b-19ab90583f83.png → 504e4927-bfeb-43ee-aa5c-35cec664a4c8.png} +0 -0
- /kaa/sprites/{756f4ca7-acac-48e1-8bcd-1c5cd8937e3a.png → 51eb4be2-22fa-4683-82c7-513f5934f7b9.png} +0 -0
- /kaa/sprites/{87f3c1ae-5117-4871-a7d6-3f5ff0c9f9fb.png → 568608bd-a1fa-4faf-ae15-179563a7e84f.png} +0 -0
- /kaa/sprites/{978873bb-e4d0-451b-9126-6977144f5395.png → 56ac84af-4c85-4b69-b449-98981c1df292.png} +0 -0
- /kaa/sprites/{db6707a2-2964-4919-9992-4d801fa43dae.png → 5a49b6d2-2bcb-49bc-a28f-b8bd1441f60a.png} +0 -0
- /kaa/sprites/{01256311-237c-476f-96ce-4136dc4bfbd3.png → 5a677634-99cf-45b5-bc0c-94120872a518.png} +0 -0
- /kaa/sprites/{8e4d8a0f-4a9d-4562-9234-63806b11d85f.png → 5ec51718-1403-4a79-bd85-46e1fe04d8c9.png} +0 -0
- /kaa/sprites/{dc97fea3-898f-4135-9c40-ad41570ab4ae.png → 5f2d0b2b-8425-4dd8-8b85-d62f4b75286c.png} +0 -0
- /kaa/sprites/{f32a41a2-c482-41ba-b718-28f048f5148c.png → 5f4abae0-a1f0-4c8c-9d93-a8525caa9dd0.png} +0 -0
- /kaa/sprites/{31e3ac2b-ecd4-4c37-88bc-985ef32e73a3.png → 6005bf30-fd7c-401e-8efd-050fa97ad7f3.png} +0 -0
- /kaa/sprites/{3b4dc708-1d34-4a88-9fe3-d8de2ec1d5c8.png → 6069f8bc-2a06-45a4-95ca-1ac9d8fa3b04.png} +0 -0
- /kaa/sprites/{962aa0b9-1dd3-4260-a4fb-c069c26e5a84.png → 60896822-de58-4e07-b2d9-86a7f4068de1.png} +0 -0
- /kaa/sprites/{889a4153-b713-49cb-a4d5-e302bcdd002d.png → 622d700e-0fd8-4a92-a286-1e8143c70570.png} +0 -0
- /kaa/sprites/{b59c0e9b-1f20-4194-ab37-286f505fa656.png → 63b74752-73ce-4020-a7c8-0a71a9f67415.png} +0 -0
- /kaa/sprites/{4a081370-b0a1-4067-8470-e3007cc68a12.png → 648d43f6-b251-4d6f-a808-ae7325c91a59.png} +0 -0
- /kaa/sprites/{bfdc9b53-2fe5-43f1-8588-7ab71217d31c.png → 65f79941-1c78-496a-a67c-c50f4227bd34.png} +0 -0
- /kaa/sprites/{9e7eaa8e-3178-44da-a5ec-34b889f8facf.png → 6f50cd3b-6e46-46c5-99ed-26728d3212ad.png} +0 -0
- /kaa/sprites/{ab237c6d-c4d8-4716-8ef7-99b8e995c9a7.png → 6f6d7af3-8380-439b-9d26-3fbd5a103b49.png} +0 -0
- /kaa/sprites/{1befe09b-cb77-417a-b21e-7746804d4e03.png → 71913fde-c3db-463d-800d-e1b35fa2c8b4.png} +0 -0
- /kaa/sprites/{e7f2734f-9fdc-4521-8d7e-8b0fe270a223.png → 71976c1a-5df9-44a5-b4ea-08b5d617d813.png} +0 -0
- /kaa/sprites/{9f7150bc-c0b8-48d6-862c-456aaf518b2b.png → 72a8bcd2-3f32-4ee5-8295-eedf441d6a1a.png} +0 -0
- /kaa/sprites/{cd0e8663-2ea1-436a-b9fb-3caa0c3ed9e8.png → 73b6f3aa-5179-41d6-a82e-22e14aa8cd6a.png} +0 -0
- /kaa/sprites/{cba0646d-dffe-4c5b-a44d-1f8d827624a6.png → 7a74b5f5-7a04-4678-8e6e-57b5de127182.png} +0 -0
- /kaa/sprites/{5930140e-effe-4bcf-b0be-c20d3990d833.png → 7b4c3a81-8f09-4a00-90ee-d4df3f57e863.png} +0 -0
- /kaa/sprites/{cb6dffd9-6474-4d09-aee6-26352ea51d31.png → 7c4ca388-5167-478a-a32b-0e108edad888.png} +0 -0
- /kaa/sprites/{96704aa3-b5ad-4e34-bb88-fad766415362.png → 7d4709f8-6d0d-493f-819e-74cb0f7c166b.png} +0 -0
- /kaa/sprites/{fcc72120-2a77-4c26-a27e-e1027c6088c0.png → 7e8904fd-5863-471f-8e9a-d69d9ca72f8f.png} +0 -0
- /kaa/sprites/{023b8f4c-15ab-4845-b141-446c861ad475.png → 80800c2e-417d-4118-b726-93aaabfc08bd.png} +0 -0
- /kaa/sprites/{f0aef696-2106-46a4-8b7f-9f16b6c89d3f.png → 81b1b160-2d0f-42ad-924a-9572a54f343a.png} +0 -0
- /kaa/sprites/{13cb0309-b713-4725-b10b-26afe46eb9c0.png → 82259f79-2bef-442b-bf16-78cb4f22e3be.png} +0 -0
- /kaa/sprites/{43a367e1-91dd-495e-8c30-41903f75a99a.png → 861a4faa-2522-41e9-8e20-7bd9180bea5a.png} +0 -0
- /kaa/sprites/{01247ebe-8d63-4573-90f4-d8dc2b7ca14c.png → 87ed135a-2eb1-4e21-8928-d0307a22ea66.png} +0 -0
- /kaa/sprites/{1cf03f98-63e9-467c-804d-c74dd97b69bd.png → 8805fead-f7e2-4905-a42e-05ebba2fbe21.png} +0 -0
- /kaa/sprites/{16a0fd47-e85b-4848-8894-9d071ea993ac.png → 88be2dcc-68ca-4596-9b2c-544a196cab64.png} +0 -0
- /kaa/sprites/{a5694c76-3c5d-462e-81d5-1e0e6cef0ec9.png → 89841ff0-e834-4a7e-b9d5-00a9490b6b7f.png} +0 -0
- /kaa/sprites/{84cabff2-7a1b-4018-b74b-46f4db06304f.png → 8bf08bab-7c55-45e1-8433-c2213a323480.png} +0 -0
- /kaa/sprites/{e5e49b44-dcc2-4e77-9180-0d2beaa3f9ad.png → 8d416e23-04ef-47bd-8cc8-7f18d1bab736.png} +0 -0
- /kaa/sprites/{c1d502eb-c77f-45cb-86b5-11b4a8a3aef5.png → 8f9dd0f0-f9af-4eec-a89e-8f2c92f88a98.png} +0 -0
- /kaa/sprites/{424a0ef5-102d-4734-a731-2b3b3c7c9682.png → 9088f8c0-59f8-41c6-994c-ae283ac94c24.png} +0 -0
- /kaa/sprites/{91a50322-52d9-4516-9e46-bc121f20667d.png → 922af7d1-75e9-4ac8-a4e7-2dad8bb1ca87.png} +0 -0
- /kaa/sprites/{d81b1325-e57a-4f22-93e1-6ad4baa28935.png → 94ed55fe-3ef8-46bc-855a-a7b1dedab801.png} +0 -0
- /kaa/sprites/{913dbd4e-ebb1-4c9f-b145-9960cde59c17.png → 95d715c3-d569-48b5-be7b-c21cd2a160db.png} +0 -0
- /kaa/sprites/{dd7bd6cd-90f1-4773-9b68-5df7f2f84da5.png → 97a3791d-fa9d-453d-8081-c574fe88b823.png} +0 -0
- /kaa/sprites/{2204967a-a0ee-4dd3-aecb-4d531e8e954c.png → 9acd9a59-004f-4e1d-a208-0c293f2702d5.png} +0 -0
- /kaa/sprites/{572a921d-633f-4465-b177-7a0d9ad7e099.png → 9f3bfe36-8462-404f-94da-9bc324b1beed.png} +0 -0
- /kaa/sprites/{799fe395-2264-4bc5-b515-813dadda8fe1.png → 9f46f543-d7dc-4836-a210-125d686475f9.png} +0 -0
- /kaa/sprites/{5bf2a814-df85-4d0a-b4b5-8883ac2ee434.png → a34502b4-10bd-42ca-9ada-a9cdb57097dc.png} +0 -0
- /kaa/sprites/{043e753e-db15-45ba-8513-53c3fc9c7f3c.png → a3fe5859-62ba-403e-9367-65db0ad15943.png} +0 -0
- /kaa/sprites/{8f7b55d8-0143-4d27-bef8-560d4d510500.png → a42ac612-acbd-45cc-88fb-104ff9b7d2d8.png} +0 -0
- /kaa/sprites/{736a9daf-05d6-46ba-810b-5a8f509152d1.png → a4c6d967-0251-4b33-acb3-81d24f82d5a4.png} +0 -0
- /kaa/sprites/{edcec31d-d5de-4f22-b666-3e3c656e06d8.png → a6ed21f0-4da4-4065-bb59-062a70e132ca.png} +0 -0
- /kaa/sprites/{e9310e38-a418-4561-bf33-eb3e6dccf477.png → a97e2840-1575-4f2c-97df-6a720c644969.png} +0 -0
- /kaa/sprites/{d644faa3-ff16-417f-928c-4c62b040bfdb.png → ae0ce964-eb8f-45a1-aa4d-f47a5c8c720f.png} +0 -0
- /kaa/sprites/{256ffeba-8e9e-4cc5-8a1c-9eaee427f1a5.png → ae106b38-da4f-4b0d-b9c3-541fd58f4de7.png} +0 -0
- /kaa/sprites/{802db04f-77c2-46a4-a6eb-f81d48ea03ce.png → aeab8f9a-fe61-4c2d-a494-ffc19a9cae91.png} +0 -0
- /kaa/sprites/{37215a56-f8e1-4f22-a148-9894136f6ab1.png → affc87db-2f63-4e4a-855e-6ff608226f1e.png} +0 -0
- /kaa/sprites/{d1ea0ea6-4a6a-4036-b140-922c95a648b5.png → b02c15b5-04b4-40d9-bb13-267786e8e049.png} +0 -0
- /kaa/sprites/{22dc4cfe-8c66-4461-8660-e2d11bbe6154.png → b7f62cab-cc24-480e-bf4c-25c43a1e801e.png} +0 -0
- /kaa/sprites/{5906d986-d0e5-452d-a7c4-ddeb7af8751d.png → bd4cd421-f702-47c0-9f8b-77914973108c.png} +0 -0
- /kaa/sprites/{8bd22fe1-b544-4d2e-b74a-34f3cf0eb512.png → c4505a31-74c5-4b3d-bfcf-a67c3ef0039e.png} +0 -0
- /kaa/sprites/{e13fc34b-accc-4986-865d-f8d8410b45e9.png → c6b6b77b-2ec7-4fb7-8033-f4d061f4e9c8.png} +0 -0
- /kaa/sprites/{2b6d2eb0-bcf7-4bea-b037-6293d9c6d728.png → c76c6ccb-d099-4c3c-9eda-13be33aa48ae.png} +0 -0
- /kaa/sprites/{0562f69f-0300-4a2b-8252-63f3e7180e4c.png → cb15d9a3-78fe-4f03-bd23-90ba6169ddff.png} +0 -0
- /kaa/sprites/{2a8626df-056c-46a2-aaf3-0060a5aef6a3.png → d1bdfa3b-34df-488d-9f9b-8c7b04dd4ab3.png} +0 -0
- /kaa/sprites/{3aed50a2-d640-4178-9b8a-4dd7973eebf1.png → d8ba1932-978c-451c-a717-d7d2b6db35d9.png} +0 -0
- /kaa/sprites/{f635499a-943d-47da-952a-1feb58daa25b.png → e7630ccb-6824-49e3-986f-2a65a2c4a948.png} +0 -0
- /kaa/sprites/{847eb5c0-0350-4b7c-9c9c-43c796709795.png → ec35a0b8-1afa-48ff-ae66-9c1ef966348d.png} +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11b3.dist-info}/WHEEL +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11b3.dist-info}/entry_points.txt +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11b3.dist-info}/licenses/LICENSE +0 -0
- {ksaa-2025.11b1.dist-info → ksaa-2025.11b3.dist-info}/top_level.txt +0 -0
kaa/main/gr.py
CHANGED
|
@@ -34,6 +34,11 @@ from kaa.config import (
|
|
|
34
34
|
from kaa.config.produce import ProduceSolution, ProduceSolutionManager, ProduceData
|
|
35
35
|
from kaa.application.adapter.misc_adapter import create_desktop_shortcut
|
|
36
36
|
from kaa.application.core.idle_mode import IdleModeManager
|
|
37
|
+
from kaa.application.core.update_service import UpdateService
|
|
38
|
+
from kaa.application.core.feedback_service import FeedbackService
|
|
39
|
+
from kaa.errors import (
|
|
40
|
+
ProduceSolutionNotFoundError, UpdateServiceError, UpdateFetchListError, FeedbackServiceError
|
|
41
|
+
)
|
|
37
42
|
|
|
38
43
|
logger = logging.getLogger(__name__)
|
|
39
44
|
GradioInput = gr.Textbox | gr.Number | gr.Checkbox | gr.Dropdown | gr.Radio | gr.Slider | gr.Tabs | gr.Tab
|
|
@@ -59,7 +64,7 @@ ConfigKey = Literal[
|
|
|
59
64
|
'select_which_contestant', 'when_no_set',
|
|
60
65
|
|
|
61
66
|
# produce
|
|
62
|
-
'produce_enabled', 'selected_solution_id', 'produce_count', 'produce_timeout_cd', 'enable_fever_month',
|
|
67
|
+
'produce_enabled', 'selected_solution_id', 'produce_count', 'produce_timeout_cd', 'interrupt_timeout', 'enable_fever_month',
|
|
63
68
|
'mission_reward_enabled',
|
|
64
69
|
|
|
65
70
|
# club reward
|
|
@@ -92,7 +97,7 @@ ConfigKey = Literal[
|
|
|
92
97
|
'trace_recommend_card_detection',
|
|
93
98
|
|
|
94
99
|
# misc
|
|
95
|
-
'check_update', 'auto_install_update', 'expose_to_lan', 'update_channel',
|
|
100
|
+
'check_update', 'auto_install_update', 'expose_to_lan', 'update_channel', 'log_level',
|
|
96
101
|
|
|
97
102
|
# idle
|
|
98
103
|
'idle_enabled', 'idle_seconds', 'idle_minimize_on_pause',
|
|
@@ -104,128 +109,6 @@ CONFIG_KEY_VALUE: tuple[str] = get_args(ConfigKey)
|
|
|
104
109
|
ConfigSetFunction = Callable[[BaseConfig, Dict[ConfigKey, Any]], None]
|
|
105
110
|
ConfigBuilderReturnValue = Tuple[ConfigSetFunction, Dict[ConfigKey, GradioInput]]
|
|
106
111
|
|
|
107
|
-
def _save_bug_report(
|
|
108
|
-
title: str,
|
|
109
|
-
description: str,
|
|
110
|
-
version: str,
|
|
111
|
-
upload: bool,
|
|
112
|
-
path: str | None = None
|
|
113
|
-
) -> Generator[str, None, str]:
|
|
114
|
-
"""
|
|
115
|
-
保存报告
|
|
116
|
-
|
|
117
|
-
:param title: 标题
|
|
118
|
-
:param description: 描述
|
|
119
|
-
:param version: 版本号
|
|
120
|
-
:param upload: 是否上传
|
|
121
|
-
:param path: 保存的路径。若为 `None`,则保存到 `./reports/bug-YY-MM-DD HH-MM-SS_标题.zip`。
|
|
122
|
-
:return: 保存的路径
|
|
123
|
-
"""
|
|
124
|
-
from kotonebot import device
|
|
125
|
-
from kotonebot.backend.context import ContextStackVars
|
|
126
|
-
import re
|
|
127
|
-
|
|
128
|
-
# 过滤标题中的非法文件名字符
|
|
129
|
-
def sanitize_filename(s: str) -> str:
|
|
130
|
-
# 替换 \/:*?"<>| 为空或下划线
|
|
131
|
-
return re.sub(r'[\\/:*?"<>|]', '_', s)
|
|
132
|
-
|
|
133
|
-
# 确保目录存在
|
|
134
|
-
os.makedirs('logs', exist_ok=True)
|
|
135
|
-
os.makedirs('reports', exist_ok=True)
|
|
136
|
-
|
|
137
|
-
error = ""
|
|
138
|
-
if path is None:
|
|
139
|
-
safe_title = sanitize_filename(title)[:30] or "无标题"
|
|
140
|
-
timestamp = datetime.now().strftime("%y-%m-%d-%H-%M-%S")
|
|
141
|
-
path = f'./reports/bug_{timestamp}_{safe_title}.zip'
|
|
142
|
-
with zipfile.ZipFile(path, 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zipf:
|
|
143
|
-
# 打包描述文件
|
|
144
|
-
yield "### 打包描述文件..."
|
|
145
|
-
try:
|
|
146
|
-
description_content = f"标题:{title}\n类型:bug\n内容:\n{description}"
|
|
147
|
-
zipf.writestr('description.txt', description_content.encode('utf-8'))
|
|
148
|
-
except Exception as e:
|
|
149
|
-
error += f"保存描述文件失败:{str(e)}\n"
|
|
150
|
-
|
|
151
|
-
# 打包截图
|
|
152
|
-
yield "### 打包上次截图..."
|
|
153
|
-
try:
|
|
154
|
-
stack = ContextStackVars.current()
|
|
155
|
-
screenshot = None
|
|
156
|
-
if stack is not None:
|
|
157
|
-
screenshot = stack._screenshot
|
|
158
|
-
if screenshot is not None:
|
|
159
|
-
img = cv2.imencode('.png', screenshot)[1].tobytes()
|
|
160
|
-
zipf.writestr('last_screenshot.png', img)
|
|
161
|
-
if screenshot is None:
|
|
162
|
-
error += "无上次截图数据\n"
|
|
163
|
-
except Exception as e:
|
|
164
|
-
error += f"保存上次截图失败:{str(e)}\n"
|
|
165
|
-
|
|
166
|
-
# 打包当前截图
|
|
167
|
-
yield "### 打包当前截图..."
|
|
168
|
-
try:
|
|
169
|
-
screenshot = device.screenshot()
|
|
170
|
-
img = cv2.imencode('.png', screenshot)[1].tobytes()
|
|
171
|
-
zipf.writestr('current_screenshot.png', img)
|
|
172
|
-
except Exception as e:
|
|
173
|
-
error += f"保存当前截图失败:{str(e)}\n"
|
|
174
|
-
|
|
175
|
-
# 打包配置文件
|
|
176
|
-
yield "### 打包配置文件..."
|
|
177
|
-
try:
|
|
178
|
-
with open('config.json', 'r', encoding='utf-8') as f:
|
|
179
|
-
zipf.writestr('config.json', f.read())
|
|
180
|
-
except Exception as e:
|
|
181
|
-
error += f"保存配置文件失败:{str(e)}\n"
|
|
182
|
-
|
|
183
|
-
# 打包 logs 文件夹
|
|
184
|
-
if os.path.exists('logs'):
|
|
185
|
-
for root, dirs, files in os.walk('logs'):
|
|
186
|
-
for file in files:
|
|
187
|
-
file_path = os.path.join(root, file)
|
|
188
|
-
arcname = os.path.join('logs', os.path.relpath(file_path, 'logs'))
|
|
189
|
-
zipf.write(file_path, arcname)
|
|
190
|
-
yield f"### 打包 log 文件:{arcname}"
|
|
191
|
-
|
|
192
|
-
# 打包 conf 文件夹
|
|
193
|
-
if os.path.exists('conf'):
|
|
194
|
-
for root, dirs, files in os.walk('conf'):
|
|
195
|
-
for file in files:
|
|
196
|
-
file_path = os.path.join(root, file)
|
|
197
|
-
arcname = os.path.join('conf', os.path.relpath(file_path, 'conf'))
|
|
198
|
-
zipf.write(file_path, arcname)
|
|
199
|
-
yield f"### 打包配置文件:{arcname}"
|
|
200
|
-
|
|
201
|
-
# 写出版本号
|
|
202
|
-
zipf.writestr('version.txt', version)
|
|
203
|
-
|
|
204
|
-
if not upload:
|
|
205
|
-
yield f"### 报告已保存至 {os.path.abspath(path)}"
|
|
206
|
-
return path
|
|
207
|
-
|
|
208
|
-
# 上传报告
|
|
209
|
-
from kotonebot.ui.file_host.sensio import upload as upload_file
|
|
210
|
-
yield "### 上传报告..."
|
|
211
|
-
url = ''
|
|
212
|
-
try:
|
|
213
|
-
url = upload_file(path)
|
|
214
|
-
except Exception as e:
|
|
215
|
-
yield f"### 上传报告失败:{str(e)}\n\n"
|
|
216
|
-
return ''
|
|
217
|
-
|
|
218
|
-
final_msg = f"### 报告导出成功:{url}\n\n"
|
|
219
|
-
expire_time = datetime.now() + timedelta(days=7)
|
|
220
|
-
if error:
|
|
221
|
-
final_msg += "### 但发生了以下错误\n\n"
|
|
222
|
-
final_msg += '\n* '.join(error.strip().split('\n'))
|
|
223
|
-
final_msg += '\n'
|
|
224
|
-
final_msg += f"### 此链接将于 {expire_time.strftime('%Y-%m-%d %H:%M:%S')}(7 天后)过期\n\n"
|
|
225
|
-
final_msg += '### 复制以上文本并反馈给开发者'
|
|
226
|
-
yield final_msg
|
|
227
|
-
return path
|
|
228
|
-
|
|
229
112
|
class KotoneBotUI:
|
|
230
113
|
def __init__(self, kaa: Kaa) -> None:
|
|
231
114
|
self.is_running: bool = False
|
|
@@ -234,6 +117,8 @@ class KotoneBotUI:
|
|
|
234
117
|
self.is_single_task_stopping: bool = False # 新增:标记单个任务是否正在停止
|
|
235
118
|
self._kaa = kaa
|
|
236
119
|
self._load_config()
|
|
120
|
+
self.update_service = UpdateService()
|
|
121
|
+
self.feedback_service = FeedbackService()
|
|
237
122
|
# IdleModeManager 空闲检测
|
|
238
123
|
def safe_get_is_running():
|
|
239
124
|
try:
|
|
@@ -1530,6 +1415,14 @@ class KotoneBotUI:
|
|
|
1530
1415
|
info=ProduceConfig.model_fields['produce_timeout_cd'].description
|
|
1531
1416
|
)
|
|
1532
1417
|
|
|
1418
|
+
interrupt_timeout = gr.Number(
|
|
1419
|
+
minimum=20,
|
|
1420
|
+
value=self.current_config.options.produce.interrupt_timeout,
|
|
1421
|
+
label="检测超时时间",
|
|
1422
|
+
interactive=True,
|
|
1423
|
+
info=ProduceConfig.model_fields['interrupt_timeout'].description
|
|
1424
|
+
)
|
|
1425
|
+
|
|
1533
1426
|
enable_fever_month = gr.Radio(
|
|
1534
1427
|
label="自动启用强化月间",
|
|
1535
1428
|
choices=[("不操作", "ignore"), ("自动启用", "on"), ("自动禁用", "off")],
|
|
@@ -1556,6 +1449,7 @@ class KotoneBotUI:
|
|
|
1556
1449
|
config.produce.selected_solution_id = data.get('selected_solution_id')
|
|
1557
1450
|
config.produce.produce_count = data.get('produce_count', 1)
|
|
1558
1451
|
config.produce.produce_timeout_cd = data.get('produce_timeout_cd', 60)
|
|
1452
|
+
config.produce.interrupt_timeout = data.get('interrupt_timeout', 180)
|
|
1559
1453
|
config.produce.enable_fever_month = data.get('enable_fever_month', 'ignore')
|
|
1560
1454
|
|
|
1561
1455
|
return set_config, {
|
|
@@ -1563,6 +1457,7 @@ class KotoneBotUI:
|
|
|
1563
1457
|
'selected_solution_id': solution_dropdown,
|
|
1564
1458
|
'produce_count': produce_count,
|
|
1565
1459
|
'produce_timeout_cd': produce_timeout_cd,
|
|
1460
|
+
'interrupt_timeout': interrupt_timeout,
|
|
1566
1461
|
'enable_fever_month': enable_fever_month
|
|
1567
1462
|
}
|
|
1568
1463
|
|
|
@@ -2452,6 +2347,16 @@ class KotoneBotUI:
|
|
|
2452
2347
|
info=MiscConfig.model_fields['update_channel'].description,
|
|
2453
2348
|
interactive=True
|
|
2454
2349
|
)
|
|
2350
|
+
log_level = gr.Dropdown(
|
|
2351
|
+
choices=[
|
|
2352
|
+
("调试", "debug"),
|
|
2353
|
+
("详细", "verbose")
|
|
2354
|
+
],
|
|
2355
|
+
value=self.current_config.options.misc.log_level,
|
|
2356
|
+
label="日志等级",
|
|
2357
|
+
info=MiscConfig.model_fields['log_level'].description,
|
|
2358
|
+
interactive=True
|
|
2359
|
+
)
|
|
2455
2360
|
with gr.Row():
|
|
2456
2361
|
gr.Button("创建桌面快捷方式").click(
|
|
2457
2362
|
fn=self._create_shortcut_button_click(False),
|
|
@@ -2467,12 +2372,14 @@ class KotoneBotUI:
|
|
|
2467
2372
|
config.misc.auto_install_update = data['auto_install_update']
|
|
2468
2373
|
config.misc.expose_to_lan = data['expose_to_lan']
|
|
2469
2374
|
config.misc.update_channel = data['update_channel']
|
|
2375
|
+
config.misc.log_level = data['log_level']
|
|
2470
2376
|
|
|
2471
2377
|
return set_config, {
|
|
2472
2378
|
'check_update': check_update,
|
|
2473
2379
|
'auto_install_update': auto_install_update,
|
|
2474
2380
|
'expose_to_lan': expose_to_lan,
|
|
2475
|
-
'update_channel': update_channel
|
|
2381
|
+
'update_channel': update_channel,
|
|
2382
|
+
'log_level': log_level
|
|
2476
2383
|
}
|
|
2477
2384
|
|
|
2478
2385
|
def _create_shortcut_button_click(self, start_immediately: bool) -> Callable[[], None]:
|
|
@@ -2644,19 +2551,43 @@ class KotoneBotUI:
|
|
|
2644
2551
|
|
|
2645
2552
|
result_text = gr.Markdown("等待操作\n\n\n")
|
|
2646
2553
|
|
|
2647
|
-
def
|
|
2648
|
-
|
|
2554
|
+
def create_report(title: str, description: str, upload: bool, progress=gr.Progress()):
|
|
2555
|
+
|
|
2556
|
+
def on_progress(data: Dict[str, Any]):
|
|
2557
|
+
progress_val = data['step'] / data['total_steps']
|
|
2558
|
+
if data['type'] == 'packing':
|
|
2559
|
+
desc = f"({data['step']}/{data['total_steps']}) 正在打包 {data['item']}"
|
|
2560
|
+
elif data['type'] == 'uploading':
|
|
2561
|
+
desc = f"({data['step']}/{data['total_steps']}) 正在上传 {data['item']}"
|
|
2562
|
+
elif data['type'] == 'done':
|
|
2563
|
+
if 'url' in data:
|
|
2564
|
+
desc = "上传完成"
|
|
2565
|
+
else:
|
|
2566
|
+
desc = "已保存至本地"
|
|
2567
|
+
else:
|
|
2568
|
+
desc = "正在处理..."
|
|
2569
|
+
progress(progress_val, desc=desc)
|
|
2649
2570
|
|
|
2650
|
-
|
|
2651
|
-
|
|
2571
|
+
try:
|
|
2572
|
+
result = self.feedback_service.report(
|
|
2573
|
+
title=title,
|
|
2574
|
+
description=description,
|
|
2575
|
+
version=self._kaa.version,
|
|
2576
|
+
upload=upload,
|
|
2577
|
+
on_progress=on_progress
|
|
2578
|
+
)
|
|
2579
|
+
return result.message
|
|
2580
|
+
except FeedbackServiceError as e:
|
|
2581
|
+
gr.Error(str(e))
|
|
2582
|
+
return f"### 操作失败\n\n{e}"
|
|
2652
2583
|
|
|
2653
2584
|
upload_report_btn.click(
|
|
2654
|
-
fn=
|
|
2585
|
+
fn=partial(create_report, upload=True),
|
|
2655
2586
|
inputs=[report_title, report_description],
|
|
2656
2587
|
outputs=[result_text]
|
|
2657
2588
|
)
|
|
2658
2589
|
save_local_report_btn.click(
|
|
2659
|
-
fn=
|
|
2590
|
+
fn=partial(create_report, upload=False),
|
|
2660
2591
|
inputs=[report_title, report_description],
|
|
2661
2592
|
outputs=[result_text]
|
|
2662
2593
|
)
|
|
@@ -2666,18 +2597,12 @@ class KotoneBotUI:
|
|
|
2666
2597
|
with gr.Tab("更新"):
|
|
2667
2598
|
gr.Markdown("## 版本管理")
|
|
2668
2599
|
|
|
2669
|
-
# 更新日志
|
|
2670
2600
|
with gr.Accordion("更新日志", open=False):
|
|
2671
2601
|
from kaa.metadata import WHATS_NEW
|
|
2672
2602
|
gr.Markdown(WHATS_NEW)
|
|
2673
2603
|
|
|
2674
|
-
# 载入信息按钮
|
|
2675
2604
|
load_info_btn = gr.Button("载入信息", variant="primary")
|
|
2676
|
-
|
|
2677
|
-
# 状态信息
|
|
2678
2605
|
status_text = gr.Markdown("")
|
|
2679
|
-
|
|
2680
|
-
# 版本选择下拉框(用于安装)
|
|
2681
2606
|
version_dropdown = gr.Dropdown(
|
|
2682
2607
|
label="选择要安装的版本",
|
|
2683
2608
|
choices=[],
|
|
@@ -2685,405 +2610,71 @@ class KotoneBotUI:
|
|
|
2685
2610
|
visible=False,
|
|
2686
2611
|
interactive=True
|
|
2687
2612
|
)
|
|
2688
|
-
|
|
2689
|
-
# 安装选定版本按钮
|
|
2690
2613
|
install_selected_btn = gr.Button("安装选定版本", visible=False)
|
|
2691
2614
|
|
|
2692
|
-
def
|
|
2693
|
-
"""
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
"""通过读取bootstrap.pyz/meta.py获取启动器版本"""
|
|
2701
|
-
import zipfile
|
|
2702
|
-
try:
|
|
2703
|
-
bootstrap_path = os.path.join(os.getcwd(), "bootstrap.pyz")
|
|
2704
|
-
if not os.path.exists(bootstrap_path):
|
|
2705
|
-
logger.warning("启动器文件不存在")
|
|
2706
|
-
gr.Warning("启动器文件不存在")
|
|
2707
|
-
return None
|
|
2708
|
-
|
|
2709
|
-
# 尝试从bootstrap.pyz中读取meta.py
|
|
2710
|
-
try:
|
|
2711
|
-
with zipfile.ZipFile(bootstrap_path, 'r') as zip_file:
|
|
2712
|
-
if 'meta.py' in zip_file.namelist():
|
|
2713
|
-
# 读取meta.py内容
|
|
2714
|
-
meta_content = zip_file.read('meta.py').decode('utf-8')
|
|
2715
|
-
|
|
2716
|
-
# 创建一个安全的执行环境
|
|
2717
|
-
exec_globals = {}
|
|
2718
|
-
exec_locals = {}
|
|
2719
|
-
|
|
2720
|
-
# 执行meta.py内容
|
|
2721
|
-
exec(meta_content, exec_globals, exec_locals)
|
|
2722
|
-
|
|
2723
|
-
# 获取VERSION变量
|
|
2724
|
-
if 'VERSION' in exec_locals:
|
|
2725
|
-
version = exec_locals['VERSION']
|
|
2726
|
-
# 移除v前缀(如果有)
|
|
2727
|
-
if isinstance(version, str) and version.startswith('v'):
|
|
2728
|
-
version = version[1:]
|
|
2729
|
-
logger.info(f"从meta.py读取到启动器版本: {version}")
|
|
2730
|
-
return str(version)
|
|
2731
|
-
else:
|
|
2732
|
-
logger.warning("meta.py中未找到VERSION变量")
|
|
2733
|
-
gr.Warning("meta.py中未找到VERSION变量")
|
|
2734
|
-
return None
|
|
2735
|
-
else:
|
|
2736
|
-
logger.warning("bootstrap.pyz中未找到meta.py文件")
|
|
2737
|
-
gr.Warning("bootstrap.pyz中未找到meta.py文件")
|
|
2738
|
-
return None
|
|
2739
|
-
except zipfile.BadZipFile:
|
|
2740
|
-
# 不是有效的zip文件,可能是旧版本启动器
|
|
2741
|
-
logger.info("bootstrap.pyz不是有效的zip文件,判断为旧版本启动器")
|
|
2742
|
-
return "0.4.x"
|
|
2743
|
-
except Exception as e:
|
|
2744
|
-
logger.warning(f"读取bootstrap.pyz失败: {str(e)}")
|
|
2745
|
-
gr.Warning(f"读取bootstrap.pyz失败: {str(e)}")
|
|
2746
|
-
return None
|
|
2747
|
-
|
|
2748
|
-
except Exception as e:
|
|
2749
|
-
logger.warning(f"检查启动器版本失败: {str(e)}")
|
|
2750
|
-
gr.Warning(f"检查启动器版本失败: {str(e)}")
|
|
2751
|
-
return None
|
|
2752
|
-
|
|
2615
|
+
def on_load_info():
|
|
2616
|
+
"""使用 UpdateService 加载版本信息。"""
|
|
2617
|
+
yield (
|
|
2618
|
+
"正在载入版本信息...",
|
|
2619
|
+
gr.Button(value="载入中...", interactive=False),
|
|
2620
|
+
gr.Dropdown(visible=False),
|
|
2621
|
+
gr.Button(visible=False)
|
|
2622
|
+
)
|
|
2753
2623
|
try:
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
]
|
|
2760
|
-
logger.info(f"执行命令: {' '.join(cmd)}")
|
|
2761
|
-
|
|
2762
|
-
# 使用 pip index versions --json 来获取版本信息
|
|
2763
|
-
result = subprocess.run(
|
|
2764
|
-
cmd,
|
|
2765
|
-
capture_output=True,
|
|
2766
|
-
text=True,
|
|
2767
|
-
timeout=30
|
|
2768
|
-
)
|
|
2769
|
-
|
|
2770
|
-
logger.info(f"命令返回码: {result.returncode}")
|
|
2771
|
-
if result.stdout:
|
|
2772
|
-
logger.info(f"命令输出: {result.stdout[:500]}...") # 只记录前500字符
|
|
2773
|
-
if result.stderr:
|
|
2774
|
-
logger.warning(f"命令错误输出: {result.stderr}")
|
|
2775
|
-
|
|
2776
|
-
if result.returncode != 0:
|
|
2777
|
-
error_msg = f"获取版本列表失败: {result.stderr}"
|
|
2778
|
-
logger.error(error_msg)
|
|
2779
|
-
return (
|
|
2780
|
-
error_msg,
|
|
2781
|
-
gr.Button(value="载入信息", interactive=True),
|
|
2782
|
-
gr.Dropdown(visible=False),
|
|
2783
|
-
gr.Button(visible=False)
|
|
2784
|
-
)
|
|
2785
|
-
|
|
2786
|
-
# 解析 JSON 输出
|
|
2787
|
-
try:
|
|
2788
|
-
data = json.loads(result.stdout)
|
|
2789
|
-
versions = data.get("versions", [])
|
|
2790
|
-
latest_version = data.get("latest", "")
|
|
2791
|
-
installed_version = data.get("installed_version", "")
|
|
2792
|
-
|
|
2793
|
-
logger.info(f"解析到 {len(versions)} 个版本")
|
|
2794
|
-
logger.info(f"最新版本: {latest_version}")
|
|
2795
|
-
logger.info(f"已安装版本: {installed_version}")
|
|
2796
|
-
|
|
2797
|
-
except json.JSONDecodeError as e:
|
|
2798
|
-
error_msg = f"解析版本信息失败: {str(e)}"
|
|
2799
|
-
logger.error(error_msg)
|
|
2800
|
-
return (
|
|
2801
|
-
error_msg,
|
|
2802
|
-
gr.Button(value="载入信息", interactive=True),
|
|
2803
|
-
gr.Dropdown(visible=False),
|
|
2804
|
-
gr.Button(visible=False)
|
|
2805
|
-
)
|
|
2806
|
-
|
|
2807
|
-
if not versions:
|
|
2808
|
-
error_msg = "未找到可用版本"
|
|
2809
|
-
logger.warning(error_msg)
|
|
2810
|
-
return (
|
|
2811
|
-
error_msg,
|
|
2812
|
-
gr.Button(value="载入信息", interactive=True),
|
|
2813
|
-
gr.Dropdown(visible=False),
|
|
2814
|
-
gr.Button(visible=False)
|
|
2815
|
-
)
|
|
2816
|
-
|
|
2817
|
-
# 检查启动器版本
|
|
2818
|
-
launcher_version = check_launcher_version()
|
|
2819
|
-
|
|
2820
|
-
# 构建状态信息
|
|
2821
|
-
status_info = []
|
|
2822
|
-
if installed_version:
|
|
2823
|
-
status_info.append(f"**当前安装版本:** {installed_version}")
|
|
2824
|
-
if latest_version:
|
|
2825
|
-
status_info.append(f"**最新版本:** {latest_version}")
|
|
2826
|
-
if launcher_version:
|
|
2827
|
-
if launcher_version == "0.4.x":
|
|
2828
|
-
status_info.append(f"**启动器版本:** < v0.5.0 (旧版本)")
|
|
2829
|
-
else:
|
|
2830
|
-
status_info.append(f"**启动器版本:** v{launcher_version}")
|
|
2831
|
-
else:
|
|
2832
|
-
status_info.append(f"**启动器版本:** 未知")
|
|
2833
|
-
status_info.append(f"**找到 {len(versions)} 个可用版本**")
|
|
2834
|
-
|
|
2835
|
-
status_message = "\n\n".join(status_info)
|
|
2836
|
-
logger.info(f"版本信息载入完成: {status_message}")
|
|
2837
|
-
|
|
2838
|
-
# 返回更新后的组件
|
|
2839
|
-
return (
|
|
2840
|
-
status_message,
|
|
2841
|
-
gr.Button(value="载入信息", interactive=True),
|
|
2842
|
-
gr.Dropdown(choices=versions, value=versions[0] if versions else None, visible=True, label="选择要安装的版本"),
|
|
2843
|
-
gr.Button(visible=True, value="安装选定版本")
|
|
2844
|
-
)
|
|
2845
|
-
|
|
2846
|
-
except subprocess.TimeoutExpired:
|
|
2847
|
-
error_msg = "获取版本列表超时"
|
|
2848
|
-
logger.error(error_msg)
|
|
2849
|
-
return (
|
|
2850
|
-
error_msg,
|
|
2851
|
-
gr.Button(value="载入信息", interactive=True),
|
|
2852
|
-
gr.Dropdown(visible=False),
|
|
2853
|
-
gr.Button(visible=False)
|
|
2854
|
-
)
|
|
2855
|
-
except Exception as e:
|
|
2856
|
-
error_msg = f"获取版本列表失败: {str(e)}"
|
|
2857
|
-
logger.error(error_msg)
|
|
2858
|
-
return (
|
|
2859
|
-
error_msg,
|
|
2624
|
+
versions_data = self.update_service.list_remote_versions()
|
|
2625
|
+
except UpdateFetchListError as e:
|
|
2626
|
+
gr.Error(str(e))
|
|
2627
|
+
yield (
|
|
2628
|
+
str(e),
|
|
2860
2629
|
gr.Button(value="载入信息", interactive=True),
|
|
2861
2630
|
gr.Dropdown(visible=False),
|
|
2862
2631
|
gr.Button(visible=False)
|
|
2863
2632
|
)
|
|
2633
|
+
return
|
|
2864
2634
|
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
if not selected_version:
|
|
2874
|
-
error_msg = "请先选择一个版本"
|
|
2875
|
-
logger.warning(error_msg)
|
|
2876
|
-
return error_msg
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
def compare_version(version1: str, version2: str) -> int:
|
|
2880
|
-
"""比较版本号,返回-1(v1<v2), 0(v1==v2), 1(v1>v2)"""
|
|
2881
|
-
# 处理特殊标记
|
|
2882
|
-
if version1 == "0.4.x":
|
|
2883
|
-
version1 = "0.4.0"
|
|
2884
|
-
|
|
2885
|
-
def parse_version(v):
|
|
2886
|
-
# 移除v前缀并解析版本号和预发布标识
|
|
2887
|
-
v = v.lstrip('v')
|
|
2888
|
-
if 'b' in v:
|
|
2889
|
-
base, beta = v.split('b', 1)
|
|
2890
|
-
return tuple(map(int, base.split('.'))) + (-1, int(beta))
|
|
2891
|
-
elif 'a' in v:
|
|
2892
|
-
base, alpha = v.split('a', 1)
|
|
2893
|
-
return tuple(map(int, base.split('.'))) + (-2, int(alpha))
|
|
2894
|
-
elif 'rc' in v:
|
|
2895
|
-
base, rc = v.split('rc', 1)
|
|
2896
|
-
return tuple(map(int, base.split('.'))) + (-0.5, int(rc))
|
|
2897
|
-
else:
|
|
2898
|
-
return tuple(map(int, v.split('.'))) + (0, 0)
|
|
2899
|
-
|
|
2900
|
-
v1_parsed = parse_version(version1)
|
|
2901
|
-
v2_parsed = parse_version(version2)
|
|
2902
|
-
|
|
2903
|
-
if v1_parsed < v2_parsed:
|
|
2904
|
-
return -1
|
|
2905
|
-
elif v1_parsed > v2_parsed:
|
|
2906
|
-
return 1
|
|
2635
|
+
status_info = [
|
|
2636
|
+
f"**当前安装版本:** {versions_data.installed_version or '未知'}",
|
|
2637
|
+
f"**最新版本:** {versions_data.latest or '未知'}",
|
|
2638
|
+
]
|
|
2639
|
+
if versions_data.launcher_version:
|
|
2640
|
+
if versions_data.launcher_version == "0.4.x":
|
|
2641
|
+
status_info.append("**启动器版本:** < v0.5.0 (旧版本)")
|
|
2907
2642
|
else:
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
# 检查启动器版本进行兼容性验证
|
|
2911
|
-
def check_launcher_version_simple():
|
|
2912
|
-
"""通过读取bootstrap.pyz/meta.py获取启动器版本"""
|
|
2913
|
-
import zipfile
|
|
2914
|
-
try:
|
|
2915
|
-
bootstrap_path = os.path.join(os.getcwd(), "bootstrap.pyz")
|
|
2916
|
-
if not os.path.exists(bootstrap_path):
|
|
2917
|
-
logger.warning("启动器文件不存在")
|
|
2918
|
-
gr.Warning("启动器文件不存在")
|
|
2919
|
-
return None
|
|
2920
|
-
|
|
2921
|
-
# 尝试从bootstrap.pyz中读取meta.py
|
|
2922
|
-
try:
|
|
2923
|
-
with zipfile.ZipFile(bootstrap_path, 'r') as zip_file:
|
|
2924
|
-
if 'meta.py' in zip_file.namelist():
|
|
2925
|
-
# 读取meta.py内容
|
|
2926
|
-
meta_content = zip_file.read('meta.py').decode('utf-8')
|
|
2927
|
-
|
|
2928
|
-
# 创建一个安全的执行环境
|
|
2929
|
-
exec_globals = {}
|
|
2930
|
-
exec_locals = {}
|
|
2931
|
-
|
|
2932
|
-
# 执行meta.py内容
|
|
2933
|
-
exec(meta_content, exec_globals, exec_locals)
|
|
2934
|
-
|
|
2935
|
-
# 获取VERSION变量
|
|
2936
|
-
if 'VERSION' in exec_locals:
|
|
2937
|
-
version = exec_locals['VERSION']
|
|
2938
|
-
# 移除v前缀(如果有)
|
|
2939
|
-
if isinstance(version, str) and version.startswith('v'):
|
|
2940
|
-
version = version[1:]
|
|
2941
|
-
logger.info(f"从meta.py读取到启动器版本: {version}")
|
|
2942
|
-
return str(version)
|
|
2943
|
-
else:
|
|
2944
|
-
logger.warning("meta.py中未找到VERSION变量")
|
|
2945
|
-
gr.Warning("meta.py中未找到VERSION变量")
|
|
2946
|
-
return None
|
|
2947
|
-
else:
|
|
2948
|
-
logger.warning("bootstrap.pyz中未找到meta.py文件")
|
|
2949
|
-
gr.Warning("bootstrap.pyz中未找到meta.py文件")
|
|
2950
|
-
return None
|
|
2951
|
-
except zipfile.BadZipFile:
|
|
2952
|
-
# 不是有效的zip文件,可能是旧版本启动器
|
|
2953
|
-
logger.info("bootstrap.pyz不是有效的zip文件,判断为旧版本启动器")
|
|
2954
|
-
return "0.4.x"
|
|
2955
|
-
except Exception as e:
|
|
2956
|
-
logger.warning(f"读取bootstrap.pyz失败: {str(e)}")
|
|
2957
|
-
gr.Warning(f"读取bootstrap.pyz失败: {str(e)}")
|
|
2958
|
-
return None
|
|
2959
|
-
|
|
2960
|
-
except Exception as e:
|
|
2961
|
-
logger.warning(f"检查启动器版本失败: {str(e)}")
|
|
2962
|
-
gr.Warning(f"检查启动器版本失败: {str(e)}")
|
|
2963
|
-
return None
|
|
2964
|
-
|
|
2965
|
-
# 执行启动器版本检查
|
|
2966
|
-
launcher_version = check_launcher_version_simple()
|
|
2967
|
-
logger.info(f"检测到启动器版本: {launcher_version}")
|
|
2968
|
-
|
|
2969
|
-
# 版本兼容性检查
|
|
2970
|
-
if launcher_version:
|
|
2971
|
-
if compare_version(launcher_version, "0.5.0") < 0:
|
|
2972
|
-
# 启动器版本低于0.5.0
|
|
2973
|
-
logger.warning(f"启动器版本 {launcher_version} 低于 v0.5.0")
|
|
2974
|
-
|
|
2975
|
-
# 检查要安装的版本是否 >= v2025.9b1
|
|
2976
|
-
if compare_version(selected_version, "2025.9b1") >= 0:
|
|
2977
|
-
error_msg = (
|
|
2978
|
-
f"❌ 版本兼容性错误\n\n"
|
|
2979
|
-
f"启动器版本: {launcher_version}\n"
|
|
2980
|
-
f"要安装的版本: {selected_version}\n\n"
|
|
2981
|
-
f"v2025.9b1 及以上版本需要**启动器 v0.5.0*** 或更高版本支持。\n"
|
|
2982
|
-
f"请先升级启动器到 v0.5.0 以上版本。[查看帮助](https://www.kdocs.cn/l/cetCY8mGKHLj?linkname=UhPH1itaSv)"
|
|
2983
|
-
)
|
|
2984
|
-
logger.error(error_msg)
|
|
2985
|
-
return error_msg
|
|
2986
|
-
else:
|
|
2987
|
-
# 版本兼容,但给出警告
|
|
2988
|
-
logger.warning(f"启动器版本较低,建议升级到 v0.5.0 以上")
|
|
2989
|
-
gr.Warning("启动器版本较低,建议升级到 v0.5.0 以上")
|
|
2643
|
+
status_info.append(f"**启动器版本:** v{versions_data.launcher_version}")
|
|
2990
2644
|
else:
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
def install_and_exit():
|
|
2996
|
-
"""在后台线程中执行安装并退出程序"""
|
|
2997
|
-
try:
|
|
2998
|
-
# 等待一小段时间确保UI响应已返回
|
|
2999
|
-
time.sleep(1)
|
|
3000
|
-
|
|
3001
|
-
# 构建启动器命令
|
|
3002
|
-
bootstrap_path = os.path.join(os.getcwd(), "bootstrap.pyz")
|
|
3003
|
-
cmd = [sys.executable, bootstrap_path, f"--install-version={selected_version}"]
|
|
3004
|
-
logger.info(f"开始通过启动器安装版本 {selected_version}")
|
|
3005
|
-
logger.info(f"执行命令: {' '.join(cmd)}")
|
|
3006
|
-
|
|
3007
|
-
# 启动启动器进程(不等待完成)
|
|
3008
|
-
subprocess.Popen(
|
|
3009
|
-
cmd,
|
|
3010
|
-
cwd=os.getcwd(),
|
|
3011
|
-
creationflags=subprocess.CREATE_NEW_CONSOLE if os.name == 'nt' else 0
|
|
3012
|
-
)
|
|
3013
|
-
|
|
3014
|
-
# 退出当前程序
|
|
3015
|
-
logger.info("安装即将开始,正在退出当前程序...")
|
|
3016
|
-
os._exit(0)
|
|
3017
|
-
|
|
3018
|
-
except Exception as e:
|
|
3019
|
-
raise
|
|
3020
|
-
|
|
3021
|
-
try:
|
|
3022
|
-
# 在后台线程中执行安装和退出
|
|
3023
|
-
install_thread = threading.Thread(target=install_and_exit, daemon=True)
|
|
3024
|
-
install_thread.start()
|
|
3025
|
-
|
|
3026
|
-
return f"正在启动器中安装版本 {selected_version},程序将自动重启..."
|
|
3027
|
-
|
|
3028
|
-
except Exception as e:
|
|
3029
|
-
error_msg = f"启动安装进程失败: {str(e)}"
|
|
3030
|
-
logger.error(error_msg)
|
|
3031
|
-
return error_msg
|
|
3032
|
-
|
|
3033
|
-
def load_info_with_button_state():
|
|
3034
|
-
"""载入信息并管理按钮状态"""
|
|
3035
|
-
import logging
|
|
3036
|
-
logger = logging.getLogger(__name__)
|
|
3037
|
-
|
|
3038
|
-
logger.info("开始载入版本信息")
|
|
2645
|
+
status_info.append("**启动器版本:** 未知")
|
|
2646
|
+
|
|
2647
|
+
status_info.append(f"**找到 {len(versions_data.versions)} 个可用版本**")
|
|
2648
|
+
status_message = "\n\n".join(status_info)
|
|
3039
2649
|
|
|
3040
|
-
# 先禁用按钮
|
|
3041
2650
|
yield (
|
|
3042
|
-
|
|
3043
|
-
gr.Button(value="
|
|
3044
|
-
gr.Dropdown(visible=
|
|
3045
|
-
gr.Button(visible=
|
|
2651
|
+
status_message,
|
|
2652
|
+
gr.Button(value="载入信息", interactive=True),
|
|
2653
|
+
gr.Dropdown(choices=versions_data.versions, value=versions_data.versions[0] if versions_data.versions else None, visible=True),
|
|
2654
|
+
gr.Button(visible=True)
|
|
3046
2655
|
)
|
|
3047
2656
|
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
2657
|
+
def on_install_selected(selected_version: str):
|
|
2658
|
+
"""使用 UpdateService 安装所选版本。"""
|
|
2659
|
+
if not selected_version:
|
|
2660
|
+
gr.Warning("请先选择一个版本。")
|
|
2661
|
+
return
|
|
2662
|
+
|
|
2663
|
+
try:
|
|
2664
|
+
self.update_service.install_version(selected_version)
|
|
2665
|
+
gr.Info(f"正在启动器中安装版本 {selected_version},程序将自动重启...")
|
|
2666
|
+
except UpdateServiceError as e:
|
|
2667
|
+
gr.Error(str(e))
|
|
3052
2668
|
|
|
3053
|
-
# 绑定事件
|
|
3054
2669
|
load_info_btn.click(
|
|
3055
|
-
fn=
|
|
2670
|
+
fn=on_load_info,
|
|
3056
2671
|
outputs=[status_text, load_info_btn, version_dropdown, install_selected_btn]
|
|
3057
2672
|
)
|
|
3058
2673
|
|
|
3059
2674
|
install_selected_btn.click(
|
|
3060
|
-
fn=
|
|
2675
|
+
fn=on_install_selected,
|
|
3061
2676
|
inputs=[version_dropdown],
|
|
3062
|
-
outputs=[
|
|
3063
|
-
)
|
|
3064
|
-
|
|
3065
|
-
def _create_screen_tab(self) -> None:
|
|
3066
|
-
with gr.Tab("画面"):
|
|
3067
|
-
gr.Markdown("## 当前设备画面")
|
|
3068
|
-
refresh_btn = gr.Button("刷新画面", variant="primary")
|
|
3069
|
-
WIDTH = 720 // 3
|
|
3070
|
-
HEIGHT = 1280 // 3
|
|
3071
|
-
last_update_text = gr.Markdown("上次更新时间:无数据")
|
|
3072
|
-
screenshot_display = gr.Image(type="numpy", width=WIDTH, height=HEIGHT)
|
|
3073
|
-
|
|
3074
|
-
def update_screenshot():
|
|
3075
|
-
ctx = ContextStackVars.current()
|
|
3076
|
-
if ctx is None:
|
|
3077
|
-
return [None, "上次更新时间:无上下文数据"]
|
|
3078
|
-
screenshot = ctx._screenshot
|
|
3079
|
-
if screenshot is None:
|
|
3080
|
-
return [None, "上次更新时间:无截图数据"]
|
|
3081
|
-
screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2RGB)
|
|
3082
|
-
return screenshot, f"上次更新时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
|
|
3083
|
-
|
|
3084
|
-
refresh_btn.click(
|
|
3085
|
-
fn=update_screenshot,
|
|
3086
|
-
outputs=[screenshot_display, last_update_text]
|
|
2677
|
+
outputs=[]
|
|
3087
2678
|
)
|
|
3088
2679
|
|
|
3089
2680
|
def _load_config(self) -> None:
|
|
@@ -3128,7 +2719,6 @@ class KotoneBotUI:
|
|
|
3128
2719
|
self._create_produce_tab()
|
|
3129
2720
|
self._create_log_tab()
|
|
3130
2721
|
self._create_whats_new_tab()
|
|
3131
|
-
self._create_screen_tab()
|
|
3132
2722
|
|
|
3133
2723
|
# 启动 IdleModeManager 后台线程
|
|
3134
2724
|
self.idle_mgr.start()
|