rsshub 1.0.0-master.ff3a9ce → 1.0.0-master.ff3ea5a

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.

Potentially problematic release.


This version of rsshub might be problematic. Click here for more details.

Files changed (388) hide show
  1. package/lib/config.ts +38 -0
  2. package/lib/errors/index.tsx +3 -2
  3. package/lib/middleware/debug.ts +6 -4
  4. package/lib/middleware/header.ts +4 -2
  5. package/lib/registry.test.ts +24 -1
  6. package/lib/registry.ts +40 -11
  7. package/lib/router.js +1 -1
  8. package/lib/routes/121/namespace.ts +9 -0
  9. package/lib/routes/121/templates/description.art +17 -0
  10. package/lib/routes/121/weather-live.ts +104 -0
  11. package/lib/routes/141jav/index.ts +3 -0
  12. package/lib/routes/141ppv/index.ts +3 -0
  13. package/lib/routes/163/news/rank.ts +1 -1
  14. package/lib/routes/18comic/album.ts +59 -64
  15. package/lib/routes/18comic/index.ts +1 -0
  16. package/lib/routes/18comic/search.ts +53 -4
  17. package/lib/routes/18comic/utils.ts +70 -1
  18. package/lib/routes/2048/index.ts +1 -0
  19. package/lib/routes/30secondsofcode/utils.ts +0 -1
  20. package/lib/routes/6park/index.ts +1 -1
  21. package/lib/routes/7mmtv/index.ts +1 -0
  22. package/lib/routes/91porn/index.ts +1 -0
  23. package/lib/routes/95mm/tab.ts +1 -0
  24. package/lib/routes/agefans/detail.ts +1 -1
  25. package/lib/routes/aliyun/database-month.ts +1 -1
  26. package/lib/routes/anthropic/research.ts +112 -0
  27. package/lib/routes/apnews/topics.ts +2 -1
  28. package/lib/routes/apnews/utils.ts +1 -1
  29. package/lib/routes/apple/design.ts +54 -0
  30. package/lib/routes/apple/namespace.ts +1 -1
  31. package/lib/routes/aqara/post.ts +1 -1
  32. package/lib/routes/augmentcode/blog.ts +161 -0
  33. package/lib/routes/augmentcode/namespace.ts +9 -0
  34. package/lib/routes/augmentcode/templates/description.art +17 -0
  35. package/lib/routes/azul/namespace.ts +9 -0
  36. package/lib/routes/azul/packages.ts +105 -0
  37. package/lib/routes/banshujiang/index.ts +763 -0
  38. package/lib/routes/banshujiang/namespace.ts +9 -0
  39. package/lib/routes/banshujiang/templates/description.art +17 -0
  40. package/lib/routes/bfl/announcements.ts +1 -1
  41. package/lib/routes/bilibili/cache.ts +78 -0
  42. package/lib/routes/bilibili/danmaku.ts +1 -1
  43. package/lib/routes/bilibili/dynamic.ts +8 -2
  44. package/lib/routes/bilibili/video.ts +31 -73
  45. package/lib/routes/biquge/index.ts +1 -1
  46. package/lib/routes/bsky/keyword.ts +15 -10
  47. package/lib/routes/capitalmind/insights.ts +40 -0
  48. package/lib/routes/capitalmind/namespace.ts +8 -0
  49. package/lib/routes/capitalmind/podcasts.ts +41 -0
  50. package/lib/routes/capitalmind/utils.ts +122 -0
  51. package/lib/routes/cartoonmad/comic.ts +1 -1
  52. package/lib/routes/chikubi/index.ts +1 -0
  53. package/lib/routes/chikubi/tag.ts +1 -0
  54. package/lib/routes/chocolatey/namespace.ts +9 -0
  55. package/lib/routes/chocolatey/packages.ts +122 -0
  56. package/lib/routes/cmde/index.ts +1 -1
  57. package/lib/routes/cockroachlabs/blog.ts +113 -0
  58. package/lib/routes/cockroachlabs/namespace.ts +7 -0
  59. package/lib/routes/cool18/index.ts +4 -1
  60. package/lib/routes/coomer/index.ts +12 -6
  61. package/lib/routes/coomer/namespace.ts +1 -1
  62. package/lib/routes/copymanga/comic.ts +7 -9
  63. package/lib/routes/css-tricks/articles.ts +48 -0
  64. package/lib/routes/css-tricks/collections.ts +62 -0
  65. package/lib/routes/css-tricks/namespace.ts +8 -0
  66. package/lib/routes/css-tricks/popular.ts +39 -0
  67. package/lib/routes/css-tricks/utils.ts +103 -0
  68. package/lib/routes/cursor/changelog.ts +26 -17
  69. package/lib/routes/cursor/namespace.ts +1 -1
  70. package/lib/routes/cw/utils.ts +6 -13
  71. package/lib/routes/dealstreetasia/home.ts +1 -1
  72. package/lib/routes/dedao/index.ts +3 -3
  73. package/lib/routes/deepl/blog.ts +422 -0
  74. package/lib/routes/deepl/namespace.ts +9 -0
  75. package/lib/routes/deepl/templates/description.art +21 -0
  76. package/lib/routes/deeplearning/the-batch.ts +1 -1
  77. package/lib/routes/dev.to/guides.ts +100 -0
  78. package/lib/routes/dev.to/namespace.ts +8 -0
  79. package/lib/routes/dev.to/top.ts +105 -0
  80. package/lib/routes/dgut/jwb.ts +73 -0
  81. package/lib/routes/dgut/namespace.ts +9 -0
  82. package/lib/routes/digitalpolicyalert/activity-tracker.ts +135 -0
  83. package/lib/routes/digitalpolicyalert/namespace.ts +9 -0
  84. package/lib/routes/dnaindia/common.ts +26 -8
  85. package/lib/routes/douban/other/list.ts +3 -3
  86. package/lib/routes/e-hentai/index.ts +4 -1
  87. package/lib/routes/ehentai/tag.ts +1 -0
  88. package/lib/routes/englishhome/index.ts +55 -0
  89. package/lib/routes/englishhome/namespace.ts +6 -0
  90. package/lib/routes/epicgames/index.ts +2 -2
  91. package/lib/routes/espn/news.ts +1 -1
  92. package/lib/routes/expats/czech-news.ts +272 -0
  93. package/lib/routes/expats/namespace.ts +9 -0
  94. package/lib/routes/fanbox/index.ts +1 -0
  95. package/lib/routes/fanbox/utils.ts +1 -1
  96. package/lib/routes/fansly/tag.ts +1 -0
  97. package/lib/routes/fantia/search.ts +1 -1
  98. package/lib/routes/fantube/creator.ts +69 -0
  99. package/lib/routes/fantube/namespace.ts +7 -0
  100. package/lib/routes/fantube/templates/post.art +17 -0
  101. package/lib/routes/fantube/types.ts +100 -0
  102. package/lib/routes/fantube/utils.ts +268 -0
  103. package/lib/routes/follow/profile.ts +1 -1
  104. package/lib/routes/followin/news.ts +1 -1
  105. package/lib/routes/foresightnews/util.ts +1 -1
  106. package/lib/routes/freexcomic/book.ts +4 -1
  107. package/lib/routes/gamer/hot.ts +5 -5
  108. package/lib/routes/gaoyu/blog.ts +145 -0
  109. package/lib/routes/gaoyu/namespace.ts +9 -0
  110. package/lib/routes/gaoyu/templates/description.art +7 -0
  111. package/lib/routes/geocaching/blogs.ts +2 -2
  112. package/lib/routes/github/namespace.ts +1 -1
  113. package/lib/routes/github/private-feed.ts +229 -0
  114. package/lib/routes/github/star.ts +1 -1
  115. package/lib/routes/google/extension.ts +9 -10
  116. package/lib/routes/gov/beijing/bphc/index.ts +1 -1
  117. package/lib/routes/gov/ccdi/index.ts +1 -1
  118. package/lib/routes/gov/chongqing/sydwgkzp.ts +22 -6
  119. package/lib/routes/gov/customs/list.ts +1 -1
  120. package/lib/routes/gov/general/general.ts +1 -1
  121. package/lib/routes/gov/hangzhou/zwfw.ts +1 -1
  122. package/lib/routes/gov/pbc/goutongjiaoliu.ts +1 -1
  123. package/lib/routes/gov/shenzhen/szlh/index.ts +77 -0
  124. package/lib/routes/gov/shenzhen/szlh/namespace.ts +8 -0
  125. package/lib/routes/grist/utils.ts +5 -4
  126. package/lib/routes/hanime1/search.ts +4 -2
  127. package/lib/routes/hellogithub/report.ts +1 -1
  128. package/lib/routes/hit/hitgs.ts +240 -54
  129. package/lib/routes/hit/templates/description.art +7 -0
  130. package/lib/routes/hlju/namespace.ts +8 -0
  131. package/lib/routes/hlju/news.ts +141 -0
  132. package/lib/routes/hostmonit/cloudflareyes.ts +1 -1
  133. package/lib/routes/hotukdeals/index.ts +1 -1
  134. package/lib/routes/hyperdash/namespace.ts +7 -0
  135. package/lib/routes/hyperdash/templates/description.art +34 -0
  136. package/lib/routes/hyperdash/top-traders.ts +84 -0
  137. package/lib/routes/hyperdash/utils.ts +49 -0
  138. package/lib/routes/hypergryph/arknights/announce.ts +1 -1
  139. package/lib/routes/ielts/index.ts +1 -1
  140. package/lib/routes/infoq/topic.ts +16 -13
  141. package/lib/routes/instagram/web-api/index.ts +17 -13
  142. package/lib/routes/instagram/web-api/utils.ts +46 -63
  143. package/lib/routes/jamesclear/book-summaries.ts +40 -0
  144. package/lib/routes/jamesclear/great-speeches.ts +40 -0
  145. package/lib/routes/jamesclear/namespace.ts +8 -0
  146. package/lib/routes/jamesclear/quotes.ts +40 -0
  147. package/lib/routes/jamesclear/three-two-one.ts +41 -0
  148. package/lib/routes/jamesclear/utils.ts +22 -0
  149. package/lib/routes/japanpost/utils.ts +2 -2
  150. package/lib/routes/javbus/index.ts +3 -0
  151. package/lib/routes/javdb/tags.ts +1 -0
  152. package/lib/routes/javlibrary/star.ts +1 -0
  153. package/lib/routes/javtiful/actress.ts +3 -0
  154. package/lib/routes/javtiful/channel.ts +3 -0
  155. package/lib/routes/javtrailers/casts.ts +3 -0
  156. package/lib/routes/jetbrains/comments.ts +99 -0
  157. package/lib/routes/jetbrains/namespace.ts +8 -0
  158. package/lib/routes/jimmyspa/books.ts +1 -1
  159. package/lib/routes/jimmyspa/news.ts +1 -1
  160. package/lib/routes/jpxgmn/tab.ts +3 -0
  161. package/lib/routes/kakuyomu/works.ts +3 -0
  162. package/lib/routes/kaopu/news.ts +1 -1
  163. package/lib/routes/kemono/const.ts +1 -1
  164. package/lib/routes/kemono/index.ts +12 -11
  165. package/lib/routes/kemono/namespace.ts +1 -1
  166. package/lib/routes/kiro/blog.ts +131 -0
  167. package/lib/routes/kiro/changelog.ts +128 -0
  168. package/lib/routes/kiro/namespace.ts +9 -0
  169. package/lib/routes/konachan/post.ts +3 -0
  170. package/lib/routes/kovidgoyal/kitty/changelog.ts +83 -0
  171. package/lib/routes/kovidgoyal/namespace.ts +7 -0
  172. package/lib/routes/kunchengblog/essay.ts +1 -1
  173. package/lib/routes/landiannews/category.ts +1 -1
  174. package/lib/routes/landiannews/index.ts +1 -1
  175. package/lib/routes/landiannews/tag.ts +1 -1
  176. package/lib/routes/line/utils.ts +1 -1
  177. package/lib/routes/lineageos/changes.ts +79 -0
  178. package/lib/routes/lineageos/namespace.ts +9 -0
  179. package/lib/routes/linkedin/cn/renderer.ts +1 -1
  180. package/lib/routes/liquipedia/cs-matches.ts +42 -14
  181. package/lib/routes/literotica/new.ts +1 -0
  182. package/lib/routes/lofter/tag.ts +27 -3
  183. package/lib/routes/makerworld/contest.ts +51 -0
  184. package/lib/routes/makerworld/namespace.ts +7 -0
  185. package/lib/routes/makerworld/trending.ts +45 -0
  186. package/lib/routes/makerworld/user-upload.ts +54 -0
  187. package/lib/routes/makerworld/utils.ts +18 -0
  188. package/lib/routes/manhuagui/comic.ts +1 -1
  189. package/lib/routes/manus/blog.ts +77 -0
  190. package/lib/routes/manus/namespace.ts +7 -0
  191. package/lib/routes/mastodon/tag.ts +48 -0
  192. package/lib/routes/mathpix/blog.ts +155 -0
  193. package/lib/routes/mathpix/namespace.ts +9 -0
  194. package/lib/routes/mathpix/templates/description.art +21 -0
  195. package/lib/routes/mckinsey/cn/category-map.ts +9 -15
  196. package/lib/routes/mckinsey/cn/index.ts +77 -40
  197. package/lib/routes/melonbooks/search.ts +1 -0
  198. package/lib/routes/metacritic/index.ts +2 -2
  199. package/lib/routes/meteoblue/namespace.ts +8 -0
  200. package/lib/routes/meteoblue/weathernews.ts +75 -0
  201. package/lib/routes/meteor/index.ts +1 -1
  202. package/lib/routes/microsoft/addon.ts +7 -9
  203. package/lib/routes/mihoyo/zzz/news.ts +106 -0
  204. package/lib/routes/missav/new.ts +2 -1
  205. package/lib/routes/mit/hanlab.ts +61 -0
  206. package/lib/routes/mit/namespace.ts +6 -0
  207. package/lib/routes/mittrchina/index.ts +3 -3
  208. package/lib/routes/mixcloud/config.ts +129 -0
  209. package/lib/routes/mixcloud/index.ts +163 -107
  210. package/lib/routes/mixcloud/user-playlist.ts +31 -0
  211. package/lib/routes/mixi2/community.ts +72 -0
  212. package/lib/routes/mixi2/discovery.ts +52 -0
  213. package/lib/routes/mixi2/home.ts +51 -0
  214. package/lib/routes/mixi2/namespace.ts +8 -0
  215. package/lib/routes/mixi2/user.ts +77 -0
  216. package/lib/routes/mixi2/utils.ts +56 -0
  217. package/lib/routes/modelscope/learn.ts +94 -0
  218. package/lib/routes/moodysmismicrosite/report.ts +1 -1
  219. package/lib/routes/musify/index.ts +130 -0
  220. package/lib/routes/musify/namespace.ts +9 -0
  221. package/lib/routes/musikguru/namespace.ts +9 -0
  222. package/lib/routes/musikguru/news.ts +146 -0
  223. package/lib/routes/musikguru/templates/description.art +21 -0
  224. package/lib/routes/myfans/post.ts +1 -0
  225. package/lib/routes/nankai/cc-notice.ts +114 -0
  226. package/lib/routes/nankai/jwc.ts +131 -0
  227. package/lib/routes/nankai/namespace.ts +7 -0
  228. package/lib/routes/nankai/notice.ts +84 -0
  229. package/lib/routes/nankai/yzb.ts +97 -0
  230. package/lib/routes/neu/yz.ts +172 -0
  231. package/lib/routes/newslaundry/explainer.ts +30 -0
  232. package/lib/routes/newslaundry/namespace.ts +8 -0
  233. package/lib/routes/newslaundry/nl-cheatsheet.ts +30 -0
  234. package/lib/routes/newslaundry/nl-collaborations.ts +30 -0
  235. package/lib/routes/newslaundry/podcast.ts +61 -0
  236. package/lib/routes/newslaundry/reports.ts +30 -0
  237. package/lib/routes/newslaundry/shot.ts +30 -0
  238. package/lib/routes/newslaundry/subscriber-only.ts +30 -0
  239. package/lib/routes/newslaundry/templates/description.art +28 -0
  240. package/lib/routes/newslaundry/utils.ts +108 -0
  241. package/lib/routes/newswav/latest.ts +100 -0
  242. package/lib/routes/newswav/namespace.ts +7 -0
  243. package/lib/routes/nhentai/index.ts +1 -0
  244. package/lib/routes/nifd/research.ts +16 -0
  245. package/lib/routes/nio/namespace.ts +9 -0
  246. package/lib/routes/nio/nioradio.ts +75 -0
  247. package/lib/routes/njust/cs.ts +58 -0
  248. package/lib/routes/njust/utils.ts +1 -1
  249. package/lib/routes/ntdm/video.ts +1 -1
  250. package/lib/routes/nuaa/utils/pypasswaf.ts +1 -1
  251. package/lib/routes/oilchem/index.ts +1 -1
  252. package/lib/routes/oncc/money18.ts +1 -1
  253. package/lib/routes/openai/cookbook.ts +1 -1
  254. package/lib/routes/paulgraham/article.ts +2 -2
  255. package/lib/routes/picuki/profile.ts +4 -0
  256. package/lib/routes/pixiv/bookmarks.ts +1 -1
  257. package/lib/routes/pixiv/novel-api/series/sfw.ts +1 -1
  258. package/lib/routes/pixiv/novels.ts +2 -2
  259. package/lib/routes/pixiv/user.ts +1 -1
  260. package/lib/routes/playno1/av.ts +1 -0
  261. package/lib/routes/pornhub/model.ts +3 -7
  262. package/lib/routes/pornhub/pornstar.ts +2 -7
  263. package/lib/routes/pornhub/users.ts +2 -7
  264. package/lib/routes/pornhub/utils.ts +12 -1
  265. package/lib/routes/qingting/podcast.ts +2 -1
  266. package/lib/routes/qipamaijia/index.ts +1 -0
  267. package/lib/routes/questmobile/report.ts +1 -1
  268. package/lib/routes/railway/index.ts +73 -0
  269. package/lib/routes/railway/namespace.ts +8 -0
  270. package/lib/routes/reuters/common.ts +0 -3
  271. package/lib/routes/rockthejvm/articles.ts +167 -0
  272. package/lib/routes/rockthejvm/namespace.ts +9 -0
  273. package/lib/routes/rockthejvm/templates/description.art +7 -0
  274. package/lib/routes/samrdprc/namespace.ts +7 -0
  275. package/lib/routes/samrdprc/news.ts +79 -0
  276. package/lib/routes/sankei/namespace.ts +7 -0
  277. package/lib/routes/sankei/news.ts +68 -0
  278. package/lib/routes/sankei/topics.ts +71 -0
  279. package/lib/routes/sciencenet/user.ts +1 -1
  280. package/lib/routes/scoop/apps.ts +188 -0
  281. package/lib/routes/scoop/namespace.ts +9 -0
  282. package/lib/routes/scoop/templates/description.art +56 -0
  283. package/lib/routes/scpta/namespace.ts +8 -0
  284. package/lib/routes/scpta/news.ts +101 -0
  285. package/lib/routes/seekingalpha/index.ts +1 -1
  286. package/lib/routes/sehuatang/index.ts +29 -31
  287. package/lib/routes/setn/index.ts +11 -2
  288. package/lib/routes/seu/cyber/index.ts +78 -0
  289. package/lib/routes/sicau/jiaowu.ts +42 -34
  290. package/lib/routes/sis001/forum.ts +1 -0
  291. package/lib/routes/sjtu/seiee/icisee.ts +67 -0
  292. package/lib/routes/sketis/isabelle-dev/blog/index.ts +1 -1
  293. package/lib/routes/smartlink/index.ts +13 -3
  294. package/lib/routes/sohu/mp.ts +17 -6
  295. package/lib/routes/sotwe/namespace.ts +1 -0
  296. package/lib/routes/sotwe/user.ts +98 -0
  297. package/lib/routes/spankbang/new-videos.ts +1 -0
  298. package/lib/routes/spglobal/ratings.ts +1 -1
  299. package/lib/routes/stanford/blog.ts +77 -0
  300. package/lib/routes/stanford/namespace.ts +7 -0
  301. package/lib/routes/syosetu/index.ts +1 -1
  302. package/lib/routes/t66y/index.ts +1 -0
  303. package/lib/routes/taobao/mysql.ts +157 -0
  304. package/lib/routes/taobao/namespace.ts +2 -2
  305. package/lib/routes/techcrunch/category.ts +48 -0
  306. package/lib/routes/telegram/channel.ts +2 -2
  307. package/lib/routes/tesla/cx.ts +1 -1
  308. package/lib/routes/test/index.ts +1 -1
  309. package/lib/routes/themoviedb/episodes.ts +1 -1
  310. package/lib/routes/thewirehindi/category.ts +78 -0
  311. package/lib/routes/thewirehindi/index.ts +43 -0
  312. package/lib/routes/thewirehindi/namespace.ts +7 -0
  313. package/lib/routes/thewirehindi/templates/description.art +9 -0
  314. package/lib/routes/thewirehindi/utils.ts +33 -0
  315. package/lib/routes/threads/utils.ts +2 -2
  316. package/lib/routes/tidb/blog.ts +314 -0
  317. package/lib/routes/tidb/namespace.ts +9 -0
  318. package/lib/routes/tumblr/namespace.ts +17 -0
  319. package/lib/routes/tumblr/posts.ts +74 -0
  320. package/lib/routes/tumblr/utils.ts +110 -0
  321. package/lib/routes/tver/namespace.ts +7 -0
  322. package/lib/routes/tver/series.ts +98 -0
  323. package/lib/routes/twitter/api/web-api/login.ts +1 -3
  324. package/lib/routes/twitter/api/web-api/utils.ts +23 -1
  325. package/lib/routes/twitter/utils.ts +21 -21
  326. package/lib/routes/udn/breaking-news.ts +2 -2
  327. package/lib/routes/uestc/auto.ts +1 -1
  328. package/lib/routes/uestc/cqe.ts +1 -1
  329. package/lib/routes/uestc/scse.ts +1 -1
  330. package/lib/routes/uestc/sice.ts +1 -1
  331. package/lib/routes/uestc/sise.ts +1 -1
  332. package/lib/routes/upc/jwc.ts +32 -46
  333. package/lib/routes/uptimerobot/rss.ts +1 -1
  334. package/lib/routes/visionias/daily-news-summary.ts +65 -0
  335. package/lib/routes/visionias/monthly-magazine.ts +68 -0
  336. package/lib/routes/visionias/news-today.ts +3 -13
  337. package/lib/routes/visionias/utils.ts +5 -5
  338. package/lib/routes/visionias/weekly-focus.ts +2 -2
  339. package/lib/routes/wdfxw/bookfree.ts +528 -0
  340. package/lib/routes/wdfxw/namespace.ts +8 -0
  341. package/lib/routes/wdfxw/templates/description.art +13 -0
  342. package/lib/routes/whu/swrh.ts +1 -1
  343. package/lib/routes/windsurf/blog.ts +118 -0
  344. package/lib/routes/windsurf/changelog.ts +100 -0
  345. package/lib/routes/windsurf/namespace.ts +9 -0
  346. package/lib/routes/windsurf/templates/description.art +21 -0
  347. package/lib/routes/x6d/index.ts +1 -1
  348. package/lib/routes/xbookcn/blog.ts +1 -0
  349. package/lib/routes/xiaohongshu/util.ts +1 -3
  350. package/lib/routes/xiaoyuzhou/pickup.ts +1 -1
  351. package/lib/routes/ximalaya/album.ts +32 -70
  352. package/lib/routes/ximalaya/types.ts +48 -0
  353. package/lib/routes/ximalaya/utils.ts +9 -7
  354. package/lib/routes/xmanhua/index.ts +1 -0
  355. package/lib/routes/xueqiu/cookies.ts +1 -1
  356. package/lib/routes/xueqiu/user.ts +1 -1
  357. package/lib/routes/xwenming/index.ts +184 -0
  358. package/lib/routes/xwenming/namespace.ts +9 -0
  359. package/lib/routes/yahoo/news/utils.ts +1 -1
  360. package/lib/routes/yande/post.ts +3 -0
  361. package/lib/routes/ymgal/game.ts +1 -0
  362. package/lib/routes/youtube/api/google.ts +27 -0
  363. package/lib/routes/youtube/api/youtubei.ts +70 -20
  364. package/lib/routes/youtube/community.ts +3 -1
  365. package/lib/routes/youtube/utils.ts +16 -14
  366. package/lib/routes/zaobao/util.ts +8 -5
  367. package/lib/routes/zhihu/activities.ts +3 -0
  368. package/lib/routes/zhihu/execlib/x-zse-96-v3.ts +5 -5
  369. package/lib/routes/zhizhuan100/namespace.ts +7 -0
  370. package/lib/routes/zhizhuan100/report.ts +79 -0
  371. package/lib/routes/zimuxia/portfolio.ts +1 -1
  372. package/lib/routes/zju/sis/index.ts +161 -0
  373. package/lib/server.ts +5 -0
  374. package/lib/types.ts +58 -54
  375. package/lib/utils/helpers.ts +1 -1
  376. package/lib/utils/logger.ts +1 -1
  377. package/lib/utils/proxy/index.ts +102 -18
  378. package/lib/utils/proxy/multi-proxy.ts +139 -0
  379. package/lib/utils/proxy/unify-proxy.ts +3 -1
  380. package/lib/utils/puppeteer-utils.test.ts +1 -1
  381. package/lib/utils/puppeteer.test.ts +14 -27
  382. package/lib/utils/puppeteer.ts +51 -37
  383. package/lib/utils/readable-social.test.ts +65 -0
  384. package/lib/utils/readable-social.ts +15 -1
  385. package/lib/utils/request-rewriter/fetch.ts +42 -4
  386. package/package.json +54 -56
  387. package/lib/routes/mixcloud/queries.ts +0 -2274
  388. package/lib/routes-deprecated/dev.to/top.js +0 -40
