feat: support seeyon sec notice and update ci config

This commit is contained in:
fan-tastic-z
2025-09-26 22:36:14 +08:00
committed by GitHub
parent 0a66f00e57
commit 61bc8d795c
7 changed files with 455 additions and 143 deletions

View File

@@ -39,3 +39,24 @@ jobs:
run: cargo clippy --all-targets --all-features --tests --benches -- -D warnings run: cargo clippy --all-targets --all-features --tests --benches -- -D warnings
- name: Execute rust tests - name: Execute rust tests
run: cargo nextest run --all-features run: cargo nextest run --all-features
build-image:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push image
uses: docker/build-push-action@v4
with:
context: .
push: true
platforms: linux/amd64
tags: ${{ vars.LATEST_IMAGE }}

274
Cargo.lock generated
View File

@@ -43,12 +43,6 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]] [[package]]
name = "android_system_properties" name = "android_system_properties"
version = "0.1.5" version = "0.1.5"
@@ -110,9 +104,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.99" version = "1.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
[[package]] [[package]]
name = "arbitrary" name = "arbitrary"
@@ -300,17 +294,16 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.41" version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
dependencies = [ dependencies = [
"android-tzdata",
"iana-time-zone", "iana-time-zone",
"js-sys", "js-sys",
"num-traits", "num-traits",
"serde", "serde",
"wasm-bindgen", "wasm-bindgen",
"windows-link", "windows-link 0.2.0",
] ]
[[package]] [[package]]
@@ -347,9 +340,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.47" version = "4.5.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@@ -357,9 +350,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.47" version = "4.5.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@@ -596,12 +589,13 @@ dependencies = [
[[package]] [[package]]
name = "ctrlc" name = "ctrlc"
version = "3.4.7" version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73" checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3"
dependencies = [ dependencies = [
"dispatch",
"nix", "nix",
"windows-sys 0.59.0", "windows-sys 0.61.1",
] ]
[[package]] [[package]]
@@ -671,9 +665,9 @@ dependencies = [
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.4.0" version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071"
dependencies = [ dependencies = [
"powerfmt", "powerfmt",
] ]
@@ -727,6 +721,12 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "dispatch"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]] [[package]]
name = "displaydoc" name = "displaydoc"
version = "0.2.5" version = "0.2.5"
@@ -807,11 +807,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]] [[package]]
name = "erased-serde" name = "erased-serde"
version = "0.4.6" version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b"
dependencies = [ dependencies = [
"serde", "serde",
"serde_core",
"typeid", "typeid",
] ]
@@ -1108,9 +1109,9 @@ dependencies = [
[[package]] [[package]]
name = "getopts" name = "getopts"
version = "0.2.23" version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1" checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"
dependencies = [ dependencies = [
"unicode-width", "unicode-width",
] ]
@@ -1596,13 +1597,14 @@ dependencies = [
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.6.0" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
dependencies = [ dependencies = [
"atomic-waker",
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-util", "futures-core",
"h2", "h2",
"http", "http",
"http-body", "http-body",
@@ -1610,6 +1612,7 @@ dependencies = [
"httpdate", "httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"pin-utils",
"smallvec", "smallvec",
"tokio", "tokio",
"want", "want",
@@ -1664,9 +1667,9 @@ dependencies = [
[[package]] [[package]]
name = "hyper-util" name = "hyper-util"
version = "0.1.16" version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
dependencies = [ dependencies = [
"base64", "base64",
"bytes", "bytes",
@@ -1690,9 +1693,9 @@ dependencies = [
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.63" version = "0.1.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
dependencies = [ dependencies = [
"android_system_properties", "android_system_properties",
"core-foundation-sys", "core-foundation-sys",
@@ -1853,9 +1856,9 @@ dependencies = [
[[package]] [[package]]
name = "inherent" name = "inherent"
version = "1.0.12" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c38228f24186d9cc68c729accb4d413be9eaed6ad07ff79e0270d9e56f3de13" checksum = "c727f80bfa4a6c6e2508d2f05b6f4bfce242030bd88ed15ae5331c5b5d30fba7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -1959,9 +1962,9 @@ dependencies = [
[[package]] [[package]]
name = "jobserver" name = "jobserver"
version = "0.1.33" version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [ dependencies = [
"getrandom 0.3.3", "getrandom 0.3.3",
"libc", "libc",
@@ -2054,9 +2057,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]] [[package]]
name = "libredox" name = "libredox"
version = "0.1.9" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"libc", "libc",
@@ -2220,9 +2223,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]] [[package]]
name = "memmap2" name = "memmap2"
version = "0.9.7" version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@@ -2645,9 +2648,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]] [[package]]
name = "pest" name = "pest"
version = "2.8.1" version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8"
dependencies = [ dependencies = [
"memchr", "memchr",
"thiserror", "thiserror",
@@ -2656,9 +2659,9 @@ dependencies = [
[[package]] [[package]]
name = "pest_derive" name = "pest_derive"
version = "2.8.1" version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663"
dependencies = [ dependencies = [
"pest", "pest",
"pest_generator", "pest_generator",
@@ -2666,9 +2669,9 @@ dependencies = [
[[package]] [[package]]
name = "pest_generator" name = "pest_generator"
version = "2.8.1" version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f"
dependencies = [ dependencies = [
"pest", "pest",
"pest_meta", "pest_meta",
@@ -2679,9 +2682,9 @@ dependencies = [
[[package]] [[package]]
name = "pest_meta" name = "pest_meta"
version = "2.8.1" version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420"
dependencies = [ dependencies = [
"pest", "pest",
"sha2", "sha2",
@@ -2900,11 +2903,11 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
version = "3.3.0" version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
dependencies = [ dependencies = [
"toml_edit 0.22.27", "toml_edit",
] ]
[[package]] [[package]]
@@ -3032,9 +3035,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.2" version = "1.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@@ -3044,9 +3047,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.4.9" version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@@ -3055,9 +3058,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.5" version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
@@ -3239,9 +3242,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.23.31" version = "0.23.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40"
dependencies = [ dependencies = [
"log", "log",
"once_cell", "once_cell",
@@ -3261,7 +3264,7 @@ dependencies = [
"openssl-probe", "openssl-probe",
"rustls-pki-types", "rustls-pki-types",
"schannel", "schannel",
"security-framework 3.3.0", "security-framework 3.5.0",
] ]
[[package]] [[package]]
@@ -3275,9 +3278,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.103.4" version = "0.103.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb"
dependencies = [ dependencies = [
"ring", "ring",
"rustls-pki-types", "rustls-pki-types",
@@ -3442,9 +3445,9 @@ dependencies = [
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "3.3.0" version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" checksum = "cc198e42d9b7510827939c9a15f5062a0c913f3371d765977e586d2fe6c16f4a"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"core-foundation 0.10.1", "core-foundation 0.10.1",
@@ -3455,9 +3458,9 @@ dependencies = [
[[package]] [[package]]
name = "security-framework-sys" name = "security-framework-sys"
version = "2.14.0" version = "2.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"
dependencies = [ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
@@ -3484,9 +3487,9 @@ dependencies = [
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.26" version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
[[package]] [[package]]
name = "serde" name = "serde"
@@ -3542,12 +3545,13 @@ dependencies = [
[[package]] [[package]]
name = "serde_path_to_error" name = "serde_path_to_error"
version = "0.1.17" version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
dependencies = [ dependencies = [
"itoa", "itoa",
"serde", "serde",
"serde_core",
] ]
[[package]] [[package]]
@@ -3707,18 +3711,18 @@ dependencies = [
[[package]] [[package]]
name = "snafu" name = "snafu"
version = "0.8.7" version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0062a372b26c4a6e9155d099a3416d732514fd47ae2f235b3695b820afcee74a" checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2"
dependencies = [ dependencies = [
"snafu-derive", "snafu-derive",
] ]
[[package]] [[package]]
name = "snafu-derive" name = "snafu-derive"
version = "0.8.7" version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e5fd9e3263fc19d73abd5107dbd4d43e37949212d2b15d4d334ee5db53022b8" checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451"
dependencies = [ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
@@ -4218,9 +4222,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.41" version = "0.3.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
dependencies = [ dependencies = [
"deranged", "deranged",
"itoa", "itoa",
@@ -4235,15 +4239,15 @@ dependencies = [
[[package]] [[package]]
name = "time-core" name = "time-core"
version = "0.1.4" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.22" version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
dependencies = [ dependencies = [
"num-conv", "num-conv",
"time-core", "time-core",
@@ -4261,9 +4265,9 @@ dependencies = [
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
dependencies = [ dependencies = [
"tinyvec_macros", "tinyvec_macros",
] ]
@@ -4331,9 +4335,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.26.2" version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd"
dependencies = [ dependencies = [
"rustls", "rustls",
"tokio", "tokio",
@@ -4363,12 +4367,6 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "0.7.2" version = "0.7.2"
@@ -4378,17 +4376,6 @@ dependencies = [
"serde_core", "serde_core",
] ]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"toml_datetime 0.6.11",
"winnow",
]
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.23.6" version = "0.23.6"
@@ -4398,7 +4385,7 @@ dependencies = [
"indexmap", "indexmap",
"serde_core", "serde_core",
"serde_spanned", "serde_spanned",
"toml_datetime 0.7.2", "toml_datetime",
"toml_parser", "toml_parser",
"toml_writer", "toml_writer",
"winnow", "winnow",
@@ -4807,7 +4794,7 @@ dependencies = [
"thiserror", "thiserror",
"tokio", "tokio",
"tokio-cron-scheduler", "tokio-cron-scheduler",
"toml_edit 0.23.6", "toml_edit",
"uuid", "uuid",
"zip", "zip",
] ]
@@ -4968,37 +4955,37 @@ dependencies = [
[[package]] [[package]]
name = "wildmatch" name = "wildmatch"
version = "2.4.0" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68ce1ab1f8c62655ebe1350f589c61e505cf94d385bc6a12899442d9081e71fd" checksum = "39b7d07a236abaef6607536ccfaf19b396dbe3f5110ddb73d39f4562902ed382"
[[package]] [[package]]
name = "winapi-util" name = "winapi-util"
version = "0.1.9" version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.60.2",
] ]
[[package]] [[package]]
name = "windows-core" name = "windows-core"
version = "0.61.2" version = "0.62.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9"
dependencies = [ dependencies = [
"windows-implement", "windows-implement",
"windows-interface", "windows-interface",
"windows-link", "windows-link 0.2.0",
"windows-result", "windows-result 0.4.0",
"windows-strings", "windows-strings 0.5.0",
] ]
[[package]] [[package]]
name = "windows-implement" name = "windows-implement"
version = "0.60.0" version = "0.60.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -5007,9 +4994,9 @@ dependencies = [
[[package]] [[package]]
name = "windows-interface" name = "windows-interface"
version = "0.59.1" version = "0.59.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -5022,15 +5009,21 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-link"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]] [[package]]
name = "windows-registry" name = "windows-registry"
version = "0.5.3" version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
dependencies = [ dependencies = [
"windows-link", "windows-link 0.1.3",
"windows-result", "windows-result 0.3.4",
"windows-strings", "windows-strings 0.4.2",
] ]
[[package]] [[package]]
@@ -5039,7 +5032,16 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [ dependencies = [
"windows-link", "windows-link 0.1.3",
]
[[package]]
name = "windows-result"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
dependencies = [
"windows-link 0.2.0",
] ]
[[package]] [[package]]
@@ -5048,7 +5050,16 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [ dependencies = [
"windows-link", "windows-link 0.1.3",
]
[[package]]
name = "windows-strings"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
dependencies = [
"windows-link 0.2.0",
] ]
[[package]] [[package]]
@@ -5087,6 +5098,15 @@ dependencies = [
"windows-targets 0.53.3", "windows-targets 0.53.3",
] ]
[[package]]
name = "windows-sys"
version = "0.61.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
dependencies = [
"windows-link 0.2.0",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.48.5" version = "0.48.5"
@@ -5124,7 +5144,7 @@ version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [ dependencies = [
"windows-link", "windows-link 0.1.3",
"windows_aarch64_gnullvm 0.53.0", "windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0", "windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0", "windows_i686_gnu 0.53.0",
@@ -5323,18 +5343,18 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.8.26" version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.8.26" version = "0.8.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@@ -17,12 +17,13 @@ VulnFeed 是一个用于收集和推送高价值漏洞和补丁公告信息的
当抓取安全补丁公告的站点数据: 当抓取安全补丁公告的站点数据:
| 名称 | 地址 | 推送策略 | | 名称 | 地址 | 推送策略 |
| --------------------- | ----------------------------------------------------------- | -------------------------------------------------- | | --------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| 用友安全中心 | <https://security.yonyou.com/#/home> | 近三条数据 | | 用友安全中心 | <https://security.yonyou.com/#/home> | 近三条数据 |
| 泛微ECOLOGY安全补丁包 | <https://www.weaver.com.cn/cs/securityDownload.html?src=cn> | "EC9.0全量补丁", "EC8.0全量补丁", "EC10.0安全补丁" | | 泛微ECOLOGY安全补丁包 | <https://www.weaver.com.cn/cs/securityDownload.html?src=cn> | "EC9.0全量补丁", "EC8.0全量补丁", "EC10.0安全补丁" |
| Smartbi安全补丁包 | <https://www.smartbi.com.cn/patchinfo> | 近三条数据 | | Smartbi安全补丁包 | <https://www.smartbi.com.cn/patchinfo> | 近三条数据 |
| 帆软安全漏洞声明 | <https://help.fanruan.com/finereport/doc-view-4833.html> | 近三条数据 | | 帆软安全漏洞声明 | <https://help.fanruan.com/finereport/doc-view-4833.html> | 近三条数据 |
| 致远安全补丁 | <https://service.seeyon.com/patchtools/tp.html#/patchList?type=%E5%AE%89%E5%85%A8%E8%A1%A5%E4%B8%81> | V5的近三条数据 |
![app](./images/app.jpg) ![app](./images/app.jpg)

View File

@@ -220,13 +220,7 @@ const SecNoticeListPage = () => {
<path fillRule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clipRule="evenodd" /> <path fillRule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clipRule="evenodd" />
</svg> </svg>
<p> <p>
发布时间: <time dateTime={notice.publish_time}>{new Date(notice.publish_time).toLocaleString('zh-CN', { 发布时间: <time dateTime={notice.publish_time}>{notice.publish_time}</time>
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
})}</time>
</p> </p>
<span className={`ml-4 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${ <span className={`ml-4 inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
notice.pushed ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800' notice.pushed ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800'

View File

@@ -23,7 +23,7 @@ services:
privileged: true privileged: true
vulnfeed: vulnfeed:
image: vulnfeed:latest image: fantasticzf/vulnfeed:latest
restart: always restart: always
depends_on: depends_on:
- postgres - postgres

View File

@@ -1,4 +1,5 @@
pub mod fanruan; pub mod fanruan;
pub mod seeyon;
pub mod smartbi; pub mod smartbi;
pub mod weaver; pub mod weaver;
pub mod yongyou; pub mod yongyou;
@@ -14,8 +15,8 @@ use crate::{
AppResult, AppResult,
domain::models::security_notice::CreateSecurityNotice, domain::models::security_notice::CreateSecurityNotice,
output::plugins::sec_notice::{ output::plugins::sec_notice::{
fanruan::FanRuanNoticePlugin, smartbi::SmartbiNoticePlugin, weaver::WeaverNoticePlugin, fanruan::FanRuanNoticePlugin, seeyon::SeeyonNoticePlugin, smartbi::SmartbiNoticePlugin,
yongyou::YongYouNoticePlugin, weaver::WeaverNoticePlugin, yongyou::YongYouNoticePlugin,
}, },
}; };
@@ -28,6 +29,7 @@ pub fn init(sender: UnboundedSender<CreateSecurityNotice>) -> AppResult<()> {
WeaverNoticePlugin::try_new(sender.clone())?; WeaverNoticePlugin::try_new(sender.clone())?;
SmartbiNoticePlugin::try_new(sender.clone())?; SmartbiNoticePlugin::try_new(sender.clone())?;
FanRuanNoticePlugin::try_new(sender.clone())?; FanRuanNoticePlugin::try_new(sender.clone())?;
SeeyonNoticePlugin::try_new(sender.clone())?;
Ok(()) Ok(())
} }

View File

@@ -0,0 +1,274 @@
use async_trait::async_trait;
use error_stack::ResultExt;
use mea::mpsc::UnboundedSender;
use serde::{Deserialize, Serialize};
use crate::{
AppResult,
domain::models::security_notice::{CreateSecurityNotice, RiskLevel},
errors::Error,
output::plugins::sec_notice::{SecNoticePlugin, register_sec_notice},
utils::http_client::HttpClient,
};
const SEEOYN_NOTICE_URL: &str = "https://service.seeyon.com/server2/rest/security/getCategory";
const SEEOYN_DETAIL_URL: &str =
"https://service.seeyon.com/server2/rest/security/getCategoryDetail";
#[derive(Debug, Clone)]
pub struct SeeyonNoticePlugin {
name: String,
display_name: String,
link: String,
http_client: HttpClient,
sender: UnboundedSender<CreateSecurityNotice>,
}
#[async_trait]
impl SecNoticePlugin for SeeyonNoticePlugin {
fn get_name(&self) -> String {
self.name.to_string()
}
fn get_display_name(&self) -> String {
self.display_name.to_string()
}
fn get_link(&self) -> String {
self.link.to_string()
}
async fn update(&self, _page_limit: i32) -> AppResult<()> {
let notices = self.parse_security_notices().await?;
for notice in notices {
let title = notice.title.clone();
let detail_response = self.get_detail_data(notice.id).await?;
let (patch_number, patch_time) = self.extract_patch_info(&detail_response.content);
let detail_link = format!("{}?id={}", SEEOYN_DETAIL_URL, notice.id);
match (patch_number, patch_time) {
(Some(patch_number), Some(patch_time)) => {
let create_security_notice = CreateSecurityNotice {
key: patch_number,
title,
product_name: "致远OA".to_string(),
risk_level: RiskLevel::High.to_string(),
source: self.link.clone(),
source_name: self.get_name(),
is_zero_day: false,
detail_link,
publish_time: patch_time,
pushed: false,
};
self.sender.send(create_security_notice).map_err(|e| {
Error::Message(format!("Failed to send security notice to queue: {}", e))
})?;
}
(_, _) => {
log::error!(
"Failed to extract patch info for notice id: {} title: {}",
notice.id,
notice.title
);
continue;
}
}
}
Ok(())
}
}
impl SeeyonNoticePlugin {
pub fn try_new(sender: UnboundedSender<CreateSecurityNotice>) -> AppResult<SeeyonNoticePlugin> {
let http_client = HttpClient::try_new()?;
let seeyon = SeeyonNoticePlugin {
name: "SeeyonPlugin".to_string(),
display_name: "致远OA安全公告".to_string(),
link: "https://service.seeyon.com".to_string(),
http_client,
sender,
};
register_sec_notice(seeyon.name.clone(), Box::new(seeyon.clone()));
Ok(seeyon)
}
async fn get_category_data(&self) -> AppResult<SeeyonCategoryResponse> {
let response = self
.http_client
.get_json(SEEOYN_NOTICE_URL)
.await
.change_context_lazy(|| {
Error::Message("Failed to fetch Seeyon category data".to_string())
})?;
let category_data: SeeyonCategoryResponse =
response.json().await.change_context_lazy(|| {
Error::Message("Failed to parse Seeyon category data".to_string())
})?;
Ok(category_data)
}
pub async fn get_detail_data(&self, id: i32) -> AppResult<SeeyonDetailResponse> {
let url = format!("{}?id={}", SEEOYN_DETAIL_URL, id);
let response = self
.http_client
.get_json(&url)
.await
.change_context_lazy(|| {
Error::Message(format!("Failed to fetch Seeyon detail data for id: {}", id))
})?;
let detail_data: SeeyonDetailResponse =
response.json().await.change_context_lazy(|| {
Error::Message(format!("Failed to parse Seeyon detail data for id: {}", id))
})?;
Ok(detail_data)
}
async fn parse_security_notices(&self) -> AppResult<Vec<SeeyonSecurityNotice>> {
let category_data = self.get_category_data().await?;
let v5_id = category_data
.iter()
.find(|item| item.classification == "V5")
.map(|item| item.id)
.ok_or_else(|| Error::Message("V5 classification not found".to_string()))?;
// Find items with pid equal to V5 id
let mut notices: Vec<SeeyonSecurityNotice> = Vec::new();
// 获取前3个ID最大的项目
let mut filtered_items: Vec<_> = category_data
.iter()
.filter(|item| item.pid == v5_id)
.collect();
filtered_items.sort_by(|a, b| b.id.cmp(&a.id));
filtered_items.truncate(3);
// 为每个项目获取详细信息
for item in filtered_items {
let mut notice = SeeyonSecurityNotice {
id: item.id,
title: item.classification.clone(),
patch_number: None,
publish_time: None,
};
// 获取详细信息
match self.get_detail_data(item.id).await {
Ok(detail) => {
notice.title = detail.title;
// 从HTML内容中提取补丁编号和发布时间
let (patch_number, publish_time) = self.extract_patch_info(&detail.content);
notice.patch_number = patch_number;
notice.publish_time = publish_time;
}
Err(e) => {
eprintln!("Failed to get detail data for id {}: {:?}", item.id, e);
}
}
notices.push(notice);
}
Ok(notices)
}
pub fn extract_patch_info(&self, content: &str) -> (Option<String>, Option<String>) {
let mut patch_number = None;
let mut publish_time = None;
let document = scraper::Html::parse_document(content);
// CSS选择器查找包含"补丁编号"文本的td元素然后获取下一个兄弟元素的文本内容
let patch_selector = scraper::Selector::parse("td").unwrap();
let elements: Vec<_> = document.select(&patch_selector).collect();
for (i, element) in elements.iter().enumerate() {
if let Some(text) = element.text().next()
&& text.contains("补丁编号")
&& i + 1 < elements.len()
{
// 获取下一个td元素作为补丁编号
patch_number = Some(
elements[i + 1]
.text()
.collect::<String>()
.trim()
.to_string(),
);
break;
}
}
// CSS选择器查找包含"发布时间"文本的td元素然后获取下一个兄弟元素的文本内容
for (i, element) in elements.iter().enumerate() {
if let Some(text) = element.text().next()
&& text.contains("发布时间")
&& i + 1 < elements.len()
{
// 获取下一个td元素作为发布时间
publish_time = Some(
elements[i + 1]
.text()
.collect::<String>()
.trim()
.to_string(),
);
break;
}
}
(patch_number, publish_time)
}
}
pub type SeeyonCategoryResponse = Vec<SeeyonCategoryItem>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SeeyonCategoryItem {
pub id: i32,
pub pid: i32,
pub classification: String,
pub sort: i32,
pub url: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SeeyonSecurityNotice {
pub id: i32,
pub title: String,
pub patch_number: Option<String>,
pub publish_time: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SeeyonDetailResponse {
pub id: i32,
pub title: String,
pub content: String,
#[serde(rename = "createTime")]
pub create_time: Option<i64>,
pub author: String,
#[serde(rename = "categoryId")]
pub category_id: i32,
#[serde(rename = "categoryName")]
pub category_name: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
use mea::mpsc::unbounded;
#[tokio::test]
pub async fn test_extract_patch_info() {
let (sender, _receiver) = unbounded::<CreateSecurityNotice>();
let plugin = SeeyonNoticePlugin::try_new(sender).unwrap();
let detail_data = plugin.get_detail_data(180).await.unwrap();
let content = &detail_data.content;
let (patch_number, publish_time) = plugin.extract_patch_info(content);
assert_eq!(patch_number, Some("250300-S006".to_string()));
assert_eq!(publish_time, Some("2025年3月".to_string()));
}
}