| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- #!/usr/bin/env node
- /**
- * 探测 TikHub 的抖音用户搜索正确 API 路径
- */
- const fs = require('fs');
- const path = require('path');
- const os = require('os');
- const https = require('https');
- const TIKHUB_TOKEN = JSON.parse(
- fs.readFileSync(
- path.join(os.homedir(), '.openclaw', 'skills', 'xiaohongshu-search-notes', 'api-config.json'),
- 'utf-8'
- )
- ).endpoint.headers.Authorization.replace(/^Bearer\s+/, '');
- const COOKIE = fs.readFileSync(path.resolve('data/douyin-cookie.txt'), 'utf-8').trim();
- const keyword = '葵花药业';
- const paths = [
- // app v3
- '/api/v1/douyin/app/v3/fetch_user_search_result',
- '/api/v1/douyin/app/v3/search_user',
- '/api/v1/douyin/app/v3/fetch_general_search_result',
- // web
- '/api/v1/douyin/web/fetch_user_search_result_v2',
- '/api/v1/douyin/web/fetch_user_search_result',
- '/api/v1/douyin/web/search_user',
- '/api/v1/douyin/web/fetch_general_search_result',
- '/api/v1/douyin/web/fetch_general_search_result_v2',
- // app v1/v2
- '/api/v1/douyin/app/v1/fetch_user_search_result',
- '/api/v1/douyin/app/v2/fetch_user_search_result',
- ];
- function get(apiPath, params) {
- const qs = Object.entries(params)
- .filter(([, v]) => v !== undefined && v !== null && v !== '')
- .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
- .join('&');
- return new Promise((resolve) => {
- const opts = {
- hostname: 'api.tikhub.io',
- path: `${apiPath}?${qs}`,
- method: 'GET',
- headers: { Authorization: `Bearer ${TIKHUB_TOKEN}`, Accept: 'application/json' },
- };
- const req = https.request(opts, (res) => {
- const chunks = [];
- res.on('data', (c) => chunks.push(c));
- res.on('end', () => {
- const body = Buffer.concat(chunks).toString('utf-8');
- try {
- resolve({ status: res.statusCode, json: JSON.parse(body) });
- } catch (e) {
- resolve({ status: res.statusCode, json: { _raw: body.slice(0, 200) } });
- }
- });
- });
- req.on('error', (e) => resolve({ status: 0, json: { _error: e.message } }));
- req.setTimeout(20000, () => { req.destroy(); resolve({ status: 0, json: { _error: 'timeout' } }); });
- req.end();
- });
- }
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
- (async () => {
- const out = [];
- for (const p of paths) {
- await sleep(800);
- const r = await get(p, { keyword, cookie: COOKIE, offset: 0, count: 10 });
- const status = r.status;
- const code = r.json?.code;
- const msg = r.json?.message_zh || r.json?.message || r.json?.detail?.message_zh || r.json?.detail?.message;
- const data = r.json?.data;
- const hasData = data != null && !Array.isArray(data) ? Object.keys(data).length : (Array.isArray(data) ? data.length : 0);
- const dataKeys = data && typeof data === 'object' && !Array.isArray(data) ? Object.keys(data).slice(0, 8).join(',') : '';
- const line = { path: p, status, code, msg: (msg || '').slice(0, 80), hasData, dataKeys };
- out.push(line);
- }
- fs.writeFileSync('data/dy-search-paths.json', JSON.stringify(out, null, 2), 'utf-8');
- console.log(JSON.stringify(out, null, 2));
- })();
|