feat(bilibili): add following adapter — get user's followed accounts
Discovered via Playwright MCP Bridge workflow (CLI-CREATOR.md):
- Navigate to space.bilibili.com/{uid}/fans/follow
- Sniff network: GET /x/relation/followings (Cookie-tier, no Wbi needed)
- Verify API response: total=1342, fields: mid/uname/sign
Also fixed .d.ts loading bug in build-manifest.ts and engine.ts:
- build-manifest now scans .js files in dist/ (not .ts)
- engine.ts skips .d.js declaration stubs
This commit is contained in:
1 parent
53b28637bb
commit
f8ee50b776
3 files changed
+55
-2
No files matched your search
@@ -114,7 +114,10 @@ if (fs.existsSync(CLIS_DIR)) {
|
||||
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
|
||||
const entry = scanYaml(filePath, site);
|
||||
if (entry) manifest.push(entry);
|
||||
} else if (file.endsWith('.ts') && file !== 'index.ts') {
|
||||
} else if (
|
||||
(file.endsWith('.ts') && !file.endsWith('.d.ts') && file !== 'index.ts') ||
|
||||
(file.endsWith('.js') && !file.endsWith('.d.js') && file !== 'index.js')
|
||||
) {
|
||||
manifest.push(scanTs(filePath, site));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { cli, Strategy } from '../../registry.js';
|
||||
import type { IPage } from '../../types.js';
|
||||
import { fetchJson, getSelfUid, resolveUid } from '../../bilibili.js';
|
||||
|
||||
cli({
|
||||
site: 'bilibili',
|
||||
name: 'following',
|
||||
description: '获取 Bilibili 用户的关注列表',
|
||||
strategy: Strategy.COOKIE,
|
||||
args: [
|
||||
{ name: 'uid', required: false, help: '目标用户 ID(默认为当前登录用户)' },
|
||||
{ name: 'page', type: 'int', required: false, default: 1, help: '页码' },
|
||||
{ name: 'limit', type: 'int', required: false, default: 50, help: '每页数量 (最大 50)' },
|
||||
],
|
||||
columns: ['mid', 'name', 'sign', 'following', 'fans'],
|
||||
func: async (page: IPage | null, kwargs: any) => {
|
||||
if (!page) throw new Error('Requires browser');
|
||||
|
||||
// 1. Resolve UID (default to self)
|
||||
const uid = kwargs.uid
|
||||
? await resolveUid(page, kwargs.uid)
|
||||
: await getSelfUid(page);
|
||||
|
||||
const pn = kwargs.page ?? 1;
|
||||
const ps = Math.min(kwargs.limit ?? 50, 50);
|
||||
|
||||
// 2. Fetch following list (standard Cookie API, no Wbi signing needed)
|
||||
const payload = await fetchJson(page,
|
||||
`https://api.bilibili.com/x/relation/followings?vmid=${uid}&pn=${pn}&ps=${ps}&order=desc`
|
||||
);
|
||||
|
||||
if (payload.code !== 0) {
|
||||
throw new Error(`获取关注列表失败: ${payload.message} (${payload.code})`);
|
||||
}
|
||||
|
||||
const list = payload.data?.list || [];
|
||||
if (list.length === 0) {
|
||||
return [{ mid: '-', name: `共 ${payload.data?.total ?? 0} 人关注,当前页无数据`, sign: '', following: '', fans: '' }];
|
||||
}
|
||||
|
||||
// 3. Map to output
|
||||
return list.map((u: any) => ({
|
||||
mid: u.mid,
|
||||
name: u.uname,
|
||||
sign: (u.sign || '').slice(0, 40),
|
||||
following: u.attribute === 6 ? '互相关注' : '已关注',
|
||||
fans: u.official_verify?.desc || '',
|
||||
}));
|
||||
},
|
||||
});
|
||||
+1
-1
@@ -102,7 +102,7 @@ async function discoverClisFromFs(dir: string): Promise<void> {
|
||||
const filePath = path.join(siteDir, file);
|
||||
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
|
||||
registerYamlCli(filePath, site);
|
||||
} else if (file.endsWith('.js')) {
|
||||
} else if (file.endsWith('.js') && !file.endsWith('.d.js')) {
|
||||
promises.push(
|
||||
import(`file://${filePath}`).catch((err: any) => {
|
||||
process.stderr.write(`Warning: failed to load module ${filePath}: ${err.message}\n`);
|
||||
|
||||
Reference in new issue
Block a user