@tikomni/skills 0.1.0

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.
Files changed (451) hide show
  1. package/.skill-package-allowlist.txt +4 -0
  2. package/LICENSE +21 -0
  3. package/README.md +167 -0
  4. package/README.zh-CN.md +167 -0
  5. package/bin/tikomni-skills.js +127 -0
  6. package/env.example +160 -0
  7. package/lib/installer.js +176 -0
  8. package/package.json +44 -0
  9. package/skills/creator-analysis/SKILL.md +71 -0
  10. package/skills/creator-analysis/agents/openai.yaml +4 -0
  11. package/skills/creator-analysis/env.example +36 -0
  12. package/skills/creator-analysis/references/api-capability-index.md +92 -0
  13. package/skills/creator-analysis/references/api-contracts/asr-api.md +130 -0
  14. package/skills/creator-analysis/references/api-contracts/bilibili-app-api.md +776 -0
  15. package/skills/creator-analysis/references/api-contracts/bilibili-web-api.md +2017 -0
  16. package/skills/creator-analysis/references/api-contracts/demo-api.md +717 -0
  17. package/skills/creator-analysis/references/api-contracts/douyin-app-v3-api.md +3594 -0
  18. package/skills/creator-analysis/references/api-contracts/douyin-billboard-api.md +2274 -0
  19. package/skills/creator-analysis/references/api-contracts/douyin-creator-api.md +1575 -0
  20. package/skills/creator-analysis/references/api-contracts/douyin-creator-v2-api.md +3254 -0
  21. package/skills/creator-analysis/references/api-contracts/douyin-search-api.md +4118 -0
  22. package/skills/creator-analysis/references/api-contracts/douyin-web-api.md +5544 -0
  23. package/skills/creator-analysis/references/api-contracts/douyin-xingtu-api.md +1916 -0
  24. package/skills/creator-analysis/references/api-contracts/douyin-xingtu-v2-api.md +1540 -0
  25. package/skills/creator-analysis/references/api-contracts/health-check.md +69 -0
  26. package/skills/creator-analysis/references/api-contracts/hybrid-parsing.md +78 -0
  27. package/skills/creator-analysis/references/api-contracts/instagram-v1-api.md +2256 -0
  28. package/skills/creator-analysis/references/api-contracts/instagram-v2-api.md +2011 -0
  29. package/skills/creator-analysis/references/api-contracts/instagram-v3-api.md +2630 -0
  30. package/skills/creator-analysis/references/api-contracts/ios-shortcut.md +44 -0
  31. package/skills/creator-analysis/references/api-contracts/kuaishou-app-api.md +1518 -0
  32. package/skills/creator-analysis/references/api-contracts/kuaishou-web-api.md +1242 -0
  33. package/skills/creator-analysis/references/api-contracts/lemon8-app-api.md +1088 -0
  34. package/skills/creator-analysis/references/api-contracts/linkedin-web-api.md +1949 -0
  35. package/skills/creator-analysis/references/api-contracts/media-ingest-api.md +126 -0
  36. package/skills/creator-analysis/references/api-contracts/pipixia-app-api.md +1142 -0
  37. package/skills/creator-analysis/references/api-contracts/reddit-app-api.md +2025 -0
  38. package/skills/creator-analysis/references/api-contracts/sora2-api.md +2266 -0
  39. package/skills/creator-analysis/references/api-contracts/temp-mail-api.md +208 -0
  40. package/skills/creator-analysis/references/api-contracts/threads-web-api.md +897 -0
  41. package/skills/creator-analysis/references/api-contracts/tikhub-downloader-api.md +134 -0
  42. package/skills/creator-analysis/references/api-contracts/tikhub-user-api.md +494 -0
  43. package/skills/creator-analysis/references/api-contracts/tiktok-ads-api.md +5947 -0
  44. package/skills/creator-analysis/references/api-contracts/tiktok-analytics-api.md +968 -0
  45. package/skills/creator-analysis/references/api-contracts/tiktok-app-v3-api.md +5735 -0
  46. package/skills/creator-analysis/references/api-contracts/tiktok-creator-api.md +1951 -0
  47. package/skills/creator-analysis/references/api-contracts/tiktok-interaction-api.md +742 -0
  48. package/skills/creator-analysis/references/api-contracts/tiktok-shop-web-api.md +1890 -0
  49. package/skills/creator-analysis/references/api-contracts/tiktok-web-api.md +4448 -0
  50. package/skills/creator-analysis/references/api-contracts/toutiao-app-api.md +342 -0
  51. package/skills/creator-analysis/references/api-contracts/toutiao-web-api.md +143 -0
  52. package/skills/creator-analysis/references/api-contracts/twitter-web-api.md +989 -0
  53. package/skills/creator-analysis/references/api-contracts/wechat-channels-api.md +809 -0
  54. package/skills/creator-analysis/references/api-contracts/wechat-media-platform-web-api.md +677 -0
  55. package/skills/creator-analysis/references/api-contracts/weibo-app-api.md +1547 -0
  56. package/skills/creator-analysis/references/api-contracts/weibo-web-api.md +798 -0
  57. package/skills/creator-analysis/references/api-contracts/weibo-web-v2-api.md +2459 -0
  58. package/skills/creator-analysis/references/api-contracts/xiaohongshu-app-api.md +1291 -0
  59. package/skills/creator-analysis/references/api-contracts/xiaohongshu-app-v2-api.md +1683 -0
  60. package/skills/creator-analysis/references/api-contracts/xiaohongshu-web-api.md +1324 -0
  61. package/skills/creator-analysis/references/api-contracts/xiaohongshu-web-v2-api.md +1209 -0
  62. package/skills/creator-analysis/references/api-contracts/xigua-app-v2-api.md +489 -0
  63. package/skills/creator-analysis/references/api-contracts/youtube-web-api.md +2636 -0
  64. package/skills/creator-analysis/references/api-contracts/youtube-web-v2-api.md +2660 -0
  65. package/skills/creator-analysis/references/api-contracts/zhihu-web-api.md +2315 -0
  66. package/skills/creator-analysis/references/api-tags/asr-api.md +100 -0
  67. package/skills/creator-analysis/references/api-tags/bilibili-app-api.md +482 -0
  68. package/skills/creator-analysis/references/api-tags/bilibili-web-api.md +1267 -0
  69. package/skills/creator-analysis/references/api-tags/demo-api.md +365 -0
  70. package/skills/creator-analysis/references/api-tags/douyin-app-v3-api.md +2012 -0
  71. package/skills/creator-analysis/references/api-tags/douyin-billboard-api.md +1428 -0
  72. package/skills/creator-analysis/references/api-tags/douyin-creator-api.md +694 -0
  73. package/skills/creator-analysis/references/api-tags/douyin-creator-v2-api.md +694 -0
  74. package/skills/creator-analysis/references/api-tags/douyin-search-api.md +1059 -0
  75. package/skills/creator-analysis/references/api-tags/douyin-web-api.md +3314 -0
  76. package/skills/creator-analysis/references/api-tags/douyin-xingtu-api.md +935 -0
  77. package/skills/creator-analysis/references/api-tags/douyin-xingtu-v2-api.md +925 -0
  78. package/skills/creator-analysis/references/api-tags/health-check.md +40 -0
  79. package/skills/creator-analysis/references/api-tags/hybrid-parsing.md +57 -0
  80. package/skills/creator-analysis/references/api-tags/instagram-v1-api.md +1224 -0
  81. package/skills/creator-analysis/references/api-tags/instagram-v2-api.md +1147 -0
  82. package/skills/creator-analysis/references/api-tags/instagram-v3-api.md +1123 -0
  83. package/skills/creator-analysis/references/api-tags/ios-shortcut.md +45 -0
  84. package/skills/creator-analysis/references/api-tags/kuaishou-app-api.md +846 -0
  85. package/skills/creator-analysis/references/api-tags/kuaishou-web-api.md +551 -0
  86. package/skills/creator-analysis/references/api-tags/lemon8-app-api.md +687 -0
  87. package/skills/creator-analysis/references/api-tags/linkedin-web-api.md +1105 -0
  88. package/skills/creator-analysis/references/api-tags/media-ingest-api.md +112 -0
  89. package/skills/creator-analysis/references/api-tags/pipixia-app-api.md +721 -0
  90. package/skills/creator-analysis/references/api-tags/reddit-app-api.md +1057 -0
  91. package/skills/creator-analysis/references/api-tags/sora2-api.md +737 -0
  92. package/skills/creator-analysis/references/api-tags/temp-mail-api.md +136 -0
  93. package/skills/creator-analysis/references/api-tags/threads-web-api.md +472 -0
  94. package/skills/creator-analysis/references/api-tags/tikhub-downloader-api.md +65 -0
  95. package/skills/creator-analysis/references/api-tags/tikhub-user-api.md +253 -0
  96. package/skills/creator-analysis/references/api-tags/tiktok-ads-api.md +1393 -0
  97. package/skills/creator-analysis/references/api-tags/tiktok-analytics-api.md +179 -0
  98. package/skills/creator-analysis/references/api-tags/tiktok-app-v3-api.md +3264 -0
  99. package/skills/creator-analysis/references/api-tags/tiktok-creator-api.md +709 -0
  100. package/skills/creator-analysis/references/api-tags/tiktok-interaction-api.md +366 -0
  101. package/skills/creator-analysis/references/api-tags/tiktok-shop-web-api.md +663 -0
  102. package/skills/creator-analysis/references/api-tags/tiktok-web-api.md +2516 -0
  103. package/skills/creator-analysis/references/api-tags/toutiao-app-api.md +220 -0
  104. package/skills/creator-analysis/references/api-tags/toutiao-web-api.md +96 -0
  105. package/skills/creator-analysis/references/api-tags/twitter-web-api.md +562 -0
  106. package/skills/creator-analysis/references/api-tags/wechat-channels-api.md +405 -0
  107. package/skills/creator-analysis/references/api-tags/wechat-media-platform-web-api.md +431 -0
  108. package/skills/creator-analysis/references/api-tags/weibo-app-api.md +851 -0
  109. package/skills/creator-analysis/references/api-tags/weibo-web-api.md +470 -0
  110. package/skills/creator-analysis/references/api-tags/weibo-web-v2-api.md +1405 -0
  111. package/skills/creator-analysis/references/api-tags/xiaohongshu-app-api.md +534 -0
  112. package/skills/creator-analysis/references/api-tags/xiaohongshu-app-v2-api.md +934 -0
  113. package/skills/creator-analysis/references/api-tags/xiaohongshu-web-api.md +757 -0
  114. package/skills/creator-analysis/references/api-tags/xiaohongshu-web-v2-api.md +762 -0
  115. package/skills/creator-analysis/references/api-tags/xigua-app-v2-api.md +308 -0
  116. package/skills/creator-analysis/references/api-tags/youtube-web-api.md +934 -0
  117. package/skills/creator-analysis/references/api-tags/youtube-web-v2-api.md +717 -0
  118. package/skills/creator-analysis/references/api-tags/zhihu-web-api.md +1384 -0
  119. package/skills/creator-analysis/references/asr-orchestration.md +33 -0
  120. package/skills/creator-analysis/references/config-templates/defaults.yaml +60 -0
  121. package/skills/creator-analysis/references/contracts/creator-card-fields.md +23 -0
  122. package/skills/creator-analysis/references/contracts/work-card-fields.md +32 -0
  123. package/skills/creator-analysis/references/platform-guides/douyin.md +49 -0
  124. package/skills/creator-analysis/references/platform-guides/generic.md +46 -0
  125. package/skills/creator-analysis/references/platform-guides/xiaohongshu.md +54 -0
  126. package/skills/creator-analysis/references/prompt-contracts/asr-clean.md +28 -0
  127. package/skills/creator-analysis/references/prompt-contracts/author-analysis-v2.md +46 -0
  128. package/skills/creator-analysis/references/prompt-contracts/author-analysis.md +49 -0
  129. package/skills/creator-analysis/references/prompt-contracts/cta.md +24 -0
  130. package/skills/creator-analysis/references/prompt-contracts/hook.md +25 -0
  131. package/skills/creator-analysis/references/prompt-contracts/insight.md +47 -0
  132. package/skills/creator-analysis/references/prompt-contracts/sampled-work-batch-explanations.md +30 -0
  133. package/skills/creator-analysis/references/prompt-contracts/structure.md +25 -0
  134. package/skills/creator-analysis/references/prompt-contracts/style.md +27 -0
  135. package/skills/creator-analysis/references/prompt-contracts/summary.md +29 -0
  136. package/skills/creator-analysis/references/prompt-contracts/topic.md +29 -0
  137. package/skills/creator-analysis/references/schemas/author-analysis-input-v1.schema.json +325 -0
  138. package/skills/creator-analysis/references/schemas/author-analysis-v2.schema.json +158 -0
  139. package/skills/creator-analysis/references/schemas/sampled-work-batch-explanations.schema.json +41 -0
  140. package/skills/creator-analysis/references/service-guides/asr-u2-u3-fallback.md +75 -0
  141. package/skills/creator-analysis/references/workflow.md +18 -0
  142. package/skills/creator-analysis/scripts/__init__.py +0 -0
  143. package/skills/creator-analysis/scripts/author_home/__init__.py +0 -0
  144. package/skills/creator-analysis/scripts/author_home/adapters/__init__.py +0 -0
  145. package/skills/creator-analysis/scripts/author_home/adapters/platform_adapters.py +299 -0
  146. package/skills/creator-analysis/scripts/author_home/analyzers/__init__.py +0 -0
  147. package/skills/creator-analysis/scripts/author_home/analyzers/author_analysis_v2_support.py +1122 -0
  148. package/skills/creator-analysis/scripts/author_home/analyzers/prompt_first_analyzers.py +260 -0
  149. package/skills/creator-analysis/scripts/author_home/analyzers/sampled_work_batch_explainer.py +260 -0
  150. package/skills/creator-analysis/scripts/author_home/asr/__init__.py +5 -0
  151. package/skills/creator-analysis/scripts/author_home/asr/home_asr.py +961 -0
  152. package/skills/creator-analysis/scripts/author_home/builders/__init__.py +0 -0
  153. package/skills/creator-analysis/scripts/author_home/builders/home_builders.py +149 -0
  154. package/skills/creator-analysis/scripts/author_home/collectors/__init__.py +0 -0
  155. package/skills/creator-analysis/scripts/author_home/collectors/homepage_collectors.py +636 -0
  156. package/skills/creator-analysis/scripts/author_home/orchestrator/__init__.py +0 -0
  157. package/skills/creator-analysis/scripts/author_home/orchestrator/run_author_analysis.py +491 -0
  158. package/skills/creator-analysis/scripts/author_home/orchestrator/work_analysis_artifacts.py +553 -0
  159. package/skills/creator-analysis/scripts/author_home/schema.py +417 -0
  160. package/skills/creator-analysis/scripts/core/__init__.py +0 -0
  161. package/skills/creator-analysis/scripts/core/analysis_pipeline.py +133 -0
  162. package/skills/creator-analysis/scripts/core/bootstrap_env.py +35 -0
  163. package/skills/creator-analysis/scripts/core/config_loader.py +418 -0
  164. package/skills/creator-analysis/scripts/core/extract_pipeline.py +173 -0
  165. package/skills/creator-analysis/scripts/core/progress_report.py +111 -0
  166. package/skills/creator-analysis/scripts/core/storage_router.py +253 -0
  167. package/skills/creator-analysis/scripts/core/tikomni_common.py +588 -0
  168. package/skills/creator-analysis/scripts/pipeline/__init__.py +0 -0
  169. package/skills/creator-analysis/scripts/pipeline/asr/__init__.py +0 -0
  170. package/skills/creator-analysis/scripts/pipeline/asr/asr_pipeline.py +1189 -0
  171. package/skills/creator-analysis/scripts/pipeline/asr/poll_u2_task.py +95 -0
  172. package/skills/creator-analysis/scripts/platform/__init__.py +0 -0
  173. package/skills/creator-analysis/scripts/platform/douyin/__init__.py +0 -0
  174. package/skills/creator-analysis/scripts/platform/douyin/douyin_video_type_matrix.py +224 -0
  175. package/skills/creator-analysis/scripts/platform/douyin/run_douyin_single_video.py +1208 -0
  176. package/skills/creator-analysis/scripts/platform/douyin/select_low_quality_video_url.py +200 -0
  177. package/skills/creator-analysis/scripts/platform/xiaohongshu/__init__.py +0 -0
  178. package/skills/creator-analysis/scripts/platform/xiaohongshu/run_xiaohongshu_extract.py +2128 -0
  179. package/skills/creator-analysis/scripts/writers/__init__.py +0 -0
  180. package/skills/creator-analysis/scripts/writers/write_author_homepage_samples.py +106 -0
  181. package/skills/creator-analysis/scripts/writers/write_benchmark_card.py +1402 -0
  182. package/skills/meta-capability/SKILL.md +69 -0
  183. package/skills/meta-capability/agents/openai.yaml +4 -0
  184. package/skills/meta-capability/env.example +42 -0
  185. package/skills/meta-capability/references/api-capability-index.md +92 -0
  186. package/skills/meta-capability/references/api-contracts/asr-api.md +130 -0
  187. package/skills/meta-capability/references/api-contracts/bilibili-app-api.md +776 -0
  188. package/skills/meta-capability/references/api-contracts/bilibili-web-api.md +2017 -0
  189. package/skills/meta-capability/references/api-contracts/demo-api.md +717 -0
  190. package/skills/meta-capability/references/api-contracts/douyin-app-v3-api.md +3594 -0
  191. package/skills/meta-capability/references/api-contracts/douyin-billboard-api.md +2274 -0
  192. package/skills/meta-capability/references/api-contracts/douyin-creator-api.md +1575 -0
  193. package/skills/meta-capability/references/api-contracts/douyin-creator-v2-api.md +3254 -0
  194. package/skills/meta-capability/references/api-contracts/douyin-search-api.md +4118 -0
  195. package/skills/meta-capability/references/api-contracts/douyin-web-api.md +5544 -0
  196. package/skills/meta-capability/references/api-contracts/douyin-xingtu-api.md +1916 -0
  197. package/skills/meta-capability/references/api-contracts/douyin-xingtu-v2-api.md +1540 -0
  198. package/skills/meta-capability/references/api-contracts/health-check.md +69 -0
  199. package/skills/meta-capability/references/api-contracts/hybrid-parsing.md +78 -0
  200. package/skills/meta-capability/references/api-contracts/instagram-v1-api.md +2256 -0
  201. package/skills/meta-capability/references/api-contracts/instagram-v2-api.md +2011 -0
  202. package/skills/meta-capability/references/api-contracts/instagram-v3-api.md +2630 -0
  203. package/skills/meta-capability/references/api-contracts/ios-shortcut.md +44 -0
  204. package/skills/meta-capability/references/api-contracts/kuaishou-app-api.md +1518 -0
  205. package/skills/meta-capability/references/api-contracts/kuaishou-web-api.md +1242 -0
  206. package/skills/meta-capability/references/api-contracts/lemon8-app-api.md +1088 -0
  207. package/skills/meta-capability/references/api-contracts/linkedin-web-api.md +1949 -0
  208. package/skills/meta-capability/references/api-contracts/media-ingest-api.md +126 -0
  209. package/skills/meta-capability/references/api-contracts/pipixia-app-api.md +1142 -0
  210. package/skills/meta-capability/references/api-contracts/reddit-app-api.md +2025 -0
  211. package/skills/meta-capability/references/api-contracts/sora2-api.md +2266 -0
  212. package/skills/meta-capability/references/api-contracts/temp-mail-api.md +208 -0
  213. package/skills/meta-capability/references/api-contracts/threads-web-api.md +897 -0
  214. package/skills/meta-capability/references/api-contracts/tikhub-downloader-api.md +134 -0
  215. package/skills/meta-capability/references/api-contracts/tikhub-user-api.md +494 -0
  216. package/skills/meta-capability/references/api-contracts/tiktok-ads-api.md +5947 -0
  217. package/skills/meta-capability/references/api-contracts/tiktok-analytics-api.md +968 -0
  218. package/skills/meta-capability/references/api-contracts/tiktok-app-v3-api.md +5735 -0
  219. package/skills/meta-capability/references/api-contracts/tiktok-creator-api.md +1951 -0
  220. package/skills/meta-capability/references/api-contracts/tiktok-interaction-api.md +742 -0
  221. package/skills/meta-capability/references/api-contracts/tiktok-shop-web-api.md +1890 -0
  222. package/skills/meta-capability/references/api-contracts/tiktok-web-api.md +4448 -0
  223. package/skills/meta-capability/references/api-contracts/toutiao-app-api.md +342 -0
  224. package/skills/meta-capability/references/api-contracts/toutiao-web-api.md +143 -0
  225. package/skills/meta-capability/references/api-contracts/twitter-web-api.md +989 -0
  226. package/skills/meta-capability/references/api-contracts/wechat-channels-api.md +809 -0
  227. package/skills/meta-capability/references/api-contracts/wechat-media-platform-web-api.md +677 -0
  228. package/skills/meta-capability/references/api-contracts/weibo-app-api.md +1547 -0
  229. package/skills/meta-capability/references/api-contracts/weibo-web-api.md +798 -0
  230. package/skills/meta-capability/references/api-contracts/weibo-web-v2-api.md +2459 -0
  231. package/skills/meta-capability/references/api-contracts/xiaohongshu-app-api.md +1291 -0
  232. package/skills/meta-capability/references/api-contracts/xiaohongshu-app-v2-api.md +1683 -0
  233. package/skills/meta-capability/references/api-contracts/xiaohongshu-web-api.md +1324 -0
  234. package/skills/meta-capability/references/api-contracts/xiaohongshu-web-v2-api.md +1209 -0
  235. package/skills/meta-capability/references/api-contracts/xigua-app-v2-api.md +489 -0
  236. package/skills/meta-capability/references/api-contracts/youtube-web-api.md +2636 -0
  237. package/skills/meta-capability/references/api-contracts/youtube-web-v2-api.md +2660 -0
  238. package/skills/meta-capability/references/api-contracts/zhihu-web-api.md +2315 -0
  239. package/skills/meta-capability/references/api-tags/asr-api.md +100 -0
  240. package/skills/meta-capability/references/api-tags/bilibili-app-api.md +482 -0
  241. package/skills/meta-capability/references/api-tags/bilibili-web-api.md +1267 -0
  242. package/skills/meta-capability/references/api-tags/demo-api.md +365 -0
  243. package/skills/meta-capability/references/api-tags/douyin-app-v3-api.md +2012 -0
  244. package/skills/meta-capability/references/api-tags/douyin-billboard-api.md +1428 -0
  245. package/skills/meta-capability/references/api-tags/douyin-creator-api.md +694 -0
  246. package/skills/meta-capability/references/api-tags/douyin-creator-v2-api.md +694 -0
  247. package/skills/meta-capability/references/api-tags/douyin-search-api.md +1059 -0
  248. package/skills/meta-capability/references/api-tags/douyin-web-api.md +3314 -0
  249. package/skills/meta-capability/references/api-tags/douyin-xingtu-api.md +935 -0
  250. package/skills/meta-capability/references/api-tags/douyin-xingtu-v2-api.md +925 -0
  251. package/skills/meta-capability/references/api-tags/health-check.md +40 -0
  252. package/skills/meta-capability/references/api-tags/hybrid-parsing.md +57 -0
  253. package/skills/meta-capability/references/api-tags/instagram-v1-api.md +1224 -0
  254. package/skills/meta-capability/references/api-tags/instagram-v2-api.md +1147 -0
  255. package/skills/meta-capability/references/api-tags/instagram-v3-api.md +1123 -0
  256. package/skills/meta-capability/references/api-tags/ios-shortcut.md +45 -0
  257. package/skills/meta-capability/references/api-tags/kuaishou-app-api.md +846 -0
  258. package/skills/meta-capability/references/api-tags/kuaishou-web-api.md +551 -0
  259. package/skills/meta-capability/references/api-tags/lemon8-app-api.md +687 -0
  260. package/skills/meta-capability/references/api-tags/linkedin-web-api.md +1105 -0
  261. package/skills/meta-capability/references/api-tags/media-ingest-api.md +112 -0
  262. package/skills/meta-capability/references/api-tags/pipixia-app-api.md +721 -0
  263. package/skills/meta-capability/references/api-tags/reddit-app-api.md +1057 -0
  264. package/skills/meta-capability/references/api-tags/sora2-api.md +737 -0
  265. package/skills/meta-capability/references/api-tags/temp-mail-api.md +136 -0
  266. package/skills/meta-capability/references/api-tags/threads-web-api.md +472 -0
  267. package/skills/meta-capability/references/api-tags/tikhub-downloader-api.md +65 -0
  268. package/skills/meta-capability/references/api-tags/tikhub-user-api.md +253 -0
  269. package/skills/meta-capability/references/api-tags/tiktok-ads-api.md +1393 -0
  270. package/skills/meta-capability/references/api-tags/tiktok-analytics-api.md +179 -0
  271. package/skills/meta-capability/references/api-tags/tiktok-app-v3-api.md +3264 -0
  272. package/skills/meta-capability/references/api-tags/tiktok-creator-api.md +709 -0
  273. package/skills/meta-capability/references/api-tags/tiktok-interaction-api.md +366 -0
  274. package/skills/meta-capability/references/api-tags/tiktok-shop-web-api.md +663 -0
  275. package/skills/meta-capability/references/api-tags/tiktok-web-api.md +2516 -0
  276. package/skills/meta-capability/references/api-tags/toutiao-app-api.md +220 -0
  277. package/skills/meta-capability/references/api-tags/toutiao-web-api.md +96 -0
  278. package/skills/meta-capability/references/api-tags/twitter-web-api.md +562 -0
  279. package/skills/meta-capability/references/api-tags/wechat-channels-api.md +405 -0
  280. package/skills/meta-capability/references/api-tags/wechat-media-platform-web-api.md +431 -0
  281. package/skills/meta-capability/references/api-tags/weibo-app-api.md +851 -0
  282. package/skills/meta-capability/references/api-tags/weibo-web-api.md +470 -0
  283. package/skills/meta-capability/references/api-tags/weibo-web-v2-api.md +1405 -0
  284. package/skills/meta-capability/references/api-tags/xiaohongshu-app-api.md +534 -0
  285. package/skills/meta-capability/references/api-tags/xiaohongshu-app-v2-api.md +934 -0
  286. package/skills/meta-capability/references/api-tags/xiaohongshu-web-api.md +757 -0
  287. package/skills/meta-capability/references/api-tags/xiaohongshu-web-v2-api.md +762 -0
  288. package/skills/meta-capability/references/api-tags/xigua-app-v2-api.md +308 -0
  289. package/skills/meta-capability/references/api-tags/youtube-web-api.md +934 -0
  290. package/skills/meta-capability/references/api-tags/youtube-web-v2-api.md +717 -0
  291. package/skills/meta-capability/references/api-tags/zhihu-web-api.md +1384 -0
  292. package/skills/meta-capability/references/config-templates/defaults.yaml +18 -0
  293. package/skills/meta-capability/references/dispatch.md +27 -0
  294. package/skills/meta-capability/references/execution-guidelines.md +25 -0
  295. package/skills/meta-capability/references/implemented-route-map.md +177 -0
  296. package/skills/meta-capability/references/service-guides/asr-u2-u3-fallback.md +75 -0
  297. package/skills/meta-capability/scripts/__init__.py +1 -0
  298. package/skills/meta-capability/scripts/call_route.py +141 -0
  299. package/skills/meta-capability/scripts/core/__init__.py +1 -0
  300. package/skills/meta-capability/scripts/core/bootstrap_env.py +32 -0
  301. package/skills/meta-capability/scripts/core/config_loader.py +204 -0
  302. package/skills/meta-capability/scripts/core/tikomni_common.py +443 -0
  303. package/skills/meta-capability/scripts/test_auth.py +98 -0
  304. package/skills/single-work-analysis/SKILL.md +62 -0
  305. package/skills/single-work-analysis/agents/openai.yaml +4 -0
  306. package/skills/single-work-analysis/env.example +36 -0
  307. package/skills/single-work-analysis/references/api-capability-index.md +92 -0
  308. package/skills/single-work-analysis/references/api-contracts/asr-api.md +130 -0
  309. package/skills/single-work-analysis/references/api-contracts/bilibili-app-api.md +776 -0
  310. package/skills/single-work-analysis/references/api-contracts/bilibili-web-api.md +2017 -0
  311. package/skills/single-work-analysis/references/api-contracts/demo-api.md +717 -0
  312. package/skills/single-work-analysis/references/api-contracts/douyin-app-v3-api.md +3594 -0
  313. package/skills/single-work-analysis/references/api-contracts/douyin-billboard-api.md +2274 -0
  314. package/skills/single-work-analysis/references/api-contracts/douyin-creator-api.md +1575 -0
  315. package/skills/single-work-analysis/references/api-contracts/douyin-creator-v2-api.md +3254 -0
  316. package/skills/single-work-analysis/references/api-contracts/douyin-search-api.md +4118 -0
  317. package/skills/single-work-analysis/references/api-contracts/douyin-web-api.md +5544 -0
  318. package/skills/single-work-analysis/references/api-contracts/douyin-xingtu-api.md +1916 -0
  319. package/skills/single-work-analysis/references/api-contracts/douyin-xingtu-v2-api.md +1540 -0
  320. package/skills/single-work-analysis/references/api-contracts/health-check.md +69 -0
  321. package/skills/single-work-analysis/references/api-contracts/hybrid-parsing.md +78 -0
  322. package/skills/single-work-analysis/references/api-contracts/instagram-v1-api.md +2256 -0
  323. package/skills/single-work-analysis/references/api-contracts/instagram-v2-api.md +2011 -0
  324. package/skills/single-work-analysis/references/api-contracts/instagram-v3-api.md +2630 -0
  325. package/skills/single-work-analysis/references/api-contracts/ios-shortcut.md +44 -0
  326. package/skills/single-work-analysis/references/api-contracts/kuaishou-app-api.md +1518 -0
  327. package/skills/single-work-analysis/references/api-contracts/kuaishou-web-api.md +1242 -0
  328. package/skills/single-work-analysis/references/api-contracts/lemon8-app-api.md +1088 -0
  329. package/skills/single-work-analysis/references/api-contracts/linkedin-web-api.md +1949 -0
  330. package/skills/single-work-analysis/references/api-contracts/media-ingest-api.md +126 -0
  331. package/skills/single-work-analysis/references/api-contracts/pipixia-app-api.md +1142 -0
  332. package/skills/single-work-analysis/references/api-contracts/reddit-app-api.md +2025 -0
  333. package/skills/single-work-analysis/references/api-contracts/sora2-api.md +2266 -0
  334. package/skills/single-work-analysis/references/api-contracts/temp-mail-api.md +208 -0
  335. package/skills/single-work-analysis/references/api-contracts/threads-web-api.md +897 -0
  336. package/skills/single-work-analysis/references/api-contracts/tikhub-downloader-api.md +134 -0
  337. package/skills/single-work-analysis/references/api-contracts/tikhub-user-api.md +494 -0
  338. package/skills/single-work-analysis/references/api-contracts/tiktok-ads-api.md +5947 -0
  339. package/skills/single-work-analysis/references/api-contracts/tiktok-analytics-api.md +968 -0
  340. package/skills/single-work-analysis/references/api-contracts/tiktok-app-v3-api.md +5735 -0
  341. package/skills/single-work-analysis/references/api-contracts/tiktok-creator-api.md +1951 -0
  342. package/skills/single-work-analysis/references/api-contracts/tiktok-interaction-api.md +742 -0
  343. package/skills/single-work-analysis/references/api-contracts/tiktok-shop-web-api.md +1890 -0
  344. package/skills/single-work-analysis/references/api-contracts/tiktok-web-api.md +4448 -0
  345. package/skills/single-work-analysis/references/api-contracts/toutiao-app-api.md +342 -0
  346. package/skills/single-work-analysis/references/api-contracts/toutiao-web-api.md +143 -0
  347. package/skills/single-work-analysis/references/api-contracts/twitter-web-api.md +989 -0
  348. package/skills/single-work-analysis/references/api-contracts/wechat-channels-api.md +809 -0
  349. package/skills/single-work-analysis/references/api-contracts/wechat-media-platform-web-api.md +677 -0
  350. package/skills/single-work-analysis/references/api-contracts/weibo-app-api.md +1547 -0
  351. package/skills/single-work-analysis/references/api-contracts/weibo-web-api.md +798 -0
  352. package/skills/single-work-analysis/references/api-contracts/weibo-web-v2-api.md +2459 -0
  353. package/skills/single-work-analysis/references/api-contracts/xiaohongshu-app-api.md +1291 -0
  354. package/skills/single-work-analysis/references/api-contracts/xiaohongshu-app-v2-api.md +1683 -0
  355. package/skills/single-work-analysis/references/api-contracts/xiaohongshu-web-api.md +1324 -0
  356. package/skills/single-work-analysis/references/api-contracts/xiaohongshu-web-v2-api.md +1209 -0
  357. package/skills/single-work-analysis/references/api-contracts/xigua-app-v2-api.md +489 -0
  358. package/skills/single-work-analysis/references/api-contracts/youtube-web-api.md +2636 -0
  359. package/skills/single-work-analysis/references/api-contracts/youtube-web-v2-api.md +2660 -0
  360. package/skills/single-work-analysis/references/api-contracts/zhihu-web-api.md +2315 -0
  361. package/skills/single-work-analysis/references/api-tags/asr-api.md +100 -0
  362. package/skills/single-work-analysis/references/api-tags/bilibili-app-api.md +482 -0
  363. package/skills/single-work-analysis/references/api-tags/bilibili-web-api.md +1267 -0
  364. package/skills/single-work-analysis/references/api-tags/demo-api.md +365 -0
  365. package/skills/single-work-analysis/references/api-tags/douyin-app-v3-api.md +2012 -0
  366. package/skills/single-work-analysis/references/api-tags/douyin-billboard-api.md +1428 -0
  367. package/skills/single-work-analysis/references/api-tags/douyin-creator-api.md +694 -0
  368. package/skills/single-work-analysis/references/api-tags/douyin-creator-v2-api.md +694 -0
  369. package/skills/single-work-analysis/references/api-tags/douyin-search-api.md +1059 -0
  370. package/skills/single-work-analysis/references/api-tags/douyin-web-api.md +3314 -0
  371. package/skills/single-work-analysis/references/api-tags/douyin-xingtu-api.md +935 -0
  372. package/skills/single-work-analysis/references/api-tags/douyin-xingtu-v2-api.md +925 -0
  373. package/skills/single-work-analysis/references/api-tags/health-check.md +40 -0
  374. package/skills/single-work-analysis/references/api-tags/hybrid-parsing.md +57 -0
  375. package/skills/single-work-analysis/references/api-tags/instagram-v1-api.md +1224 -0
  376. package/skills/single-work-analysis/references/api-tags/instagram-v2-api.md +1147 -0
  377. package/skills/single-work-analysis/references/api-tags/instagram-v3-api.md +1123 -0
  378. package/skills/single-work-analysis/references/api-tags/ios-shortcut.md +45 -0
  379. package/skills/single-work-analysis/references/api-tags/kuaishou-app-api.md +846 -0
  380. package/skills/single-work-analysis/references/api-tags/kuaishou-web-api.md +551 -0
  381. package/skills/single-work-analysis/references/api-tags/lemon8-app-api.md +687 -0
  382. package/skills/single-work-analysis/references/api-tags/linkedin-web-api.md +1105 -0
  383. package/skills/single-work-analysis/references/api-tags/media-ingest-api.md +112 -0
  384. package/skills/single-work-analysis/references/api-tags/pipixia-app-api.md +721 -0
  385. package/skills/single-work-analysis/references/api-tags/reddit-app-api.md +1057 -0
  386. package/skills/single-work-analysis/references/api-tags/sora2-api.md +737 -0
  387. package/skills/single-work-analysis/references/api-tags/temp-mail-api.md +136 -0
  388. package/skills/single-work-analysis/references/api-tags/threads-web-api.md +472 -0
  389. package/skills/single-work-analysis/references/api-tags/tikhub-downloader-api.md +65 -0
  390. package/skills/single-work-analysis/references/api-tags/tikhub-user-api.md +253 -0
  391. package/skills/single-work-analysis/references/api-tags/tiktok-ads-api.md +1393 -0
  392. package/skills/single-work-analysis/references/api-tags/tiktok-analytics-api.md +179 -0
  393. package/skills/single-work-analysis/references/api-tags/tiktok-app-v3-api.md +3264 -0
  394. package/skills/single-work-analysis/references/api-tags/tiktok-creator-api.md +709 -0
  395. package/skills/single-work-analysis/references/api-tags/tiktok-interaction-api.md +366 -0
  396. package/skills/single-work-analysis/references/api-tags/tiktok-shop-web-api.md +663 -0
  397. package/skills/single-work-analysis/references/api-tags/tiktok-web-api.md +2516 -0
  398. package/skills/single-work-analysis/references/api-tags/toutiao-app-api.md +220 -0
  399. package/skills/single-work-analysis/references/api-tags/toutiao-web-api.md +96 -0
  400. package/skills/single-work-analysis/references/api-tags/twitter-web-api.md +562 -0
  401. package/skills/single-work-analysis/references/api-tags/wechat-channels-api.md +405 -0
  402. package/skills/single-work-analysis/references/api-tags/wechat-media-platform-web-api.md +431 -0
  403. package/skills/single-work-analysis/references/api-tags/weibo-app-api.md +851 -0
  404. package/skills/single-work-analysis/references/api-tags/weibo-web-api.md +470 -0
  405. package/skills/single-work-analysis/references/api-tags/weibo-web-v2-api.md +1405 -0
  406. package/skills/single-work-analysis/references/api-tags/xiaohongshu-app-api.md +534 -0
  407. package/skills/single-work-analysis/references/api-tags/xiaohongshu-app-v2-api.md +934 -0
  408. package/skills/single-work-analysis/references/api-tags/xiaohongshu-web-api.md +757 -0
  409. package/skills/single-work-analysis/references/api-tags/xiaohongshu-web-v2-api.md +762 -0
  410. package/skills/single-work-analysis/references/api-tags/xigua-app-v2-api.md +308 -0
  411. package/skills/single-work-analysis/references/api-tags/youtube-web-api.md +934 -0
  412. package/skills/single-work-analysis/references/api-tags/youtube-web-v2-api.md +717 -0
  413. package/skills/single-work-analysis/references/api-tags/zhihu-web-api.md +1384 -0
  414. package/skills/single-work-analysis/references/asr-and-fallback.md +20 -0
  415. package/skills/single-work-analysis/references/config-templates/defaults.yaml +58 -0
  416. package/skills/single-work-analysis/references/contracts/work-card-fields.md +41 -0
  417. package/skills/single-work-analysis/references/platform-guides/douyin.md +47 -0
  418. package/skills/single-work-analysis/references/platform-guides/generic.md +43 -0
  419. package/skills/single-work-analysis/references/platform-guides/xiaohongshu.md +54 -0
  420. package/skills/single-work-analysis/references/prompt-contracts/asr-clean.md +28 -0
  421. package/skills/single-work-analysis/references/prompt-contracts/cta.md +24 -0
  422. package/skills/single-work-analysis/references/prompt-contracts/hook.md +25 -0
  423. package/skills/single-work-analysis/references/prompt-contracts/insight.md +47 -0
  424. package/skills/single-work-analysis/references/prompt-contracts/structure.md +25 -0
  425. package/skills/single-work-analysis/references/prompt-contracts/style.md +27 -0
  426. package/skills/single-work-analysis/references/prompt-contracts/summary.md +29 -0
  427. package/skills/single-work-analysis/references/prompt-contracts/topic.md +29 -0
  428. package/skills/single-work-analysis/references/schemas/work-card.schema.json +39 -0
  429. package/skills/single-work-analysis/references/service-guides/asr-u2-u3-fallback.md +75 -0
  430. package/skills/single-work-analysis/scripts/__init__.py +0 -0
  431. package/skills/single-work-analysis/scripts/core/__init__.py +0 -0
  432. package/skills/single-work-analysis/scripts/core/analysis_pipeline.py +133 -0
  433. package/skills/single-work-analysis/scripts/core/bootstrap_env.py +35 -0
  434. package/skills/single-work-analysis/scripts/core/config_loader.py +418 -0
  435. package/skills/single-work-analysis/scripts/core/extract_pipeline.py +173 -0
  436. package/skills/single-work-analysis/scripts/core/progress_report.py +111 -0
  437. package/skills/single-work-analysis/scripts/core/storage_router.py +253 -0
  438. package/skills/single-work-analysis/scripts/core/tikomni_common.py +588 -0
  439. package/skills/single-work-analysis/scripts/pipeline/__init__.py +0 -0
  440. package/skills/single-work-analysis/scripts/pipeline/asr/__init__.py +0 -0
  441. package/skills/single-work-analysis/scripts/pipeline/asr/asr_pipeline.py +1189 -0
  442. package/skills/single-work-analysis/scripts/pipeline/asr/poll_u2_task.py +95 -0
  443. package/skills/single-work-analysis/scripts/platform/__init__.py +0 -0
  444. package/skills/single-work-analysis/scripts/platform/douyin/__init__.py +0 -0
  445. package/skills/single-work-analysis/scripts/platform/douyin/douyin_video_type_matrix.py +224 -0
  446. package/skills/single-work-analysis/scripts/platform/douyin/run_douyin_single_video.py +1233 -0
  447. package/skills/single-work-analysis/scripts/platform/douyin/select_low_quality_video_url.py +200 -0
  448. package/skills/single-work-analysis/scripts/platform/xiaohongshu/__init__.py +0 -0
  449. package/skills/single-work-analysis/scripts/platform/xiaohongshu/run_xiaohongshu_extract.py +2156 -0
  450. package/skills/single-work-analysis/scripts/writers/__init__.py +0 -0
  451. package/skills/single-work-analysis/scripts/writers/write_benchmark_card.py +1402 -0
