refactor: 收口 BangDream 属性资源仓储

This commit is contained in:
sunlei 2026-06-07 02:23:08 +08:00
parent 88a99c858c
commit 24ca3417f0
4 changed files with 67 additions and 5 deletions

View File

@ -304,6 +304,7 @@ export interface TsuguHook {
- 已新增 `models/event-stage-data-repository.ts`,把 `EventStage` 的 festival stages/rotationMusics 数据请求从 `bestdoriUrl + callAPIAndCacheResponse` 收口到 provider-backed repository`event-stage-data-repository.spec.ts` 覆盖两个 festival API 路径和缓存参数,本地 `/查试炼 310` 保持拆成 5 张图片输出。
- 已新增 `models/character-resource-repository.ts`,把 `Character` 的详情请求、角色图标、KV 立绘和名称横幅资源路径从 `bestdoriUrl + callAPIAndCacheResponse/downloadFileCache` 收口到 provider-backed repository`character-resource-repository.spec.ts` 覆盖详情缓存策略和三类资源路径,本地 `/查角色 1` 图片 smoke 输出非空。
- 已新增 `models/band-resource-repository.ts`,把 `Band` 的乐队 Logo 和乐队图标 SVG 资源路径从 `bestdoriUrl + downloadFileCache` 收口到 provider-backed repository`band-resource-repository.spec.ts` 覆盖两类资源路径和下载调用,本地 `/查角色 1` 图片 smoke 保持非空输出。
- 已新增 `models/attribute-resource-repository.ts`,把 `Attribute` 的属性图标 SVG 资源路径从 `bestdoriUrl + downloadFileCache` 收口到 provider-backed repository`attribute-resource-repository.spec.ts` 覆盖属性图标路径和下载调用,本地 `/查卡 472` 图片 smoke 保持非空输出。
- 固化Windows 下不要用反斜杠测试路径直接调用 Jest pattern容易出现 `Pattern ... - 0 matches`;指定文件测试统一使用 `pnpm exec jest --runInBand --runTestsByPath test/qqbot/plugins/bangDream/tsugu/<file>.spec.ts ...`,路径用正斜杠。
### Phase 4搜索 specification 和 matcher

View File

@ -0,0 +1,28 @@
import { bangDreamBestdoriProvider } from '@/qqbot/plugins/bangDream/tsugu/data-clients/bestdori-provider';
import type { BangDreamDataProvider } from '@/qqbot/plugins/bangDream/tsugu/data-clients/data-provider';
export class AttributeResourceRepository {
constructor(
private readonly provider: BangDreamDataProvider = bangDreamBestdoriProvider,
) {}
/**
* SVG
*
* @param attributeName -
*/
getIconSvgPath(attributeName: string): string {
return `/res/icon/${attributeName}.svg`;
}
/**
* SVG
*
* @param attributeName -
*/
async getIconSvgBuffer(attributeName: string): Promise<Buffer> {
return await this.provider.getAsset(this.getIconSvgPath(attributeName));
}
}
export const attributeResourceRepository = new AttributeResourceRepository();

View File

@ -1,7 +1,6 @@
import { loadImage, Image } from 'skia-canvas';
import { downloadFileCache } from '@/qqbot/plugins/bangDream/tsugu/data-clients/asset-cache-client';
import { bestdoriUrl } from '@/qqbot/plugins/bangDream/tsugu/runtime/config';
import { convertSvgToPngBuffer } from '@/qqbot/plugins/bangDream/tsugu/canvas/image-utils';
import { attributeResourceRepository } from '@/qqbot/plugins/bangDream/tsugu/models/attribute-resource-repository';
const attributeColor = {
happy: '#ff6600',
@ -49,9 +48,8 @@ async function getAttributeIcon(attributeName: string): Promise<Image> {
if (attributeIconCache[attributeName]) {
return attributeIconCache[attributeName];
}
const iconSvgBuffer = await downloadFileCache(
`${bestdoriUrl}/res/icon/${attributeName}.svg`,
);
const iconSvgBuffer =
await attributeResourceRepository.getIconSvgBuffer(attributeName);
const iconPngBuffer = await convertSvgToPngBuffer(iconSvgBuffer);
const image = await loadImage(iconPngBuffer);
attributeIconCache[attributeName] = image;

View File

@ -0,0 +1,35 @@
import type { BangDreamDataProvider } from '@/qqbot/plugins/bangDream/tsugu/data-clients/data-provider';
import { AttributeResourceRepository } from '@/qqbot/plugins/bangDream/tsugu/models/attribute-resource-repository';
function createProviderMock(): jest.Mocked<BangDreamDataProvider> {
return {
getAsset: jest.fn(),
getJson: jest.fn(),
getTracker: jest.fn(),
name: 'MockBestdori',
resolveUrl: jest.fn((pathOrUrl) => `https://bestdori.example${pathOrUrl}`),
};
}
describe('BangDream attribute resource repository', () => {
it('builds attribute icon paths', () => {
const repository = new AttributeResourceRepository(createProviderMock());
expect(repository.getIconSvgPath('powerful')).toBe(
'/res/icon/powerful.svg',
);
});
it('downloads attribute icon assets through the provider', async () => {
const provider = createProviderMock();
const iconBuffer = Buffer.from('<svg />');
provider.getAsset.mockResolvedValue(iconBuffer);
const repository = new AttributeResourceRepository(provider);
await expect(repository.getIconSvgBuffer('powerful')).resolves.toBe(
iconBuffer,
);
expect(provider.getAsset).toHaveBeenCalledWith('/res/icon/powerful.svg');
});
});