fix: Quanben and Add Filters (#1877)

* fix quanben +added filters

* remove https://69shu.biz
This commit is contained in:
Mousica
2025-11-13 14:00:23 +02:00
committed by GitHub
parent 820b8b3bcd
commit e2d53b7832
5 changed files with 413 additions and 784 deletions
+6 -38
View File
@@ -283,7 +283,6 @@
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.5.tgz", "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.5.tgz",
"integrity": "sha512-6zeCUxUH+EPF1s+YF/2hPVODeV/7V07YU5x+2tfuRL8MdW6rv5vb2+CBEGTGwBdux0OIERcOS+RzxeK80k2DsQ==", "integrity": "sha512-6zeCUxUH+EPF1s+YF/2hPVODeV/7V07YU5x+2tfuRL8MdW6rv5vb2+CBEGTGwBdux0OIERcOS+RzxeK80k2DsQ==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5", "@emotion/babel-plugin": "^11.13.5",
@@ -327,7 +326,6 @@
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.5.tgz", "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.5.tgz",
"integrity": "sha512-gnOQ+nGLPvDXgIx119JqGalys64lhMdnNQA9TMxhDA4K0Hq5+++OE20Zs5GxiCV9r814xQ2K5WmtofSpHVW6BQ==", "integrity": "sha512-gnOQ+nGLPvDXgIx119JqGalys64lhMdnNQA9TMxhDA4K0Hq5+++OE20Zs5GxiCV9r814xQ2K5WmtofSpHVW6BQ==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5", "@emotion/babel-plugin": "^11.13.5",
@@ -1069,7 +1067,6 @@
"resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.9.tgz", "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.9.tgz",
"integrity": "sha512-NwqIN0bdsgzSbZd5JFcC+2ez0XW/XNs8uiV2PDHrqQ4qf/FEasFJG1z6g8JbCN0YlTrHZekVb17X0Fv0qcYJfQ==", "integrity": "sha512-NwqIN0bdsgzSbZd5JFcC+2ez0XW/XNs8uiV2PDHrqQ4qf/FEasFJG1z6g8JbCN0YlTrHZekVb17X0Fv0qcYJfQ==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@babel/runtime": "^7.26.0", "@babel/runtime": "^7.26.0",
"@mui/core-downloads-tracker": "^6.1.9", "@mui/core-downloads-tracker": "^6.1.9",
@@ -3005,7 +3002,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.66.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.66.tgz",
"integrity": "sha512-OYTmMI4UigXeFMF/j4uv0lBBEbongSgptPrHBxqME44h9+yNov+oL6Z3ocJKo0WyXR84sQUNeyIp9MRfckvZpg==", "integrity": "sha512-OYTmMI4UigXeFMF/j4uv0lBBEbongSgptPrHBxqME44h9+yNov+oL6Z3ocJKo0WyXR84sQUNeyIp9MRfckvZpg==",
"devOptional": true, "devOptional": true,
"peer": true,
"dependencies": { "dependencies": {
"@types/prop-types": "*", "@types/prop-types": "*",
"@types/scheduler": "*", "@types/scheduler": "*",
@@ -3017,7 +3013,6 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz",
"integrity": "sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==", "integrity": "sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==",
"devOptional": true, "devOptional": true,
"peer": true,
"dependencies": { "dependencies": {
"@types/react": "*" "@types/react": "*"
} }
@@ -3090,7 +3085,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz",
"integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "7.14.1", "@typescript-eslint/scope-manager": "7.14.1",
"@typescript-eslint/types": "7.14.1", "@typescript-eslint/types": "7.14.1",
@@ -3306,7 +3300,6 @@
"version": "8.12.0", "version": "8.12.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz",
"integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -4966,7 +4959,6 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
"integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
@@ -7575,7 +7567,6 @@
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
}, },
@@ -7587,7 +7578,6 @@
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0", "loose-envify": "^1.1.0",
"scheduler": "^0.23.2" "scheduler": "^0.23.2"
@@ -7607,7 +7597,6 @@
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
"integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
"dev": true, "dev": true,
"peer": true,
"dependencies": { "dependencies": {
"@types/use-sync-external-store": "^0.0.3", "@types/use-sync-external-store": "^0.0.3",
"use-sync-external-store": "^1.0.0" "use-sync-external-store": "^1.0.0"
@@ -7760,8 +7749,7 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"dev": true, "dev": true
"peer": true
}, },
"node_modules/redux-thunk": { "node_modules/redux-thunk": {
"version": "3.1.0", "version": "3.1.0",
@@ -8586,7 +8574,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -8658,7 +8645,6 @@
"version": "5.7.2", "version": "5.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
"integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -8848,7 +8834,6 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
"integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.4.4", "fdir": "^6.4.4",
@@ -8954,7 +8939,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -9349,7 +9333,6 @@
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.5.tgz", "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.5.tgz",
"integrity": "sha512-6zeCUxUH+EPF1s+YF/2hPVODeV/7V07YU5x+2tfuRL8MdW6rv5vb2+CBEGTGwBdux0OIERcOS+RzxeK80k2DsQ==", "integrity": "sha512-6zeCUxUH+EPF1s+YF/2hPVODeV/7V07YU5x+2tfuRL8MdW6rv5vb2+CBEGTGwBdux0OIERcOS+RzxeK80k2DsQ==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5", "@emotion/babel-plugin": "^11.13.5",
@@ -9385,7 +9368,6 @@
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.5.tgz", "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.5.tgz",
"integrity": "sha512-gnOQ+nGLPvDXgIx119JqGalys64lhMdnNQA9TMxhDA4K0Hq5+++OE20Zs5GxiCV9r814xQ2K5WmtofSpHVW6BQ==", "integrity": "sha512-gnOQ+nGLPvDXgIx119JqGalys64lhMdnNQA9TMxhDA4K0Hq5+++OE20Zs5GxiCV9r814xQ2K5WmtofSpHVW6BQ==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@babel/runtime": "^7.18.3", "@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5", "@emotion/babel-plugin": "^11.13.5",
@@ -9774,7 +9756,6 @@
"resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.9.tgz", "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.9.tgz",
"integrity": "sha512-NwqIN0bdsgzSbZd5JFcC+2ez0XW/XNs8uiV2PDHrqQ4qf/FEasFJG1z6g8JbCN0YlTrHZekVb17X0Fv0qcYJfQ==", "integrity": "sha512-NwqIN0bdsgzSbZd5JFcC+2ez0XW/XNs8uiV2PDHrqQ4qf/FEasFJG1z6g8JbCN0YlTrHZekVb17X0Fv0qcYJfQ==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@babel/runtime": "^7.26.0", "@babel/runtime": "^7.26.0",
"@mui/core-downloads-tracker": "^6.1.9", "@mui/core-downloads-tracker": "^6.1.9",
@@ -10753,7 +10734,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.66.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.66.tgz",
"integrity": "sha512-OYTmMI4UigXeFMF/j4uv0lBBEbongSgptPrHBxqME44h9+yNov+oL6Z3ocJKo0WyXR84sQUNeyIp9MRfckvZpg==", "integrity": "sha512-OYTmMI4UigXeFMF/j4uv0lBBEbongSgptPrHBxqME44h9+yNov+oL6Z3ocJKo0WyXR84sQUNeyIp9MRfckvZpg==",
"devOptional": true, "devOptional": true,
"peer": true,
"requires": { "requires": {
"@types/prop-types": "*", "@types/prop-types": "*",
"@types/scheduler": "*", "@types/scheduler": "*",
@@ -10765,7 +10745,6 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.22.tgz",
"integrity": "sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==", "integrity": "sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==",
"devOptional": true, "devOptional": true,
"peer": true,
"requires": { "requires": {
"@types/react": "*" "@types/react": "*"
} }
@@ -10822,7 +10801,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz",
"integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "7.14.1", "@typescript-eslint/scope-manager": "7.14.1",
"@typescript-eslint/types": "7.14.1", "@typescript-eslint/types": "7.14.1",
@@ -10951,8 +10929,7 @@
"acorn": { "acorn": {
"version": "8.12.0", "version": "8.12.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz",
"integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw=="
"peer": true
}, },
"acorn-jsx": { "acorn-jsx": {
"version": "5.3.2", "version": "5.3.2",
@@ -12154,7 +12131,6 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
"integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
@@ -13890,7 +13866,6 @@
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"peer": true,
"requires": { "requires": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }
@@ -13899,7 +13874,6 @@
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"peer": true,
"requires": { "requires": {
"loose-envify": "^1.1.0", "loose-envify": "^1.1.0",
"scheduler": "^0.23.2" "scheduler": "^0.23.2"
@@ -13916,7 +13890,6 @@
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
"integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==", "integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@types/use-sync-external-store": "^0.0.3", "@types/use-sync-external-store": "^0.0.3",
"use-sync-external-store": "^1.0.0" "use-sync-external-store": "^1.0.0"
@@ -13996,8 +13969,7 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
"dev": true, "dev": true
"peer": true
}, },
"redux-thunk": { "redux-thunk": {
"version": "3.1.0", "version": "3.1.0",
@@ -14567,8 +14539,7 @@
"picomatch": { "picomatch": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="
"peer": true
} }
} }
}, },
@@ -14617,8 +14588,7 @@
"typescript": { "typescript": {
"version": "5.7.2", "version": "5.7.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
"integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg=="
"peer": true
}, },
"typescript-eslint": { "typescript-eslint": {
"version": "7.14.1", "version": "7.14.1",
@@ -14742,7 +14712,6 @@
"version": "6.3.5", "version": "6.3.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
"integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
"peer": true,
"requires": { "requires": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.4.4", "fdir": "^6.4.4",
@@ -14762,8 +14731,7 @@
"picomatch": { "picomatch": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="
"peer": true
} }
} }
}, },
-201
View File
@@ -1,201 +0,0 @@
import { load as parseHTML } from 'cheerio';
import { fetchText } from '@/lib/fetch';
import { FilterTypes, Filters } from '@libs/filterInputs';
import { Plugin } from '@/types/plugin';
import { encode } from 'urlencode';
import { NovelStatus } from '@libs/novelStatus';
class XinShu69 implements Plugin.PluginBase {
id = '69xinshu';
name = '69书吧';
icon = 'src/cn/69xinshu/icon.png';
site = 'https://69shu.biz';
version = '0.1.2';
async popularNovels(
pageNo: number,
{ filters }: Plugin.PopularNovelsOptions<typeof this.filters>,
): Promise<Plugin.NovelItem[]> {
let url: string;
if (pageNo === 1) {
url = `${this.site}/novels/class/${filters.class.value}.htm`;
} else {
url = `${this.site}/ajax_novels/class/${filters.class.value}/${pageNo}.htm`;
}
const body = await fetchText(url, {}, 'gbk');
if (body === '') throw Error('无法获取小说列表,请检查网络');
const loadedCheerio = parseHTML(body);
const novels: Plugin.NovelItem[] = [];
const novelsList =
pageNo === 1
? loadedCheerio('.newlistbox > ul > li')
: loadedCheerio('li');
novelsList.each((i, e) => {
const novelUrl = loadedCheerio(e).find('div > h3 > a').attr('href');
if (novelUrl) {
const novelName = loadedCheerio(e).find('div > h3 > a').text();
const novelCover = loadedCheerio(e).find('a > img').attr('data-src');
const novel = {
name: novelName,
cover: novelCover,
path: novelUrl.replace(this.site, ''),
};
novels.push(novel);
}
});
return novels;
}
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
const url = this.site + novelPath;
const body = await fetchText(url, {}, 'gbk');
if (body === '') throw Error('无法获取小说内容,请检查网络');
const loadedCheerio = parseHTML(body);
const novel: Plugin.SourceNovel = {
path: novelPath,
chapters: [],
name: loadedCheerio('h1 > a').text(),
};
novel.cover = loadedCheerio('div.bookimg2 > img').attr('src');
novel.summary = loadedCheerio('div.navtxt').text().trim();
const bookInfo = loadedCheerio('div.booknav2').text();
const authorMatch = bookInfo.match(/作者:(.*)/);
if (authorMatch) {
novel.author = authorMatch[1];
}
novel.artist = undefined;
novel.status = bookInfo.includes('连载')
? NovelStatus.Ongoing
: NovelStatus.Completed;
const genresMatch = bookInfo.match(/分类:(.*)/);
if (genresMatch) {
novel.genres = genresMatch[1];
}
// Table of Content is on a different page than the summary page
const chapters: Plugin.ChapterItem[] = [];
const chaptersUrl = loadedCheerio('a.more-btn').attr('href');
if (chaptersUrl) {
const chaptersBody = await fetchText(chaptersUrl, {}, 'gbk');
const chaptersLoadedCheerio = parseHTML(chaptersBody);
chaptersLoadedCheerio('li').each((i, e) => {
const chapterUrl = chaptersLoadedCheerio(e).find('a').attr('href');
if (chapterUrl?.startsWith('https://')) {
const chapterName = chaptersLoadedCheerio(e).find('a').text().trim();
chapters.push({
name: chapterName,
path: chapterUrl.replace(this.site, ''),
});
}
});
}
novel.chapters = chapters;
return novel;
}
async parseChapter(chapterPath: string): Promise<string> {
const body = await fetchText(this.site + chapterPath, {}, 'gbk');
const loadedCheerio = parseHTML(body);
const chapterText = (loadedCheerio('div.txtnav').prop('innerText') ?? '')
.split('\n')
// remove empty lines
.map((line: string) => line.trim())
.filter((line: string) => line !== '')
// remove the first two lines which are the chapter name and author name
.slice(2)
.map((line: string) => `<p>${line}</p>`)
.join('\n');
return chapterText;
}
async searchNovels(
searchTerm: string,
pageNo: number,
): Promise<Plugin.NovelItem[]> {
if (pageNo > 1) return [];
const searchUrl = `${this.site}/modules/article/search.php`;
const formData = new FormData();
formData.append('searchkey', encode(searchTerm, 'gbk'));
formData.append('searchtype', 'all');
const body = await fetchText(
searchUrl,
{ method: 'post', body: formData },
'gbk',
);
if (body === '') throw Error('无法获取搜索结果,请检查网络');
const loadedCheerio = parseHTML(body);
const novels: Plugin.NovelItem[] = [];
loadedCheerio('.newbox > ul > li').each((i, e) => {
const novelUrl = loadedCheerio(e).find('a').attr('href')!;
const novelName = loadedCheerio(e).find('div.newnav > h3').text();
const novelCover = loadedCheerio(e).find('img').attr('data-src');
const novel = {
name: novelName,
path: novelUrl.replace(this.site, ''),
cover: novelCover,
};
novels.push(novel);
});
return novels;
}
filters = {
class: {
label: '分类',
value: '0',
options: [
{ label: '全部分类', value: '0' },
{ label: '言情小说', value: '3' },
{ label: '玄幻魔法', value: '1' },
{ label: '修真武侠', value: '2' },
{ label: '穿越时空', value: '11' },
{ label: '都市小说', value: '9' },
{ label: '历史军事', value: '4' },
{ label: '游戏竞技', value: '5' },
{ label: '科幻空间', value: '6' },
{ label: '悬疑惊悚', value: '7' },
{ label: '同人小说', value: '8' },
{ label: '官场职场', value: '10' },
{ label: '青春校园', value: '12' },
],
type: FilterTypes.Picker,
},
} satisfies Filters;
}
export default new XinShu69();
+173 -309
View File
@@ -1,53 +1,44 @@
import { Plugin } from '@/types/plugin'; import { Plugin } from '@/types/plugin';
import { FilterTypes, Filters } from '@libs/filterInputs'; import { FilterTypes, Filters } from '@libs/filterInputs';
import { fetchApi, fetchFile } from '@/lib/fetch'; import { fetchApi } from '@/lib/fetch';
import { NovelStatus } from '@libs/novelStatus'; import { NovelStatus } from '@libs/novelStatus';
import { load as parseHTML } from 'cheerio'; import { load as parseHTML } from 'cheerio';
import { defaultCover } from '@libs/defaultCover'; import { defaultCover } from '@libs/defaultCover';
const getStandardNovelPath = (url: string | undefined): string | undefined => { const parseUrl = (url?: string): URL | undefined => {
if (!url) return undefined; if (!url) return undefined;
try { try {
const parsedUrl = new URL(url); return new URL(url, 'https://www.quanben.io');
const match = parsedUrl.pathname.match(/^(\/amp)?(\/n\/[^\/]+\/)/); } catch {
return match?.[2];
} catch (error) {
return undefined; return undefined;
} }
}; };
const getChapterFileName = (url: string | undefined): string | undefined => { const getStandardNovelPath = (url?: string): string | undefined => {
if (!url) return undefined; const parsedUrl = parseUrl(url);
try { if (!parsedUrl) return undefined;
const parsedUrl = new URL(url); const match = parsedUrl.pathname.match(/^(\/amp)?(\/n\/[^\/]+\/)/);
const pathParts = parsedUrl.pathname.split('/'); return match?.[2];
const fileName = pathParts[pathParts.length - 1]; };
if (fileName && /^\d+\.html$/.test(fileName)) {
return fileName; const getChapterFileName = (url?: string): string | undefined => {
} const parsedUrl = parseUrl(url);
return undefined; if (!parsedUrl) return undefined;
} catch (error) { const fileName = parsedUrl.pathname.split('/').pop();
return undefined; if (fileName && /^\d+\.html$/.test(fileName)) return fileName;
} return undefined;
}; };
const makeAbsolute = ( const makeAbsolute = (
relativeUrl: string | undefined, relativeUrl?: string,
baseUrl: string, baseUrl?: string,
): string | undefined => { ): string | undefined => {
if (!relativeUrl) return undefined; if (!relativeUrl || !baseUrl) return undefined;
try { try {
if (relativeUrl.startsWith('//')) { if (relativeUrl.startsWith('//')) return 'https:' + relativeUrl;
return 'https:' + relativeUrl; if (/^https?:\/\//.test(relativeUrl)) return relativeUrl;
}
if (
relativeUrl.startsWith('http://') ||
relativeUrl.startsWith('https://')
) {
return relativeUrl;
}
return new URL(relativeUrl, baseUrl).href; return new URL(relativeUrl, baseUrl).href;
} catch (e) { } catch {
return undefined; return undefined;
} }
}; };
@@ -56,357 +47,230 @@ class QuanbenPlugin implements Plugin.PluginBase {
id = 'quanben'; id = 'quanben';
name = 'Quanben'; name = 'Quanben';
site = 'https://www.quanben.io/'; site = 'https://www.quanben.io/';
version = '1.0.0'; version = '1.0.1';
icon = 'src/cn/quanben/icon.png'; icon = 'src/cn/quanben/icon.png';
defaultCover = defaultCover; defaultCover = defaultCover;
filters = {} satisfies Filters; // filters
filters = {
genre: {
label: '分类',
value: 'all',
options: [
{ label: '全部', value: 'all' },
{ label: '玄幻', value: 'xuanhuan' },
{ label: '都市', value: 'dushi' },
{ label: '言情', value: 'yanqing' },
{ label: '穿越', value: 'chuanyue' },
{ label: '青春', value: 'qingchun' },
{ label: '仙侠', value: 'xianxia' },
{ label: '灵异', value: 'lingyi' },
{ label: '悬疑', value: 'xuanyi' },
{ label: '历史', value: 'lishi' },
{ label: '军事', value: 'junshi' },
{ label: '游戏', value: 'youxi' },
{ label: '竞技', value: 'jingji' },
{ label: '科幻', value: 'kehuan' },
{ label: '职场', value: 'zhichang' },
{ label: '官场', value: 'guanchang' },
{ label: '现言', value: 'xianyan' },
{ label: '耽美', value: 'danmei' },
{ label: '其它', value: 'qita' },
],
type: FilterTypes.Picker,
},
} satisfies Filters;
async popularNovels(_pageNo: number): Promise<Plugin.NovelItem[]> { // homepage, when you first open the extension (with the applied filters if any)
const url = this.site + 'amp/'; async popularNovels(
const result = await fetchApi(url); _pageNo: number,
if (!result.ok) { { filters }: Plugin.PopularNovelsOptions<typeof this.filters>,
throw new Error( ): Promise<Plugin.NovelItem[]> {
`[Quanben] Failed to fetch AMP popular novels page: ${url} - Status: ${result.status}`, const url =
); filters.genre.value === 'all'
} ? this.site
const body = await result.text(); : `${this.site}c/${filters.genre.value}.html`;
const $ = parseHTML(body);
const res = await fetchApi(url);
if (!res.ok)
throw new Error(`[Quanben] Failed to fetch: ${url} - ${res.status}`);
const $ = parseHTML(await res.text());
const novels: Plugin.NovelItem[] = []; const novels: Plugin.NovelItem[] = [];
const processedAmpPaths = new Set<string>();
$('div.box').each((_i, box) => { $('div.list2').each((_i, list2) => {
const $box = $(box); const $list2 = $(list2);
const $link = $list2.find('h3 > a').first();
const href = $link.attr('href')?.trim();
const name = $link.text().trim();
const rawCover =
$list2.find('img').attr('src')?.trim() ||
$list2.find('img').attr('data-src')?.trim();
const cover = makeAbsolute(rawCover, this.site) || this.defaultCover;
// 1. Process the featured novel (div.list2) if it exists if (href && name) {
const $featured = $box.find('div.list2'); const path = getStandardNovelPath(href);
if ($featured.length > 0) { if (path) novels.push({ name, path, cover });
const $link = $featured.find('h3 > a');
const ampPath = $link.attr('href')?.trim();
const name = $link.text().trim();
const rawCoverSrc = $featured.find('amp-img').attr('src')?.trim();
const cover = makeAbsolute(rawCoverSrc, this.site) || this.defaultCover;
if (ampPath && name && !processedAmpPaths.has(ampPath)) {
novels.push({ name, path: ampPath, cover });
processedAmpPaths.add(ampPath);
}
} }
});
// 2. Process novels in the list (ul.list) // only first entry bcs the others dont have an image
$box.find('ul.list li').each((_j, listItem) => { $('ul.list').each((_i, ul) => {
const $listItem = $(listItem); const $firstLi = $(ul).find('li').first();
const $link = $listItem.find('a'); const $a = $firstLi.find('a').first();
const ampPath = $link.attr('href')?.trim(); const href = $a.attr('href')?.trim();
const name = $link.find('span').first().text().trim(); // Name is inside a span within the link const name =
$a.text().trim() || $firstLi.find('span.author').text().trim();
const cover = this.defaultCover;
if (ampPath && name && !processedAmpPaths.has(ampPath)) { if (href && name) {
novels.push({ name, path: ampPath, cover: this.defaultCover }); // Use default cover for list items const path = getStandardNovelPath(href);
processedAmpPaths.add(ampPath); if (path) novels.push({ name, path, cover });
} }
});
}); });
return novels; return novels;
} }
// novel details and metadata
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> { async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
// ** Expects AMP path: /amp/n/novel-name/ ** const standardPath = novelPath.replace(/^\/amp/, '');
if ( if (!standardPath.startsWith('/n/') || !standardPath.endsWith('/'))
!novelPath || throw new Error(`[Quanben parseNovel] Invalid path: ${novelPath}`);
!novelPath.startsWith('/amp/n/') ||
!novelPath.endsWith('/')
) {
throw new Error(
`[Quanben parseNovel] Invalid novelPath received: "${novelPath}". Expected AMP format: "/amp/n/novel-name/"`,
);
}
// Construct full AMP novel URL const fullUrl = makeAbsolute(standardPath, this.site);
const fullNovelUrl = makeAbsolute(novelPath, this.site); if (!fullUrl)
if (!fullNovelUrl) { throw new Error(`[Quanben parseNovel] Could not construct full URL`);
throw new Error(
`[Quanben parseNovel] Could not construct full AMP novel URL from path: ${novelPath}`,
);
}
// 1. Fetch AMP Novel Page HTML const res = await fetchApi(fullUrl);
const novelPageResult = await fetchApi(fullNovelUrl); if (!res.ok)
if (!novelPageResult.ok) { throw new Error(`[Quanben parseNovel] Failed to fetch: ${fullUrl}`);
throw new Error(
`[Quanben parseNovel] Failed to fetch AMP novel page: ${fullNovelUrl} - Status: ${novelPageResult.status}`,
);
}
const novelPageHtml = await novelPageResult.text();
const $ = parseHTML(novelPageHtml);
// 2. Parse Novel Details from AMP page - **Refined Selectors** const $ = parseHTML(await res.text());
const $infoBox = $('div.list2'); // Base element for many details const $info = $('div.list2').first();
const $descriptionBox = $('div.description'); // Separate element for summary const $desc = $('div.description').first();
const novel: Plugin.SourceNovel = { const novel: Plugin.SourceNovel = {
path: novelPath, // Use the input AMP path path: standardPath,
name: name: $info.find('h3').text().trim() || 'Unknown Novel',
$infoBox.find('h3').text().trim() || // **Use h3 inside list2**
$('h1[itemprop="name headline"]').text().trim() || // Fallback H1
'Unknown Novel Name',
cover: cover:
makeAbsolute($infoBox.find('amp-img').attr('src'), this.site) || // **amp-img inside list2** makeAbsolute($info.find('img').attr('src'), this.site) ||
this.defaultCover, this.defaultCover,
summary: summary:
$descriptionBox.find('p').text().trim() || // **Use p inside div.description** $desc.find('p').text().trim() || $desc.text().trim() || undefined,
$descriptionBox.text().trim() || // Fallback to div.description text author: $info.find("p:contains('作者:') span").text().trim() || undefined,
undefined, status: NovelStatus.Unknown,
// Use :contains() for more robust selection within the info box genres: $info.find("p:contains('类别:') span").text().trim() || undefined,
author: chapters: await this.parseChapterList(standardPath),
$infoBox.find("p:contains('作者:') span").text().trim() || undefined,
status: NovelStatus.Unknown, // Parsed below
genres:
$infoBox.find("p:contains('类别:') span").text().trim() || undefined,
chapters: [], // Parsed below
}; };
// Parse Status from AMP page novel.status = NovelStatus.Completed;
const statusText =
$infoBox.find("p:contains('状态:') span").text().trim() || // Try specific span first
$infoBox.text(); // Fallback to full text
if (statusText.includes('完结') || statusText.includes('已完成')) {
novel.status = NovelStatus.Completed;
} else if (statusText.includes('连载中') || statusText.includes('进行中')) {
novel.status = NovelStatus.Ongoing;
}
// 3. Fetch and Parse Chapter List
novel.chapters = await this.parseChapterList(novelPath);
return novel; return novel;
} }
// Separate function to handle chapter list parsing - **Using AMP**
async parseChapterList(novelPath: string): Promise<Plugin.ChapterItem[]> { async parseChapterList(novelPath: string): Promise<Plugin.ChapterItem[]> {
// ** Expects AMP path: /amp/n/novel-name/ ** if (!novelPath.startsWith('/n/') || !novelPath.endsWith('/')) return [];
if (
!novelPath ||
!novelPath.startsWith('/amp/n/') ||
!novelPath.endsWith('/')
) {
return [];
}
// Construct the AMP chapter list URL const url = makeAbsolute(novelPath + 'list.html', this.site);
const ampChapterListUrl = makeAbsolute(novelPath + 'list.html', this.site); if (!url) return [];
if (!ampChapterListUrl) {
return [];
}
const chapterListResult = await fetchApi(ampChapterListUrl); const res = await fetchApi(url);
if (!chapterListResult.ok) { if (!res.ok) return [];
return [];
}
const chapterListHtml = await chapterListResult.text();
const $ = parseHTML(chapterListHtml);
const $ = parseHTML(await res.text());
const chapters: Plugin.ChapterItem[] = []; const chapters: Plugin.ChapterItem[] = [];
// Extract standard novel name from AMP path for chapter path storage const novelName = novelPath.match(/\/n\/([^\/]+)\//)?.[1];
const standardNovelPathMatch = novelPath.match(/(\/n\/[^\/]+\/)/); if (!novelName) return [];
if (!standardNovelPathMatch || !standardNovelPathMatch[1]) {
return [];
}
const novelNameOnly = standardNovelPathMatch[1].replace(/^\/n\/|\/$/g, '');
// 1. Parse chapters from ALL list3 uls in the AMP HTML
$('ul.list3 li a').each((_i, el) => { $('ul.list3 li a').each((_i, el) => {
const $el = $(el); const $el = $(el);
const chapterName = $el.text().trim(); const name = $el.text().trim();
const chapterHref = $el.attr('href'); const href = $el.attr('href');
if (chapterName && chapterHref) { if (!name || !href) return;
// URLs in AMP page usually point to the standard chapter URLs
const absoluteUrl = makeAbsolute(chapterHref, this.site); // Use base site URL const fileName = getChapterFileName(makeAbsolute(href, this.site));
const chapterFileName = getChapterFileName(absoluteUrl); if (!fileName) return;
if (chapterFileName) {
// ** Store chapter path in standard format for parseChapter ** chapters.push({
const chapterPathForStorage = novelNameOnly + '/' + chapterFileName; name,
chapters.push({ path: `${novelName}/${fileName}`,
name: chapterName, });
path: chapterPathForStorage,
// chapterNumber assigned later
});
}
}
}); });
// 2. Deduplicate chapters based on path const uniqueChapters = Array.from(
const chapterMap = new Map<string, Plugin.ChapterItem>(); new Map(chapters.map(c => [c.path, c])).values(),
chapters.forEach(chapter => { );
if (!chapterMap.has(chapter.path)) {
chapterMap.set(chapter.path, chapter);
}
});
const uniqueChapters = Array.from(chapterMap.values());
// 3. Sort chapters numerically based on filename
uniqueChapters.sort((a, b) => { uniqueChapters.sort((a, b) => {
const numA = parseInt(a.path.match(/(\d+)\.html$/)?.[1] || '0', 10); const numA = parseInt(a.path.match(/(\d+)\.html$/)?.[1] || '0', 10);
const numB = parseInt(b.path.match(/(\d+)\.html$/)?.[1] || '0', 10); const numB = parseInt(b.path.match(/(\d+)\.html$/)?.[1] || '0', 10);
return numA - numB; return numA - numB;
}); });
// 4. Assign chapter numbers return uniqueChapters.map((c, idx) => ({ ...c, chapterNumber: idx + 1 }));
return uniqueChapters.map((chapter, index) => ({
...chapter,
chapterNumber: index + 1,
}));
} }
async parseChapter(chapterPath: string): Promise<string> { async parseChapter(chapterPath: string): Promise<string> {
// ** Expects standard path: novel-name/chapterFileName.html ** if (!chapterPath.includes('/') || chapterPath.endsWith('/'))
if ( throw new Error(`[Quanben] Invalid chapter path: "${chapterPath}"`);
!chapterPath ||
!chapterPath.includes('/') ||
chapterPath.endsWith('/')
) {
throw new Error(
`[Quanben] Invalid chapterPath format received in parseChapter: "${chapterPath}". Expected format: "novel-name/chapterFileName.html"`,
);
}
// Construct the standard chapter URL using /n/ prefix const url = `${this.site}n/${chapterPath}`;
const chapterUrl = `${this.site}n/${chapterPath}`; const res = await fetchApi(url);
if (!res.ok) throw new Error(`[Quanben] Failed to fetch chapter: ${url}`);
const result = await fetchApi(chapterUrl); return this.extractChapterContent(await res.text());
if (!result.ok) {
// Handle potential redirects (e.g., chapter moved) - check Location header if status is 3xx
if (result.status >= 300 && result.status < 400) {
const redirectUrl = result.headers.get('Location');
if (redirectUrl) {
const absoluteRedirectUrl = makeAbsolute(redirectUrl, chapterUrl);
if (!absoluteRedirectUrl) {
throw new Error(
`[Quanben] Failed to make redirected URL absolute: ${redirectUrl}`,
);
}
const redirectResult = await fetchApi(absoluteRedirectUrl);
if (!redirectResult.ok) {
throw new Error(
`[Quanben] Failed to fetch redirected chapter content: ${absoluteRedirectUrl} - Status: ${redirectResult.status}`,
);
}
return this.extractChapterContent(
await redirectResult.text(),
absoluteRedirectUrl,
);
}
}
throw new Error(
`[Quanben] Failed to fetch chapter content: ${chapterUrl} - Status: ${result.status}`,
);
}
const body = await result.text();
return this.extractChapterContent(body, chapterUrl);
} }
// Helper function to extract and clean chapter content from HTML body // Helper function to extract and clean chapter content from HTML body
private extractChapterContent(body: string, urlForLog: string): string { private extractChapterContent(body: string): string {
const $ = parseHTML(body); const $ = parseHTML(body);
let $content = $('#contentbody'); let $content = $('#contentbody, #content, .content').first();
if (!$content.length) { if (!$content.length) return 'Error: Chapter content not found.';
$content = $('#content');
}
if (!$content.length) {
$content = $('.content');
}
if (!$content.length) {
return 'Error: Could not find chapter content container.';
}
$content $content
.find( .find(
'script, style, ins, iframe, [class*="ads"], [id*="ads"], [class*="google"], [id*="google"], [class*="recommend"], div[align="center"]', 'script, style, ins, iframe, [class*="ads"], [id*="ads"], [class*="google"], [id*="google"], [class*="recommend"], div[align="center"]',
) )
.remove(); .remove();
$content.find('p').each((_i, el) => {
const $p = $(el); return (
const pText = $p.text().trim(); ($content.html() || '').replace(/[\t ]+/g, ' ').trim() ||
if ( 'Error: Chapter content empty.'
pText.includes('请记住本书首发域名') || );
pText.includes('手机版阅读网址') ||
pText.includes('quanben') ||
pText.includes('最新网址') ||
pText.includes('章节报错') ||
pText.match(/app|APP|下载|客户端/) ||
pText.length === 0 ||
($p
.html()
?.replace(/&nbsp;/g, '')
.trim() === '' &&
$p.find('img').length === 0)
) {
$p.remove();
}
});
$content
.contents()
.filter(function () {
return this.type === 'comment';
})
.remove();
let chapterText = $content.html();
if (!chapterText) {
return 'Error: Chapter content was empty after cleaning.';
}
chapterText = chapterText.replace(/<\s*p[^>]*>/gi, '\n\n');
chapterText = chapterText.replace(/<\s*br[^>]*>/gi, '\n');
chapterText = chapterText.replace(/<[^>]+>/g, '');
chapterText = parseHTML(`<div>${chapterText}</div>`).text();
chapterText = chapterText.replace(/[\t ]+/g, ' ');
chapterText = chapterText.replace(/\n{3,}/g, '\n\n');
chapterText = chapterText.trim();
return chapterText;
} }
async searchNovels( // add search
searchTerm: string, async searchNovels(searchTerm: string): Promise<Plugin.NovelItem[]> {
_pageNo: number, const url = `${this.site}index.php?c=book&a=search&keywords=${encodeURIComponent(searchTerm)}`;
): Promise<Plugin.NovelItem[]> { const res = await fetchApi(url);
const searchUrl = `${this.site}index.php?c=book&a=search&keywords=${encodeURIComponent(searchTerm)}`; if (!res.ok) return [];
const result = await fetchApi(searchUrl);
if (!result.ok) {
return [];
}
const body = await result.text();
const $ = parseHTML(body);
const $ = parseHTML(await res.text());
const novels: Plugin.NovelItem[] = []; const novels: Plugin.NovelItem[] = [];
$('div.list2').each((_i, element) => { $('div.list2').each((_i, el) => {
const $el = $(element); const $el = $(el);
const nameLink = $el.find('h3 > a').first(); const $link = $el.find('h3 > a').first();
const img = $el.find('img').first(); const href = $link.attr('href');
const name = $link.text().trim();
const cover = makeAbsolute(
$el.find('img').attr('src') || $el.find('img').attr('data-src'),
this.site,
);
const novelName = nameLink.text().trim(); if (href && name) {
const novelHref = nameLink.attr('href'); const path = getStandardNovelPath(makeAbsolute(href, this.site));
const novelCover = img.attr('src') || img.attr('data-src'); if (path)
if (novelHref && novelName) {
const absoluteUrl = makeAbsolute(novelHref, this.site);
const standardPath = getStandardNovelPath(absoluteUrl);
if (standardPath) {
// **Construct AMP Path for storage**
const ampPath = '/amp' + standardPath;
const absoluteCover = makeAbsolute(novelCover, this.site);
novels.push({ novels.push({
name: novelName, name,
path: ampPath, // **Store the AMP path** path: '/amp' + path,
cover: absoluteCover || this.defaultCover, cover: cover || this.defaultCover,
}); });
}
} }
}); });
return novels; return novels;
} }
// Use fetchApi for fetchImage as it handles potential errors and returns Response
async fetchImage(url: string): Promise<Response> { async fetchImage(url: string): Promise<Response> {
return fetchApi(url); return fetchApi(url);
} }
+234 -236
View File
@@ -11,241 +11,240 @@ import p_8 from '@plugins/arabic/dilartube';
import p_9 from '@plugins/arabic/rewayatclub'; import p_9 from '@plugins/arabic/rewayatclub';
import p_10 from '@plugins/arabic/sunovels'; import p_10 from '@plugins/arabic/sunovels';
import p_11 from '@plugins/chinese/69shu'; import p_11 from '@plugins/chinese/69shu';
import p_12 from '@plugins/chinese/69xinshu'; import p_12 from '@plugins/chinese/Quanben';
import p_13 from '@plugins/chinese/Quanben'; import p_13 from '@plugins/chinese/ixdzs8';
import p_14 from '@plugins/chinese/ixdzs8'; import p_14 from '@plugins/chinese/linovel';
import p_15 from '@plugins/chinese/linovel'; import p_15 from '@plugins/chinese/linovelib';
import p_16 from '@plugins/chinese/linovelib'; import p_16 from '@plugins/chinese/linovelib_tw';
import p_17 from '@plugins/chinese/linovelib_tw'; import p_17 from '@plugins/chinese/novel543';
import p_18 from '@plugins/chinese/novel543'; import p_18 from '@plugins/english/AllNovelFull[readnovelfull]';
import p_19 from '@plugins/english/AllNovelFull[readnovelfull]'; import p_19 from '@plugins/english/AllNovel[readnovelfull]';
import p_20 from '@plugins/english/AllNovel[readnovelfull]'; import p_20 from '@plugins/english/ArcaneTranslations[lightnovelwp]';
import p_21 from '@plugins/english/ArcaneTranslations[lightnovelwp]'; import p_21 from '@plugins/english/BelleReservoir[madara]';
import p_22 from '@plugins/english/BelleReservoir[madara]'; import p_22 from '@plugins/english/BoxNovel[readnovelfull]';
import p_23 from '@plugins/english/BoxNovel[readnovelfull]'; import p_23 from '@plugins/english/CPUnovel[lightnovelwp]';
import p_24 from '@plugins/english/CPUnovel[lightnovelwp]'; import p_24 from '@plugins/english/CitrusAurora[madara]';
import p_25 from '@plugins/english/CitrusAurora[madara]'; import p_25 from '@plugins/english/CoralBoutique[madara]';
import p_26 from '@plugins/english/CoralBoutique[madara]'; import p_26 from '@plugins/english/DaoNovel[madara]';
import p_27 from '@plugins/english/DaoNovel[madara]'; import p_27 from '@plugins/english/DaoTranslate[lightnovelwp]';
import p_28 from '@plugins/english/DaoTranslate[lightnovelwp]'; import p_28 from '@plugins/english/DaoistQuest[fictioneer]';
import p_29 from '@plugins/english/DaoistQuest[fictioneer]'; import p_29 from '@plugins/english/DearestRosalie[fictioneer]';
import p_30 from '@plugins/english/DearestRosalie[fictioneer]'; import p_30 from '@plugins/english/DragonTea[madara]';
import p_31 from '@plugins/english/DragonTea[madara]'; import p_31 from '@plugins/english/Dragonholic[madara]';
import p_32 from '@plugins/english/Dragonholic[madara]'; import p_32 from '@plugins/english/DuskBlossoms[madara]';
import p_33 from '@plugins/english/DuskBlossoms[madara]'; import p_33 from '@plugins/english/ElloTL[lightnovelwp]';
import p_34 from '@plugins/english/ElloTL[lightnovelwp]'; import p_34 from '@plugins/english/Eternalune[madara]';
import p_35 from '@plugins/english/Eternalune[madara]'; import p_35 from '@plugins/english/EtudeTranslations[madara]';
import p_36 from '@plugins/english/EtudeTranslations[madara]'; import p_36 from '@plugins/english/FanNovel[readwn]';
import p_37 from '@plugins/english/FanNovel[readwn]'; import p_37 from '@plugins/english/FansMTL[readwn]';
import p_38 from '@plugins/english/FansMTL[readwn]'; import p_38 from '@plugins/english/FansTranslations[madara]';
import p_39 from '@plugins/english/FansTranslations[madara]'; import p_39 from '@plugins/english/FirstKissNovel[madara]';
import p_40 from '@plugins/english/FirstKissNovel[madara]'; import p_40 from '@plugins/english/Foxaholic[madara]';
import p_41 from '@plugins/english/Foxaholic[madara]'; import p_41 from '@plugins/english/FreeWebNovel[readnovelfull]';
import p_42 from '@plugins/english/FreeWebNovel[readnovelfull]'; import p_42 from '@plugins/english/GalaxyTranslations[madara]';
import p_43 from '@plugins/english/GalaxyTranslations[madara]'; import p_43 from '@plugins/english/Guavaread[madara]';
import p_44 from '@plugins/english/Guavaread[madara]'; import p_44 from '@plugins/english/HiraethTranslation[madara]';
import p_45 from '@plugins/english/HiraethTranslation[madara]'; import p_45 from '@plugins/english/HotNovelPub[hotnovelpub]';
import p_46 from '@plugins/english/HotNovelPub[hotnovelpub]'; import p_46 from '@plugins/english/Ippotranslations[lightnovelwp]';
import p_47 from '@plugins/english/Ippotranslations[lightnovelwp]'; import p_47 from '@plugins/english/KeopiTranslations[lightnovelwp]';
import p_48 from '@plugins/english/KeopiTranslations[lightnovelwp]'; import p_48 from '@plugins/english/KnoxT[lightnovelwp]';
import p_49 from '@plugins/english/KnoxT[lightnovelwp]'; import p_49 from '@plugins/english/LazyGirlTranslations[lightnovelwp]';
import p_50 from '@plugins/english/LazyGirlTranslations[lightnovelwp]'; import p_50 from '@plugins/english/LibRead[readnovelfull]';
import p_51 from '@plugins/english/LibRead[readnovelfull]'; import p_51 from '@plugins/english/LightNovelCave[lightnovelworld]';
import p_52 from '@plugins/english/LightNovelCave[lightnovelworld]'; import p_52 from '@plugins/english/LightNovelHeaven[madara]';
import p_53 from '@plugins/english/LightNovelHeaven[madara]'; import p_53 from '@plugins/english/LightNovelPlus[readnovelfull]';
import p_54 from '@plugins/english/LightNovelPlus[readnovelfull]'; import p_54 from '@plugins/english/LightNovelPubVip[lightnovelworld]';
import p_55 from '@plugins/english/LightNovelPubVip[lightnovelworld]'; import p_55 from '@plugins/english/LightNovelUpdates[madara]';
import p_56 from '@plugins/english/LightNovelUpdates[madara]'; import p_56 from '@plugins/english/LightNovelWord[lightnovelworld]';
import p_57 from '@plugins/english/LightNovelWord[lightnovelworld]'; import p_57 from '@plugins/english/LilyontheValley[fictioneer]';
import p_58 from '@plugins/english/LilyontheValley[fictioneer]'; import p_58 from '@plugins/english/Ltnovel[readwn]';
import p_59 from '@plugins/english/Ltnovel[readwn]'; import p_59 from '@plugins/english/LunarLetters[madara]';
import p_60 from '@plugins/english/LunarLetters[madara]'; import p_60 from '@plugins/english/MTLNovel[madara]';
import p_61 from '@plugins/english/MTLNovel[madara]'; import p_61 from '@plugins/english/MTLNovel[mtlnovel]';
import p_62 from '@plugins/english/MTLNovel[mtlnovel]'; import p_62 from '@plugins/english/Meownovel[madara]';
import p_63 from '@plugins/english/Meownovel[madara]'; import p_63 from '@plugins/english/MoonlightNovels[lightnovelwp]';
import p_64 from '@plugins/english/MoonlightNovels[lightnovelwp]'; import p_64 from '@plugins/english/MostNovel[madara]';
import p_65 from '@plugins/english/MostNovel[madara]'; import p_65 from '@plugins/english/MysticalSeries[madara]';
import p_66 from '@plugins/english/MysticalSeries[madara]'; import p_66 from '@plugins/english/NeoSekaiTranslations[madara]';
import p_67 from '@plugins/english/NeoSekaiTranslations[madara]'; import p_67 from '@plugins/english/NitroManga[madara]';
import p_68 from '@plugins/english/NitroManga[madara]'; import p_68 from '@plugins/english/NobleMTL[lightnovelwp]';
import p_69 from '@plugins/english/NobleMTL[lightnovelwp]'; import p_69 from '@plugins/english/NoiceTranslations[madara]';
import p_70 from '@plugins/english/NoiceTranslations[madara]'; import p_70 from '@plugins/english/NovelBin[readnovelfull]';
import p_71 from '@plugins/english/NovelBin[readnovelfull]'; import p_71 from '@plugins/english/NovelCool[novelcool]';
import p_72 from '@plugins/english/NovelCool[novelcool]'; import p_72 from '@plugins/english/NovelFull[readnovelfull]';
import p_73 from '@plugins/english/NovelFull[readnovelfull]'; import p_73 from '@plugins/english/NovelLib[fictioneer]';
import p_74 from '@plugins/english/NovelLib[fictioneer]'; import p_74 from '@plugins/english/NovelMultiverse[madara]';
import p_75 from '@plugins/english/NovelMultiverse[madara]'; import p_75 from '@plugins/english/NovelOnline';
import p_76 from '@plugins/english/NovelOnline'; import p_76 from '@plugins/english/NovelTranslate[madara]';
import p_77 from '@plugins/english/NovelTranslate[madara]'; import p_77 from '@plugins/english/NovelsKnight[lightnovelwp]';
import p_78 from '@plugins/english/NovelsKnight[lightnovelwp]'; import p_78 from '@plugins/english/PandaMachineTranslations[lightnovelwp]';
import p_79 from '@plugins/english/PandaMachineTranslations[lightnovelwp]'; import p_79 from '@plugins/english/PastelTales[madara]';
import p_80 from '@plugins/english/PastelTales[madara]'; import p_80 from '@plugins/english/PenguinSquad[fictioneer]';
import p_81 from '@plugins/english/PenguinSquad[fictioneer]'; import p_81 from '@plugins/english/Prizma[fictioneer]';
import p_82 from '@plugins/english/Prizma[fictioneer]'; import p_82 from '@plugins/english/Ranobes[ranobes]';
import p_83 from '@plugins/english/Ranobes[ranobes]'; import p_83 from '@plugins/english/Ranovel[madara]';
import p_84 from '@plugins/english/Ranovel[madara]'; import p_84 from '@plugins/english/ReadFanfic[madara]';
import p_85 from '@plugins/english/ReadFanfic[madara]'; import p_85 from '@plugins/english/ReadNovelFull[readnovelfull]';
import p_86 from '@plugins/english/ReadNovelFull[readnovelfull]'; import p_86 from '@plugins/english/RequiemTranslations[lightnovelwp]';
import p_87 from '@plugins/english/RequiemTranslations[lightnovelwp]'; import p_87 from '@plugins/english/SalmonLatte[madara]';
import p_88 from '@plugins/english/SalmonLatte[madara]'; import p_88 from '@plugins/english/SleepyTranslations[madara]';
import p_89 from '@plugins/english/SleepyTranslations[madara]'; import p_89 from '@plugins/english/SonicMTL[madara]';
import p_90 from '@plugins/english/SonicMTL[madara]'; import p_90 from '@plugins/english/SrankManga[madara]';
import p_91 from '@plugins/english/SrankManga[madara]'; import p_91 from '@plugins/english/StorySeedling';
import p_92 from '@plugins/english/StorySeedling'; import p_92 from '@plugins/english/SweetEscape[madara]';
import p_93 from '@plugins/english/SweetEscape[madara]'; import p_93 from '@plugins/english/SystemTranslation[lightnovelwp]';
import p_94 from '@plugins/english/SystemTranslation[lightnovelwp]'; import p_94 from '@plugins/english/TranslatinOtaku[madara]';
import p_95 from '@plugins/english/TranslatinOtaku[madara]'; import p_95 from '@plugins/english/TranslationWeaver[lightnovelwp]';
import p_96 from '@plugins/english/TranslationWeaver[lightnovelwp]'; import p_96 from '@plugins/english/UniversalNovel[lightnovelwp]';
import p_97 from '@plugins/english/UniversalNovel[lightnovelwp]'; import p_97 from '@plugins/english/VandyTranslate[lightnovelwp]';
import p_98 from '@plugins/english/VandyTranslate[lightnovelwp]'; import p_98 from '@plugins/english/VioletLily[madara]';
import p_99 from '@plugins/english/VioletLily[madara]'; import p_99 from '@plugins/english/WebNovelLover[madara]';
import p_100 from '@plugins/english/WebNovelLover[madara]'; import p_100 from '@plugins/english/WebNovelPub[lightnovelworld]';
import p_101 from '@plugins/english/WebNovelPub[lightnovelworld]'; import p_101 from '@plugins/english/WebNovelTranslation[madara]';
import p_102 from '@plugins/english/WebNovelTranslation[madara]'; import p_102 from '@plugins/english/WhiteMoonlightNovels[lightnovelwp]';
import p_103 from '@plugins/english/WhiteMoonlightNovels[lightnovelwp]'; import p_103 from '@plugins/english/WooksTeahouse[madara]';
import p_104 from '@plugins/english/WooksTeahouse[madara]'; import p_104 from '@plugins/english/WordExcerpt[madara]';
import p_105 from '@plugins/english/WordExcerpt[madara]'; import p_105 from '@plugins/english/WuxiaSpace[readwn]';
import p_106 from '@plugins/english/WuxiaSpace[readwn]'; import p_106 from '@plugins/english/WuxiaV[readwn]';
import p_107 from '@plugins/english/WuxiaV[readwn]'; import p_107 from '@plugins/english/WuxiaWorldSite[madara]';
import p_108 from '@plugins/english/WuxiaWorldSite[madara]'; import p_108 from '@plugins/english/Wuxiabox[readwn]';
import p_109 from '@plugins/english/Wuxiabox[readwn]'; import p_109 from '@plugins/english/Wuxiafox[readwn]';
import p_110 from '@plugins/english/Wuxiafox[readwn]'; import p_110 from '@plugins/english/ZetroTranslation[madara]';
import p_111 from '@plugins/english/ZetroTranslation[madara]'; import p_111 from '@plugins/english/ao3';
import p_112 from '@plugins/english/ao3'; import p_112 from '@plugins/english/bestlightnovel';
import p_113 from '@plugins/english/bestlightnovel'; import p_113 from '@plugins/english/chrysanthemumgarden';
import p_114 from '@plugins/english/chrysanthemumgarden'; import p_114 from '@plugins/english/divinedaolibrary';
import p_115 from '@plugins/english/divinedaolibrary'; import p_115 from '@plugins/english/dreambigtl';
import p_116 from '@plugins/english/dreambigtl'; import p_116 from '@plugins/english/earlynovel';
import p_117 from '@plugins/english/earlynovel'; import p_117 from '@plugins/english/faqwikius';
import p_118 from '@plugins/english/faqwikius'; import p_118 from '@plugins/english/fenrirrealm';
import p_119 from '@plugins/english/fenrirrealm'; import p_119 from '@plugins/english/fictionzone';
import p_120 from '@plugins/english/fictionzone'; import p_120 from '@plugins/english/foxteller';
import p_121 from '@plugins/english/foxteller'; import p_121 from '@plugins/english/genesis';
import p_122 from '@plugins/english/genesis'; import p_122 from '@plugins/english/inkitt';
import p_123 from '@plugins/english/inkitt'; import p_123 from '@plugins/english/kdtnovels';
import p_124 from '@plugins/english/kdtnovels'; import p_124 from '@plugins/english/lightnovelpub';
import p_125 from '@plugins/english/lightnovelpub'; import p_125 from '@plugins/english/lightnoveltranslation';
import p_126 from '@plugins/english/lightnoveltranslation'; import p_126 from '@plugins/english/lnmtl';
import p_127 from '@plugins/english/lnmtl'; import p_127 from '@plugins/english/mtlreader';
import p_128 from '@plugins/english/mtlreader'; import p_128 from '@plugins/english/mvlempyr';
import p_129 from '@plugins/english/mvlempyr'; import p_129 from '@plugins/english/novelbuddy';
import p_130 from '@plugins/english/novelbuddy'; import p_130 from '@plugins/english/novelfire';
import p_131 from '@plugins/english/novelfire'; import p_131 from '@plugins/english/novelhall';
import p_132 from '@plugins/english/novelhall'; import p_132 from '@plugins/english/novelight';
import p_133 from '@plugins/english/novelight'; import p_133 from '@plugins/english/novelupdates';
import p_134 from '@plugins/english/novelupdates'; import p_134 from '@plugins/english/pawread';
import p_135 from '@plugins/english/pawread'; import p_135 from '@plugins/english/rainofsnow';
import p_136 from '@plugins/english/rainofsnow'; import p_136 from '@plugins/english/readfrom';
import p_137 from '@plugins/english/readfrom'; import p_137 from '@plugins/english/readlitenovel';
import p_138 from '@plugins/english/readlitenovel'; import p_138 from '@plugins/english/reaperscans';
import p_139 from '@plugins/english/reaperscans'; import p_139 from '@plugins/english/relibrary';
import p_140 from '@plugins/english/relibrary'; import p_140 from '@plugins/english/royalroad';
import p_141 from '@plugins/english/royalroad'; import p_141 from '@plugins/english/scribblehub';
import p_142 from '@plugins/english/scribblehub'; import p_142 from '@plugins/english/vynovel';
import p_143 from '@plugins/english/vynovel'; import p_143 from '@plugins/english/webnovel';
import p_144 from '@plugins/english/webnovel'; import p_144 from '@plugins/english/wtrlab';
import p_145 from '@plugins/english/wtrlab'; import p_145 from '@plugins/english/wuxiaworld';
import p_146 from '@plugins/english/wuxiaworld'; import p_146 from '@plugins/french/LighNovelFR[lightnovelwp]';
import p_147 from '@plugins/french/LighNovelFR[lightnovelwp]'; import p_147 from '@plugins/french/MTLNovel(FR)[mtlnovel]';
import p_148 from '@plugins/french/MTLNovel(FR)[mtlnovel]'; import p_148 from '@plugins/french/MassNovel[madara]';
import p_149 from '@plugins/french/MassNovel[madara]'; import p_149 from '@plugins/french/WorldNovel[madara]';
import p_150 from '@plugins/french/WorldNovel[madara]'; import p_150 from '@plugins/french/chireads';
import p_151 from '@plugins/french/chireads'; import p_151 from '@plugins/french/harkeneliwood';
import p_152 from '@plugins/french/harkeneliwood'; import p_152 from '@plugins/french/kisswood';
import p_153 from '@plugins/french/kisswood'; import p_153 from '@plugins/french/noveldeglace';
import p_154 from '@plugins/french/noveldeglace'; import p_154 from '@plugins/french/novhell';
import p_155 from '@plugins/french/novhell'; import p_155 from '@plugins/french/phenixscans';
import p_156 from '@plugins/french/phenixscans'; import p_156 from '@plugins/french/warriorlegendtrad';
import p_157 from '@plugins/french/warriorlegendtrad'; import p_157 from '@plugins/french/wuxialnscantrad';
import p_158 from '@plugins/french/wuxialnscantrad'; import p_158 from '@plugins/french/xiaowaz';
import p_159 from '@plugins/french/xiaowaz'; import p_159 from '@plugins/indonesian/BacaLightNovel[lightnovelwp]';
import p_160 from '@plugins/indonesian/BacaLightNovel[lightnovelwp]'; import p_160 from '@plugins/indonesian/MTLNovel(ID)[mtlnovel]';
import p_161 from '@plugins/indonesian/MTLNovel(ID)[mtlnovel]'; import p_161 from '@plugins/indonesian/MeioNovel[madara]';
import p_162 from '@plugins/indonesian/MeioNovel[madara]'; import p_162 from '@plugins/indonesian/NovelBookID[madara]';
import p_163 from '@plugins/indonesian/NovelBookID[madara]'; import p_163 from '@plugins/indonesian/Risenovel[madara]';
import p_164 from '@plugins/indonesian/Risenovel[madara]'; import p_164 from '@plugins/indonesian/SekteNovel[lightnovelwp]';
import p_165 from '@plugins/indonesian/SekteNovel[lightnovelwp]'; import p_165 from '@plugins/indonesian/WBNovel[madara]';
import p_166 from '@plugins/indonesian/WBNovel[madara]'; import p_166 from '@plugins/indonesian/indowebnovel';
import p_167 from '@plugins/indonesian/indowebnovel'; import p_167 from '@plugins/indonesian/novelringan';
import p_168 from '@plugins/indonesian/novelringan'; import p_168 from '@plugins/indonesian/sakuranovel';
import p_169 from '@plugins/indonesian/sakuranovel'; import p_169 from '@plugins/japanese/Syosetu';
import p_170 from '@plugins/japanese/Syosetu'; import p_170 from '@plugins/japanese/kakuyomu';
import p_171 from '@plugins/japanese/kakuyomu'; import p_171 from '@plugins/korean/Agitoon';
import p_172 from '@plugins/korean/Agitoon'; import p_172 from '@plugins/korean/FortuneEternal[madara]';
import p_173 from '@plugins/korean/FortuneEternal[madara]'; import p_173 from '@plugins/multi/komga';
import p_174 from '@plugins/multi/komga'; import p_174 from '@plugins/polish/novelki';
import p_175 from '@plugins/polish/novelki'; import p_175 from '@plugins/portuguese/BetterNovels[lightnovelwp]';
import p_176 from '@plugins/portuguese/BetterNovels[lightnovelwp]'; import p_176 from '@plugins/portuguese/CentralNovel[lightnovelwp]';
import p_177 from '@plugins/portuguese/CentralNovel[lightnovelwp]'; import p_177 from '@plugins/portuguese/Kiniga[madara]';
import p_178 from '@plugins/portuguese/Kiniga[madara]'; import p_178 from '@plugins/portuguese/LaNovels[hotnovelpub]';
import p_179 from '@plugins/portuguese/LaNovels[hotnovelpub]'; import p_179 from '@plugins/portuguese/LightNovelBrasil[lightnovelwp]';
import p_180 from '@plugins/portuguese/LightNovelBrasil[lightnovelwp]'; import p_180 from '@plugins/portuguese/MTLNovel(PT)[mtlnovel]';
import p_181 from '@plugins/portuguese/MTLNovel(PT)[mtlnovel]'; import p_181 from '@plugins/portuguese/blogdoamonnovels';
import p_182 from '@plugins/portuguese/blogdoamonnovels'; import p_182 from '@plugins/portuguese/novelmania';
import p_183 from '@plugins/portuguese/novelmania'; import p_183 from '@plugins/portuguese/tsundoku';
import p_184 from '@plugins/portuguese/tsundoku'; import p_184 from '@plugins/russian/Bookhamster[ifreedom]';
import p_185 from '@plugins/russian/Bookhamster[ifreedom]'; import p_185 from '@plugins/russian/Erolate[rulate]';
import p_186 from '@plugins/russian/Erolate[rulate]'; import p_186 from '@plugins/russian/EzNovels[hotnovelpub]';
import p_187 from '@plugins/russian/EzNovels[hotnovelpub]'; import p_187 from '@plugins/russian/LitSpace';
import p_188 from '@plugins/russian/LitSpace'; import p_188 from '@plugins/russian/MTLNovel(RU)[mtlnovel]';
import p_189 from '@plugins/russian/MTLNovel(RU)[mtlnovel]'; import p_189 from '@plugins/russian/NovelCool(RU)[novelcool]';
import p_190 from '@plugins/russian/NovelCool(RU)[novelcool]'; import p_190 from '@plugins/russian/Ranobes(RU)[ranobes]';
import p_191 from '@plugins/russian/Ranobes(RU)[ranobes]'; import p_191 from '@plugins/russian/Rulate[rulate]';
import p_192 from '@plugins/russian/Rulate[rulate]'; import p_192 from '@plugins/russian/authortoday';
import p_193 from '@plugins/russian/authortoday'; import p_193 from '@plugins/russian/bookriver';
import p_194 from '@plugins/russian/bookriver'; import p_194 from '@plugins/russian/ficbook';
import p_195 from '@plugins/russian/ficbook'; import p_195 from '@plugins/russian/jaomix';
import p_196 from '@plugins/russian/jaomix'; import p_196 from '@plugins/russian/neobook';
import p_197 from '@plugins/russian/neobook'; import p_197 from '@plugins/russian/novelOvh';
import p_198 from '@plugins/russian/novelOvh'; import p_198 from '@plugins/russian/novelTL';
import p_199 from '@plugins/russian/novelTL'; import p_199 from '@plugins/russian/ranobehub';
import p_200 from '@plugins/russian/ranobehub'; import p_200 from '@plugins/russian/ranobelib';
import p_201 from '@plugins/russian/ranobelib'; import p_201 from '@plugins/russian/ranoberf';
import p_202 from '@plugins/russian/ranoberf'; import p_202 from '@plugins/russian/renovels';
import p_203 from '@plugins/russian/renovels'; import p_203 from '@plugins/russian/ruvers';
import p_204 from '@plugins/russian/ruvers'; import p_204 from '@plugins/russian/topliba';
import p_205 from '@plugins/russian/topliba'; import p_205 from '@plugins/russian/zelluloza';
import p_206 from '@plugins/russian/zelluloza'; import p_206 from '@plugins/russian/СвободныйМирРанобэ[ifreedom]';
import p_207 from '@plugins/russian/СвободныйМирРанобэ[ifreedom]'; import p_207 from '@plugins/spanish/AllNovelRead[lightnovelwp]';
import p_208 from '@plugins/spanish/AllNovelRead[lightnovelwp]'; import p_208 from '@plugins/spanish/AnimesHoy12[madara]';
import p_209 from '@plugins/spanish/AnimesHoy12[madara]'; import p_209 from '@plugins/spanish/LightNovelDaily[hotnovelpub]';
import p_210 from '@plugins/spanish/LightNovelDaily[hotnovelpub]'; import p_210 from '@plugins/spanish/MTLNovel(ES)[mtlnovel]';
import p_211 from '@plugins/spanish/MTLNovel(ES)[mtlnovel]'; import p_211 from '@plugins/spanish/PanchoTranslations[madara]';
import p_212 from '@plugins/spanish/PanchoTranslations[madara]'; import p_212 from '@plugins/spanish/TC&Sega[lightnovelwp]';
import p_213 from '@plugins/spanish/TC&Sega[lightnovelwp]'; import p_213 from '@plugins/spanish/TraduccionesAmistosas[madara]';
import p_214 from '@plugins/spanish/TraduccionesAmistosas[madara]'; import p_214 from '@plugins/spanish/hasutl';
import p_215 from '@plugins/spanish/hasutl'; import p_215 from '@plugins/spanish/novelasligera';
import p_216 from '@plugins/spanish/novelasligera'; import p_216 from '@plugins/spanish/novelawuxia';
import p_217 from '@plugins/spanish/novelawuxia'; import p_217 from '@plugins/spanish/oasistranslations';
import p_218 from '@plugins/spanish/oasistranslations'; import p_218 from '@plugins/spanish/skynovels';
import p_219 from '@plugins/spanish/skynovels'; import p_219 from '@plugins/spanish/tunovelaligera';
import p_220 from '@plugins/spanish/tunovelaligera'; import p_220 from '@plugins/spanish/yukitls';
import p_221 from '@plugins/spanish/yukitls'; import p_221 from '@plugins/thai/NovelLucky[madara]';
import p_222 from '@plugins/thai/NovelLucky[madara]'; import p_222 from '@plugins/thai/NovelPDF[madara]';
import p_223 from '@plugins/thai/NovelPDF[madara]'; import p_223 from '@plugins/turkish/ArazNovel[madara]';
import p_224 from '@plugins/turkish/ArazNovel[madara]'; import p_224 from '@plugins/turkish/EKTAPLAR[madara]';
import p_225 from '@plugins/turkish/EKTAPLAR[madara]'; import p_225 from '@plugins/turkish/KodeksLibrary[lightnovelwp]';
import p_226 from '@plugins/turkish/KodeksLibrary[lightnovelwp]'; import p_226 from '@plugins/turkish/MangaTR';
import p_227 from '@plugins/turkish/MangaTR'; import p_227 from '@plugins/turkish/NABSCANS[madara]';
import p_228 from '@plugins/turkish/NABSCANS[madara]'; import p_228 from '@plugins/turkish/Namevt[lightnovelwp]';
import p_229 from '@plugins/turkish/Namevt[lightnovelwp]'; import p_229 from '@plugins/turkish/NovelTR[lightnovelwp]';
import p_230 from '@plugins/turkish/NovelTR[lightnovelwp]'; import p_230 from '@plugins/turkish/Noveloku[madara]';
import p_231 from '@plugins/turkish/Noveloku[madara]'; import p_231 from '@plugins/turkish/RagnarScans[madara]';
import p_232 from '@plugins/turkish/RagnarScans[madara]'; import p_232 from '@plugins/turkish/ThNovels[hotnovelpub]';
import p_233 from '@plugins/turkish/ThNovels[hotnovelpub]'; import p_233 from '@plugins/turkish/TurkceLightNovels[madara]';
import p_234 from '@plugins/turkish/TurkceLightNovels[madara]'; import p_234 from '@plugins/turkish/WebNovelOku[madara]';
import p_235 from '@plugins/turkish/WebNovelOku[madara]'; import p_235 from '@plugins/turkish/epiknovel';
import p_236 from '@plugins/turkish/epiknovel'; import p_236 from '@plugins/turkish/kakikata[madara]';
import p_237 from '@plugins/turkish/kakikata[madara]'; import p_237 from '@plugins/ukrainian/bakainua';
import p_238 from '@plugins/ukrainian/bakainua'; import p_238 from '@plugins/ukrainian/smakolykytl';
import p_239 from '@plugins/ukrainian/smakolykytl'; import p_239 from '@plugins/ukrainian/uaranobeclub';
import p_240 from '@plugins/ukrainian/uaranobeclub'; import p_240 from '@plugins/vietnamese/LNHako';
import p_241 from '@plugins/vietnamese/LNHako'; import p_241 from '@plugins/vietnamese/Truyenconect';
import p_242 from '@plugins/vietnamese/Truyenconect'; import p_242 from '@plugins/vietnamese/lightnovelvn';
import p_243 from '@plugins/vietnamese/lightnovelvn'; import p_243 from '@plugins/vietnamese/nettruyen';
import p_244 from '@plugins/vietnamese/nettruyen'; import p_244 from '@plugins/vietnamese/truyenchu';
import p_245 from '@plugins/vietnamese/truyenchu'; import p_245 from '@plugins/vietnamese/truyenfull';
import p_246 from '@plugins/vietnamese/truyenfull';
const PLUGINS: Plugin.PluginBase[] = [ const PLUGINS: Plugin.PluginBase[] = [
p_0, p_0,
@@ -494,6 +493,5 @@ const PLUGINS: Plugin.PluginBase[] = [
p_243, p_243,
p_244, p_244,
p_245, p_245,
p_246,
]; ];
export default PLUGINS; export default PLUGINS;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB