From 69cf6d99c49bdf16dcf609b310582cb958871a3a Mon Sep 17 00:00:00 2001 From: sunlei Date: Fri, 19 Jun 2026 17:10:10 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=AF=E6=8C=81b23=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E7=9B=B4=E8=A7=A3=E6=9E=90=E8=A7=86=E9=A2=91ID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/domain/bilibili-url-parser.ts | 17 ++++++++++----- .../bilibili-card/bilibili-url-parser.spec.ts | 21 +++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/modules/qqbot/plugins/bilibili-card/src/domain/bilibili-url-parser.ts b/src/modules/qqbot/plugins/bilibili-card/src/domain/bilibili-url-parser.ts index 04c7439..d8514f0 100644 --- a/src/modules/qqbot/plugins/bilibili-card/src/domain/bilibili-url-parser.ts +++ b/src/modules/qqbot/plugins/bilibili-card/src/domain/bilibili-url-parser.ts @@ -59,12 +59,19 @@ export function parseBilibiliVideoReference( const url = new URL(cleaned); const pathSegments = url.pathname.split('/').filter(Boolean); - const videoSegmentIndex = pathSegments.findIndex( - (segment) => segment.toLowerCase() === 'video', - ); - if (videoSegmentIndex < 0) return null; + const hostname = url.hostname.toLowerCase(); + let videoIdSegment: string | undefined; + + if (hostname === B23_HOST) { + videoIdSegment = pathSegments[0]; + } else { + const videoSegmentIndex = pathSegments.findIndex( + (segment) => segment.toLowerCase() === 'video', + ); + if (videoSegmentIndex < 0) return null; + videoIdSegment = pathSegments[videoSegmentIndex + 1]; + } - const videoIdSegment = pathSegments[videoSegmentIndex + 1]; if (videoIdSegment && BVID_PATTERN.test(videoIdSegment)) { return { canonicalVideoId: videoIdSegment, diff --git a/test/modules/qqbot/plugins/bilibili-card/bilibili-url-parser.spec.ts b/test/modules/qqbot/plugins/bilibili-card/bilibili-url-parser.spec.ts index 39479c1..9adc902 100644 --- a/test/modules/qqbot/plugins/bilibili-card/bilibili-url-parser.spec.ts +++ b/test/modules/qqbot/plugins/bilibili-card/bilibili-url-parser.spec.ts @@ -29,6 +29,22 @@ describe('Bilibili URL parser', () => { }); }); + it('parses b23.tv paths that directly embed BV or av ids', () => { + expect(parseBilibiliVideoReference('https://b23.tv/BV1xx411c7mD')).toEqual({ + canonicalVideoId: 'BV1xx411c7mD', + kind: 'bvid', + sourceUrl: 'https://b23.tv/BV1xx411c7mD', + value: 'BV1xx411c7mD', + }); + expect(parseBilibiliVideoReference('https://b23.tv/av170001')).toMatchObject( + { + canonicalVideoId: 'av170001', + kind: 'aid', + value: '170001', + }, + ); + }); + it('allows only Bilibili and b23.tv hosts', () => { expect(isAllowedBilibiliUrl('https://b23.tv/abc123')).toBe(true); expect(isAllowedBilibiliUrl('https://space.bilibili.com/1')).toBe(true); @@ -56,6 +72,11 @@ describe('Bilibili URL parser', () => { 'https://www.bilibili.com/search?keyword=BV1xx411c7mD', ), ).toBeNull(); + expect( + parseBilibiliVideoReference( + 'https://space.bilibili.com/1#/video/BV1xx411c7mD', + ), + ).toBeNull(); }); it('rejects malformed BV path segments with extra characters', () => {