rsshub 1.0.0-master.f9003f9 → 1.0.0-master.f917bdc

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 (532) hide show
  1. package/README.md +1 -0
  2. package/lib/api/category/one.ts +54 -0
  3. package/lib/api/index.ts +10 -4
  4. package/lib/app.tsx +2 -0
  5. package/lib/config.ts +43 -17
  6. package/lib/errors/index.test.ts +9 -5
  7. package/lib/errors/index.tsx +11 -4
  8. package/lib/index.ts +5 -2
  9. package/lib/middleware/anti-hotlink.test.ts +6 -6
  10. package/lib/middleware/cache.ts +21 -6
  11. package/lib/middleware/logger.ts +5 -1
  12. package/lib/middleware/template.tsx +15 -11
  13. package/lib/middleware/trace.ts +25 -0
  14. package/lib/registry.test.ts +8 -0
  15. package/lib/registry.ts +10 -2
  16. package/lib/router.js +0 -9
  17. package/lib/routes/141jav/index.ts +25 -21
  18. package/lib/routes/141ppv/index.ts +24 -20
  19. package/lib/routes/2048/index.ts +13 -10
  20. package/lib/routes/3dmgame/news-center.ts +1 -1
  21. package/lib/routes/51read/article.ts +82 -0
  22. package/lib/routes/51read/namespace.ts +6 -0
  23. package/lib/routes/69shu/article.ts +8 -8
  24. package/lib/routes/69shu/namespace.ts +1 -1
  25. package/lib/routes/academia/namespace.ts +6 -0
  26. package/lib/routes/academia/topics.ts +49 -0
  27. package/lib/routes/alistapart/utils.ts +2 -2
  28. package/lib/routes/aljazeera/index.ts +2 -2
  29. package/lib/routes/alpinelinux/namespace.ts +11 -0
  30. package/lib/routes/alpinelinux/pkgs.ts +104 -0
  31. package/lib/routes/apnews/rss.ts +10 -4
  32. package/lib/routes/apnews/topics.ts +11 -5
  33. package/lib/routes/apnews/utils.ts +36 -12
  34. package/lib/routes/apple/apps.ts +30 -8
  35. package/lib/routes/asmr-200/index.ts +66 -0
  36. package/lib/routes/asmr-200/namespace.ts +6 -0
  37. package/lib/routes/asmr-200/templates/work.art +7 -0
  38. package/lib/routes/asmr-200/type.ts +96 -0
  39. package/lib/routes/autocentre/index.ts +29 -0
  40. package/lib/routes/autocentre/namespace.ts +7 -0
  41. package/lib/routes/bbc/index.ts +3 -1
  42. package/lib/routes/bc3ts/list.ts +72 -0
  43. package/lib/routes/bc3ts/namespace.ts +7 -0
  44. package/lib/routes/bc3ts/templates/media.art +10 -0
  45. package/lib/routes/bc3ts/types.ts +118 -0
  46. package/lib/routes/beijingprice/index.ts +193 -0
  47. package/lib/routes/beijingprice/namespace.ts +8 -0
  48. package/lib/routes/bilibili/api-interface.d.ts +1 -0
  49. package/lib/routes/bilibili/dynamic.ts +35 -18
  50. package/lib/routes/bilibili/namespace.ts +1 -1
  51. package/lib/routes/bilibili/ranking.ts +99 -8
  52. package/lib/routes/bilibili/video.ts +3 -5
  53. package/lib/routes/bing/daily-wallpaper.ts +57 -18
  54. package/lib/routes/bjnews/cat.ts +43 -0
  55. package/lib/routes/bjnews/column.ts +43 -0
  56. package/lib/routes/bjnews/namespace.ts +6 -0
  57. package/lib/routes/bjnews/utils.ts +19 -0
  58. package/lib/routes/bjx/fd.ts +63 -0
  59. package/lib/routes/bjx/namespace.ts +1 -1
  60. package/lib/routes/bluearchive/namespace.ts +7 -0
  61. package/lib/routes/bluearchive/news.ts +88 -0
  62. package/lib/routes/bt0/mv.ts +65 -0
  63. package/lib/routes/bt0/namespace.ts +9 -0
  64. package/lib/routes/bt0/tlist.ts +67 -0
  65. package/lib/routes/bt0/util.ts +51 -0
  66. package/lib/routes/buaa/jiaowu.ts +124 -0
  67. package/lib/routes/buaa/lib/space/newbook.ts +171 -0
  68. package/lib/routes/buaa/lib/space/templates/newbook.art +44 -0
  69. package/lib/routes/buaa/news/index.ts +15 -13
  70. package/lib/routes/buaa/sme.ts +5 -3
  71. package/lib/routes/bugzilla/bug.ts +59 -0
  72. package/lib/routes/bugzilla/namespace.ts +11 -0
  73. package/lib/routes/cara/constant.ts +5 -0
  74. package/lib/routes/cara/likes.ts +56 -0
  75. package/lib/routes/cara/namespace.ts +6 -0
  76. package/lib/routes/cara/portfolio.ts +40 -0
  77. package/lib/routes/cara/templates/post.art +6 -0
  78. package/lib/routes/cara/timeline.ts +56 -0
  79. package/lib/routes/cara/types.ts +45 -0
  80. package/lib/routes/cara/utils.ts +62 -0
  81. package/lib/routes/cbaigui/utils.ts +1 -1
  82. package/lib/routes/cccfna/index.ts +82 -0
  83. package/lib/routes/cccfna/namespace.ts +6 -0
  84. package/lib/routes/cffex/announcement.ts +73 -0
  85. package/lib/routes/cffex/namespace.ts +6 -0
  86. package/lib/routes/cfr/index.ts +58 -0
  87. package/lib/routes/cfr/namespace.ts +6 -0
  88. package/lib/routes/cfr/types.ts +30 -0
  89. package/lib/routes/cfr/utils.ts +284 -0
  90. package/lib/routes/chaping/newsflash.ts +2 -2
  91. package/lib/routes/chlinlearn/daily-blog.ts +48 -0
  92. package/lib/routes/chlinlearn/namespcae.ts +6 -0
  93. package/lib/routes/cnbc/rss.ts +1 -1
  94. package/lib/routes/codeforces/contests.ts +2 -2
  95. package/lib/routes/codeforces/recent-actions.ts +2 -2
  96. package/lib/routes/copymanga/comic.ts +3 -1
  97. package/lib/routes/dangdang/namespace.ts +6 -0
  98. package/lib/routes/dangdang/notice.ts +69 -0
  99. package/lib/routes/dataguidance/index.ts +66 -0
  100. package/lib/routes/dataguidance/namespace.ts +7 -0
  101. package/lib/routes/dblp/publication.ts +4 -6
  102. package/lib/routes/deadbydaylight/index.ts +69 -0
  103. package/lib/routes/deadbydaylight/namespace.ts +12 -0
  104. package/lib/routes/devolverdigital/blog.ts +59 -42
  105. package/lib/routes/dewu/declaration.ts +86 -0
  106. package/lib/routes/dewu/namespace.ts +6 -0
  107. package/lib/routes/dhu/jiaowu/news.ts +53 -24
  108. package/lib/routes/dhu/namespace.ts +1 -1
  109. package/lib/routes/dhu/xxgk/news.ts +48 -20
  110. package/lib/routes/digitalcameraworld/news.ts +1 -1
  111. package/lib/routes/discord/channel.ts +10 -10
  112. package/lib/routes/discord/discord-api.ts +27 -32
  113. package/lib/routes/discord/templates/message.art +15 -0
  114. package/lib/routes/discourse/notifications.ts +4 -2
  115. package/lib/routes/dlnews/utils.ts +2 -2
  116. package/lib/routes/dockerhub/build.ts +11 -6
  117. package/lib/routes/domp4/detail.ts +1 -1
  118. package/lib/routes/domp4/latest-movie-bt.ts +71 -0
  119. package/lib/routes/dongqiudi/result.ts +1 -1
  120. package/lib/routes/douban/other/group.ts +24 -3
  121. package/lib/routes/duckdb/namespace.ts +6 -0
  122. package/lib/routes/duckdb/news.ts +65 -0
  123. package/lib/routes/dushu/fuzhou/index.ts +10 -11
  124. package/lib/routes/epicgames/index.ts +14 -4
  125. package/lib/routes/famitsu/category.ts +110 -43
  126. package/lib/routes/famitsu/templates/description.art +7 -0
  127. package/lib/routes/famitsu/types.ts +117 -0
  128. package/lib/routes/fanbox/namespace.ts +1 -1
  129. package/lib/routes/fanqienovel/namespace.ts +7 -0
  130. package/lib/routes/fanqienovel/page.ts +100 -0
  131. package/lib/routes/fansly/post.ts +1 -2
  132. package/lib/routes/fansly/tag.ts +1 -2
  133. package/lib/routes/fansly/utils.ts +5 -4
  134. package/lib/routes/fashionnetwork/index.ts +192 -0
  135. package/lib/routes/fashionnetwork/namespace.ts +8 -0
  136. package/lib/routes/fashionnetwork/templates/description.art +17 -0
  137. package/lib/routes/fediverse/namespace.ts +6 -0
  138. package/lib/routes/fediverse/timeline.ts +98 -0
  139. package/lib/routes/finviz/news.ts +4 -4
  140. package/lib/routes/foresightnews/util.ts +1 -1
  141. package/lib/routes/fortunechina/index.ts +24 -14
  142. package/lib/routes/freebuf/index.ts +3 -3
  143. package/lib/routes/ftchinese/channel.ts +3 -3
  144. package/lib/routes/gdut/oa-news.ts +12 -17
  145. package/lib/routes/getitfree/util.ts +1 -1
  146. package/lib/routes/github/activity.ts +55 -0
  147. package/lib/routes/github/issue.ts +26 -3
  148. package/lib/routes/github/search.ts +20 -18
  149. package/lib/routes/github/star.ts +4 -3
  150. package/lib/routes/github/trending.ts +27 -5
  151. package/lib/routes/google/citations.ts +2 -2
  152. package/lib/routes/google/research.ts +45 -0
  153. package/lib/routes/google/scholar.ts +2 -2
  154. package/lib/routes/gov/beijing/bphc/index.ts +3 -3
  155. package/lib/routes/gov/immiau/news.ts +2 -2
  156. package/lib/routes/gov/sh/fgw/index.ts +155 -0
  157. package/lib/routes/gov/sh/fgw/templates/description.art +17 -0
  158. package/lib/routes/gov/sh/namespace.ts +8 -0
  159. package/lib/routes/gov/{shanghai → sh}/rsj/ksxm.ts +2 -2
  160. package/lib/routes/gov/{shanghai → sh}/wgj/wgj.ts +3 -3
  161. package/lib/routes/gov/{shanghai → sh}/wsjkw/yqtb/index.ts +2 -2
  162. package/lib/routes/gov/{shanghai → sh}/yjj/index.ts +3 -3
  163. package/lib/routes/gov/stats/index.ts +8 -8
  164. package/lib/routes/gov/zhengce/index.ts +3 -6
  165. package/lib/routes/gov/zj/ningbogzw-notice.ts +50 -0
  166. package/lib/routes/gov/zj/ningborsjnotice.ts +50 -0
  167. package/lib/routes/gq/news.ts +1 -1
  168. package/lib/routes/grist/utils.ts +2 -2
  169. package/lib/routes/guokr/utils.ts +1 -1
  170. package/lib/routes/healthz.ts +8 -0
  171. package/lib/routes/hitcon/zeroday.ts +1 -1
  172. package/lib/routes/hket/index.ts +80 -76
  173. package/lib/routes/hrbeu/job/calendar.ts +8 -6
  174. package/lib/routes/huxiu/util.ts +2 -2
  175. package/lib/routes/hypergryph/arknights/arktca.ts +124 -0
  176. package/lib/routes/ieee/journal.ts +50 -67
  177. package/lib/routes/ieee/templates/description.art +1 -1
  178. package/lib/routes/imdb/chart.ts +61 -0
  179. package/lib/routes/imdb/namespace.ts +6 -0
  180. package/lib/routes/imdb/templates/chart.art +15 -0
  181. package/lib/routes/imdb/types.ts +103 -0
  182. package/lib/routes/imop/namespace.ts +10 -0
  183. package/lib/routes/imop/tianshu.ts +53 -0
  184. package/lib/routes/informedainews/docs.ts +78 -0
  185. package/lib/routes/informedainews/namespace.ts +18 -0
  186. package/lib/routes/inspirehep/author.ts +46 -0
  187. package/lib/routes/inspirehep/literature.ts +42 -0
  188. package/lib/routes/inspirehep/namespace.ts +7 -0
  189. package/lib/routes/inspirehep/types.ts +210 -0
  190. package/lib/routes/inspirehep/utils.ts +15 -0
  191. package/lib/routes/instagram/private-api/index.ts +28 -6
  192. package/lib/routes/investor/index.ts +213 -0
  193. package/lib/routes/investor/namespace.ts +8 -0
  194. package/lib/routes/iplaysoft/index.ts +68 -0
  195. package/lib/routes/iplaysoft/namespace.ts +6 -0
  196. package/lib/routes/j-test/namespace.ts +6 -0
  197. package/lib/routes/j-test/news.ts +64 -0
  198. package/lib/routes/japanpost/namespace.ts +7 -1
  199. package/lib/routes/japanpost/router.ts +40 -0
  200. package/lib/routes/japanpost/track.ts +1 -23
  201. package/lib/routes/javbus/index.ts +8 -1
  202. package/lib/routes/javdb/actors.ts +6 -2
  203. package/lib/routes/javdb/index.ts +4 -3
  204. package/lib/routes/javdb/series.ts +1 -1
  205. package/lib/routes/javdb/utils.ts +6 -0
  206. package/lib/routes/javdb/videocodes.ts +56 -0
  207. package/lib/routes/jike/topic.ts +1 -1
  208. package/lib/routes/jike/user.ts +1 -1
  209. package/lib/routes/jingzhengu/namespace.ts +6 -0
  210. package/lib/routes/jingzhengu/news.ts +77 -0
  211. package/lib/routes/jingzhengu/types.ts +39 -0
  212. package/lib/routes/jingzhengu/utils.ts +35 -0
  213. package/lib/routes/jinritemai/docs.ts +74 -0
  214. package/lib/routes/jinritemai/namespace.ts +6 -0
  215. package/lib/routes/jiuyangongshe/community.ts +147 -0
  216. package/lib/routes/jiuyangongshe/namespace.ts +7 -0
  217. package/lib/routes/jiuyangongshe/templates/community-description.art +4 -0
  218. package/lib/routes/jjwxc/book.ts +4 -3
  219. package/lib/routes/jlu/ccst/xwzx/index.ts +63 -0
  220. package/lib/routes/jlu/jwc.ts +55 -0
  221. package/lib/routes/jlu/namespace.ts +6 -0
  222. package/lib/routes/juejin/dynamic.ts +114 -0
  223. package/lib/routes/kadokawa/blog.ts +134 -0
  224. package/lib/routes/kadokawa/namespace.ts +8 -0
  225. package/lib/routes/kadokawa/templates/description.art +21 -0
  226. package/lib/routes/kaopu/news.ts +3 -3
  227. package/lib/routes/kelownacapnews/namespace.ts +6 -0
  228. package/lib/routes/kelownacapnews/news.ts +93 -0
  229. package/lib/routes/kemono/index.ts +21 -0
  230. package/lib/routes/keylol/index.ts +56 -11
  231. package/lib/routes/kurogames/namespace.ts +7 -0
  232. package/lib/routes/kurogames/wutheringwaves/news.ts +59 -0
  233. package/lib/routes/kyodonews/index.ts +1 -1
  234. package/lib/routes/leetcode/articles.ts +19 -21
  235. package/lib/routes/line/today.ts +1 -1
  236. package/lib/routes/linkedin/cn/renderer.ts +1 -1
  237. package/lib/routes/lmu/jobs.ts +96 -0
  238. package/lib/routes/lmu/namespace.ts +17 -0
  239. package/lib/routes/lmu/templates/jobPosting.art +11 -0
  240. package/lib/routes/lofter/user.ts +2 -1
  241. package/lib/routes/logclub/index.ts +1 -2
  242. package/lib/routes/luogu/user-blog.ts +6 -6
  243. package/lib/routes/luolei/index.ts +1 -2
  244. package/lib/routes/maccms/index.ts +72 -0
  245. package/lib/routes/maccms/namespace.ts +9 -0
  246. package/lib/routes/maccms/templates/vod.art +12 -0
  247. package/lib/routes/maccms/type.ts +102 -0
  248. package/lib/routes/mangadex/namespace.ts +1 -1
  249. package/lib/routes/manyvids/namespace.ts +7 -0
  250. package/lib/routes/manyvids/templates/video.art +3 -0
  251. package/lib/routes/manyvids/types.ts +89 -0
  252. package/lib/routes/manyvids/video.ts +51 -0
  253. package/lib/routes/matters/author.ts +63 -0
  254. package/lib/routes/matters/latest.ts +74 -0
  255. package/lib/routes/matters/namespace.ts +7 -0
  256. package/lib/routes/matters/tags.ts +85 -0
  257. package/lib/routes/matters/utils.ts +30 -0
  258. package/lib/routes/mcmod/index.ts +105 -0
  259. package/lib/routes/mcmod/namespace.ts +6 -0
  260. package/lib/routes/mcmod/templates/mod.art +13 -0
  261. package/lib/routes/meituan/namespace.ts +6 -0
  262. package/lib/routes/meituan/tech.ts +67 -0
  263. package/lib/routes/metacritic/index.ts +10 -0
  264. package/lib/routes/metrics.ts +12 -0
  265. package/lib/routes/microsoft/mcr.ts +63 -0
  266. package/lib/routes/microsoft/namespace.ts +2 -2
  267. package/lib/routes/mihoyo/bbs/img-ranking.ts +4 -4
  268. package/lib/routes/mihoyo/bbs/static-data.ts +7 -0
  269. package/lib/routes/minecraft/version.ts +1 -1
  270. package/lib/routes/mirrormedia/category.ts +101 -0
  271. package/lib/routes/mirrormedia/index.ts +43 -0
  272. package/lib/routes/mirrormedia/namespace.ts +6 -0
  273. package/lib/routes/mirrormedia/utils.ts +19 -0
  274. package/lib/routes/misskey/user-timeline.ts +42 -0
  275. package/lib/routes/misskey/utils.ts +41 -1
  276. package/lib/routes/modb/topic.ts +5 -6
  277. package/lib/routes/my-formosa/index.ts +78 -0
  278. package/lib/routes/my-formosa/namespace.ts +6 -0
  279. package/lib/routes/myfans/namespace.ts +6 -0
  280. package/lib/routes/myfans/post.ts +64 -0
  281. package/lib/routes/myfans/templates/post.art +8 -0
  282. package/lib/routes/myfans/types.ts +104 -0
  283. package/lib/routes/myfans/utils.ts +39 -0
  284. package/lib/routes/nasa/apod.ts +4 -3
  285. package/lib/routes/nasa/namespace.ts +1 -1
  286. package/lib/routes/nationalgeographic/latest-stories.ts +1 -1
  287. package/lib/routes/nationalgeographic/templates/stories.art +1 -1
  288. package/lib/routes/neea/index.ts +47 -19
  289. package/lib/routes/neea/jlpt.ts +12 -15
  290. package/lib/routes/neea/namespace.ts +2 -2
  291. package/lib/routes/newrank/utils.ts +1 -1
  292. package/lib/routes/newzmz/util.ts +1 -1
  293. package/lib/routes/nextjs/blog.ts +63 -0
  294. package/lib/routes/nextjs/namespace.ts +6 -0
  295. package/lib/routes/nga/forum.ts +3 -2
  296. package/lib/routes/nikkei/asia/index.ts +1 -10
  297. package/lib/routes/nikkei/cn/index.ts +39 -3
  298. package/lib/routes/nikkei/index.ts +5 -4
  299. package/lib/routes/nikkei/namespace.ts +1 -1
  300. package/lib/routes/nikkei/news.ts +2 -2
  301. package/lib/routes/nmc/weatheralarm.ts +1 -0
  302. package/lib/routes/notion/release.ts +81 -0
  303. package/lib/routes/npm/package.ts +15 -8
  304. package/lib/routes/nyaa/main.ts +2 -3
  305. package/lib/routes/nyaa/namespace.ts +10 -0
  306. package/lib/routes/ollama/blog.ts +39 -0
  307. package/lib/routes/ollama/models.ts +7 -4
  308. package/lib/routes/oschina/news.ts +6 -2
  309. package/lib/routes/people/index.ts +4 -2
  310. package/lib/routes/picnob/namespace.ts +1 -4
  311. package/lib/routes/picnob/user.ts +3 -2
  312. package/lib/routes/picuki/namespace.ts +1 -4
  313. package/lib/routes/picuki/profile.ts +11 -7
  314. package/lib/routes/pixiv/ranking.ts +73 -10
  315. package/lib/routes/pixiv/search.ts +58 -7
  316. package/lib/routes/pixiv/user.ts +3 -1
  317. package/lib/routes/pixiv/utils.ts +3 -3
  318. package/lib/routes/podwise/collections.ts +46 -0
  319. package/lib/routes/podwise/episodes.ts +119 -0
  320. package/lib/routes/podwise/namespace.ts +9 -0
  321. package/lib/routes/ps/monthly-games.ts +3 -2
  322. package/lib/routes/psyche/namespace.ts +6 -0
  323. package/lib/routes/psyche/templates/essay.art +3 -0
  324. package/lib/routes/psyche/templates/video.art +10 -0
  325. package/lib/routes/psyche/topic.ts +46 -0
  326. package/lib/routes/psyche/type.ts +53 -0
  327. package/lib/routes/psyche/utils.ts +107 -0
  328. package/lib/routes/pubscholar/explore.ts +62 -0
  329. package/lib/routes/pubscholar/namespace.ts +7 -0
  330. package/lib/routes/pubscholar/types.ts +41 -0
  331. package/lib/routes/pubscholar/utils.ts +44 -0
  332. package/lib/routes/pwc/sustainability.ts +53 -49
  333. package/lib/routes/qidian/chapter.ts +4 -3
  334. package/lib/routes/raycast/changelog.ts +54 -0
  335. package/lib/routes/raycast/namespace.ts +7 -0
  336. package/lib/routes/react/blog.ts +57 -0
  337. package/lib/routes/react/namespace.ts +6 -0
  338. package/lib/routes/readwise/list.ts +152 -0
  339. package/lib/routes/readwise/namespace.ts +6 -0
  340. package/lib/routes/reuters/common.ts +3 -2
  341. package/lib/routes/reuters/namespace.ts +1 -1
  342. package/lib/routes/rss3/index.ts +148 -0
  343. package/lib/routes/rss3/namespace.ts +7 -0
  344. package/lib/routes/rsshub/routes.ts +36 -14
  345. package/lib/routes/ruc/ai.ts +87 -0
  346. package/lib/routes/ruc/namespace.ts +5 -2
  347. package/lib/routes/samd/namespace.ts +6 -0
  348. package/lib/routes/samd/news.ts +74 -0
  349. package/lib/routes/sara/index.ts +1 -1
  350. package/lib/routes/sciencedirect/cf-email.ts +0 -1
  351. package/lib/routes/sehuatang/index.ts +33 -14
  352. package/lib/routes/sehuatang/user.ts +1 -1
  353. package/lib/routes/shiep/config.ts +4 -10
  354. package/lib/routes/shiep/index.ts +9 -9
  355. package/lib/routes/showstart/artist.ts +5 -4
  356. package/lib/routes/showstart/brand.ts +5 -4
  357. package/lib/routes/showstart/event.ts +8 -7
  358. package/lib/routes/showstart/search.ts +10 -8
  359. package/lib/routes/showstart/service.ts +81 -53
  360. package/lib/routes/showstart/site.ts +41 -0
  361. package/lib/routes/showstart/utils.ts +9 -8
  362. package/lib/routes/sicau/jiaowu.ts +77 -0
  363. package/lib/routes/sicau/jk.ts +210 -0
  364. package/lib/routes/sicau/namespace.ts +1 -1
  365. package/lib/routes/sjtu/jwc.ts +4 -1
  366. package/lib/routes/sjtu/yzb/zkxx.ts +36 -16
  367. package/lib/routes/smzdm/keyword.ts +3 -2
  368. package/lib/routes/smzdm/ranking.ts +180 -46
  369. package/lib/routes/spotify/artist.ts +16 -18
  370. package/lib/routes/spotify/artists-top.ts +7 -8
  371. package/lib/routes/spotify/playlist.ts +10 -10
  372. package/lib/routes/spotify/saved.ts +7 -8
  373. package/lib/routes/spotify/show.ts +8 -9
  374. package/lib/routes/spotify/tracks-top.ts +7 -8
  375. package/lib/routes/spotify/utils.ts +22 -22
  376. package/lib/routes/springer/journal.ts +10 -12
  377. package/lib/routes/sspai/author.ts +8 -2
  378. package/lib/routes/sspai/column.ts +1 -1
  379. package/lib/routes/sspai/index.ts +10 -4
  380. package/lib/routes/sspai/matrix.ts +8 -2
  381. package/lib/routes/sspai/prime-community.ts +83 -0
  382. package/lib/routes/sspai/series-update.ts +1 -1
  383. package/lib/routes/sspai/tag.ts +8 -2
  384. package/lib/routes/sspai/topic.ts +8 -2
  385. package/lib/routes/sspai/topics.ts +1 -1
  386. package/lib/routes/steam/sharefile-changelog.ts +65 -0
  387. package/lib/routes/steam/templates/workshop-search-description.art +5 -0
  388. package/lib/routes/steam/workshop-search.ts +109 -0
  389. package/lib/routes/stockedge/utils.ts +9 -11
  390. package/lib/routes/stream-capital/namespace.ts +6 -0
  391. package/lib/routes/stream-capital/search.ts +79 -0
  392. package/lib/routes/stream-capital/types.ts +44 -0
  393. package/lib/routes/stream-capital/utils.ts +18 -0
  394. package/lib/routes/sustainabilitymag/articles.ts +144 -0
  395. package/lib/routes/sustainabilitymag/namespace.ts +6 -0
  396. package/lib/routes/t66y/index.ts +29 -7
  397. package/lib/routes/techcrunch/news.ts +20 -29
  398. package/lib/routes/techcrunch/templates/description.art +7 -0
  399. package/lib/routes/telecompaper/news.ts +1 -1
  400. package/lib/routes/telegram/channel.ts +37 -31
  401. package/lib/routes/tencent/cloud/developer/column.ts +81 -0
  402. package/lib/routes/tencent/namespace.ts +2 -2
  403. package/lib/routes/tesla/cx.ts +1 -1
  404. package/lib/routes/test/index.ts +5 -1
  405. package/lib/routes/test/namespace.ts +1 -1
  406. package/lib/routes/the/index.ts +210 -0
  407. package/lib/routes/the/namespace.ts +8 -0
  408. package/lib/routes/the/templates/description.art +27 -0
  409. package/lib/routes/the/util.ts +307 -0
  410. package/lib/routes/theinitium/channel.ts +1 -1
  411. package/lib/routes/theinitium/follow.ts +1 -6
  412. package/lib/routes/theinitium/utils.ts +2 -18
  413. package/lib/routes/thoughtworks/index.ts +71 -0
  414. package/lib/routes/thoughtworks/namespace.ts +6 -0
  415. package/lib/routes/trending/all-trending.ts +2 -2
  416. package/lib/routes/tsdm39/bd.ts +101 -0
  417. package/lib/routes/tsdm39/namespace.ts +7 -0
  418. package/lib/routes/tvb/news.ts +1 -0
  419. package/lib/routes/twitter/api/index.ts +1 -1
  420. package/lib/routes/twitter/api/mobile-api/api.ts +9 -6
  421. package/lib/routes/twitter/api/mobile-api/login.ts +161 -138
  422. package/lib/routes/twitter/api/mobile-api/token.ts +16 -22
  423. package/lib/routes/twitter/api/web-api/api.ts +1 -0
  424. package/lib/routes/twitter/api/web-api/utils.ts +89 -17
  425. package/lib/routes/twitter/home.ts +2 -2
  426. package/lib/routes/twitter/keyword.ts +3 -2
  427. package/lib/routes/twitter/likes.ts +1 -1
  428. package/lib/routes/twitter/list.ts +1 -1
  429. package/lib/routes/twitter/media.ts +4 -3
  430. package/lib/routes/twitter/namespace.ts +2 -2
  431. package/lib/routes/twitter/user.ts +5 -4
  432. package/lib/routes/twitter/utils.ts +14 -5
  433. package/lib/routes/twreporter/category.ts +67 -22
  434. package/lib/routes/twreporter/fetch-article.ts +11 -5
  435. package/lib/routes/twreporter/newest.ts +2 -2
  436. package/lib/routes/typst/universe.ts +34 -8
  437. package/lib/routes/udn/breaking-news.ts +9 -0
  438. package/lib/routes/utgd/category.ts +18 -59
  439. package/lib/routes/utgd/timeline.ts +9 -45
  440. package/lib/routes/utgd/topic.ts +9 -51
  441. package/lib/routes/utgd/utils.ts +41 -0
  442. package/lib/routes/v2ex/tab.ts +3 -2
  443. package/lib/routes/v2ex/topics.ts +19 -3
  444. package/lib/routes/v2ex/xna.ts +55 -0
  445. package/lib/routes/vice/namespace.ts +6 -0
  446. package/lib/routes/vice/templates/article.art +19 -0
  447. package/lib/routes/vice/topic.ts +103 -0
  448. package/lib/routes/watasuke/blog.ts +1 -1
  449. package/lib/routes/weibo/friends.ts +1 -0
  450. package/lib/routes/weibo/group.ts +1 -0
  451. package/lib/routes/weibo/keyword.ts +3 -2
  452. package/lib/routes/weibo/namespace.ts +1 -1
  453. package/lib/routes/weibo/search/hot.ts +12 -7
  454. package/lib/routes/weibo/user-bookmarks.ts +191 -0
  455. package/lib/routes/weibo/user.ts +11 -8
  456. package/lib/routes/weibo/utils.ts +32 -2
  457. package/lib/routes/wfu/news.ts +1 -1
  458. package/lib/routes/wired/namespace.ts +7 -0
  459. package/lib/routes/wired/tag.ts +97 -0
  460. package/lib/routes/wired/types.ts +81 -0
  461. package/lib/routes/wordpress/util.ts +1 -1
  462. package/lib/routes/xiaoyuzhou/podcast.ts +2 -1
  463. package/lib/routes/ximalaya/album.ts +27 -19
  464. package/lib/routes/ximalaya/types.ts +68 -0
  465. package/lib/routes/ximalaya/utils.ts +38 -1
  466. package/lib/routes/xinhuanet/app.ts +109 -0
  467. package/lib/routes/xinhuanet/namespace.ts +8 -0
  468. package/lib/routes/xsijishe/forum.ts +23 -3
  469. package/lib/routes/xsijishe/rank.ts +23 -3
  470. package/lib/routes/yahoo/news/index.ts +149 -0
  471. package/lib/routes/yahoo/news/listid.ts +67 -0
  472. package/lib/routes/yahoo/news/{tw/provider-helper.ts → provider-helper.ts} +9 -4
  473. package/lib/routes/yahoo/news/{tw/provider.ts → provider.ts} +21 -6
  474. package/lib/routes/yahoo/news/{tw/utils.ts → utils.ts} +24 -15
  475. package/lib/routes/yicai/carousel.ts +48 -0
  476. package/lib/routes/yicai/utils.ts +23 -17
  477. package/lib/routes/ymgal/article.ts +1 -1
  478. package/lib/routes/youtube/channel.ts +1 -0
  479. package/lib/routes/youtube/custom.ts +2 -0
  480. package/lib/routes/youtube/live.ts +1 -0
  481. package/lib/routes/youtube/playlist.ts +1 -0
  482. package/lib/routes/youtube/subscriptions.ts +2 -0
  483. package/lib/routes/youtube/user.ts +16 -4
  484. package/lib/routes/zaobao/interactive.ts +2 -11
  485. package/lib/routes/zaobao/{index.ts → other.ts} +2 -10
  486. package/lib/routes/zaobao/realtime.ts +0 -8
  487. package/lib/routes/zaobao/util.ts +14 -10
  488. package/lib/routes/zcool/discover.ts +2 -1
  489. package/lib/routes/zhihu/activities.ts +2 -1
  490. package/lib/routes/zhihu/execlib/x-zse-96-v3.ts +2 -0
  491. package/lib/routes/zhihu/hot.ts +56 -7
  492. package/lib/routes/zhihu/namespace.ts +3 -0
  493. package/lib/routes/zhihu/posts.ts +20 -15
  494. package/lib/routes/zhihu/types.ts +104 -0
  495. package/lib/routes/zhihu/utils.ts +25 -4
  496. package/lib/routes/zhihu/zhuanlan.ts +8 -2
  497. package/lib/routes/zhubai/top20.ts +2 -2
  498. package/lib/routes/zhuwang/index.ts +1 -1
  499. package/lib/routes/zjgtjy/index.ts +3 -9
  500. package/lib/routes.test.ts +11 -5
  501. package/lib/types.ts +34 -2
  502. package/lib/utils/cache/index.ts +8 -0
  503. package/lib/utils/ofetch.ts +15 -1
  504. package/lib/utils/otel/index.ts +2 -0
  505. package/lib/utils/otel/metric.ts +66 -0
  506. package/lib/utils/otel/trace.ts +28 -0
  507. package/lib/utils/request-rewriter/fetch.ts +21 -2
  508. package/lib/utils/request-rewriter.test.ts +14 -0
  509. package/lib/views/atom.tsx +2 -2
  510. package/lib/views/error.tsx +4 -4
  511. package/lib/views/index.tsx +5 -4
  512. package/lib/views/json.ts +1 -1
  513. package/lib/views/layout.tsx +1 -1
  514. package/lib/views/rss.tsx +3 -2
  515. package/lib/views/rss3.test.ts +99 -0
  516. package/package.json +69 -56
  517. package/lib/routes/ieee/earlyaccess.ts +0 -100
  518. package/lib/routes/ieee/recent.ts +0 -107
  519. package/lib/routes/yahoo/news/tw/index.ts +0 -80
  520. package/lib/routes/yahoo/news/us/index.ts +0 -55
  521. package/lib/routes/zhihu/hotlist.ts +0 -72
  522. package/lib/routes-deprecated/bjnews/news.js +0 -44
  523. package/lib/routes-deprecated/iplay/home.js +0 -26
  524. package/lib/routes-deprecated/iplay/utils.js +0 -57
  525. package/lib/routes-deprecated/matters/author.js +0 -49
  526. package/lib/routes-deprecated/matters/latest.js +0 -69
  527. package/lib/routes-deprecated/matters/tags.js +0 -56
  528. /package/lib/routes/gov/{shanghai → sh}/rsj/templates/ksxm.art +0 -0
  529. /package/lib/routes/gov/{shanghai → sh}/wgj/templates/wgj.art +0 -0
  530. /package/lib/routes/hypergryph/{announce.ts → arknights/announce.ts} +0 -0
  531. /package/lib/routes/hypergryph/{japan.ts → arknights/japan.ts} +0 -0
  532. /package/lib/routes/hypergryph/{news.ts → arknights/news.ts} +0 -0