package/lib/config.ts CHANGED
@@ -37,6 +37,7 @@ export type Config = {
37
37
  };
38
38
  // proxy
39
39
  proxyUri?: string;
40
+ proxyUris?: string[];
40
41
  proxy: {
41
42
  protocol?: string;
42
43
  host?: string;
@@ -44,6 +45,8 @@ export type Config = {
44
45
  auth?: string;
45
46
  url_regex: string;
46
47
  strategy: 'on_retry' | 'all';
48
+ failoverTimeout?: number;
49
+ healthCheckInterval?: number;
47
50
  };
48
51
  pacUri?: string;
49
52
  pacScript?: string;
@@ -73,6 +76,7 @@ export type Config = {
73
76
  allow_user_hotlink_template: boolean;
74
77
  filter_regex_engine: string;
75
78
  allow_user_supply_unsafe_domain: boolean;
79
+ disable_nsfw: boolean;
76
80
  };
77
81
  suffix?: string;
78
82
  titleLengthLimit: number;
@@ -98,6 +102,7 @@ export type Config = {
98
102
  cookies: Record<string, string | undefined>;
99
103
  dmImgList?: string;
100
104
  dmImgInter?: string;
105
+ excludeSubtitles?: boolean;
101
106
  };
102
107
  bitbucket: {
103
108
  username?: string;
@@ -216,6 +221,9 @@ export type Config = {
216
221
  lightnovel: {
217
222
  cookie?: string;
218
223
  };
224
+ lofter: {
225
+ cookies?: string;
226
+ };
219
227
  lorientlejour: {
220
228
  token?: string;
221
229
  username?: string;
@@ -255,6 +263,10 @@ export type Config = {
255
263
  misskey: {
256
264
  accessToken?: string;
257
265
  };
266
+ mixi2: {
267
+ authToken?: string;
268
+ authKey?: string;
269
+ };
258
270
  mox: {
259
271
  cookie: string;
260
272
  };
@@ -348,6 +360,11 @@ export type Config = {
348
360
  tsdm39: {
349
361
  cookie: string;
350
362
  };
363
+ tumblr: {
364
+ clientId?: string;
365
+ clientSecret?: string;
366
+ refreshToken?: string;
367
+ };
351
368
  twitter: {
352
369
  username?: string[];
353
370
  password?: string[];
@@ -487,6 +504,11 @@ const calculateValue = () => {
487
504
  },
488
505
  // proxy
489
506
  proxyUri: envs.PROXY_URI,
507
+ proxyUris: envs.PROXY_URIS
508
+ ? envs.PROXY_URIS.split(',')
509
+ .map((uri) => uri.trim())
510
+ .filter(Boolean)
511
+ : undefined,
490
512
  proxy: {
491
513
  protocol: envs.PROXY_PROTOCOL,
492
514
  host: envs.PROXY_HOST,
@@ -494,6 +516,8 @@ const calculateValue = () => {
494
516
  auth: envs.PROXY_AUTH,
495
517
  url_regex: envs.PROXY_URL_REGEX || '.*',
496
518
  strategy: envs.PROXY_STRATEGY || 'all', // all / on_retry
519
+ failoverTimeout: toInt(envs.PROXY_FAILOVER_TIMEOUT, 5000),
520
+ healthCheckInterval: toInt(envs.PROXY_HEALTH_CHECK_INTERVAL, 60000),
497
521
  },
498
522
  pacUri: envs.PAC_URI,
499
523
  pacScript: envs.PAC_SCRIPT,
@@ -524,6 +548,7 @@ const calculateValue = () => {
524
548
  allow_user_hotlink_template: toBoolean(envs.ALLOW_USER_HOTLINK_TEMPLATE, false),
525
549
  filter_regex_engine: envs.FILTER_REGEX_ENGINE || 're2',
526
550
  allow_user_supply_unsafe_domain: toBoolean(envs.ALLOW_USER_SUPPLY_UNSAFE_DOMAIN, false),
551
+ disable_nsfw: toBoolean(envs.DISABLE_NSFW, false),
527
552
  },
528
553
  suffix: envs.SUFFIX,
529
554
  titleLengthLimit: toInt(envs.TITLE_LENGTH_LIMIT, 150),
@@ -549,6 +574,7 @@ const calculateValue = () => {
549
574
  cookies: bilibili_cookies,
550
575
  dmImgList: envs.BILIBILI_DM_IMG_LIST,
551
576
  dmImgInter: envs.BILIBILI_DM_IMG_INTER,
577
+ excludeSubtitles: toBoolean(envs.BILIBILI_EXCLUDE_SUBTITLES, false),
552
578
  },
553
579
  bitbucket: {
554
580
  username: envs.BITBUCKET_USERNAME,
@@ -667,6 +693,9 @@ const calculateValue = () => {
667
693
  lightnovel: {
668
694
  cookie: envs.SECURITY_KEY,
669
695
  },
696
+ lofter: {
697
+ cookies: envs.LOFTER_COOKIE,
698
+ },
670
699
  lorientlejour: {
671
700
  token: envs.LORIENTLEJOUR_TOKEN,
672
701
  username: envs.LORIENTLEJOUR_USERNAME,
@@ -706,6 +735,10 @@ const calculateValue = () => {
706
735
  misskey: {
707
736
  accessToken: envs.MISSKEY_ACCESS_TOKEN,
708
737
  },
738
+ mixi2: {
739
+ authToken: envs.MIXI2_AUTH_TOKEN,
740
+ authKey: envs.MIXI2_AUTH_KEY,
741
+ },
709
742
  mox: {
710
743
  cookie: envs.MOX_COOKIE,
711
744
  },
@@ -799,6 +832,11 @@ const calculateValue = () => {
799
832
  tsdm39: {
800
833
  cookie: envs.TSDM39_COOKIES,
801
834
  },
835
+ tumblr: {
836
+ clientId: envs.TUMBLR_CLIENT_ID,
837
+ clientSecret: envs.TUMBLR_CLIENT_SECRET,
838
+ refreshToken: envs.TUMBLR_REFRESH_TOKEN,
839
+ },
802
840
  twitter: {
803
841
  username: envs.TWITTER_USERNAME?.split(','),
804
842
  password: envs.TWITTER_PASSWORD?.split(','),
@@ -1,4 +1,5 @@
1
1
  import { type NotFoundHandler, type ErrorHandler } from 'hono';
2
+ import { routePath } from 'hono/route';
2
3
  import { getDebugInfo, setDebugInfo } from '@/utils/debug-info';
3
4
  import { config } from '@/config';
4
5
  import * as Sentry from '@sentry/node';
@@ -11,7 +12,7 @@ import { requestMetric } from '@/utils/otel';
11
12
 
12
13
  export const errorHandler: ErrorHandler = (error, ctx) => {
13
14
  const requestPath = ctx.req.path;
14
- const matchedRoute = ctx.req.routePath;
15
+ const matchedRoute = routePath(ctx);
15
16
  const hasMatchedRoute = matchedRoute !== '/*';
16
17
 
17
18
  const debug = getDebugInfo();
@@ -42,7 +43,7 @@ export const errorHandler: ErrorHandler = (error, ctx) => {
42
43
  });
43
44
  }
44
45
 
45
- let errorMessage = process.env.NODE_ENV === 'production' ? error.message : error.stack || error.message;
46
+ let errorMessage = (process.env.NODE_ENV || process.env.VERCEL_ENV) === 'production' ? error.message : error.stack || error.message;
46
47
  switch (error.constructor.name) {
47
48
  case 'HTTPError':
48
49
  case 'RequestError':
@@ -1,4 +1,5 @@
1
1
  import { MiddlewareHandler } from 'hono';
2
+ import { routePath } from 'hono/route';
2
3
  import { getDebugInfo, setDebugInfo } from '@/utils/debug-info';
3
4
 
4
5
  const middleware: MiddlewareHandler = async (ctx, next) => {
@@ -17,11 +18,12 @@ const middleware: MiddlewareHandler = async (ctx, next) => {
17
18
 
18
19
  {
19
20
  const debug = getDebugInfo();
20
- const hasMatchedRoute = ctx.req.routePath !== '/*';
21
- if (!debug.routes[ctx.req.routePath] && hasMatchedRoute) {
22
- debug.routes[ctx.req.routePath] = 0;
21
+ const rPath = routePath(ctx);
22
+ const hasMatchedRoute = rPath !== '/*';
23
+ if (!debug.routes[rPath] && hasMatchedRoute) {
24
+ debug.routes[rPath] = 0;
23
25
  }
24
- hasMatchedRoute && debug.routes[ctx.req.routePath]++;
26
+ hasMatchedRoute && debug.routes[rPath]++;
25
27
 
26
28
  if (ctx.res.headers.get('RSSHub-Cache-Status')) {
27
29
  debug.hitCache++;
@@ -1,4 +1,5 @@
1
1
  import { MiddlewareHandler } from 'hono';
2
+ import { routePath } from 'hono/route';
2
3
  import etagCalculate from 'etag';
3
4
  import { config } from '@/config';
4
5
  import { Data } from '@/types';
@@ -24,9 +25,10 @@ const middleware: MiddlewareHandler = async (ctx, next) => {
24
25
  ctx.header('Access-Control-Allow-Origin', config.allowOrigin || new URL(ctx.req.url).host);
25
26
 
26
27
  await next();
28
+ const rPath = routePath(ctx);
27
29
 
28
- if (ctx.req.routePath !== '/*') {
29
- ctx.header('X-RSSHub-Route', ctx.req.routePath);
30
+ if (rPath !== '/*') {
31
+ ctx.header('X-RSSHub-Route', rPath);
30
32
  }
31
33
 
32
34
  const data: Data = ctx.get('data');
@@ -1,4 +1,4 @@
1
- import { describe, expect, it } from 'vitest';
1
+ import { describe, expect, it, vi } from 'vitest';
2
2
  import app from '@/app';
3
3
  import { config } from '@/config';
4
4
 
@@ -37,4 +37,27 @@ describe('registry', () => {
37
37
  expect(response.headers.get('cache-control')).toBe('no-cache');
38
38
  expect(await response.text()).toBe('ok');
39
39
  });
40
+
41
+ it('namespaces respects DISABLE_NSFW=true', async () => {
42
+ vi.resetModules();
43
+ vi.stubEnv('DISABLE_NSFW', 'true');
44
+
45
+ const { namespaces } = await import('./registry');
46
+
47
+ // All routes in all namespaces should not have nsfw features
48
+ for (const ns of Object.values(namespaces)) {
49
+ for (const route of Object.values(ns.routes)) {
50
+ expect(route.features?.nsfw).not.toBe(true);
51
+ }
52
+ }
53
+ expect(namespaces['2048']).toBeUndefined();
54
+ });
55
+
56
+ it('namespaces includes NSFW routes when DISABLE_NSFW=false', async () => {
57
+ vi.resetModules();
58
+ vi.stubEnv('DISABLE_NSFW', 'false');
59
+
60
+ const { namespaces } = await import('./registry');
61
+ expect(namespaces['2048']).toBeDefined();
62
+ });
40
63
  });
package/lib/registry.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { APIRoute, Namespace, Route } from '@/types';
2
2
  import { directoryImport } from 'directory-import';
3
3
  import { Hono, type Handler } from 'hono';
4
+ import { routePath } from 'hono/route';
4
5
  import path from 'node:path';
5
6
  import { serveStatic } from '@hono/node-server/serve-static';
6
7
  import { config } from '@/config';
@@ -13,16 +14,34 @@ import logger from '@/utils/logger';
13
14
 
14
15
  const __dirname = import.meta.dirname;
15
16
 
17
+ function isSafeRoutes(routes: RoutesType): boolean {
18
+ return Object.values(routes).every((route: Route) => !route.features?.nsfw);
19
+ }
20
+
21
+ function safeNamespaces(namespaces: NamespacesType): NamespacesType {
22
+ const safe: NamespacesType = {};
23
+
24
+ for (const [key, value] of Object.entries(namespaces)) {
25
+ if (value.routes === null || value.routes === undefined || isSafeRoutes(value.routes)) {
26
+ safe[key] = value;
27
+ }
28
+ }
29
+ return safe;
30
+ }
31
+
16
32
  let modules: Record<string, { route: Route } | { namespace: Namespace }> = {};
17
- let namespaces: Record<
33
+
34
+ type RoutesType = Record<
35
+ string,
36
+ Route & {
37
+ location: string;
38
+ }
39
+ >;
40
+
41
+ export type NamespacesType = Record<
18
42
  string,
19
43
  Namespace & {
20
- routes: Record<
21
- string,
22
- Route & {
23
- location: string;
24
- }
25
- >;
44
+ routes: RoutesType;
26
45
  apiRoutes: Record<
27
46
  string,
28
47
  APIRoute & {
@@ -30,15 +49,21 @@ let namespaces: Record<
30
49
  }
31
50
  >;
32
51
  }
33
- > = {};
52
+ >;
34
53
 
35
- switch (process.env.NODE_ENV) {
54
+ let namespaces: NamespacesType = {};
55
+
56
+ switch (process.env.NODE_ENV || process.env.VERCEL_ENV) {
36
57
  case 'production':
37
58
  namespaces = (await import('../assets/build/routes.js')).default;
38
59
  break;
39
60
  case 'test':
40
61
  // @ts-expect-error
41
62
  namespaces = await import('../assets/build/routes.json');
63
+ if (namespaces.default) {
64
+ // @ts-ignore
65
+ namespaces = namespaces.default;
66
+ }
42
67
  break;
43
68
  default:
44
69
  modules = directoryImport({
@@ -47,6 +72,10 @@ switch (process.env.NODE_ENV) {
47
72
  }) as typeof modules;
48
73
  }
49
74
 
75
+ if (config.feature.disable_nsfw) {
76
+ namespaces = safeNamespaces(namespaces);
77
+ }
78
+
50
79
  if (Object.keys(modules).length) {
51
80
  for (const module in modules) {
52
81
  const content = modules[module] as
@@ -158,7 +187,7 @@ for (const namespace in namespaces) {
158
187
 
159
188
  for (const [path, routeData] of sortedRoutes) {
160
189
  const wrappedHandler: Handler = async (ctx) => {
161
- logger.debug(`Matched route: ${ctx.req.routePath}`);
190
+ logger.debug(`Matched route: ${routePath(ctx)}`);
162
191
  if (!ctx.get('data')) {
163
192
  if (typeof routeData.handler !== 'function') {
164
193
  if (process.env.NODE_ENV === 'test') {
@@ -222,7 +251,7 @@ if (config.debugInfo) {
222
251
  app.use(
223
252
  '/*',
224
253
  serveStatic({
225
- root: './lib/assets',
254
+ root: path.join(__dirname, 'assets'),
226
255
  rewriteRequestPath: (path) => (path === '/favicon.ico' ? '/favicon.png' : path),
227
256
  })
228
257
  );
package/lib/router.js CHANGED
@@ -1357,7 +1357,7 @@ router.get('/forum4399/:mtag', lazyloadRouteHandler('./routes/game4399/forum'));
1357
1357
  router.get('/nudt/yjszs/:id?', lazyloadRouteHandler('./routes/universities/nudt/yjszs'));
1358
1358
 
1359
1359
  // dev.to
1360
- router.get('/dev.to/top/:period', lazyloadRouteHandler('./routes/dev.to/top'));
1360
+ // router.get('/dev.to/top/:period', lazyloadRouteHandler('./routes/dev.to/top'));
1361
1361
 
1362
1362
  // GameRes 游资网
1363
1363
  router.get('/gameres/hot', lazyloadRouteHandler('./routes/gameres/hot'));
@@ -0,0 +1,9 @@
1
+ import type { Namespace } from '@/types';
2
+
3
+ export const namespace: Namespace = {
4
+ name: '深圳台风网',
5
+ url: '121.com.cn',
6
+ categories: ['forecast'],
7
+ description: '',
8
+ lang: 'zh-CN',
9
+ };
@@ -0,0 +1,17 @@
1
+ {{ if description }}
2
+ <p>{{ description }}</p>
3
+ {{ /if }}
4
+
5
+ {{ if images }}
6
+ {{ each images image }}
7
+ {{ if image?.src }}
8
+ <figure>
9
+ <img
10
+ {{ if image.alt }}
11
+ alt="{{ image.alt }}"
12
+ {{ /if }}
13
+ src="{{ image.src }}">
14
+ </figure>
15
+ {{ /if }}
16
+ {{ /each }}
17
+ {{ /if }}
@@ -0,0 +1,104 @@
1
+ import { type Data, type DataItem, type Route, ViewType } from '@/types';
2
+
3
+ import { art } from '@/utils/render';
4
+ import ofetch from '@/utils/ofetch';
5
+ import { parseDate } from '@/utils/parse-date';
6
+
7
+ import { type CheerioAPI, load } from 'cheerio';
8
+ import { type Context } from 'hono';
9
+ import path from 'node:path';
10
+
11
+ export const handler = async (ctx: Context): Promise<Data> => {
12
+ const limit: number = Number.parseInt(ctx.req.query('limit') ?? '100', 10);
13
+
14
+ const baseUrl: string = 'https://tf.121.com.cn';
15
+ const imgBaseUrl: string = 'https://wx.121.com.cn';
16
+ const targetUrl: string = new URL('web/weatherLive/', baseUrl).href;
17
+ const apiUrl: string = new URL('weather/weibo/message.js', baseUrl).href;
18
+
19
+ const targetResponse = await ofetch(targetUrl);
20
+ const $: CheerioAPI = load(targetResponse);
21
+ const language = $('html').attr('lang') ?? 'zh';
22
+
23
+ const response = await ofetch(apiUrl);
24
+ const messages = await response.text();
25
+
26
+ const items: DataItem[] = JSON.parse(messages.split(/var\smessage=/).pop())
27
+ .slice(0, limit)
28
+ .map((item): DataItem => {
29
+ const title: string = item.Title;
30
+ const description: string | undefined = art(path.join(__dirname, 'templates/description.art'), {
31
+ description: item.Content,
32
+ images: item.Img?.map((img: string) => ({
33
+ src: new URL(`WeChat/data/weiweb/images/lwspic/${img}`, imgBaseUrl).href,
34
+ alt: title,
35
+ })),
36
+ });
37
+ const pubDate: number | string = item.DDatetime;
38
+ const linkUrl: string | undefined = targetUrl;
39
+ const guid: string = `121-${title}-${pubDate}`;
40
+ const image: string | undefined = item.Img?.length > 0 ? new URL(`WeChat/data/weiweb/images/lwspic/${item.Img[0]}`, imgBaseUrl).href : undefined;
41
+ const updated: number | string = pubDate;
42
+
43
+ const processedItem: DataItem = {
44
+ title,
45
+ description,
46
+ pubDate: pubDate ? parseDate(pubDate) : undefined,
47
+ link: linkUrl ?? new URL(item.id, baseUrl).href,
48
+ guid,
49
+ id: guid,
50
+ content: {
51
+ html: description,
52
+ text: description,
53
+ },
54
+ image,
55
+ banner: image,
56
+ updated: updated ? parseDate(updated) : undefined,
57
+ language,
58
+ };
59
+
60
+ return processedItem;
61
+ });
62
+
63
+ const title: string = $('title').text();
64
+
65
+ return {
66
+ title,
67
+ description: title,
68
+ link: targetUrl,
69
+ item: items,
70
+ allowEmpty: true,
71
+ image: $('img').first().attr('src') ? new URL($('img').first().attr('src') as string, baseUrl).href : undefined,
72
+ author: $('div#webnameDiv').text(),
73
+ language,
74
+ id: targetUrl,
75
+ };
76
+ };
77
+
78
+ export const route: Route = {
79
+ path: '/weatherLive',
80
+ name: '深圳天气直播',
81
+ url: 'tf.121.com.cn',
82
+ maintainers: ['nczitzk'],
83
+ handler,
84
+ example: '/121/weatherLive',
85
+ parameters: undefined,
86
+ description: undefined,
87
+ categories: ['forecast'],
88
+ features: {
89
+ requireConfig: false,
90
+ requirePuppeteer: false,
91
+ antiCrawler: false,
92
+ supportRadar: true,
93
+ supportBT: false,
94
+ supportPodcast: false,
95
+ supportScihub: false,
96
+ },
97
+ radar: [
98
+ {
99
+ source: ['tf.121.com.cn', 'tf.121.com.cn/web/weatherLive'],
100
+ target: '/weatherLive',
101
+ },
102
+ ],
103
+ view: ViewType.Notifications,
104
+ };
@@ -47,6 +47,9 @@ export const route: Route = {
47
47
  - \`/141jav/date/2020/07/30\`
48
48
 
49
49
  \`date\` 类型的关键词必须填写 **日期(年/月/日)**`,
50
+ features: {
51
+ nsfw: true,
52
+ },
50
53
  };
51
54
 
52
55
  async function handler(ctx) {
@@ -47,6 +47,9 @@ export const route: Route = {
47
47
  - \`/141ppv/date/2020/07/30\`
48
48
 
49
49
  \`date\` 类型的关键词必须填写 **日期(年/月/日)**`,
50
+ features: {
51
+ nsfw: true,
52
+ },
50
53
  };
51
54
 
52
55
  async function handler(ctx) {
@@ -135,7 +135,7 @@ async function handler(ctx) {
135
135
  const $ = load(iconv.decode(response.data, 'gbk'));
136
136
 
137
137
  const list = $('div.tabContents')
138
- .eq(timeRange[time].index + (category === 'whole' ? (type === 'click' ? -1 : 2) : (type === 'click' ? 0 : 2)))
138
+ .eq(timeRange[time].index + (category === 'whole' ? (type === 'click' ? -1 : 2) : type === 'click' ? 0 : 2))
139
139
  .find('table tbody tr td a')
140
140
  .toArray()
141
141
  .map((item) => {
@@ -1,10 +1,8 @@
1
1
  import { Route } from '@/types';
2
+ import { defaultDomain, getApiUrl, getRootUrl, processApiItems } from './utils';
3
+ import { art } from '@/utils/render';
4
+ import path from 'node:path';
2
5
  import cache from '@/utils/cache';
3
- import got from '@/utils/got';
4
- import { load } from 'cheerio';
5
- import { parseDate } from '@/utils/parse-date';
6
-
7
- import { defaultDomain, getRootUrl } from './utils';
8
6
 
9
7
  export const route: Route = {
10
8
  path: '/album/:id',
@@ -37,71 +35,68 @@ async function handler(ctx) {
37
35
  const id = ctx.req.param('id');
38
36
  const { domain = defaultDomain } = ctx.req.query();
39
37
  const rootUrl = getRootUrl(domain);
40
-
41
38
  const currentUrl = `${rootUrl}/album/${id}`;
42
39
 
43
- const response = await got({
44
- method: 'get',
45
- url: currentUrl,
46
- });
47
-
48
- const $ = load(response.data);
40
+ const apiUrl = `${getApiUrl()}/album?id=${id}`;
49
41
 
50
- const category = $('span[data-type="tags"]')
51
- .first()
52
- .find('a')
53
- .toArray()
54
- .map((c) => $(c).text());
55
- const author = $('span[data-type="author"]')
56
- .first()
57
- .find('a')
58
- .toArray()
59
- .map((a) => $(a).text())
60
- .join(', ');
42
+ const apiResult = await processApiItems(apiUrl);
61
43
 
62
- let items = $('.btn-toolbar')
63
- .first()
64
- .find('a')
65
- .toArray()
66
- .map((item) => {
67
- item = $(item);
68
-
69
- return {
70
- title: item.text(),
71
- link: `${rootUrl}${item.attr('href')}`,
72
- guid: `https://18comic.org${item.attr('href')}`,
73
- pubDate: parseDate(item.find('.hidden-xs').text()),
74
- };
44
+ const category = apiResult.tags;
45
+ const author = apiResult.author.join(', ');
46
+ const description = apiResult.description;
47
+ const addTime = apiResult.addtime;
48
+ let results: any[] = [];
49
+ if (apiResult.series.length === 0) {
50
+ results.push({
51
+ title: apiResult.name,
52
+ link: `${rootUrl}/photo/${id}`,
53
+ guid: `${rootUrl}/photo/${id}`,
54
+ updated: new Date(addTime * 1000),
55
+ pubDate: new Date(addTime * 1000),
56
+ category,
57
+ author,
58
+ description: art(path.join(__dirname, 'templates/description.art'), {
59
+ introduction: description,
60
+ // 不取图片,因为专辑的图片会被分割排序,所以只取封面图
61
+ images: [`https://cdn-msp3.${domain}/media/albums/${id}_3x4.jpg`],
62
+ cover: `https://cdn-msp3.${domain}/media/albums/${id}_3x4.jpg`,
63
+ category,
64
+ }),
75
65
  });
76
-
77
- items = await Promise.all(
78
- items.map((item) =>
79
- cache.tryGet(item.guid, async () => {
80
- const detailResponse = await got({
81
- method: 'get',
82
- url: item.link,
83
- });
84
-
85
- const content = load(detailResponse.data);
86
-
87
- content('.tab-content').remove();
88
-
89
- item.author = author;
90
- item.category = category;
91
- item.description = `<img src="${content('.thumb-overlay-albums img[data-original]')
92
- .toArray()
93
- .map((image) => content(image).attr('data-original'))
94
- .join('"><img src="')}">`;
95
-
96
- return item;
97
- })
98
- )
99
- );
66
+ } else {
67
+ results = await Promise.all(
68
+ apiResult.series.map((item, index) =>
69
+ cache.tryGet(`18comic:album:${item.id}`, async () => {
70
+ const chapterApiUrl = `${getApiUrl()}/chapter?id=${item.id}`;
71
+ const chapterResult = await processApiItems(chapterApiUrl);
72
+ const result = {};
73
+ const chapterNum = index + 1;
74
+ result.title = `第${String(chapterNum)}話 ${item.name === '' ? `${String(chapterNum)}` : item.name}`;
75
+ result.link = `${rootUrl}/photo/${item.id}`;
76
+ result.guid = `${rootUrl}/photo/${item.id}`;
77
+ result.updated = new Date(chapterResult.addtime * 1000);
78
+ result.pubDate = addTime;
79
+ result.category = category;
80
+ result.author = author;
81
+ result.description = art(path.join(__dirname, 'templates/description.art'), {
82
+ introduction: description,
83
+ // 不取图片,因为专辑的图片会被分割排序,所以只取封面图
84
+ images: [`https://cdn-msp3.${domain}/media/albums/${item.id}_3x4.jpg`],
85
+ cover: `https://cdn-msp3.${domain}/media/albums/${item.id}_3x4.jpg`,
86
+ category,
87
+ });
88
+ return result;
89
+ })
90
+ )
91
+ );
92
+ results = results.toReversed();
93
+ }
100
94
 
101
95
  return {
102
- title: $('title').text(),
103
- link: currentUrl,
104
- item: items,
105
- description: $('meta[property="og:description"]').attr('content'),
96
+ title: `${apiResult.name} - 禁漫天堂`,
97
+ link: currentUrl.replace(/\?$/, ''),
98
+ item: results,
99
+ allowEmpty: true,
100
+ description,
106
101
  };
107
102
  }
@@ -13,6 +13,7 @@ export const route: Route = {
13
13
  supportBT: false,
14
14
  supportPodcast: false,
15
15
  supportScihub: false,
16
+ nsfw: true,
16
17
  },
17
18
  radar: [
18
19
  {