fix: 兼容 BangDream 相对缓存地址

This commit is contained in:
sunlei 2026-06-06 22:02:39 +08:00
parent 5d97b8822a
commit b0337fb70a
3 changed files with 47 additions and 3 deletions

View File

@ -397,6 +397,7 @@ export interface TsuguHook {
- 已新增 `tsugu/runtime/operation-pipeline.ts`,把主数据 ready、operation resolve、handler render、output hook 和 error hook 固定为 `TsuguOperationPipeline.run``TsuguApplicationService.execute` 只负责调用 pipeline。 - 已新增 `tsugu/runtime/operation-pipeline.ts`,把主数据 ready、operation resolve、handler render、output hook 和 error hook 固定为 `TsuguOperationPipeline.run``TsuguApplicationService.execute` 只负责调用 pipeline。
- `scripts/bangdream-render-smoke.ps1` 已切到 `TsuguApplicationService`,本地 smoke 继续走真实应用入口,避免 facade 改造后验证脚本回退到旧链路。 - `scripts/bangdream-render-smoke.ps1` 已切到 `TsuguApplicationService`,本地 smoke 继续走真实应用入口,避免 facade 改造后验证脚本回退到旧链路。
- 已新增 `hook-registry.spec.ts`、`operation-pipeline.spec.ts` 和 `tsugu-application.service.spec.ts`,覆盖 hook 顺序、错误 hook、pipeline 成功/未知 operation/handler 错误、应用入口执行、字典刷新和错误字符串化;本地 Phase 7 smoke 已生成 `phase7-hook-event-50.jpg`、`phase7-hook-cutoff-detail-100-50-cn.jpg`、`phase7-hook-cutoff-recent-100-50-cn.jpg`、`phase7-pipeline-event-50.jpg`、`phase7-pipeline-cutoff-detail-100-50-cn.jpg`、`phase7-pipeline-cutoff-recent-100-50-cn.jpg`。 - 已新增 `hook-registry.spec.ts`、`operation-pipeline.spec.ts` 和 `tsugu-application.service.spec.ts`,覆盖 hook 顺序、错误 hook、pipeline 成功/未知 operation/handler 错误、应用入口执行、字典刷新和错误字符串化;本地 Phase 7 smoke 已生成 `phase7-hook-event-50.jpg`、`phase7-hook-cutoff-detail-100-50-cn.jpg`、`phase7-hook-cutoff-recent-100-50-cn.jpg`、`phase7-pipeline-event-50.jpg`、`phase7-pipeline-cutoff-detail-100-50-cn.jpg`、`phase7-pipeline-cutoff-recent-100-50-cn.jpg`。
- 线上 `qqbot/command/test` 复测时曾出现 `bangdream.event.search``Invalid URL`,根因按风险点固化为:缓存层不能假设所有调用方都已把 `/api`、`/assets` 相对路径解析成完整 Bestdori URL已在 `data-clients/cache-path.ts` 增加 `resolveCacheUrl` 兜底,并新增 `cache-path.spec.ts` 覆盖相对资产路径、相对 API 路径和完整 URL。线上/远程临时 Node 调试脚本必须同时设置外层 `timeout`,并在成功和失败分支显式 `process.exit(...)`,避免 SSH 会话被后台 timer 卡住。
## 文件迁移优先级 ## 文件迁移优先级

View File

@ -1,4 +1,8 @@
import { cacheRootPath } from '@/qqbot/plugins/bangDream/tsugu/runtime/config'; import {
bestdoriUrl,
cacheRootPath,
} from '@/qqbot/plugins/bangDream/tsugu/runtime/config';
import { resolveBangDreamProviderUrl } from './data-provider';
import * as path from 'path'; import * as path from 'path';
/** /**
@ -8,7 +12,7 @@ import * as path from 'path';
* @returns * @returns
*/ */
export function getCacheDirectory(url: string): string { export function getCacheDirectory(url: string): string {
const urlObj = new URL(url); const urlObj = new URL(resolveCacheUrl(url));
let pathname = urlObj.pathname; let pathname = urlObj.pathname;
// 如果结尾是文件名,去掉文件名 // 如果结尾是文件名,去掉文件名
if (path.basename(pathname).indexOf('.') != -1) { if (path.basename(pathname).indexOf('.') != -1) {
@ -28,7 +32,7 @@ export function getCacheDirectory(url: string): string {
* @returns * @returns
*/ */
export function getFileNameFromUrl(url: string): string { export function getFileNameFromUrl(url: string): string {
const urlObj = new URL(url); const urlObj = new URL(resolveCacheUrl(url));
let fileName = path.basename(urlObj.pathname); let fileName = path.basename(urlObj.pathname);
// Remove query string if present // Remove query string if present
@ -58,3 +62,11 @@ function sanitizeDirectoryName(dirName: string): string {
return dirName.replace(illegalChars, replacementChar); return dirName.replace(illegalChars, replacementChar);
} }
function resolveCacheUrl(url: string): string {
const source = `${url || ''}`.trim();
if (!source) {
throw new Error('cache url is empty');
}
return resolveBangDreamProviderUrl(bestdoriUrl, source);
}

View File

@ -0,0 +1,31 @@
import * as path from 'path';
import {
getCacheDirectory,
getFileNameFromUrl,
} from '@/qqbot/plugins/bangDream/tsugu/data-clients/cache-path';
describe('BangDream cache path', () => {
it('resolves relative asset paths before creating cache directories', () => {
const directory = getCacheDirectory(
'/assets/cn/event/foo/topscreen_rip/bg_eventtop.png',
);
expect(directory).toContain(
path.join('.kt-workspace', 'cache', 'bangdream'),
);
expect(directory).toContain('bestdori.com');
expect(directory).toContain(
path.join('assets', 'cn', 'event', 'foo', 'topscreen_rip'),
);
});
it('resolves relative api paths before creating cache file names', () => {
expect(getFileNameFromUrl('/api/events/50.json')).toBe('50.json');
});
it('keeps absolute urls unchanged for cache file names', () => {
expect(getFileNameFromUrl('https://example.com/api/events/50')).toBe(
'50.json',
);
});
});