refactor: 收口 BangDream 乐队资源仓储
This commit is contained in:
parent
00ff99d2b6
commit
88a99c858c
@ -303,6 +303,7 @@ export interface TsuguHook {
|
||||
- 已新增 `models/gacha-resource-repository.ts`,把 `Gacha` 的详情请求、首页横幅、screen 背景、`bg1` fallback 和 Logo 资源路径收口到 provider-backed repository;`gacha-resource-repository.spec.ts` 覆盖 `/api/gacha` 缓存参数、CN 优先 screen 路径、横幅缺失回退 Logo 和背景 fallback,本地 `/查卡池 259`、`/抽卡模拟 10 259` 图片 smoke 输出非空。
|
||||
- 已新增 `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 保持非空输出。
|
||||
- 固化:Windows 下不要用反斜杠测试路径直接调用 Jest pattern,容易出现 `Pattern ... - 0 matches`;指定文件测试统一使用 `pnpm exec jest --runInBand --runTestsByPath test/qqbot/plugins/bangDream/tsugu/<file>.spec.ts ...`,路径用正斜杠。
|
||||
|
||||
### Phase 4:搜索 specification 和 matcher
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
import { bangDreamBestdoriProvider } from '@/qqbot/plugins/bangDream/tsugu/data-clients/bestdori-provider';
|
||||
import type { BangDreamDataProvider } from '@/qqbot/plugins/bangDream/tsugu/data-clients/data-provider';
|
||||
import { formatNumber } from '@/qqbot/plugins/bangDream/tsugu/models/model-utils';
|
||||
|
||||
export class BandResourceRepository {
|
||||
constructor(
|
||||
private readonly provider: BangDreamDataProvider = bangDreamBestdoriProvider,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 获取乐队 Logo 资源路径。
|
||||
*
|
||||
* @param bandId - 乐队 ID。
|
||||
*/
|
||||
getLogoPath(bandId: number): string {
|
||||
return `/assets/jp/band/logo/${formatNumber(bandId, 3)}_rip/logoL.png`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取乐队图标 SVG 资源路径。
|
||||
*
|
||||
* @param bandId - 乐队 ID。
|
||||
*/
|
||||
getIconSvgPath(bandId: number): string {
|
||||
return `/res/icon/band_${bandId}.svg`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载乐队 Logo 资源。
|
||||
*
|
||||
* @param bandId - 乐队 ID。
|
||||
*/
|
||||
async getLogoBuffer(bandId: number): Promise<Buffer> {
|
||||
return await this.provider.getAsset(this.getLogoPath(bandId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载乐队图标 SVG 资源。
|
||||
*
|
||||
* @param bandId - 乐队 ID。
|
||||
*/
|
||||
async getIconSvgBuffer(bandId: number): Promise<Buffer> {
|
||||
return await this.provider.getAsset(this.getIconSvgPath(bandId));
|
||||
}
|
||||
}
|
||||
|
||||
export const bandResourceRepository = new BandResourceRepository();
|
||||
@ -1,10 +1,8 @@
|
||||
import mainAPI from '@/qqbot/plugins/bangDream/tsugu/models/main-data-store';
|
||||
import { Character } from '@/qqbot/plugins/bangDream/tsugu/models/character';
|
||||
import { Image, loadImage } from 'skia-canvas';
|
||||
import { downloadFileCache } from '@/qqbot/plugins/bangDream/tsugu/data-clients/asset-cache-client';
|
||||
import { formatNumber } from '@/qqbot/plugins/bangDream/tsugu/models/model-utils';
|
||||
import { bestdoriUrl } from '@/qqbot/plugins/bangDream/tsugu/runtime/config';
|
||||
import { convertSvgToPngBuffer } from '@/qqbot/plugins/bangDream/tsugu/canvas/image-utils';
|
||||
import { bandResourceRepository } from '@/qqbot/plugins/bangDream/tsugu/models/band-resource-repository';
|
||||
|
||||
export class Band {
|
||||
bandId: number;
|
||||
@ -61,9 +59,7 @@ export class Band {
|
||||
* @returns 异步处理结果。
|
||||
*/
|
||||
async getLogo(): Promise<Image> {
|
||||
const logoBuffer = await downloadFileCache(
|
||||
`${bestdoriUrl}/assets/jp/band/logo/${formatNumber(this.bandId, 3)}_rip/logoL.png`,
|
||||
);
|
||||
const logoBuffer = await bandResourceRepository.getLogoBuffer(this.bandId);
|
||||
return await loadImage(logoBuffer);
|
||||
}
|
||||
}
|
||||
@ -80,9 +76,7 @@ export async function getBandIcon(bandId: number): Promise<Image> {
|
||||
if (bandIconCache[bandId]) {
|
||||
return bandIconCache[bandId];
|
||||
}
|
||||
const iconSvgBuffer = await downloadFileCache(
|
||||
`${bestdoriUrl}/res/icon/band_${bandId}.svg`,
|
||||
);
|
||||
const iconSvgBuffer = await bandResourceRepository.getIconSvgBuffer(bandId);
|
||||
const iconPngBuffer = await convertSvgToPngBuffer(iconSvgBuffer);
|
||||
const image = await loadImage(iconPngBuffer);
|
||||
bandIconCache[bandId] = image;
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
import type { BangDreamDataProvider } from '@/qqbot/plugins/bangDream/tsugu/data-clients/data-provider';
|
||||
import { BandResourceRepository } from '@/qqbot/plugins/bangDream/tsugu/models/band-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 band resource repository', () => {
|
||||
it('builds band logo and icon paths', () => {
|
||||
const repository = new BandResourceRepository(createProviderMock());
|
||||
|
||||
expect(repository.getLogoPath(1)).toBe(
|
||||
'/assets/jp/band/logo/001_rip/logoL.png',
|
||||
);
|
||||
expect(repository.getIconSvgPath(1)).toBe('/res/icon/band_1.svg');
|
||||
});
|
||||
|
||||
it('downloads band logo and icon assets through the provider', async () => {
|
||||
const provider = createProviderMock();
|
||||
const logoBuffer = Buffer.from('logo');
|
||||
const iconBuffer = Buffer.from('<svg />');
|
||||
provider.getAsset
|
||||
.mockResolvedValueOnce(logoBuffer)
|
||||
.mockResolvedValueOnce(iconBuffer);
|
||||
const repository = new BandResourceRepository(provider);
|
||||
|
||||
await expect(repository.getLogoBuffer(1)).resolves.toBe(logoBuffer);
|
||||
await expect(repository.getIconSvgBuffer(1)).resolves.toBe(iconBuffer);
|
||||
|
||||
expect(provider.getAsset).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
'/assets/jp/band/logo/001_rip/logoL.png',
|
||||
);
|
||||
expect(provider.getAsset).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'/res/icon/band_1.svg',
|
||||
);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user