diff --git a/tests/builtin_plugins/plugin_store/test_add_plugin.py b/tests/builtin_plugins/plugin_store/test_add_plugin.py index 9f2d61449..3dd2ebbb1 100644 --- a/tests/builtin_plugins/plugin_store/test_add_plugin.py +++ b/tests/builtin_plugins/plugin_store/test_add_plugin.py @@ -16,8 +16,10 @@ @pytest.mark.parametrize("package_api", ["jsd", "gh"]) +@pytest.mark.parametrize("is_commit", [True, False]) async def test_add_plugin_basic( package_api: str, + is_commit: bool, app: App, mocker: MockerFixture, mocked_api: MockRouter, @@ -40,6 +42,12 @@ async def test_add_plugin_basic( if package_api != "gh": mocked_api["zhenxun_bot_plugins_tree"].respond(404) + if not is_commit: + mocked_api["zhenxun_bot_plugins_commit"].respond(404) + mocked_api["zhenxun_bot_plugins_commit_proxy"].respond(404) + mocked_api["zhenxun_bot_plugins_index_commit"].respond(404) + mocked_api["zhenxun_bot_plugins_index_commit_proxy"].respond(404) + plugin_id = 1 async with app.test_matcher(_matcher) as ctx: @@ -67,15 +75,22 @@ async def test_add_plugin_basic( result=None, bot=bot, ) - assert mocked_api["basic_plugins"].called - assert mocked_api["extra_plugins"].called - assert mocked_api["search_image_plugin_file_init"].called + if is_commit: + assert mocked_api["search_image_plugin_file_init_commit"].called + assert mocked_api["basic_plugins"].called + assert mocked_api["extra_plugins"].called + else: + assert mocked_api["search_image_plugin_file_init"].called + assert mocked_api["basic_plugins_no_commit"].called + assert mocked_api["extra_plugins_no_commit"].called assert (mock_base_path / "plugins" / "search_image" / "__init__.py").is_file() @pytest.mark.parametrize("package_api", ["jsd", "gh"]) +@pytest.mark.parametrize("is_commit", [True, False]) async def test_add_plugin_basic_commit_version( package_api: str, + is_commit: bool, app: App, mocker: MockerFixture, mocked_api: MockRouter, @@ -98,6 +113,11 @@ async def test_add_plugin_basic_commit_version( if package_api != "gh": mocked_api["zhenxun_bot_plugins_tree_commit"].respond(404) + if not is_commit: + mocked_api["zhenxun_bot_plugins_commit"].respond(404) + mocked_api["zhenxun_bot_plugins_commit_proxy"].respond(404) + mocked_api["zhenxun_bot_plugins_index_commit"].respond(404) + mocked_api["zhenxun_bot_plugins_index_commit_proxy"].respond(404) plugin_id = 3 async with app.test_matcher(_matcher) as ctx: @@ -125,19 +145,25 @@ async def test_add_plugin_basic_commit_version( result=None, bot=bot, ) - assert mocked_api["basic_plugins"].called - assert mocked_api["extra_plugins"].called if package_api == "jsd": assert mocked_api["zhenxun_bot_plugins_metadata_commit"].called if package_api == "gh": assert mocked_api["zhenxun_bot_plugins_tree_commit"].called + if is_commit: + assert mocked_api["basic_plugins"].called + assert mocked_api["extra_plugins"].called + else: + assert mocked_api["basic_plugins_no_commit"].called + assert mocked_api["extra_plugins_no_commit"].called assert mocked_api["bilibili_sub_plugin_file_init"].called assert (mock_base_path / "plugins" / "bilibili_sub" / "__init__.py").is_file() @pytest.mark.parametrize("package_api", ["jsd", "gh"]) +@pytest.mark.parametrize("is_commit", [True, False]) async def test_add_plugin_basic_is_not_dir( package_api: str, + is_commit: bool, app: App, mocker: MockerFixture, mocked_api: MockRouter, @@ -160,6 +186,12 @@ async def test_add_plugin_basic_is_not_dir( if package_api != "gh": mocked_api["zhenxun_bot_plugins_tree"].respond(404) + if not is_commit: + mocked_api["zhenxun_bot_plugins_commit"].respond(404) + mocked_api["zhenxun_bot_plugins_commit_proxy"].respond(404) + mocked_api["zhenxun_bot_plugins_index_commit"].respond(404) + mocked_api["zhenxun_bot_plugins_index_commit_proxy"].respond(404) + plugin_id = 0 async with app.test_matcher(_matcher) as ctx: @@ -187,15 +219,22 @@ async def test_add_plugin_basic_is_not_dir( result=None, bot=bot, ) - assert mocked_api["basic_plugins"].called - assert mocked_api["extra_plugins"].called - assert mocked_api["jitang_plugin_file"].called + if is_commit: + assert mocked_api["jitang_plugin_file_commit"].called + assert mocked_api["basic_plugins"].called + assert mocked_api["extra_plugins"].called + else: + assert mocked_api["jitang_plugin_file"].called + assert mocked_api["basic_plugins_no_commit"].called + assert mocked_api["extra_plugins_no_commit"].called assert (mock_base_path / "plugins" / "alapi" / "jitang.py").is_file() @pytest.mark.parametrize("package_api", ["jsd", "gh"]) +@pytest.mark.parametrize("is_commit", [True, False]) async def test_add_plugin_extra( package_api: str, + is_commit: bool, app: App, mocker: MockerFixture, mocked_api: MockRouter, @@ -218,6 +257,14 @@ async def test_add_plugin_extra( if package_api != "gh": mocked_api["zhenxun_github_sub_tree"].respond(404) + if not is_commit: + mocked_api["zhenxun_github_sub_commit"].respond(404) + mocked_api["zhenxun_github_sub_commit_proxy"].respond(404) + mocked_api["zhenxun_bot_plugins_commit"].respond(404) + mocked_api["zhenxun_bot_plugins_commit_proxy"].respond(404) + mocked_api["zhenxun_bot_plugins_index_commit"].respond(404) + mocked_api["zhenxun_bot_plugins_index_commit_proxy"].respond(404) + plugin_id = 4 async with app.test_matcher(_matcher) as ctx: @@ -245,9 +292,14 @@ async def test_add_plugin_extra( result=None, bot=bot, ) - assert mocked_api["basic_plugins"].called - assert mocked_api["extra_plugins"].called - assert mocked_api["github_sub_plugin_file_init"].called + if is_commit: + assert mocked_api["github_sub_plugin_file_init_commit"].called + assert mocked_api["basic_plugins"].called + assert mocked_api["extra_plugins"].called + else: + assert mocked_api["github_sub_plugin_file_init"].called + assert mocked_api["basic_plugins_no_commit"].called + assert mocked_api["extra_plugins_no_commit"].called assert (mock_base_path / "plugins" / "github_sub" / "__init__.py").is_file() diff --git a/tests/builtin_plugins/plugin_store/test_plugin_store.py b/tests/builtin_plugins/plugin_store/test_plugin_store.py index 90ce3f60f..4e8eae16d 100644 --- a/tests/builtin_plugins/plugin_store/test_plugin_store.py +++ b/tests/builtin_plugins/plugin_store/test_plugin_store.py @@ -112,7 +112,7 @@ async def test_plugin_store_fail( init_mocked_api(mocked_api=mocked_api) mocked_api.get( - "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/main/plugins.json", + "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/b101fbc/plugins.json", name="basic_plugins", ).respond(404) diff --git a/tests/builtin_plugins/plugin_store/test_update_all_plugin.py b/tests/builtin_plugins/plugin_store/test_update_all_plugin.py index 7fc3b5887..2a490da76 100644 --- a/tests/builtin_plugins/plugin_store/test_update_all_plugin.py +++ b/tests/builtin_plugins/plugin_store/test_update_all_plugin.py @@ -65,7 +65,7 @@ async def test_update_all_plugin_basic_need_update( ) assert mocked_api["basic_plugins"].called assert mocked_api["extra_plugins"].called - assert mocked_api["search_image_plugin_file_init"].called + assert mocked_api["search_image_plugin_file_init_commit"].called assert (mock_base_path / "plugins" / "search_image" / "__init__.py").is_file() diff --git a/tests/builtin_plugins/plugin_store/test_update_plugin.py b/tests/builtin_plugins/plugin_store/test_update_plugin.py index 59fb0bc3a..952191d68 100644 --- a/tests/builtin_plugins/plugin_store/test_update_plugin.py +++ b/tests/builtin_plugins/plugin_store/test_update_plugin.py @@ -65,7 +65,7 @@ async def test_update_plugin_basic_need_update( ) assert mocked_api["basic_plugins"].called assert mocked_api["extra_plugins"].called - assert mocked_api["search_image_plugin_file_init"].called + assert mocked_api["search_image_plugin_file_init_commit"].called assert (mock_base_path / "plugins" / "search_image" / "__init__.py").is_file() diff --git a/tests/builtin_plugins/plugin_store/utils.py b/tests/builtin_plugins/plugin_store/utils.py index 831290716..781aad5e4 100644 --- a/tests/builtin_plugins/plugin_store/utils.py +++ b/tests/builtin_plugins/plugin_store/utils.py @@ -30,6 +30,10 @@ def init_mocked_api(mocked_api: MockRouter) -> None: "https://data.jsdelivr.com/v1/packages/gh/zhenxun-org/zhenxun_bot_plugins@b101fbc", name="zhenxun_bot_plugins_metadata_commit", ).respond(json=get_response_json("zhenxun_bot_plugins_metadata.json")) + mocked_api.get( + "https://data.jsdelivr.com/v1/packages/gh/xuanerwa/zhenxun_github_sub@f524632f78d27f9893beebdf709e0e7885cd08f1", + name="zhenxun_github_sub_metadata_commit", + ).respond(json=get_response_json("zhenxun_github_sub_metadata.json")) # tree mocked_api.get( @@ -44,6 +48,10 @@ def init_mocked_api(mocked_api: MockRouter) -> None: "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins/git/trees/b101fbc?recursive=1", name="zhenxun_bot_plugins_tree_commit", ).respond(json=get_response_json("zhenxun_bot_plugins_tree.json")) + mocked_api.get( + "https://api.github.com/repos/xuanerwa/zhenxun_github_sub/git/trees/f524632f78d27f9893beebdf709e0e7885cd08f1?recursive=1", + name="zhenxun_github_sub_tree_commit", + ).respond(json=get_response_json("zhenxun_github_sub_tree.json")) mocked_api.head( "https://raw.githubusercontent.com/", @@ -51,36 +59,89 @@ def init_mocked_api(mocked_api: MockRouter) -> None: ).respond(200, text="") mocked_api.get( - "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/main/plugins.json", + "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/b101fbc/plugins.json", name="basic_plugins", ).respond(json=get_response_json("basic_plugins.json")) mocked_api.get( - "https://cdn.jsdelivr.net/gh/zhenxun-org/zhenxun_bot_plugins@main/plugins.json", + "https://cdn.jsdelivr.net/gh/zhenxun-org/zhenxun_bot_plugins@b101fbc/plugins.json", name="basic_plugins_jsdelivr", ).respond(200, json=get_response_json("basic_plugins.json")) + mocked_api.get( + "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/main/plugins.json", + name="basic_plugins_no_commit", + ).respond(json=get_response_json("basic_plugins.json")) + mocked_api.get( + "https://cdn.jsdelivr.net/gh/zhenxun-org/zhenxun_bot_plugins@main/plugins.json", + name="basic_plugins_jsdelivr_no_commit", + ).respond(200, json=get_response_json("basic_plugins.json")) mocked_api.get( - "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins_index/index/plugins.json", + "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins_index/2ed61284873c526802752b12a3fd3b5e1a59d948/plugins.json", name="extra_plugins", ).respond(200, json=get_response_json("extra_plugins.json")) mocked_api.get( - "https://cdn.jsdelivr.net/gh/zhenxun-org/zhenxun_bot_plugins_index@index/plugins.json", + "https://cdn.jsdelivr.net/gh/zhenxun-org/zhenxun_bot_plugins_index@2ed61284873c526802752b12a3fd3b5e1a59d948/plugins.json", name="extra_plugins_jsdelivr", ).respond(200, json=get_response_json("extra_plugins.json")) + mocked_api.get( + "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins_index/index/plugins.json", + name="extra_plugins_no_commit", + ).respond(200, json=get_response_json("extra_plugins.json")) + mocked_api.get( + "https://cdn.jsdelivr.net/gh/zhenxun-org/zhenxun_bot_plugins_index@index/plugins.json", + name="extra_plugins_jsdelivr_no_commit", + ).respond(200, json=get_response_json("extra_plugins.json")) mocked_api.get( "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/main/plugins/search_image/__init__.py", name="search_image_plugin_file_init", ).respond(content=get_content_bytes("search_image.py")) + mocked_api.get( + "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/b101fbc/plugins/search_image/__init__.py", + name="search_image_plugin_file_init_commit", + ).respond(content=get_content_bytes("search_image.py")) mocked_api.get( "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/main/plugins/alapi/jitang.py", name="jitang_plugin_file", ).respond(content=get_content_bytes("jitang.py")) + mocked_api.get( + "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/b101fbc/plugins/alapi/jitang.py", + name="jitang_plugin_file_commit", + ).respond(content=get_content_bytes("jitang.py")) mocked_api.get( "https://raw.githubusercontent.com/xuanerwa/zhenxun_github_sub/main/github_sub/__init__.py", name="github_sub_plugin_file_init", ).respond(content=get_content_bytes("github_sub.py")) + mocked_api.get( + "https://raw.githubusercontent.com/xuanerwa/zhenxun_github_sub/f524632f78d27f9893beebdf709e0e7885cd08f1/github_sub/__init__.py", + name="github_sub_plugin_file_init_commit", + ).respond(content=get_content_bytes("github_sub.py")) mocked_api.get( "https://raw.githubusercontent.com/zhenxun-org/zhenxun_bot_plugins/b101fbc/plugins/bilibili_sub/__init__.py", name="bilibili_sub_plugin_file_init", ).respond(content=get_content_bytes("bilibili_sub.py")) + + mocked_api.get( + "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins/commits/main", + name="zhenxun_bot_plugins_commit", + ).respond(json=get_response_json("zhenxun_bot_plugins_commit.json")) + mocked_api.get( + "https://git-api.zhenxun.org/repos/zhenxun-org/zhenxun_bot_plugins/commits/main", + name="zhenxun_bot_plugins_commit_proxy", + ).respond(json=get_response_json("zhenxun_bot_plugins_commit.json")) + mocked_api.get( + "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins_index/commits/index", + name="zhenxun_bot_plugins_index_commit", + ).respond(json=get_response_json("zhenxun_bot_plugins_index_commit.json")) + mocked_api.get( + "https://git-api.zhenxun.org/repos/zhenxun-org/zhenxun_bot_plugins_index/commits/index", + name="zhenxun_bot_plugins_index_commit_proxy", + ).respond(json=get_response_json("zhenxun_bot_plugins_index_commit.json")) + mocked_api.get( + "https://api.github.com/repos/xuanerwa/zhenxun_github_sub/commits/main", + name="zhenxun_github_sub_commit", + ).respond(json=get_response_json("zhenxun_github_sub_commit.json")) + mocked_api.get( + "https://git-api.zhenxun.org/repos/xuanerwa/zhenxun_github_sub/commits/main", + name="zhenxun_github_sub_commit_proxy", + ).respond(json=get_response_json("zhenxun_github_sub_commit.json")) diff --git a/tests/response/plugin_store/zhenxun_bot_plugins_commit.json b/tests/response/plugin_store/zhenxun_bot_plugins_commit.json new file mode 100644 index 000000000..cbd2f59e4 --- /dev/null +++ b/tests/response/plugin_store/zhenxun_bot_plugins_commit.json @@ -0,0 +1,101 @@ +{ + "sha": "b101fbc", + "node_id": "C_kwDOMndPGNoAKGIxMDFmYmNlODg4NjA4ZTJiYmU1YjVmZDI3OWUxNDY1MTY4ODEyYzc", + "commit": { + "author": { + "name": "xuaner", + "email": "xuaner_wa@qq.com", + "date": "2024-09-20T12:08:27Z" + }, + "committer": { + "name": "xuaner", + "email": "xuaner_wa@qq.com", + "date": "2024-09-20T12:08:27Z" + }, + "message": "🐛修复B站订阅bug", + "tree": { + "sha": "0566306219a434f7122798647498faef692c1879", + "url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins/git/trees/0566306219a434f7122798647498faef692c1879" + }, + "url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins/git/commits/b101fbce888608e2bbe5b5fd279e1465168812c7", + "comment_count": 0, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null, + "verified_at": null + } + }, + "url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins/commits/b101fbce888608e2bbe5b5fd279e1465168812c7", + "html_url": "https://github.com/zhenxun-org/zhenxun_bot_plugins/commit/b101fbce888608e2bbe5b5fd279e1465168812c7", + "comments_url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins/commits/b101fbce888608e2bbe5b5fd279e1465168812c7/comments", + "author": { + "login": "xuanerwa", + "id": 58063798, + "node_id": "MDQ6VXNlcjU4MDYzNzk4", + "avatar_url": "https://avatars.githubusercontent.com/u/58063798?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/xuanerwa", + "html_url": "https://github.com/xuanerwa", + "followers_url": "https://api.github.com/users/xuanerwa/followers", + "following_url": "https://api.github.com/users/xuanerwa/following{/other_user}", + "gists_url": "https://api.github.com/users/xuanerwa/gists{/gist_id}", + "starred_url": "https://api.github.com/users/xuanerwa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/xuanerwa/subscriptions", + "organizations_url": "https://api.github.com/users/xuanerwa/orgs", + "repos_url": "https://api.github.com/users/xuanerwa/repos", + "events_url": "https://api.github.com/users/xuanerwa/events{/privacy}", + "received_events_url": "https://api.github.com/users/xuanerwa/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "committer": { + "login": "xuanerwa", + "id": 58063798, + "node_id": "MDQ6VXNlcjU4MDYzNzk4", + "avatar_url": "https://avatars.githubusercontent.com/u/58063798?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/xuanerwa", + "html_url": "https://github.com/xuanerwa", + "followers_url": "https://api.github.com/users/xuanerwa/followers", + "following_url": "https://api.github.com/users/xuanerwa/following{/other_user}", + "gists_url": "https://api.github.com/users/xuanerwa/gists{/gist_id}", + "starred_url": "https://api.github.com/users/xuanerwa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/xuanerwa/subscriptions", + "organizations_url": "https://api.github.com/users/xuanerwa/orgs", + "repos_url": "https://api.github.com/users/xuanerwa/repos", + "events_url": "https://api.github.com/users/xuanerwa/events{/privacy}", + "received_events_url": "https://api.github.com/users/xuanerwa/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "parents": [ + { + "sha": "a545dfa0c4e149595f7ddd50dc34c55513738fb9", + "url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins/commits/a545dfa0c4e149595f7ddd50dc34c55513738fb9", + "html_url": "https://github.com/zhenxun-org/zhenxun_bot_plugins/commit/a545dfa0c4e149595f7ddd50dc34c55513738fb9" + } + ], + "stats": { + "total": 4, + "additions": 2, + "deletions": 2 + }, + "files": [ + { + "sha": "0fbc9695db04c56174e3bff933f670d8d2df2abc", + "filename": "plugins/bilibili_sub/data_source.py", + "status": "modified", + "additions": 2, + "deletions": 2, + "changes": 4, + "blob_url": "https://github.com/zhenxun-org/zhenxun_bot_plugins/blob/b101fbce888608e2bbe5b5fd279e1465168812c7/plugins%2Fbilibili_sub%2Fdata_source.py", + "raw_url": "https://github.com/zhenxun-org/zhenxun_bot_plugins/raw/b101fbce888608e2bbe5b5fd279e1465168812c7/plugins%2Fbilibili_sub%2Fdata_source.py", + "contents_url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins/contents/plugins%2Fbilibili_sub%2Fdata_source.py?ref=b101fbce888608e2bbe5b5fd279e1465168812c7", + "patch": "@@ -271,14 +271,14 @@ async def _get_live_status(id_: int) -> list:\n sub = await BilibiliSub.get_or_none(sub_id=id_)\n msg_list = []\n if sub.live_status != live_status:\n+ await BilibiliSub.sub_handle(id_, live_status=live_status)\n image = None\n try:\n image_bytes = await fetch_image_bytes(cover)\n image = BuildImage(background = image_bytes)\n except Exception as e:\n logger.error(f\"图片构造失败,错误信息:{e}\")\n if sub.live_status in [0, 2] and live_status == 1 and image:\n- await BilibiliSub.sub_handle(id_, live_status=live_status)\n msg_list = [\n image,\n \"\\n\",\n@@ -322,7 +322,7 @@ async def _get_up_status(id_: int) -> list:\n video = video_info[\"list\"][\"vlist\"][0]\n latest_video_created = video[\"created\"]\n msg_list = []\n- if dynamic_img:\n+ if dynamic_img and _user.dynamic_upload_time < dynamic_upload_time:\n await BilibiliSub.sub_handle(id_, dynamic_upload_time=dynamic_upload_time)\n msg_list = [f\"{uname} 发布了动态!📢\\n\", dynamic_img, f\"\\n查看详情:{link}\"]\n if (" + } + ] +} \ No newline at end of file diff --git a/tests/response/plugin_store/zhenxun_bot_plugins_index_commit.json b/tests/response/plugin_store/zhenxun_bot_plugins_index_commit.json new file mode 100644 index 000000000..3ede7a3da --- /dev/null +++ b/tests/response/plugin_store/zhenxun_bot_plugins_index_commit.json @@ -0,0 +1,101 @@ +{ + "sha": "2ed61284873c526802752b12a3fd3b5e1a59d948", + "node_id": "C_kwDOGK5Du9oAKDJlZDYxMjg0ODczYzUyNjgwMjc1MmIxMmEzZmQzYjVlMWE1OWQ5NDg", + "commit": { + "author": { + "name": "zhenxunflow[bot]", + "email": "179375394+zhenxunflow[bot]@users.noreply.github.com", + "date": "2025-01-26T09:04:55Z" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com", + "date": "2025-01-26T09:04:55Z" + }, + "message": ":beers: publish plugin AI全家桶 (#235) (#236)\n\nCo-authored-by: molanp ", + "tree": { + "sha": "64ea463e084b6ab0def0322c6ad53799054ec9b3", + "url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins_index/git/trees/64ea463e084b6ab0def0322c6ad53799054ec9b3" + }, + "url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins_index/git/commits/2ed61284873c526802752b12a3fd3b5e1a59d948", + "comment_count": 0, + "verification": { + "verified": true, + "reason": "valid", + "signature": "-----BEGIN PGP SIGNATURE-----\n\nwsFcBAABCAAQBQJnlfq3CRC1aQ7uu5UhlAAA+n0QADPVjQQIHFlNcTEgdq3LGQ1X\nm8+H5N07E5JD+83LdyU9/YOvqY/WURwFsQ0T4+23icUWEOD4LB5qZIdVJBYHseto\nbJNmYd1kZxpvsONoiK/2Uk6JoeVnEQIR+dTbB0wBlbL0lRt1WtTXHpLQbFXuXn3q\nJh4SdSj283UZ6D2sBADblPZ7DqaTmLlpgwrTPx0OH5wIhcuORkzOl6x0DabcVAYu\nu5zHSKM9c7g+jEmrqRuVy+ZlZMDPN4S3gDNzEhoTn4tn+KNzSIja4n7ZMRD+1a5X\nMIP3aXcVBqCyuYc6DU76IvjlaL/MjnlPwfOtx1zu+pNxZKNaSpojtqopp3blfk0E\n8s8lD9utDgUaUrdPWgpiMDjj+oNMye91CGomNDfv0fNGUlBGT6r48qaq1z8BwAAR\nzgDsF13kDuKTTkT/6T8CdgCpJtwvxMptUr2XFRtn4xwf/gJdqrbEc4fHTOSHqxzh\ncDfXuP+Sorla4oJ0duygTsulpr/zguX8RJWJml35VjERw54ARAVvhZn19G9qQVJo\n2QIp+xtyTjkM3yTeN4UDXFt4lDuxz3+l1MBduj+CHn+WTgxyJUpX2TA1GVfni9xT\npOMOtzuDQfDIxTNB6hFjSWATb1/E5ys1lfK09n+dRhmvC/Be+b5M4WlyX3cqy/za\ns0XxuZ+CHzLfHaPxFUem\n=VYpl\n-----END PGP SIGNATURE-----\n", + "payload": "tree 64ea463e084b6ab0def0322c6ad53799054ec9b3\nparent 5df26081d40e3000a7beedb73954d4df397c93fa\nauthor zhenxunflow[bot] <179375394+zhenxunflow[bot]@users.noreply.github.com> 1737882295 +0800\ncommitter GitHub 1737882295 +0800\n\n:beers: publish plugin AI全家桶 (#235) (#236)\n\nCo-authored-by: molanp ", + "verified_at": "2025-01-26T09:04:58Z" + } + }, + "url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins_index/commits/2ed61284873c526802752b12a3fd3b5e1a59d948", + "html_url": "https://github.com/zhenxun-org/zhenxun_bot_plugins_index/commit/2ed61284873c526802752b12a3fd3b5e1a59d948", + "comments_url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins_index/commits/2ed61284873c526802752b12a3fd3b5e1a59d948/comments", + "author": { + "login": "zhenxunflow[bot]", + "id": 179375394, + "node_id": "BOT_kgDOCrENIg", + "avatar_url": "https://avatars.githubusercontent.com/in/978723?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/zhenxunflow%5Bbot%5D", + "html_url": "https://github.com/apps/zhenxunflow", + "followers_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/followers", + "following_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/following{/other_user}", + "gists_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/gists{/gist_id}", + "starred_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/subscriptions", + "organizations_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/orgs", + "repos_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/repos", + "events_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/events{/privacy}", + "received_events_url": "https://api.github.com/users/zhenxunflow%5Bbot%5D/received_events", + "type": "Bot", + "user_view_type": "public", + "site_admin": false + }, + "committer": { + "login": "web-flow", + "id": 19864447, + "node_id": "MDQ6VXNlcjE5ODY0NDQ3", + "avatar_url": "https://avatars.githubusercontent.com/u/19864447?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/web-flow", + "html_url": "https://github.com/web-flow", + "followers_url": "https://api.github.com/users/web-flow/followers", + "following_url": "https://api.github.com/users/web-flow/following{/other_user}", + "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", + "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", + "organizations_url": "https://api.github.com/users/web-flow/orgs", + "repos_url": "https://api.github.com/users/web-flow/repos", + "events_url": "https://api.github.com/users/web-flow/events{/privacy}", + "received_events_url": "https://api.github.com/users/web-flow/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "parents": [ + { + "sha": "5df26081d40e3000a7beedb73954d4df397c93fa", + "url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins_index/commits/5df26081d40e3000a7beedb73954d4df397c93fa", + "html_url": "https://github.com/zhenxun-org/zhenxun_bot_plugins_index/commit/5df26081d40e3000a7beedb73954d4df397c93fa" + } + ], + "stats": { + "total": 11, + "additions": 11, + "deletions": 0 + }, + "files": [ + { + "sha": "3d98392c25d38f5d375b830aed6e2298e47e5601", + "filename": "plugins.json", + "status": "modified", + "additions": 11, + "deletions": 0, + "changes": 11, + "blob_url": "https://github.com/zhenxun-org/zhenxun_bot_plugins_index/blob/2ed61284873c526802752b12a3fd3b5e1a59d948/plugins.json", + "raw_url": "https://github.com/zhenxun-org/zhenxun_bot_plugins_index/raw/2ed61284873c526802752b12a3fd3b5e1a59d948/plugins.json", + "contents_url": "https://api.github.com/repos/zhenxun-org/zhenxun_bot_plugins_index/contents/plugins.json?ref=2ed61284873c526802752b12a3fd3b5e1a59d948", + "patch": "@@ -53,5 +53,16 @@\n \"plugin_type\": \"NORMAL\",\n \"is_dir\": true,\n \"github_url\": \"https://github.com/PackageInstaller/zhenxun_plugin_draw_painting/tree/master\"\n+ },\n+ \"AI全家桶\": {\n+ \"module\": \"zhipu_toolkit\",\n+ \"module_path\": \"zhipu_toolkit\",\n+ \"description\": \"AI全家桶,一次安装,到处使用,省时省力省心\",\n+ \"usage\": \"AI全家桶,一次安装,到处使用,省时省力省心\\n usage:\\n 生成图片 \\n 生成视频 \\n 清理我的会话: 用于清理你与AI的聊天记录\\n 或者与机器人聊天,\\n 例如;\\n @Bot抱抱\\n 小真寻老婆\",\n+ \"author\": \"molanp\",\n+ \"version\": \"0.1\",\n+ \"plugin_type\": \"NORMAL\",\n+ \"is_dir\": true,\n+ \"github_url\": \"https://github.com/molanp/zhenxun_plugin_zhipu_toolkit\"\n }\n }" + } + ] + } \ No newline at end of file diff --git a/tests/response/plugin_store/zhenxun_github_sub_commit.json b/tests/response/plugin_store/zhenxun_github_sub_commit.json new file mode 100644 index 000000000..582d7890b --- /dev/null +++ b/tests/response/plugin_store/zhenxun_github_sub_commit.json @@ -0,0 +1,101 @@ +{ + "sha": "f524632f78d27f9893beebdf709e0e7885cd08f1", + "node_id": "C_kwDOJAjBPdoAKGY1MjQ2MzJmNzhkMjdmOTg5M2JlZWJkZjcwOWUwZTc4ODVjZDA4ZjE", + "commit": { + "author": { + "name": "xuaner", + "email": "xuaner_wa@qq.com", + "date": "2024-11-18T18:17:15Z" + }, + "committer": { + "name": "xuaner", + "email": "xuaner_wa@qq.com", + "date": "2024-11-18T18:17:15Z" + }, + "message": "fix bug", + "tree": { + "sha": "b6b1b4f06cc869b9f38d7b51bdca3a2c575255e4", + "url": "https://api.github.com/repos/xuanerwa/zhenxun_github_sub/git/trees/b6b1b4f06cc869b9f38d7b51bdca3a2c575255e4" + }, + "url": "https://api.github.com/repos/xuanerwa/zhenxun_github_sub/git/commits/f524632f78d27f9893beebdf709e0e7885cd08f1", + "comment_count": 0, + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null, + "verified_at": null + } + }, + "url": "https://api.github.com/repos/xuanerwa/zhenxun_github_sub/commits/f524632f78d27f9893beebdf709e0e7885cd08f1", + "html_url": "https://github.com/xuanerwa/zhenxun_github_sub/commit/f524632f78d27f9893beebdf709e0e7885cd08f1", + "comments_url": "https://api.github.com/repos/xuanerwa/zhenxun_github_sub/commits/f524632f78d27f9893beebdf709e0e7885cd08f1/comments", + "author": { + "login": "xuanerwa", + "id": 58063798, + "node_id": "MDQ6VXNlcjU4MDYzNzk4", + "avatar_url": "https://avatars.githubusercontent.com/u/58063798?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/xuanerwa", + "html_url": "https://github.com/xuanerwa", + "followers_url": "https://api.github.com/users/xuanerwa/followers", + "following_url": "https://api.github.com/users/xuanerwa/following{/other_user}", + "gists_url": "https://api.github.com/users/xuanerwa/gists{/gist_id}", + "starred_url": "https://api.github.com/users/xuanerwa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/xuanerwa/subscriptions", + "organizations_url": "https://api.github.com/users/xuanerwa/orgs", + "repos_url": "https://api.github.com/users/xuanerwa/repos", + "events_url": "https://api.github.com/users/xuanerwa/events{/privacy}", + "received_events_url": "https://api.github.com/users/xuanerwa/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "committer": { + "login": "xuanerwa", + "id": 58063798, + "node_id": "MDQ6VXNlcjU4MDYzNzk4", + "avatar_url": "https://avatars.githubusercontent.com/u/58063798?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/xuanerwa", + "html_url": "https://github.com/xuanerwa", + "followers_url": "https://api.github.com/users/xuanerwa/followers", + "following_url": "https://api.github.com/users/xuanerwa/following{/other_user}", + "gists_url": "https://api.github.com/users/xuanerwa/gists{/gist_id}", + "starred_url": "https://api.github.com/users/xuanerwa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/xuanerwa/subscriptions", + "organizations_url": "https://api.github.com/users/xuanerwa/orgs", + "repos_url": "https://api.github.com/users/xuanerwa/repos", + "events_url": "https://api.github.com/users/xuanerwa/events{/privacy}", + "received_events_url": "https://api.github.com/users/xuanerwa/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + }, + "parents": [ + { + "sha": "91e5e2c792e79193830441d555769aa54acd2d15", + "url": "https://api.github.com/repos/xuanerwa/zhenxun_github_sub/commits/91e5e2c792e79193830441d555769aa54acd2d15", + "html_url": "https://github.com/xuanerwa/zhenxun_github_sub/commit/91e5e2c792e79193830441d555769aa54acd2d15" + } + ], + "stats": { + "total": 2, + "additions": 1, + "deletions": 1 + }, + "files": [ + { + "sha": "764a5f7b81554c4c10d29486ea5d9105e505cec3", + "filename": "github_sub/__init__.py", + "status": "modified", + "additions": 1, + "deletions": 1, + "changes": 2, + "blob_url": "https://github.com/xuanerwa/zhenxun_github_sub/blob/f524632f78d27f9893beebdf709e0e7885cd08f1/github_sub%2F__init__.py", + "raw_url": "https://github.com/xuanerwa/zhenxun_github_sub/raw/f524632f78d27f9893beebdf709e0e7885cd08f1/github_sub%2F__init__.py", + "contents_url": "https://api.github.com/repos/xuanerwa/zhenxun_github_sub/contents/github_sub%2F__init__.py?ref=f524632f78d27f9893beebdf709e0e7885cd08f1", + "patch": "@@ -168,7 +168,7 @@ async def _(session: EventSession):\n # 推送\n @scheduler.scheduled_job(\n \"interval\",\n- seconds=base_config.get(\"CHECK_API_TIME\") if base_config.get(\"CHECK_TIME\") else 30,\n+ seconds=base_config.get(\"CHECK_API_TIME\") if base_config.get(\"CHECK_API_TIME\") else 30,\n )\n async def _():\n bots = nonebot.get_bots()" + } + ] + } \ No newline at end of file diff --git a/zhenxun/builtin_plugins/plugin_store/data_source.py b/zhenxun/builtin_plugins/plugin_store/data_source.py index 39c7d2636..6e662a815 100644 --- a/zhenxun/builtin_plugins/plugin_store/data_source.py +++ b/zhenxun/builtin_plugins/plugin_store/data_source.py @@ -80,12 +80,17 @@ async def get_data(cls) -> dict[str, StorePluginInfo]: 返回: dict: 插件信息数据 """ - default_github_url = await GithubUtils.parse_github_url( - DEFAULT_GITHUB_URL - ).get_raw_download_urls("plugins.json") - extra_github_url = await GithubUtils.parse_github_url( - EXTRA_GITHUB_URL - ).get_raw_download_urls("plugins.json") + default_github_repo = GithubUtils.parse_github_url(DEFAULT_GITHUB_URL) + extra_github_repo = GithubUtils.parse_github_url(EXTRA_GITHUB_URL) + for repo_info in [default_github_repo, extra_github_repo]: + if await repo_info.update_repo_commit(): + logger.info(f"获取最新提交: {repo_info.branch}", "插件管理") + else: + logger.warning(f"获取最新提交失败: {repo_info}", "插件管理") + default_github_url = await default_github_repo.get_raw_download_urls( + "plugins.json" + ) + extra_github_url = await extra_github_repo.get_raw_download_urls("plugins.json") res = await AsyncHttpx.get(default_github_url) res2 = await AsyncHttpx.get(extra_github_url) @@ -218,6 +223,10 @@ async def install_plugin_with_repo( files: list[str] repo_api: RepoAPI repo_info = GithubUtils.parse_github_url(github_url) + if await repo_info.update_repo_commit(): + logger.info(f"获取最新提交: {repo_info.branch}", "插件管理") + else: + logger.warning(f"获取最新提交失败: {repo_info}", "插件管理") logger.debug(f"成功获取仓库信息: {repo_info}", "插件管理") for repo_api in GithubUtils.iter_api_strategies(): try: diff --git a/zhenxun/utils/github_utils/const.py b/zhenxun/utils/github_utils/const.py index 13b013bea..23effa4cd 100644 --- a/zhenxun/utils/github_utils/const.py +++ b/zhenxun/utils/github_utils/const.py @@ -33,3 +33,11 @@ "https://codeload.github.com/{owner}/{repo}/legacy.{compress}/refs/tags/{version}" ) """release 源码格式""" + +GIT_API_COMMIT_FORMAT = "https://api.github.com/repos/{owner}/{repo}/commits/{branch}" +"""git api commit地址格式""" + +GIT_API_PROXY_COMMIT_FORMAT = ( + "https://git-api.zhenxun.org/repos/{owner}/{repo}/commits/{branch}" +) +"""git api commit地址格式 (代理)""" diff --git a/zhenxun/utils/github_utils/models.py b/zhenxun/utils/github_utils/models.py index d21c23873..e3e5dfe36 100644 --- a/zhenxun/utils/github_utils/models.py +++ b/zhenxun/utils/github_utils/models.py @@ -1,3 +1,4 @@ +import contextlib from typing import Protocol from aiocache import cached @@ -7,7 +8,13 @@ from zhenxun.utils.http_utils import AsyncHttpx -from .const import CACHED_API_TTL, GIT_API_TREES_FORMAT, JSD_PACKAGE_API_FORMAT +from .const import ( + CACHED_API_TTL, + GIT_API_COMMIT_FORMAT, + GIT_API_PROXY_COMMIT_FORMAT, + GIT_API_TREES_FORMAT, + JSD_PACKAGE_API_FORMAT, +) from .func import ( get_fastest_archive_formats, get_fastest_raw_formats, @@ -58,9 +65,29 @@ async def get_release_source_download_urls_zip(self, version: str) -> list[str]: for url_format in url_formats ] + async def update_repo_commit(self): + with contextlib.suppress(Exception): + newest_commit = await self.get_newest_commit( + self.owner, self.repo, self.branch + ) + if newest_commit: + self.branch = newest_commit + return True + return False + def to_dict(self, **kwargs): return model_dump(self, **kwargs) + @classmethod + @cached(ttl=CACHED_API_TTL) + async def get_newest_commit(cls, owner: str, repo: str, branch: str) -> str: + commit_url = GIT_API_COMMIT_FORMAT.format(owner=owner, repo=repo, branch=branch) + commit_url_proxy = GIT_API_PROXY_COMMIT_FORMAT.format( + owner=owner, repo=repo, branch=branch + ) + resp = await AsyncHttpx().get([commit_url, commit_url_proxy]) + return "" if resp.status_code != 200 else resp.json()["sha"] + class APIStrategy(Protocol): """API策略"""