From 5411d31da5de0d09e189021304d47cb750eac317 Mon Sep 17 00:00:00 2001 From: chivehao Date: Wed, 19 Jun 2024 23:01:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E7=AD=BE=E5=90=8D=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.MD | 6 + console/package-lock.json | 183 +++++++++++++++++- gradle.properties | 2 +- .../run/ikaros/plugin/alist/AListClient.java | 61 +++++- .../ikaros/plugin/alist/AListEndpoint.java | 9 + src/main/resources/plugin.yaml | 2 +- 6 files changed, 257 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index b33e204..52c26c4 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -2,6 +2,12 @@ 更新日志文档,版本顺序从新到旧,最新版本在最前(上)面。 +# 0.12.11 + +## 新特性 + +- 添加刷新alist目录URL的接口 + # 0.12.10 ## 修复 diff --git a/console/package-lock.json b/console/package-lock.json index 7640012..2464534 100644 --- a/console/package-lock.json +++ b/console/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "@element-plus/icons-vue": "^2.1.0", "@runikaros/shared": "^0.0.2", - "vue": "^3.2.47" + "axios": "^1.7.2", + "js-base64": "^3.7.7" }, "devDependencies": { "@types/node": "^16.18.0", @@ -20,6 +21,9 @@ "typescript": "^5.0.2", "vite": "^4.3.9", "vue-tsc": "^1.4.2" + }, + "peerDependencies": { + "vue": "^3.2.45" } }, "node_modules/@ampproject/remapping": { @@ -1102,6 +1106,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", + "peer": true, "dependencies": { "@vue/shared": "3.4.27" } @@ -1110,6 +1115,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", + "peer": true, "dependencies": { "@vue/reactivity": "3.4.27", "@vue/shared": "3.4.27" @@ -1119,6 +1125,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", + "peer": true, "dependencies": { "@vue/runtime-core": "3.4.27", "@vue/shared": "3.4.27", @@ -1129,6 +1136,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", + "peer": true, "dependencies": { "@vue/compiler-ssr": "3.4.27", "@vue/shared": "3.4.27" @@ -1167,6 +1175,21 @@ "node": ">= 8" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1323,6 +1346,17 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/computeds": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", @@ -1338,7 +1372,8 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "peer": true }, "node_modules/de-indent": { "version": "1.0.2", @@ -1363,6 +1398,14 @@ } } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.783", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz", @@ -1452,6 +1495,38 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1574,6 +1649,11 @@ "node": ">=0.12.0" } }, + "node_modules/js-base64": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", + "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1621,6 +1701,25 @@ "@jridgewell/sourcemap-codec": "^1.4.15" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", @@ -1730,6 +1829,11 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1933,6 +2037,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.4.27", "@vue/compiler-sfc": "3.4.27", @@ -2724,6 +2829,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", + "peer": true, "requires": { "@vue/shared": "3.4.27" } @@ -2732,6 +2838,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", + "peer": true, "requires": { "@vue/reactivity": "3.4.27", "@vue/shared": "3.4.27" @@ -2741,6 +2848,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", + "peer": true, "requires": { "@vue/runtime-core": "3.4.27", "@vue/shared": "3.4.27", @@ -2751,6 +2859,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", + "peer": true, "requires": { "@vue/compiler-ssr": "3.4.27", "@vue/shared": "3.4.27" @@ -2780,6 +2889,21 @@ "picomatch": "^2.0.4" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "requires": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2876,6 +3000,14 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "computeds": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", @@ -2891,7 +3023,8 @@ "csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "peer": true }, "de-indent": { "version": "1.0.2", @@ -2908,6 +3041,11 @@ "ms": "2.1.2" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "electron-to-chromium": { "version": "1.4.783", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz", @@ -2975,6 +3113,21 @@ "to-regex-range": "^5.0.1" } }, + "follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3057,6 +3210,11 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "js-base64": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", + "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3092,6 +3250,19 @@ "@jridgewell/sourcemap-codec": "^1.4.15" } }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, "minimatch": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", @@ -3157,6 +3328,11 @@ "source-map-js": "^1.2.0" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3259,6 +3435,7 @@ "version": "3.4.27", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", + "peer": true, "requires": { "@vue/compiler-dom": "3.4.27", "@vue/compiler-sfc": "3.4.27", diff --git a/gradle.properties b/gradle.properties index b0e7fd1..1961978 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ group=run.ikaros.plugin.alist description=A ikaros plugin for alist. -version=0.12.10 \ No newline at end of file +version=0.12.11 \ No newline at end of file diff --git a/src/main/java/run/ikaros/plugin/alist/AListClient.java b/src/main/java/run/ikaros/plugin/alist/AListClient.java index 0642ad1..5dc2746 100644 --- a/src/main/java/run/ikaros/plugin/alist/AListClient.java +++ b/src/main/java/run/ikaros/plugin/alist/AListClient.java @@ -12,8 +12,9 @@ import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Retryable; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; -import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; import reactor.core.Disposable; import reactor.core.publisher.Flux; @@ -22,6 +23,7 @@ import run.ikaros.api.core.attachment.Attachment; import run.ikaros.api.core.attachment.AttachmentConst; import run.ikaros.api.core.attachment.AttachmentOperate; +import run.ikaros.api.core.attachment.AttachmentSearchCondition; import run.ikaros.api.core.setting.ConfigMap; import run.ikaros.api.custom.ReactiveCustomClient; import run.ikaros.api.infra.utils.StringUtils; @@ -32,6 +34,7 @@ import java.time.Duration; import java.time.LocalDateTime; import java.util.*; +import java.util.concurrent.ThreadPoolExecutor; @Slf4j @Component @@ -43,6 +46,7 @@ public class AListClient implements InitializingBean, DisposableBean { private final ReactiveCustomClient customClient; private final AttachmentOperate attachmentOperate; + private ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); public AListClient(ReactiveCustomClient customClient, AttachmentOperate attachmentOperate) { this.customClient = customClient; @@ -174,6 +178,50 @@ private Mono saveAListAttachment(AListAttachment aListAttachmen }); } + public Mono doRefreshAlistUrlSigns() { + return attachmentOperate.findByTypeAndParentIdAndName(AttachmentType.Directory, AttachmentConst.ROOT_DIRECTORY_ID, + AListConst.Attachment.DEFAULT_PARENT_NAME) + .switchIfEmpty(attachmentOperate.createDirectory(AttachmentConst.ROOT_DIRECTORY_ID, AListConst.Attachment.DEFAULT_PARENT_NAME)) + .map(Attachment::getId) + .flatMapMany(this::refreshAttachmentAlistUrlSignsRecursively) + .then(); + } + + private Flux refreshAttachmentAlistUrlSignsRecursively(Long alistRootAttParentId) { + return attachmentOperate.listByCondition(AttachmentSearchCondition.builder() + .parentId(alistRootAttParentId) + .page(1) + .size(Integer.MAX_VALUE) + .build()) + .map(JsonUtils::obj2Json) + .mapNotNull(json -> JsonUtils.json2obj(json, HashMap.class)) + .map(map -> map.get("items")) + .map(JsonUtils::obj2Json) + .mapNotNull(json -> JsonUtils.json2ObjArr(json, new TypeReference() { + })) + .flatMapMany(Flux::fromArray) + .flatMap(attachment -> { + if (attachment.getType().equals(AttachmentType.Directory)) { + executor.execute(()-> refreshAttachmentAlistUrlSignsRecursively(attachment.getId()) + .doOnError(error -> log.error("refresh attachment alist url fail for alist path[{}], " + + "err msg:[{}]", + attachment.getFsPath(), error.getMessage(), error)).subscribe()); + return Mono.empty(); + } else { + LocalDateTime now = LocalDateTime.now(); + if (attachment.getUpdateTime().plusDays(2).isAfter(now)) return Mono.empty(); + AListAttachment aListAttachment = fetchAttachmentDetail(attachment.getFsPath(), null); + String rawUrl = aListAttachment.getRaw_url(); + attachment.setUrl(rawUrl); + attachment.setUpdateTime(now); + log.debug("refresh attachment url for \n att path: [{}] \n alist path: [{}]", + attachment.getPath(), attachment.getFsPath()); + return attachmentOperate.save(attachment) + .then(); + } + }); + } + /** * @see @@ -283,6 +331,7 @@ private AListAttachment fetchAttachmentDetail(String path, AListAttachment attac if (apiResult != null && apiResult.getCode() == 200) { AListAttachment aListAttachment = JsonUtils.json2obj(JsonUtils.obj2Json(apiResult.getData()), AListAttachment.class); if (Objects.isNull(aListAttachment)) return attachment; + if (Objects.isNull(attachment)) return aListAttachment; aListAttachment.setPaths(attachment.getPaths()); aListAttachment.setId(attachment.getId()); aListAttachment.setParentId(attachment.getParentId()); @@ -361,6 +410,7 @@ public void destroy() throws Exception { if (Objects.nonNull(refreshTokenTaskDisposable) && !refreshTokenTaskDisposable.isDisposed()) { refreshTokenTaskDisposable.dispose(); } + executor.shutdown(); } @Override @@ -377,6 +427,15 @@ public void afterPropertiesSet() throws Exception { // token is null, get config from db. updateOperateByToken().subscribe(); } + + executor.setCorePoolSize(5); + executor.setMaxPoolSize(20); + executor.setQueueCapacity(200000); + executor.setKeepAliveSeconds(200); + executor.setThreadNamePrefix("ikaros-alist-thread-pool-"); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.setWaitForTasksToCompleteOnShutdown(true); + executor.initialize(); } diff --git a/src/main/java/run/ikaros/plugin/alist/AListEndpoint.java b/src/main/java/run/ikaros/plugin/alist/AListEndpoint.java index 961d69f..6203b11 100644 --- a/src/main/java/run/ikaros/plugin/alist/AListEndpoint.java +++ b/src/main/java/run/ikaros/plugin/alist/AListEndpoint.java @@ -9,6 +9,7 @@ import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; import run.ikaros.api.custom.GroupVersionKind; import run.ikaros.api.endpoint.CustomEndpoint; import run.ikaros.api.infra.utils.StringUtils; @@ -49,6 +50,9 @@ public RouterFunction endpoint() { .content(contentBuilder() .mediaType(MediaType.APPLICATION_JSON_VALUE)) .implementation(AListImportPostBody.class))) + .POST("/alist/sign/refresh", this::doRefreshAlistUrlSigns, + builder -> builder.operationId("RefreshAListUrlSigns") + .tag(tag).description("Refresh AList URL signs.")) .build(); } @@ -76,6 +80,11 @@ Mono doImportFilesFromAList(ServerRequest request) { .switchIfEmpty(ServerResponse.notFound().build()); } + Mono doRefreshAlistUrlSigns(ServerRequest request) { + return aListClient.doRefreshAlistUrlSigns() + .then(ServerResponse.ok().build()); + } + /** * 支持直接复制AList浏览器URL,而无需去区分是不是相对路径。 * diff --git a/src/main/resources/plugin.yaml b/src/main/resources/plugin.yaml index 3f71bca..1c3c7ef 100644 --- a/src/main/resources/plugin.yaml +++ b/src/main/resources/plugin.yaml @@ -4,7 +4,7 @@ name: PluginAList # plugin entry class that extends BasePlugin clazz: run.ikaros.plugin.alist.AListPlugin # plugin 'version' is a valid semantic version string (see semver.org). -version: 0.12.10 +version: 0.12.11 requires: ">=0.12.0" author: name: Ikaros OSS Team