#!/usr/bin/env node // C 组重试:TikTok Shop 正确路径探测(/api/v1/tiktokshop/* 等变体) const fs = require('fs'), path = require('path'), os = require('os'), https = require('https'); const 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+/, ''); function get(p, params = {}) { const qs = Object.entries(params).filter(([, v]) => v !== '' && v != null).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&'); const full = qs ? `${p}?${qs}` : p; return new Promise((r) => { const req = https.request({ hostname: 'api.tikhub.io', path: full, method: 'GET', headers: { Authorization: 'Bearer ' + TOKEN, Accept: 'application/json' } }, (res) => { let b = ''; res.on('data', (c) => b += c); res.on('end', () => { try { r({ s: res.statusCode, j: JSON.parse(b) }); } catch { r({ s: res.statusCode, j: { raw: b.slice(0, 200) } }); } }); }); req.on('error', (e) => r({ s: 0, j: { err: e.message } })); req.setTimeout(15000, () => { req.destroy(); r({ s: 0, j: { err: 'to' } }); }); req.end(); }); } const PATHS = [ // Apifox 文档里的 TikTok-Shop-Web-API 猜测 { p: '/api/v1/tiktokshop/fetch_search_products_v1', q: { keyword: 'milk thistle', region: 'US', page: 1 } }, { p: '/api/v1/tiktokshop/fetch_search_products_v3', q: { keyword: 'milk thistle', region: 'US', page: 1 } }, { p: '/api/v1/tiktokshop/search_products_v1', q: { keyword: 'milk thistle', region: 'US' } }, { p: '/api/v1/tiktokshop/search_products_v3', q: { keyword: 'milk thistle', region: 'US' } }, { p: '/api/v1/tiktok_shop/search_products_v1', q: { keyword: 'milk thistle', region: 'US' } }, { p: '/api/v1/tiktok_shop/fetch_search_products_v1', q: { keyword: 'milk thistle', region: 'US' } }, { p: '/api/v1/tikhub/tiktok_shop/search_products', q: { keyword: 'milk thistle' } }, { p: '/api/v1/tts/search_products_v1', q: { keyword: 'milk thistle', region: 'US' } }, { p: '/api/v1/tts/search_products_v3', q: { keyword: 'milk thistle', region: 'US' } }, { p: '/api/v1/tts/fetch_hot_selling_products', q: { region: 'US' } }, // 或许是 tiktok 大前缀下? { p: '/api/v1/tiktok/shop_web/search_products_v1', q: { keyword: 'milk thistle' } }, { p: '/api/v1/tiktok/shop_web/fetch_search_products_v1', q: { keyword: 'milk thistle' } }, { p: '/api/v1/tiktok/shop_web/fetch_search_products_v3', q: { keyword: 'milk thistle' } }, // 其他可能 { p: '/api/v1/tiktok/tts/search_products_v1', q: { keyword: 'milk thistle' } }, { p: '/api/v1/tiktok/web/tts_search_products_v1', q: { keyword: 'milk thistle' } }, ]; (async () => { for (const x of PATHS) { const r = await get(x.p, x.q); const msg = r.j.message || r.j.msg || r.j.raw || r.j.err || ''; const tag = r.s === 200 ? '✓' : (r.s === 404 ? '—' : '?'); console.log(`${tag} ${r.s.toString().padEnd(4)} ${x.p} ${String(msg).slice(0, 80)}`); if (r.s === 200 && r.j.data) { console.log(' data keys:', Object.keys(r.j.data).slice(0, 6)); } await new Promise((r) => setTimeout(r, 400)); } })();