probe-tikhub-douyin4.js 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #!/usr/bin/env node
  2. /** 尝试不需 cookie 的 TikHub douyin endpoints + TikTok */
  3. const fs = require('fs');
  4. const path = require('path');
  5. const os = require('os');
  6. const https = require('https');
  7. 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+/, '');
  8. function req(opts) {
  9. return new Promise((resolve) => {
  10. const r = https.request(opts, (res) => {
  11. const chunks = [];
  12. res.on('data', (c) => chunks.push(c));
  13. res.on('end', () => resolve({ status: res.statusCode, body: Buffer.concat(chunks).toString('utf-8') }));
  14. });
  15. r.on('error', (e) => resolve({ status: 0, body: e.message }));
  16. r.setTimeout(30000, () => { r.destroy(); resolve({ status: 0, body: 'timeout' }); });
  17. r.end();
  18. });
  19. }
  20. const kw = '乳酸菌素片';
  21. const kwE = encodeURIComponent(kw);
  22. // 尝试各种可能不要 cookie 的 endpoints
  23. const tries = [
  24. // Douyin web search variations
  25. `/thapi/v1/douyin/web/fetch_general_search_result?keyword=${kwE}&offset=0&count=20&sort_type=0&publish_time=0&search_channel=aweme_general`,
  26. // Specific challenge / hashtag search (不要 cookie)
  27. `/thapi/v1/douyin/web/fetch_challenge_search?keyword=${kwE}&offset=0&count=20`,
  28. `/thapi/v1/douyin/app/v1/fetch_challenge_search?keyword=${kwE}&offset=0&count=20`,
  29. // Hot video / hot search
  30. `/thapi/v1/douyin/web/fetch_hot_search_list`,
  31. `/thapi/v1/douyin/app/v3/fetch_hot_search_list`,
  32. // Video by ID (如果我们已知 aweme_id)
  33. `/thapi/v1/douyin/web/fetch_one_video?aweme_id=7358400000000000000`,
  34. // Live search
  35. `/thapi/v1/douyin/web/fetch_live_search?keyword=${kwE}&offset=0&count=20`,
  36. // User search
  37. `/thapi/v1/douyin/web/fetch_user_search_result?keyword=${kwE}&offset=0&count=20`,
  38. // TikTok (海外版)
  39. `/thapi/v1/tiktok/app/v3/fetch_general_search_result?keyword=${kwE}&offset=0&count=20`,
  40. `/thapi/v1/tiktok/web/fetch_general_search?keyword=${kwE}&offset=0&count=20`,
  41. ];
  42. (async () => {
  43. for (const p of tries) {
  44. const r = await req({
  45. hostname: 'server.fmode.cn', path: p, method: 'GET',
  46. headers: { Authorization: `Bearer ${TOKEN}`, Accept: 'application/json' },
  47. });
  48. let summary = '';
  49. try {
  50. const j = JSON.parse(r.body);
  51. if (Array.isArray(j.data)) {
  52. const first = j.data[0];
  53. summary = `data=Array(${j.data.length}), status_msg=${first?.status_msg || '(none)'}`;
  54. } else if (j.data) {
  55. const k = Object.keys(j.data);
  56. summary = `data=Object{${k.slice(0, 5).join(',')}}`;
  57. if (j.data.data && Array.isArray(j.data.data)) summary += `, data.data=Array(${j.data.data.length})`;
  58. if (j.data.aweme_list) summary += `, aweme_list=${j.data.aweme_list.length}`;
  59. if (j.data.user_list) summary += `, user_list=${j.data.user_list.length}`;
  60. if (j.data.challenge_list) summary += `, challenge_list=${j.data.challenge_list.length}`;
  61. } else if (j.detail) {
  62. summary = `detail=${JSON.stringify(j.detail).slice(0, 80)}`;
  63. }
  64. } catch (e) { summary = r.body.slice(0, 80); }
  65. console.log(`[${r.status}] ${p.slice(0, 85)}`);
  66. console.log(` → ${summary}`);
  67. await new Promise((r) => setTimeout(r, 700));
  68. }
  69. })();