@@ -0,0 +1,307 @@
1
+ import got from '@/utils/got';
2
+ import { load } from 'cheerio';
3
+
4
+ const apiSlug = 'wp-json/wp/v2';
5
+
6
+ interface Filter {
7
+ id: string;
8
+ name: string;
9
+ slug: string;
10
+ }
11
+
12
+ const filterKeys: Record<string, string> = {
13
+ search: 's',
14
+ };
15
+
16
+ const filterApiKeys: Record<string, string | undefined> = {
17
+ category: 'categories',
18
+ tag: 'tags',
19
+ search: undefined,
20
+ };
21
+
22
+ const filterApiKeysWithNoId = new Set(['search']);
23
+
24
+ /**
25
+ * Bake filter search parameters.
26
+ *
27
+ * @param filterPairs - The filter pairs object.
28
+ * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`.
29
+ * @param pairKey - The filter pair key.
30
+ * e.g. `{ id: ..., name: ..., slug: ... }`.
31
+ * @param isApi - Indicates if the search parameters are for API.
32
+ * @returns The baked filter search parameters.
33
+ */
34
+ const bakeFilterSearchParams = (filterPairs: Record<string, Filter[] | string[]>, pairKey: string, isApi: boolean = false): URLSearchParams => {
35
+ /**
36
+ * Bake filters recursively.
37
+ *
38
+ * @param filterPairs - The filter pairs object.
39
+ * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`.
40
+ * @param filterSearchParams - The filter search parameters.
41
+ * e.g. `category=a,b&tag=c`.
42
+ * @returns The baked filter search parameters.
43
+ * e.g. `category=a,b&tag=c`.
44
+ */
45
+ const bakeFilters = (filterPairs: Record<string, Filter[] | string[]>, filterSearchParams: URLSearchParams): URLSearchParams => {
46
+ const keys = Object.keys(filterPairs).filter((key) => filterPairs[key]?.length > 0 && (isApi ? Object.hasOwn(filterApiKeys, key) : Object.hasOwn(filterKeys, key)));
47
+
48
+ if (keys.length === 0) {
49
+ return filterSearchParams;
50
+ }
51
+
52
+ const key = keys[0];
53
+ const pairs = filterPairs[key];
54
+
55
+ const originalFilters = { ...filterPairs };
56
+ delete originalFilters[key];
57
+
58
+ const filterKey = getFilterKeyForSearchParams(key, isApi);
59
+ const pairValues = pairs.map((pair) => (Object.hasOwn(pair, pairKey) ? pair[pairKey] : pair));
60
+
61
+ if (filterKey) {
62
+ filterSearchParams.append(filterKey, pairValues.join(','));
63
+ }
64
+
65
+ return bakeFilters(originalFilters, filterSearchParams);
66
+ };
67
+
68
+ return bakeFilters(filterPairs, new URLSearchParams());
69
+ };
70
+
71
+ /**
72
+ * Bake filters with pair.
73
+ *
74
+ * @param filters - The filters object.
75
+ * e.g. `{ category: [ a, b ], tag: [ c ] }`.
76
+ * @returns The baked filters.
77
+ * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`.
78
+ */
79
+ const bakeFiltersWithPair = async (filters: Record<string, string[]>, rootUrl: string) => {
80
+ /**
81
+ * Bake keywords recursively.
82
+ *
83
+ * @param key - The key.
84
+ * e.g. `category` or `tag`.
85
+ * @param keywords - The keywords.
86
+ * e.g. `[ a, b ]`.
87
+ * @returns The baked keywords.
88
+ * e.g. `[ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ]`.
89
+ */
90
+ const bakeKeywords = async (key: string, keywords: string[]) => {
91
+ if (keywords.length === 0) {
92
+ return [];
93
+ }
94
+
95
+ const [keyword, ...rest] = keywords;
96
+
97
+ const filter = await getFilterByKeyAndKeyword(key, keyword, rootUrl);
98
+
99
+ return [
100
+ ...(filter?.id && filter?.slug
101
+ ? [
102
+ {
103
+ id: filter.id,
104
+ name: filter.name,
105
+ slug: filter.slug,
106
+ },
107
+ ]
108
+ : []),
109
+ ...(await bakeKeywords(key, rest)),
110
+ ];
111
+ };
112
+
113
+ /**
114
+ * Bake filters recursively.
115
+ *
116
+ * @param filters - The filters object.
117
+ * e.g. `{ category: [ a, b ], tag: [ c ] }`.
118
+ * @param filtersWithPair - The filters with pairs.
119
+ * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`.
120
+ * @returns The baked filters.
121
+ * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`.
122
+ */
123
+ const bakeFilters = async (filters: Record<string, string[]>, filtersWithPair: Record<string, Filter[]>) => {
124
+ const keys = Object.keys(filters);
125
+
126
+ if (keys.length === 0) {
127
+ return filtersWithPair;
128
+ }
129
+
130
+ const key = keys[0];
131
+ const keywords = filters[key];
132
+
133
+ const originalFilters = { ...filters };
134
+ delete originalFilters[key];
135
+
136
+ return bakeFilters(originalFilters, {
137
+ ...filtersWithPair,
138
+ [key]: filterApiKeysWithNoId.has(key) ? keywords : await bakeKeywords(key, keywords),
139
+ });
140
+ };
141
+
142
+ return await bakeFilters(filters, {});
143
+ };
144
+
145
+ /**
146
+ * Bake URL with search parameters.
147
+ *
148
+ * @param url - The URL.
149
+ * @param rootUrl - The root URL.
150
+ * @param searchParams - The search parameters.
151
+ * @returns The baked URL.
152
+ */
153
+ const bakeUrl = (url: string, rootUrl: string, searchParams: URLSearchParams = new URLSearchParams()): string => {
154
+ const searchParamsStr = searchParams.toString();
155
+ const searchParamsSuffix = searchParamsStr ? `?${searchParamsStr}` : '';
156
+
157
+ return `${rootUrl}/${url}${searchParamsSuffix}`;
158
+ };
159
+
160
+ /**
161
+ * Fetch data from the specified URL.
162
+ *
163
+ * @param url - The URL to fetch data from.
164
+ * @param rootUrl - The root URL.
165
+ * @returns A promise that resolves to an object containing the fetched data to be added into `ctx.state.data`.
166
+ */
167
+ const fetchData = async (url: string, rootUrl: string): Promise<object> => {
168
+ /**
169
+ * Request URLs recursively.
170
+ *
171
+ * @param urls - The URLs to request.
172
+ * @returns A promise that resolves to the response data or undefined if no response is available.
173
+ */
174
+ const requestUrls = async (urls: string[]): Promise<string | undefined> => {
175
+ if (urls.length === 0) {
176
+ return;
177
+ }
178
+
179
+ const [currentUrl, ...remainingUrls] = urls;
180
+ try {
181
+ const { data: response } = await got.get(currentUrl);
182
+ return response;
183
+ } catch {
184
+ return requestUrls(remainingUrls);
185
+ }
186
+ };
187
+
188
+ const response = await requestUrls([url, rootUrl]);
189
+
190
+ if (!response) {
191
+ return {};
192
+ }
193
+
194
+ const $ = load(response);
195
+
196
+ const title = $('title').first().text();
197
+ const image = new URL('wp-content/uploads/site_logo.png', rootUrl).href;
198
+
199
+ return {
200
+ title,
201
+ description: $('meta[property="og:description"]').attr('content') || $('meta[name="description"]').attr('content'),
202
+ link: url,
203
+ allowEmpty: true,
204
+ image,
205
+ author: $('meta[property="og:site_name"]').attr('content'),
206
+ language: $('html').attr('lang'),
207
+ };
208
+ };
209
+
210
+ /**
211
+ * Get filter by key and keyword.
212
+ *
213
+ * @param key - The key.
214
+ * e.g. `category` or `tag`.
215
+ * @param keyword - The keywords.
216
+ * e.g. `keyword1`.
217
+ * @returns A promise that resolves to the filter object if found, or undefined if not found.
218
+ */
219
+ const getFilterByKeyAndKeyword = async (key: string, keyword: string, rootUrl: string): Promise<Filter | undefined> => {
220
+ const apiFilterUrl = `${rootUrl}/${apiSlug}/${getFilterKeyForSearchParams(key, true)}`;
221
+
222
+ const { data: response } = await got(apiFilterUrl, {
223
+ searchParams: {
224
+ search: keyword,
225
+ },
226
+ });
227
+
228
+ return response.length > 0 ? response[0] : undefined;
229
+ };
230
+
231
+ /**
232
+ * Get filter key for search parameters.
233
+ *
234
+ * @param key - The key. e.g. `category` or `tag`.
235
+ * @param isApi - Indicates whether the key is for the API.
236
+ * @returns The filter key for search parameters, or undefined if not found.
237
+ * e.g. `categories` or `tags`.
238
+ */
239
+ const getFilterKeyForSearchParams = (key: string, isApi: boolean = false): string | undefined => {
240
+ const keys = isApi ? filterApiKeys : filterKeys;
241
+
242
+ return Object.hasOwn(keys, key) ? (keys[key] ?? key) : undefined;
243
+ };
244
+
245
+ /**
246
+ * Get filter parameters for URL.
247
+ *
248
+ * @param filterPairs - The filter pairs object.
249
+ * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`.
250
+ * @returns The filter parameters for the URL, or undefined if no filters are available.
251
+ */
252
+ const getFilterParamsForUrl = (filterPairs: Record<string, Filter[]>): string | undefined => {
253
+ const keys = Object.keys(filterPairs).filter((key) => filterPairs[key].length > 0 && !Object.hasOwn(filterKeys, key));
254
+
255
+ if (keys.length === 0) {
256
+ return;
257
+ }
258
+
259
+ const key = keys[0];
260
+
261
+ return filterPairs[key].map((pair) => pair.slug).join('/');
262
+ };
263
+
264
+ /**
265
+ * Parses a filter string into a filters object.
266
+ *
267
+ * @param filterStr - The filter string to parse.
268
+ * e.g. `category/a,b/tag/c`.
269
+ * @returns The parsed filters object.
270
+ * e.g. `{ category: [ 'a', 'b' ], tag: [ 'c' ] }`.
271
+ */
272
+ const parseFilterStr = (filterStr: string | undefined): Record<string, string[]> => {
273
+ /**
274
+ * Recursively parses a filter string.
275
+ *
276
+ * @param remainingStr - The remaining filter string to parse.
277
+ * e.g. `category/a,b/tag/c`.
278
+ * @param filters - The accumulated filters object.
279
+ * e.g. `{ category: [ a, b ], tag: [ c ] }`.
280
+ * @param currentKey - The current filter key.
281
+ * e.g. `category` or `tag`.
282
+ * @returns The parsed filters object.
283
+ */
284
+ const parseStr = (remainingStr: string | undefined, filters: Record<string, string[]> = {}, currentKey?: string): Record<string, string[]> => {
285
+ if (!remainingStr) {
286
+ return filters;
287
+ }
288
+
289
+ const [word, ...rest] = remainingStr.split(/\/|,/);
290
+
291
+ const isKey = Object.hasOwn(filterApiKeys, word);
292
+ const key = isKey ? word : currentKey;
293
+
294
+ const newFilters = key
295
+ ? {
296
+ ...filters,
297
+ [key]: [...(filters[key] || []), ...(isKey ? [] : [word])],
298
+ }
299
+ : filters;
300
+
301
+ return parseStr(rest.join('/'), newFilters, key);
302
+ };
303
+
304
+ return parseStr(filterStr, {});
305
+ };
306
+
307
+ export { apiSlug, bakeFilterSearchParams, bakeFiltersWithPair, bakeUrl, fetchData, getFilterParamsForUrl, parseFilterStr };
@@ -6,7 +6,7 @@ const handler = (ctx) => processFeed('channel', ctx);
6
6
  export const route: Route = {
7
7
  path: '/channel/:type?/:language?',
8
8
  name: '专题・栏目',
9
- maintainers: ['prnake'],
9
+ maintainers: ['prnake', 'mintyfrankie'],
10
10
  parameters: {
11
11
  type: '栏目,缺省为最新',
12
12
  language: '语言,简体`zh-hans`,繁体`zh-hant`,缺省为简体',
@@ -20,7 +20,7 @@ export const route: Route = {
20
20
  handler,
21
21
  example: '/theinitium/author/ninghuilulu/zh-hans',
22
22
  categories: ['new-media'],
23
- description: 'Web 版认证 token 和 iOS 内购回执认证 token 只需选择其一填入即可。你也可选择直接在环境设置中填写明文的用户名和密码',
23
+ description: '需填入 Web 版认证 token, 也可选择直接在环境设置中填写明文的用户名和密码',
24
24
  features: {
25
25
  requireConfig: [
26
26
  {
@@ -28,11 +28,6 @@ export const route: Route = {
28
28
  optional: true,
29
29
  description: `端传媒 Web 版认证 token。获取方式:登陆后打开端传媒站内任意页面,打开浏览器开发者工具中 “网络”(Network) 选项卡,筛选 URL 找到任一个地址为 \`api.initium.com\` 开头的请求,点击检查其 “消息头”,在 “请求头” 中找到Authorization字段,将其值复制填入配置即可。你的配置应该形如 \`INITIUM_BEARER_TOKEN: 'Bearer eyJxxxx......xx_U8'\`。使用 token 部署的好处是避免占据登陆设备数的额度,但这个 token 一般有效期为两周,因此只可作临时测试使用。`,
30
30
  },
31
- {
32
- name: 'INITIUM_IAP_RECEIPT',
33
- optional: true,
34
- description: `端传媒 iOS 版内购回执认证 token。获取方式:登陆后打开端传媒 iOS app 内任意页面,打开抓包工具,筛选 URL 找到任一个地址为 \`api.initium.com\` 开头的请求,点击检查其 “消息头”,在 “请求头” 中找到 \`X-IAP-Receipt\` 字段,将其值复制填入配置即可。你的配置应该形如 \`INITIUM_IAP_RECEIPT: ef81dee9e4e2fe084a0af1ea82da2f7b16e75f756db321618a119fa62b52550e\`。`,
35
- },
36
31
  {
37
32
  name: 'INITIUM_USERNAME',
38
33
  optional: true,
@@ -39,7 +39,6 @@ export const processFeed = async (model: string, ctx: Context) => {
39
39
  const key = {
40
40
  email: config.initium.username,
41
41
  password: config.initium.password,
42
- iapReceipt: config.initium.iap_receipt,
43
42
  };
44
43
  const body = JSON.stringify(key);
45
44
 
@@ -59,25 +58,11 @@ export const processFeed = async (model: string, ctx: Context) => {
59
58
  Accept: 'application/json',
60
59
  Connection: 'keep-alive',
61
60
  Authorization: TOKEN,
62
- Origin: `https://theinitium.com/`,
63
- Referer: `https://theinitium.com/`,
64
- 'X-Client-Name': 'Web',
65
61
  },
66
62
  body,
67
63
  });
68
64
 
69
- /*
70
- const devices = login.data.access.devices;
71
-
72
- for (const key in devices) {
73
- const device = devices[key];
74
- if (device.status === 'logged_in' && !device.logout_at && device.platform === 'web') {
75
- token = 'Bearer ' + device.device_id;
76
- break;
77
- }
78
- }
79
- */
80
- token = 'Bearer ' + login.data.token;
65
+ token = 'token ' + login.data.token;
81
66
  cache.set('initium:token', token);
82
67
  }
83
68
 
@@ -85,7 +70,6 @@ export const processFeed = async (model: string, ctx: Context) => {
85
70
  Accept: '*/*',
86
71
  Connection: 'keep-alive',
87
72
  Authorization: token,
88
- 'X-IAP-Receipt': key.iapReceipt || '',
89
73
  };
90
74
 
91
75
  let response;
@@ -154,7 +138,7 @@ export const processFeed = async (model: string, ctx: Context) => {
154
138
  const items = await Promise.all(
155
139
  articles
156
140
  .filter((a) => a.article)
157
- .slice(0, token === TOKEN && key.iapReceipt === undefined ? 25 : articles.length)
141
+ .slice(0, token === TOKEN ? 25 : articles.length)
158
142
  .map(async (item) => {
159
143
  item.article.date = parseDate(item.article.date);
160
144
  item.article.updated = parseDate(item.article.updated);
@@ -0,0 +1,71 @@
1
+ import { Route } from '@/types';
2
+ import ofetch from '@/utils/ofetch'; // 统一使用的请求库
3
+ import { parseDate } from '@/utils/parse-date';
4
+
5
+ export const route: Route = {
6
+ path: '/blog',
7
+ categories: ['programming'],
8
+ example: '/thoughtworks/blog',
9
+ radar: [
10
+ {
11
+ source: ['www.thoughtworks.com/zh-cn/insights/blog'],
12
+ },
13
+ ],
14
+ name: 'Inside Blog',
15
+ maintainers: ['Hyvi'],
16
+ handler,
17
+ };
18
+ async function handler() {
19
+ // https://www.thoughtworks.com/rest/search/config 里的 BLOG_SEARCH_TOKEN
20
+ const tokenData = await ofetch('https://www.thoughtworks.com/rest/search/config', {
21
+ headers: {
22
+ 'content-type': 'application/json',
23
+ origin: 'https://www.thoughtworks.com',
24
+ referer: 'https://www.thoughtworks.com/',
25
+ },
26
+ });
27
+
28
+ // 'Bearer ' + token
29
+ const bearerToken = 'Bearer ' + tokenData.BLOG_SEARCH_TOKEN;
30
+
31
+ const data = await ofetch('https://platform-eu.cloud.coveo.com/rest/search/v2?organizationId=thoughtworksproductionhcqoag0q', {
32
+ method: 'POST',
33
+ headers: {
34
+ authorization: bearerToken,
35
+ 'content-type': 'application/json',
36
+ origin: 'https://www.thoughtworks.com',
37
+ referer: 'https://www.thoughtworks.com/',
38
+ },
39
+ body: {
40
+ context: { countryLocale: 'zh-cn' },
41
+ fieldsToInclude: ['author', 'language', 'objecttype', 'collection', 'source', 'tw_content_type', 'tw_topic', 'tw_published_date'],
42
+ sortCriteria: '@tw_published_date descending',
43
+ numberOfResults: 10,
44
+ firstResult: 0,
45
+ },
46
+ });
47
+ // 从 API 响应中提取相关数据
48
+ const items = data.results.map((item) => ({
49
+ // 文章标题
50
+ title: item.title,
51
+ // 文章链接
52
+ link: item.uri,
53
+ // 文章正文
54
+ description: item.excerpt,
55
+ // 文章发布日期
56
+ pubDate: parseDate(item.raw.tw_published_date),
57
+ // 如果有的话,文章作者
58
+ author: item.raw.sysauthor,
59
+ // 如果有的话,文章分类
60
+ // category: item.labels.map((label) => label.name),
61
+ }));
62
+
63
+ return {
64
+ // 源标题
65
+ title: 'ThoughtWorks Blog',
66
+ // 源链接
67
+ link: 'https://www.thoughtworks.com/zh-cn/insights/blog',
68
+ // 源文章
69
+ item: items,
70
+ };
71
+ }
@@ -0,0 +1,6 @@
1
+ import type { Namespace } from '@/types';
2
+
3
+ export const namespace: Namespace = {
4
+ name: 'ThoughtWorks',
5
+ url: 'www.thoughtworks.com/zh-cn/insights/blog',
6
+ };
@@ -8,7 +8,7 @@ import utc from 'dayjs/plugin/utc';
8
8
  import timezone from 'dayjs/plugin/timezone';
9
9
  dayjs.extend(utc);
10
10
  dayjs.extend(timezone);
11
- import got from '@/utils/got';
11
+ import ofetch from '@/utils/ofetch';
12
12
  import { art } from '@/utils/render';
13
13
  import path from 'node:path';
14
14
  import { config } from '@/config';
@@ -75,7 +75,7 @@ const filterKeyword = (keywordList) => (res) => res.filter(({ title }) => hasKey
75
75
  // Data Fetcher
76
76
  // TODO: support channel selection
77
77
  const fetchAllData = async (keywordList = [], dateList = [], cache) => {
78
- const cachedGetData = (url) => cache.tryGet(url, () => got(url).json(), config.cache.contentExpire, false);
78
+ const cachedGetData = (url) => cache.tryGet(url, () => ofetch(url), config.cache.contentExpire, false);
79
79
 
80
80
  let data = await Promise.all(
81
81
  dateList.map(async (dateTime) => ({
@@ -0,0 +1,101 @@
1
+ import type { DataItem, Route } from '@/types';
2
+ import { config } from '@/config';
3
+ import ofetch from '@/utils/ofetch';
4
+ import { load } from 'cheerio';
5
+ import { parseDate } from '@/utils/parse-date';
6
+ import ConfigNotFoundError from '@/errors/types/config-not-found';
7
+
8
+ // type id => display name
9
+ type Mapping = Record<string, string>;
10
+
11
+ const TYPE: Mapping = {
12
+ '403': '720P',
13
+ '404': '1080P',
14
+ '405': 'BDMV',
15
+ '4130': '4K',
16
+ '5815': 'AV1',
17
+ };
18
+
19
+ // render into MD table
20
+ const mkTable = (mapping: Mapping): string => {
21
+ const heading: string[] = [],
22
+ separator: string[] = [],
23
+ body: string[] = [];
24
+
25
+ for (const key in mapping) {
26
+ heading.push(mapping[key]);
27
+ separator.push(':--:');
28
+ body.push(key);
29
+ }
30
+
31
+ return [heading.join(' | '), separator.join(' | '), body.join(' | ')].map((s) => `| ${s} |`).join('\n');
32
+ };
33
+
34
+ const handler: Route['handler'] = async (ctx) => {
35
+ const { type } = ctx.req.param();
36
+
37
+ const cookie = config.tsdm39.cookie;
38
+ if (!cookie) {
39
+ throw new ConfigNotFoundError('缺少 TSDM39 用户登录后的 Cookie 值 <a href="https://docs.rsshub.app/zh/deploy/config#route-specific-configurations">TSDM 相关路由</a>');
40
+ }
41
+
42
+ const html = await ofetch(`https://www.tsdm39.com/forum.php?mod=forumdisplay&fid=85${type ? `&filter=typeid&typeid=${type}` : ''}`, {
43
+ headers: {
44
+ Cookie: cookie,
45
+ },
46
+ });
47
+
48
+ const $ = load(html);
49
+
50
+ const item = $('tbody.tsdm_normalthread')
51
+ .toArray()
52
+ .map<DataItem>((item) => {
53
+ const $ = load(item);
54
+
55
+ const title = $('a.xst').text();
56
+ const price = $('span.xw1').last().text();
57
+ const link = $('a.xst').attr('href');
58
+ const date = $('td.by em').first().text().trim();
59
+
60
+ return {
61
+ title,
62
+ description: `价格:${price}`,
63
+ link,
64
+ pubDate: parseDate(date),
65
+ };
66
+ });
67
+
68
+ return {
69
+ title: '天使动漫论坛 - BD',
70
+ link: 'https://www.tsdm39.com/forum.php?mod=forumdisplay&fid=85',
71
+ language: 'zh-Hans',
72
+ item,
73
+ };
74
+ };
75
+
76
+ export const route: Route = {
77
+ path: '/bd/:type?',
78
+ name: 'BD',
79
+ categories: ['anime'],
80
+ maintainers: ['equt'],
81
+ example: '/tsdm39/bd',
82
+ parameters: {
83
+ type: 'BD type, checkout the table below for details',
84
+ },
85
+ features: {
86
+ requireConfig: [
87
+ {
88
+ name: 'TSDM39_COOKIES',
89
+ optional: false,
90
+ description: '天使动漫论坛登陆后的 cookie 值,可在浏览器控制台通过 `document.cookie` 获取。',
91
+ },
92
+ ],
93
+ requirePuppeteer: false,
94
+ antiCrawler: false,
95
+ supportBT: false,
96
+ supportPodcast: false,
97
+ supportScihub: false,
98
+ },
99
+ handler,
100
+ description: [TYPE].map((el) => mkTable(el)).join('\n\n'),
101
+ };
@@ -0,0 +1,7 @@
1
+ import type { Namespace } from '@/types';
2
+
3
+ export const namespace: Namespace = {
4
+ name: '天使动漫论坛',
5
+ url: 'www.tsdm39.com',
6
+ categories: ['anime'],
7
+ };
@@ -96,6 +96,7 @@ async function handler(ctx) {
96
96
  lang: language,
97
97
  page: 1,
98
98
  limit: ctx.req.query('limit') ?? 50,
99
+ country: 'HK',
99
100
  },
100
101
  });
101
102
 
@@ -4,7 +4,7 @@ import webApi from './web-api/api';
4
4
  import { config } from '@/config';
5
5
 
6
6
  const enableMobileApi = config.twitter.username && config.twitter.password;
7
- const enableWebApi = config.twitter.cookie;
7
+ const enableWebApi = config.twitter.authToken;
8
8
 
9
9
  type ApiItem = (id: string, params?: Record<string, any>) => Promise<Record<string, any>> | Record<string, any> | null;
10
10
  let api: {
@@ -1,18 +1,18 @@
1
1
  import { baseUrl, gqlMap, gqlFeatures, consumerKey, consumerSecret } from './constants';
2
2
  import { config } from '@/config';
3
3
  import logger from '@/utils/logger';
4
- import got from '@/utils/got';
5
4
  import OAuth from 'oauth-1.0a';
6
5
  import CryptoJS from 'crypto-js';
7
6
  import queryString from 'query-string';
8
- import { initToken, getToken } from './token';
7
+ import { getToken } from './token';
9
8
  import cache from '@/utils/cache';
10
9
  import InvalidParameterError from '@/errors/types/invalid-parameter';
10
+ import ofetch from '@/utils/ofetch';
11
11
 
12
12
  const twitterGot = async (url, params) => {
13
13
  const token = await getToken();
14
14
 
15
- const oauth = OAuth({
15
+ const oauth = new OAuth({
16
16
  consumer: {
17
17
  key: consumerKey,
18
18
  secret: consumerSecret,
@@ -36,11 +36,14 @@ const twitterGot = async (url, params) => {
36
36
  },
37
37
  };
38
38
 
39
- const response = await got(requestData.url, {
39
+ const response = await ofetch.raw(requestData.url, {
40
40
  headers: oauth.toHeader(oauth.authorize(requestData, token)),
41
41
  });
42
+ if (response.status === 401) {
43
+ cache.globalCache.set(token.cacheKey, '');
44
+ }
42
45
 
43
- return response.data;
46
+ return response._data;
44
47
  };
45
48
 
46
49
  const paginationTweets = async (endpoint, userId, variables, path) => {
@@ -279,5 +282,5 @@ export default {
279
282
  excludeRetweet,
280
283
  getSearch,
281
284
  getUserTweet,
282
- init: initToken,
285
+ init: () => void 0,
283
286
  };