@@ -0,0 +1,636 @@
1
+ #!/usr/bin/env python3
2
+ """Collectors for author homepage profile + paginated posts."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Any, Dict, List, Optional, Tuple
7
+ from urllib.parse import parse_qs, urlparse
8
+
9
+ from scripts.core.extract_pipeline import build_api_trace
10
+ from scripts.core.progress_report import ProgressReporter
11
+ from scripts.core.tikomni_common import call_json_api, deep_find_first
12
+
13
+
14
+ def _to_text(value: Any) -> str:
15
+ if value is None:
16
+ return ""
17
+ if isinstance(value, str):
18
+ return value.strip()
19
+ return str(value).strip()
20
+
21
+
22
+ def _pick_text(payload: Any, keys: List[str]) -> str:
23
+ hit = deep_find_first(payload, keys)
24
+ if hit is None:
25
+ return ""
26
+ return _to_text(hit)
27
+
28
+
29
+ def _pick_int(payload: Any, keys: List[str], default: int = 0) -> int:
30
+ hit = deep_find_first(payload, keys)
31
+ if hit is None:
32
+ return default
33
+ try:
34
+ if isinstance(hit, (int, float)):
35
+ return int(hit)
36
+ return int(float(str(hit).replace(",", "")))
37
+ except Exception:
38
+ return default
39
+
40
+
41
+ def _pick_list(payload: Any, keys: List[str]) -> List[Any]:
42
+ if isinstance(payload, list):
43
+ return payload
44
+
45
+ ordered_keys = [str(key) for key in keys if str(key).strip()]
46
+
47
+ def _walk(node: Any) -> Optional[List[Any]]:
48
+ if isinstance(node, dict):
49
+ for key in ordered_keys:
50
+ if key not in node:
51
+ continue
52
+ value = node.get(key)
53
+ if isinstance(value, list):
54
+ return value
55
+ if isinstance(value, dict):
56
+ hit = _walk(value)
57
+ if hit is not None:
58
+ return hit
59
+ for value in node.values():
60
+ hit = _walk(value)
61
+ if hit is not None:
62
+ return hit
63
+ elif isinstance(node, list):
64
+ for item in node:
65
+ hit = _walk(item)
66
+ if hit is not None:
67
+ return hit
68
+ return None
69
+
70
+ hit = _walk(payload)
71
+ return hit if isinstance(hit, list) else []
72
+
73
+
74
+ def _looks_like_douyin_sec_user_id(value: str) -> bool:
75
+ return value.startswith("MS4wLjA")
76
+
77
+
78
+ def _extract_douyin_sec_user_id(payload: Any) -> str:
79
+ sec_user_keys = ["sec_user_id", "sec_uid", "secUserId", "secuid"]
80
+
81
+ def _walk(node: Any, depth: int = 0) -> str:
82
+ if depth > 8:
83
+ return ""
84
+ if isinstance(node, dict):
85
+ for key in sec_user_keys:
86
+ if key not in node:
87
+ continue
88
+ candidate = _to_text(node.get(key))
89
+ if candidate:
90
+ return candidate
91
+
92
+ if "data" in node:
93
+ data_node = node.get("data")
94
+ if isinstance(data_node, str):
95
+ text = _to_text(data_node)
96
+ if text and _looks_like_douyin_sec_user_id(text):
97
+ return text
98
+ nested = _walk(data_node, depth + 1)
99
+ if nested:
100
+ return nested
101
+
102
+ for value in node.values():
103
+ nested = _walk(value, depth + 1)
104
+ if nested:
105
+ return nested
106
+ return ""
107
+
108
+ if isinstance(node, list):
109
+ for item in node:
110
+ nested = _walk(item, depth + 1)
111
+ if nested:
112
+ return nested
113
+ return ""
114
+
115
+ if isinstance(node, str):
116
+ text = _to_text(node)
117
+ if text and _looks_like_douyin_sec_user_id(text):
118
+ return text
119
+ return ""
120
+
121
+ return _walk(payload, 0)
122
+
123
+
124
+ def _preview(value: Any, max_len: int = 160) -> str:
125
+ text = _to_text(value)
126
+ if not text:
127
+ return ""
128
+ text = " ".join(text.split())
129
+ return text[:max_len]
130
+
131
+
132
+ def _pick_request_id(responses: List[Optional[Dict[str, Any]]], trace: Optional[List[Dict[str, Any]]] = None) -> Optional[str]:
133
+ for response in responses:
134
+ if isinstance(response, dict) and response.get("request_id"):
135
+ return str(response.get("request_id"))
136
+
137
+ for step in trace or []:
138
+ if isinstance(step, dict) and step.get("request_id"):
139
+ return str(step.get("request_id"))
140
+ return None
141
+
142
+
143
+ def _build_field_completeness(fields: Dict[str, bool], *, core_keys: List[str]) -> Dict[str, Any]:
144
+ filled_count = sum(1 for value in fields.values() if value)
145
+ missing_core = [key for key in core_keys if not fields.get(key)]
146
+ return {
147
+ "fields": fields,
148
+ "filled_count": filled_count,
149
+ "total_fields": len(fields),
150
+ "ratio": round(filled_count / max(len(fields), 1), 3),
151
+ "missing_core": missing_core,
152
+ "core_ready": not missing_core,
153
+ }
154
+
155
+
156
+ def _xhs_profile_field_completeness(payload: Any, resolved_author_id: str) -> Dict[str, Any]:
157
+ fields = {
158
+ "user_id": bool(_pick_text(payload, ["user_id", "userid", "uid", "id"]) or resolved_author_id),
159
+ "nickname": bool(_pick_text(payload, ["nickname", "name"])),
160
+ "avatar": bool(_pick_text(payload, ["image", "avatar", "avatar_url"])),
161
+ "fans": _pick_int(payload, ["fans", "fans_count", "follower_count"], default=0) > 0,
162
+ "works_count": _pick_int(payload, ["notes", "note_count", "works_count"], default=0) > 0,
163
+ }
164
+ return _build_field_completeness(fields, core_keys=["user_id", "nickname"])
165
+
166
+
167
+ def _xhs_posts_field_completeness(payload: Any) -> Dict[str, Any]:
168
+ page_items = _pick_list(payload, ["notes", "note_list", "noteList", "items", "list"])
169
+ has_more_flag = _pick_int(payload, ["has_more", "hasMore"], default=-1) >= 0
170
+ cursor_hit = bool(_pick_text(payload, ["cursor", "next_cursor", "last_cursor", "last_note_id"]))
171
+ fields = {
172
+ "items": len(page_items) > 0,
173
+ "note_id": bool(_pick_text(payload, ["note_id", "id", "item_id"])),
174
+ "cursor": cursor_hit,
175
+ "has_more_flag": has_more_flag,
176
+ "response_shape": len(page_items) > 0 or bool(_pick_text(payload, ["note_id", "id", "item_id"])) or cursor_hit or has_more_flag,
177
+ }
178
+ return _build_field_completeness(fields, core_keys=["response_shape"])
179
+
180
+
181
+ def _xhs_route_should_accept(response: Dict[str, Any], completeness: Dict[str, Any]) -> bool:
182
+ return bool(response.get("ok") and completeness.get("core_ready"))
183
+
184
+
185
+ def _call_xhs_route(
186
+ *,
187
+ base_url: str,
188
+ token: str,
189
+ timeout_ms: int,
190
+ path: str,
191
+ route_label: str,
192
+ params: Dict[str, Any],
193
+ fallback_reason: Optional[str],
194
+ completeness_builder,
195
+ ) -> Dict[str, Any]:
196
+ response = call_json_api(
197
+ base_url=base_url,
198
+ path=path,
199
+ token=token,
200
+ method="GET",
201
+ timeout_ms=timeout_ms,
202
+ params=params,
203
+ )
204
+ response["_endpoint"] = path
205
+ response["_route_label"] = route_label
206
+ if fallback_reason:
207
+ response["fallback_trigger_reason"] = fallback_reason
208
+ response["_field_completeness"] = completeness_builder(response.get("data")) if response.get("ok") else {
209
+ "fields": {},
210
+ "filled_count": 0,
211
+ "total_fields": 0,
212
+ "ratio": 0.0,
213
+ "missing_core": [],
214
+ "core_ready": False,
215
+ }
216
+ return response
217
+
218
+
219
+ def _guess_douyin_sec_user_id(input_value: str) -> str:
220
+ value = (input_value or "").strip()
221
+ if not value:
222
+ return ""
223
+ if "sec_uid=" in value:
224
+ query = parse_qs(urlparse(value).query)
225
+ sec = query.get("sec_uid") or query.get("sec_user_id")
226
+ if sec and sec[0]:
227
+ return sec[0]
228
+ if value.startswith("MS4wLjAB") or value.startswith("MS4wLjA"):
229
+ return value
230
+ return ""
231
+
232
+
233
+ def _guess_xhs_ids(input_value: str) -> Tuple[str, str]:
234
+ value = (input_value or "").strip()
235
+ if not value:
236
+ return "", ""
237
+ parsed = urlparse(value)
238
+ if parsed.query:
239
+ query = parse_qs(parsed.query)
240
+ uid = (query.get("user_id") or query.get("userid") or [""])[0]
241
+ xsec = (query.get("xsec_token") or [""])[0]
242
+ if uid:
243
+ return uid, xsec
244
+ if "/user/profile/" in value:
245
+ tail = value.split("/user/profile/", 1)[-1].split("?", 1)[0].split("/", 1)[0].strip()
246
+ if tail:
247
+ return tail, ""
248
+ return "", ""
249
+
250
+
251
+ def collect_douyin_author_home_raw(
252
+ *,
253
+ input_value: str,
254
+ base_url: str,
255
+ token: str,
256
+ timeout_ms: int,
257
+ page_size: int,
258
+ pages_max: int,
259
+ max_items: int,
260
+ progress: Optional[ProgressReporter] = None,
261
+ ) -> Dict[str, Any]:
262
+ trace: List[Dict[str, Any]] = []
263
+ if progress is not None:
264
+ progress.started(stage="author_home.collect", message="collecting douyin author homepage")
265
+ sec_user_id = _guess_douyin_sec_user_id(input_value)
266
+ resolve_resp: Optional[Dict[str, Any]] = None
267
+ request_id_candidates: List[Optional[Dict[str, Any]]] = []
268
+
269
+ if not sec_user_id:
270
+ resolve_resp = call_json_api(
271
+ base_url=base_url,
272
+ path="/api/u1/v1/douyin/web/get_sec_user_id",
273
+ token=token,
274
+ method="GET",
275
+ timeout_ms=timeout_ms,
276
+ params={"url": input_value, "share_url": input_value},
277
+ )
278
+ trace.append(build_api_trace(step="douyin.resolve_sec_user_id", endpoint="/api/u1/v1/douyin/web/get_sec_user_id", response=resolve_resp))
279
+ request_id_candidates.append(resolve_resp)
280
+ resolve_data = resolve_resp.get("data")
281
+ sec_user_id = _extract_douyin_sec_user_id(resolve_data)
282
+ if not sec_user_id:
283
+ trace.append(
284
+ {
285
+ "step": "douyin.resolve_sec_user_id.unresolved",
286
+ "endpoint": "/api/u1/v1/douyin/web/get_sec_user_id",
287
+ "ok": False,
288
+ "status_code": resolve_resp.get("status_code"),
289
+ "request_id": resolve_resp.get("request_id"),
290
+ "error_reason": resolve_resp.get("error_reason"),
291
+ "resolve_data_type": type(resolve_data).__name__,
292
+ "resolve_data_keys": list(resolve_data.keys())[:8] if isinstance(resolve_data, dict) else [],
293
+ "resolve_data_preview": _preview(resolve_data),
294
+ "input_hint": _preview(input_value, max_len=120),
295
+ }
296
+ )
297
+
298
+ profile_resp = call_json_api(
299
+ base_url=base_url,
300
+ path="/api/u1/v1/douyin/app/v3/handler_user_profile",
301
+ token=token,
302
+ method="GET",
303
+ timeout_ms=timeout_ms,
304
+ params={"sec_user_id": sec_user_id},
305
+ )
306
+ trace.append(build_api_trace(step="douyin.profile", endpoint="/api/u1/v1/douyin/app/v3/handler_user_profile", response=profile_resp))
307
+ request_id_candidates.append(profile_resp)
308
+
309
+ profile_author_id = _pick_text(profile_resp.get("data"), ["sec_user_id", "sec_uid", "secUserId", "uid", "user_id"])
310
+ resolved_author_id = sec_user_id or profile_author_id
311
+ if not resolved_author_id:
312
+ trace.append(
313
+ {
314
+ "step": "douyin.author_id.unresolved",
315
+ "endpoint": "/api/u1/v1/douyin/app/v3/handler_user_profile",
316
+ "ok": False,
317
+ "status_code": profile_resp.get("status_code"),
318
+ "request_id": profile_resp.get("request_id"),
319
+ "error_reason": profile_resp.get("error_reason"),
320
+ "profile_data_type": type(profile_resp.get("data")).__name__,
321
+ "profile_data_keys": list(profile_resp.get("data").keys())[:8] if isinstance(profile_resp.get("data"), dict) else [],
322
+ "profile_data_preview": _preview(profile_resp.get("data")),
323
+ }
324
+ )
325
+
326
+ works: List[Dict[str, Any]] = []
327
+ seen_ids = set()
328
+ cursor = 0
329
+ has_more = True
330
+ page = 0
331
+ pagination_trace: List[Dict[str, Any]] = []
332
+
333
+ while has_more and page < max(pages_max, 1) and len(works) < max_items:
334
+ page += 1
335
+ posts_resp = call_json_api(
336
+ base_url=base_url,
337
+ path="/api/u1/v1/douyin/app/v3/fetch_user_post_videos",
338
+ token=token,
339
+ method="GET",
340
+ timeout_ms=timeout_ms,
341
+ params={
342
+ "sec_user_id": sec_user_id,
343
+ "count": min(max(page_size, 1), 20),
344
+ "max_cursor": cursor,
345
+ "sort_type": 0,
346
+ },
347
+ )
348
+ trace.append(
349
+ build_api_trace(
350
+ step="douyin.posts_page",
351
+ endpoint="/api/u1/v1/douyin/app/v3/fetch_user_post_videos",
352
+ response=posts_resp,
353
+ extra={"page": page, "cursor": cursor, "sort_type": 0},
354
+ )
355
+ )
356
+ if progress is not None:
357
+ progress.progress(
358
+ stage="author_home.collect.pagination",
359
+ message="douyin pagination page requested",
360
+ data={"page": page, "cursor_in": cursor},
361
+ )
362
+ request_id_candidates.append(posts_resp)
363
+ response_payload = posts_resp.get("data")
364
+ page_items = _pick_list(response_payload, ["aweme_list", "items", "list"])
365
+ if not page_items and isinstance(response_payload, dict):
366
+ page_items = _pick_list(response_payload.get("data"), ["aweme_list", "items", "list"])
367
+
368
+ data = response_payload
369
+ next_cursor = _pick_int(data, ["max_cursor", "cursor", "next_cursor"], default=0)
370
+ has_more_flag = _pick_int(data, ["has_more", "hasMore"], default=0)
371
+ pagination_trace.append(
372
+ {
373
+ "page": page,
374
+ "cursor_in": cursor,
375
+ "cursor_out": next_cursor,
376
+ "has_more": has_more_flag,
377
+ "items": len(page_items),
378
+ }
379
+ )
380
+
381
+ for item in page_items:
382
+ if not isinstance(item, dict):
383
+ continue
384
+ work_id = _pick_text(item, ["aweme_id", "item_id", "id"])
385
+ dedupe_key = work_id or f"p{page}-i{len(works)}"
386
+ if dedupe_key in seen_ids:
387
+ continue
388
+ seen_ids.add(dedupe_key)
389
+ works.append(item)
390
+ if len(works) >= max_items:
391
+ break
392
+
393
+ has_more = bool(has_more_flag == 1 and next_cursor != cursor)
394
+ cursor = next_cursor
395
+
396
+ request_id = _pick_request_id(request_id_candidates, trace)
397
+ if progress is not None:
398
+ progress.done(
399
+ stage="author_home.collect",
400
+ message="douyin author homepage collected",
401
+ data={"works_count": len(works), "pages": len(pagination_trace), "request_id": request_id},
402
+ )
403
+
404
+ return {
405
+ "platform": "douyin",
406
+ "resolved_author_id": resolved_author_id,
407
+ "profile_response": profile_resp,
408
+ "works": works,
409
+ "pagination": {
410
+ "sort": "latest",
411
+ "sort_type": 0,
412
+ "cursor_mode": "max_cursor",
413
+ "pages": pagination_trace,
414
+ "total_collected": len(works),
415
+ "max_items": max_items,
416
+ },
417
+ "extract_trace": trace,
418
+ "request_id": request_id,
419
+ }
420
+
421
+
422
+ def collect_xhs_author_home_raw(
423
+ *,
424
+ input_value: str,
425
+ base_url: str,
426
+ token: str,
427
+ timeout_ms: int,
428
+ page_size: int,
429
+ pages_max: int,
430
+ max_items: int,
431
+ progress: Optional[ProgressReporter] = None,
432
+ ) -> Dict[str, Any]:
433
+ trace: List[Dict[str, Any]] = []
434
+ if progress is not None:
435
+ progress.started(stage="author_home.collect", message="collecting xiaohongshu author homepage")
436
+ user_id, xsec_token = _guess_xhs_ids(input_value)
437
+ resolve_resp: Optional[Dict[str, Any]] = None
438
+ request_id_candidates: List[Optional[Dict[str, Any]]] = []
439
+
440
+ if not user_id:
441
+ resolve_resp = call_json_api(
442
+ base_url=base_url,
443
+ path="/api/u1/v1/xiaohongshu/app/get_user_id_and_xsec_token",
444
+ token=token,
445
+ method="GET",
446
+ timeout_ms=timeout_ms,
447
+ params={"share_link": input_value, "share_url": input_value, "url": input_value},
448
+ )
449
+ trace.append(
450
+ build_api_trace(
451
+ step="xhs.resolve_user_id",
452
+ endpoint="/api/u1/v1/xiaohongshu/app/get_user_id_and_xsec_token",
453
+ response=resolve_resp,
454
+ )
455
+ )
456
+ request_id_candidates.append(resolve_resp)
457
+ data = resolve_resp.get("data")
458
+ user_id = _pick_text(data, ["user_id", "userid", "uid"])
459
+ if not xsec_token:
460
+ xsec_token = _pick_text(data, ["xsec_token", "xsecToken"])
461
+
462
+ profile_routes = [
463
+ ("xhs.profile.primary", "/api/u1/v1/xiaohongshu/app_v2/get_user_info", "app_v2_primary"),
464
+ ("xhs.profile.secondary", "/api/u1/v1/xiaohongshu/web_v2/fetch_user_info_app", "web_v2_secondary"),
465
+ ("xhs.profile.fallback", "/api/u1/v1/xiaohongshu/app/get_user_info", "app_v1_fallback"),
466
+ ]
467
+ profile_resp: Dict[str, Any] = {}
468
+ profile_reason: Optional[str] = None
469
+ for step_name, path, route_label in profile_routes:
470
+ profile_resp = _call_xhs_route(
471
+ base_url=base_url,
472
+ token=token,
473
+ timeout_ms=timeout_ms,
474
+ path=path,
475
+ route_label=route_label,
476
+ params={"user_id": user_id, "share_text": input_value, "xsec_token": xsec_token or None},
477
+ fallback_reason=profile_reason,
478
+ completeness_builder=lambda data, resolved_author_id=user_id: _xhs_profile_field_completeness(data, resolved_author_id),
479
+ )
480
+ trace.append(
481
+ build_api_trace(
482
+ step=step_name,
483
+ endpoint=path,
484
+ response=profile_resp,
485
+ extra={
486
+ "route_label": route_label,
487
+ "field_completeness": profile_resp.get("_field_completeness"),
488
+ },
489
+ )
490
+ )
491
+ request_id_candidates.append(profile_resp)
492
+ if _xhs_route_should_accept(profile_resp, profile_resp.get("_field_completeness") or {}):
493
+ break
494
+ if profile_resp.get("ok"):
495
+ profile_resp["fallback_trigger_reason"] = "field_completeness_below_threshold"
496
+ profile_reason = "field_completeness_below_threshold"
497
+ else:
498
+ profile_reason = "primary_timeout_retry_exhausted" if profile_resp.get("timeout_retry_exhausted") else "primary_non_timeout_failure"
499
+
500
+ trace.append(
501
+ {
502
+ "step": "xhs.profile.route_decision",
503
+ "chosen_route": profile_resp.get("_route_label"),
504
+ "request_id": profile_resp.get("request_id"),
505
+ "field_completeness": profile_resp.get("_field_completeness"),
506
+ }
507
+ )
508
+
509
+ works: List[Dict[str, Any]] = []
510
+ seen_ids = set()
511
+ cursor: Any = ""
512
+ has_more = True
513
+ page = 0
514
+ pagination_trace: List[Dict[str, Any]] = []
515
+
516
+ while has_more and page < max(pages_max, 1) and len(works) < max_items:
517
+ page += 1
518
+ if progress is not None:
519
+ progress.progress(
520
+ stage="author_home.collect.pagination",
521
+ message="xiaohongshu pagination page requested",
522
+ data={"page": page, "cursor_in": cursor},
523
+ )
524
+ posts_routes = [
525
+ ("xhs.posts.primary", "/api/u1/v1/xiaohongshu/app_v2/get_user_posted_notes", "app_v2_primary"),
526
+ ("xhs.posts.secondary", "/api/u1/v1/xiaohongshu/web_v2/fetch_home_notes_app", "web_v2_secondary"),
527
+ ("xhs.posts.fallback", "/api/u1/v1/xiaohongshu/app/get_user_notes", "app_v1_fallback"),
528
+ ]
529
+ posts_resp: Dict[str, Any] = {}
530
+ posts_reason: Optional[str] = None
531
+ for step_name, path, route_label in posts_routes:
532
+ posts_resp = _call_xhs_route(
533
+ base_url=base_url,
534
+ token=token,
535
+ timeout_ms=timeout_ms,
536
+ path=path,
537
+ route_label=route_label,
538
+ params={
539
+ "user_id": user_id,
540
+ "share_text": input_value,
541
+ "cursor": cursor or None,
542
+ "num": min(max(page_size, 1), 20),
543
+ "xsec_token": xsec_token or None,
544
+ },
545
+ fallback_reason=posts_reason,
546
+ completeness_builder=_xhs_posts_field_completeness,
547
+ )
548
+ trace.append(
549
+ build_api_trace(
550
+ step=step_name,
551
+ endpoint=path,
552
+ response=posts_resp,
553
+ extra={
554
+ "page": page,
555
+ "cursor": cursor,
556
+ "route_label": route_label,
557
+ "field_completeness": posts_resp.get("_field_completeness"),
558
+ },
559
+ )
560
+ )
561
+ request_id_candidates.append(posts_resp)
562
+ if _xhs_route_should_accept(posts_resp, posts_resp.get("_field_completeness") or {}):
563
+ break
564
+ if posts_resp.get("ok"):
565
+ posts_resp["fallback_trigger_reason"] = "field_completeness_below_threshold"
566
+ posts_reason = "field_completeness_below_threshold"
567
+ else:
568
+ posts_reason = "primary_timeout_retry_exhausted" if posts_resp.get("timeout_retry_exhausted") else "primary_non_timeout_failure"
569
+
570
+ trace.append(
571
+ {
572
+ "step": "xhs.posts.route_decision",
573
+ "page": page,
574
+ "cursor_in": cursor,
575
+ "chosen_route": posts_resp.get("_route_label"),
576
+ "request_id": posts_resp.get("request_id"),
577
+ "field_completeness": posts_resp.get("_field_completeness"),
578
+ }
579
+ )
580
+
581
+ data = posts_resp.get("data")
582
+ page_items = _pick_list(data, ["notes", "note_list", "noteList", "items", "list"])
583
+ next_cursor = _pick_text(data, ["cursor", "next_cursor", "last_cursor", "last_note_id"])
584
+ has_more_flag = _pick_int(data, ["has_more", "hasMore"], default=0)
585
+ pagination_trace.append(
586
+ {
587
+ "page": page,
588
+ "cursor_in": cursor,
589
+ "cursor_out": next_cursor,
590
+ "has_more": has_more_flag,
591
+ "items": len(page_items),
592
+ "route_label": posts_resp.get("_route_label"),
593
+ "request_id": posts_resp.get("request_id"),
594
+ }
595
+ )
596
+
597
+ for item in page_items:
598
+ if not isinstance(item, dict):
599
+ continue
600
+ work_id = _pick_text(item, ["note_id", "id", "item_id"])
601
+ dedupe_key = work_id or f"p{page}-i{len(works)}"
602
+ if dedupe_key in seen_ids:
603
+ continue
604
+ seen_ids.add(dedupe_key)
605
+ works.append(item)
606
+ if len(works) >= max_items:
607
+ break
608
+
609
+ has_more = bool(has_more_flag == 1 and next_cursor and str(next_cursor) != str(cursor))
610
+ cursor = next_cursor
611
+
612
+ request_id = _pick_request_id(request_id_candidates, trace)
613
+ if progress is not None:
614
+ progress.done(
615
+ stage="author_home.collect",
616
+ message="xiaohongshu author homepage collected",
617
+ data={"works_count": len(works), "pages": len(pagination_trace), "request_id": request_id},
618
+ )
619
+
620
+ return {
621
+ "platform": "xiaohongshu",
622
+ "resolved_author_id": user_id,
623
+ "resolved_xsec_token": xsec_token,
624
+ "profile_response": profile_resp,
625
+ "works": works,
626
+ "pagination": {
627
+ "sort": "latest",
628
+ "sort_type": "latest",
629
+ "cursor_mode": "cursor",
630
+ "pages": pagination_trace,
631
+ "total_collected": len(works),
632
+ "max_items": max_items,
633
+ },
634
+ "extract_trace": trace,
635
+ "request_id": request_id,
636
+ }