fix: 保持Bilibili卡片事件异常不外抛
This commit is contained in:
parent
c14bcea2dc
commit
98e26616bb
@ -122,14 +122,19 @@ export class BilibiliCardApplication {
|
||||
if (cached && cached.expiresAt > current) return cached.value;
|
||||
|
||||
const config = readBilibiliCardRuntimeConfig(this.host);
|
||||
const value = (
|
||||
await this.host.getBoundEventPluginKeys(normalizedSelfId)
|
||||
).includes(this.manifest.pluginKey);
|
||||
this.boundCache.set(normalizedSelfId, {
|
||||
expiresAt: current + Math.min(config.dedupeTtlMs, 60000),
|
||||
value,
|
||||
});
|
||||
return value;
|
||||
try {
|
||||
const value = (
|
||||
await this.host.getBoundEventPluginKeys(normalizedSelfId)
|
||||
).includes(this.manifest.pluginKey);
|
||||
this.boundCache.set(normalizedSelfId, {
|
||||
expiresAt: current + Math.min(config.dedupeTtlMs, 60000),
|
||||
value,
|
||||
});
|
||||
return value;
|
||||
} catch (error) {
|
||||
this.warn(`Bilibili 事件绑定查询失败: ${normalizeError(error)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,7 +152,14 @@ export class BilibiliCardApplication {
|
||||
* @param message - Warning message safe for platform logs.
|
||||
*/
|
||||
private warn(message: string) {
|
||||
this.host.warn?.(message);
|
||||
try {
|
||||
const result = this.host.warn?.(message) as unknown;
|
||||
if (isThenable(result)) {
|
||||
result.catch(() => undefined);
|
||||
}
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,6 +194,22 @@ function isB23ShortLink(url: string) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects promise-like warning results so rejected async loggers cannot escape later.
|
||||
* @param value - Return value from the optional host warning hook.
|
||||
* @returns `true` when the value exposes a callable `catch` method.
|
||||
*/
|
||||
function isThenable(
|
||||
value: unknown,
|
||||
): value is { catch: (handler: () => void) => unknown } {
|
||||
return (
|
||||
typeof value === 'object' &&
|
||||
value !== null &&
|
||||
'catch' in value &&
|
||||
typeof value.catch === 'function'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts thrown values to stable warning text.
|
||||
* @param error - Error or arbitrary thrown value from host or domain code.
|
||||
|
||||
@ -25,6 +25,29 @@ describe('Bilibili card application', () => {
|
||||
expect(host.sendText).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('warns and returns false when binding lookup fails', async () => {
|
||||
const host = createHost({
|
||||
getBoundEventPluginKeys: jest
|
||||
.fn()
|
||||
.mockRejectedValue(new Error('binding down')),
|
||||
});
|
||||
const application = new BilibiliCardApplication(host, createManifest());
|
||||
|
||||
await expect(
|
||||
application.handleMessage(
|
||||
createMessage({
|
||||
messageText: 'https://www.bilibili.com/video/BV1xx411c7mD',
|
||||
}),
|
||||
),
|
||||
).resolves.toBe(false);
|
||||
|
||||
expect(host.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining('binding down'),
|
||||
);
|
||||
expect(host.requestJson).not.toHaveBeenCalled();
|
||||
expect(host.sendText).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('ignores messages sent by the bot itself', async () => {
|
||||
const host = createHost({
|
||||
getBoundEventPluginKeys: jest.fn().mockResolvedValue(['bilibili-card']),
|
||||
@ -169,6 +192,70 @@ describe('Bilibili card application', () => {
|
||||
expect(host.sendText).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns false when warning throws during binding lookup failure', async () => {
|
||||
const host = createHost({
|
||||
getBoundEventPluginKeys: jest
|
||||
.fn()
|
||||
.mockRejectedValue(new Error('binding down')),
|
||||
warn: jest.fn(() => {
|
||||
throw new Error('logger down');
|
||||
}),
|
||||
});
|
||||
const application = new BilibiliCardApplication(host, createManifest());
|
||||
|
||||
await expect(
|
||||
application.handleMessage(
|
||||
createMessage({
|
||||
messageText: 'https://www.bilibili.com/video/BV1xx411c7mD',
|
||||
}),
|
||||
),
|
||||
).resolves.toBe(false);
|
||||
});
|
||||
|
||||
it('returns false when warning throws during short-link failure', async () => {
|
||||
const host = createHost({
|
||||
getBoundEventPluginKeys: jest.fn().mockResolvedValue(['bilibili-card']),
|
||||
resolveRedirect: jest.fn().mockRejectedValue(new Error('redirect down')),
|
||||
warn: jest.fn(() => {
|
||||
throw new Error('logger down');
|
||||
}),
|
||||
});
|
||||
const application = new BilibiliCardApplication(host, createManifest());
|
||||
|
||||
await expect(
|
||||
application.handleMessage(
|
||||
createMessage({
|
||||
messageText: 'https://b23.tv/abc123',
|
||||
}),
|
||||
),
|
||||
).resolves.toBe(false);
|
||||
});
|
||||
|
||||
it('attaches a rejection handler when warning returns a promise', async () => {
|
||||
const catchSpy = jest.fn();
|
||||
const host = createHost({
|
||||
getBoundEventPluginKeys: jest.fn().mockResolvedValue(['bilibili-card']),
|
||||
resolveRedirect: jest.fn().mockRejectedValue(new Error('redirect down')),
|
||||
warn: jest.fn(
|
||||
() =>
|
||||
({
|
||||
catch: catchSpy,
|
||||
}) as unknown as void,
|
||||
),
|
||||
});
|
||||
const application = new BilibiliCardApplication(host, createManifest());
|
||||
|
||||
await expect(
|
||||
application.handleMessage(
|
||||
createMessage({
|
||||
messageText: 'https://b23.tv/abc123',
|
||||
}),
|
||||
),
|
||||
).resolves.toBe(false);
|
||||
|
||||
expect(catchSpy).toHaveBeenCalledWith(expect.any(Function));
|
||||
});
|
||||
|
||||
it('warns and returns false when short-link resolution fails', async () => {
|
||||
const host = createHost({
|
||||
getBoundEventPluginKeys: jest.fn().mockResolvedValue(['bilibili-card']),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user