@sns-parse/core 0.4.0-alpha.4 → 0.4.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -138,6 +138,36 @@ function pick(...vals) {
138
138
  return v;
139
139
  return '';
140
140
  }
141
+ /** BFS 深取子树中第一个非空的指定键值(X GraphQL 用户结构随版本漂移:legacy ↔ core/avatar) */
142
+ function deepPick(node, key) {
143
+ const queue = [node];
144
+ while (queue.length) {
145
+ const cur = queue.shift();
146
+ if (!cur || typeof cur !== 'object')
147
+ continue;
148
+ const v = cur[key];
149
+ if (v !== undefined && v !== null && v !== '')
150
+ return v;
151
+ for (const k of Object.keys(cur))
152
+ queue.push(cur[k]);
153
+ }
154
+ return undefined;
155
+ }
156
+ /** BFS 找子树中最长的 text 字符串(笔记正文位置随版本漂移,取最长以避开截断副本) */
157
+ function deepFindLongestText(node) {
158
+ let best;
159
+ const queue = [node];
160
+ while (queue.length) {
161
+ const cur = queue.shift();
162
+ if (!cur || typeof cur !== 'object')
163
+ continue;
164
+ if (typeof cur.text === 'string' && cur.text && (!best || cur.text.length > best.length))
165
+ best = cur.text;
166
+ for (const k of Object.keys(cur))
167
+ queue.push(cur[k]);
168
+ }
169
+ return best;
170
+ }
141
171
  /** 清理描述中的 t.co 短链(Twitter 自动附加的截断 URL,无实际内容价值) */
142
172
  function cleanDesc(text) {
143
173
  if (!text)
@@ -273,9 +303,10 @@ function mapGraphql(rawResult) {
273
303
  }
274
304
  const legacy = result.legacy || {};
275
305
  const user = result.core?.user_results?.result;
276
- const ulegacy = user?.legacy || {};
277
- // 长推(note tweet):legacy.full_text 是截断版,全文在 note_tweet.note_results.note.text
278
- const text = String(pick(result.note_tweet?.note_results?.note?.text, legacy.full_text, ''));
306
+ const ures = user || {};
307
+ // 长推(note tweet):legacy.full_text 是截断版,全文在 note_tweet 子树(位置随版本漂移,深取最长 text)
308
+ // 用户字段同理:legacy ↔ core/avatar/profile_bio 漂移,深取键值
309
+ const text = String(pick(deepFindLongestText(result.note_tweet), legacy.full_text, ''));
279
310
  const p = baseParsed();
280
311
  const media = Array.isArray(legacy.entities?.media) ? legacy.entities.media : [];
281
312
  const photos = [];
@@ -319,9 +350,9 @@ function mapGraphql(rawResult) {
319
350
  p.title = cleaned.slice(0, 100);
320
351
  p.desc = cleaned;
321
352
  p.lang = legacy.lang ? String(legacy.lang) : undefined;
322
- p.author = String(pick(ulegacy.name, ulegacy.screen_name, ''));
323
- p.uid = String(pick(ulegacy.screen_name, user?.rest_id, ''));
324
- p.avatar = String(pick(ulegacy.profile_image_url_https, ''));
353
+ p.author = String(pick(deepPick(ures, 'name'), ''));
354
+ p.uid = String(pick(deepPick(ures, 'screen_name'), user?.rest_id, ''));
355
+ p.avatar = String(pick(deepPick(ures, 'profile_image_url_https'), deepPick(ures, 'image_url'), ''));
325
356
  p.like = Number(pick(legacy.favorite_count, 0)) || 0;
326
357
  p.comment = Number(pick(legacy.reply_count, 0)) || 0;
327
358
  p.share = Number(pick(legacy.retweet_count, 0)) || 0;
@@ -332,8 +363,8 @@ function mapGraphql(rawResult) {
332
363
  if (!isNaN(t))
333
364
  p.publishTime = t;
334
365
  }
335
- p.author_followers = Number(pick(ulegacy.followers_count, 0)) || 0;
336
- p.author_signature = String(pick(ulegacy.description, ''));
366
+ p.author_followers = Number(pick(deepPick(ures, 'followers_count'), 0)) || 0;
367
+ p.author_signature = String(pick(deepPick(ures, 'description'), ''));
337
368
  if (p.title && p.desc && p.desc.startsWith(p.title))
338
369
  p.title = '';
339
370
  return p;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sns-parse/core",
3
- "version": "0.4.0-alpha.4+upstream.1.6.7",
3
+ "version": "0.4.0-alpha.5+upstream.1.6.7",
4
4
  "description": "sns-parse 核心:契约、宿主抽象、配置 DSL 与解析引擎(fetcher/parser/翻译/X 原生解析/合并/GIF/TLS 指纹客户端)",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",