rsshub 1.0.0-master.f9ec483 → 1.0.0-master.fa1dcc5

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 (334) hide show
  1. package/lib/config.ts +42 -1
  2. package/lib/middleware/access-control.ts +3 -3
  3. package/lib/middleware/cache.ts +5 -3
  4. package/lib/middleware/template.test.ts +6 -0
  5. package/lib/middleware/template.tsx +3 -1
  6. package/lib/router.js +0 -6
  7. package/lib/routes/141jav/index.ts +1 -1
  8. package/lib/routes/141ppv/index.ts +1 -1
  9. package/lib/routes/36kr/hot-list.ts +1 -1
  10. package/lib/routes/36kr/index.ts +1 -1
  11. package/lib/routes/78dm/index.ts +429 -43
  12. package/lib/routes/78dm/namespace.ts +2 -0
  13. package/lib/routes/78dm/templates/description.art +17 -0
  14. package/lib/routes/abc/index.ts +10 -9
  15. package/lib/routes/aeon/category.ts +1 -1
  16. package/lib/routes/aeon/type.ts +1 -1
  17. package/lib/routes/afr/latest.ts +69 -0
  18. package/lib/routes/afr/namespace.ts +7 -0
  19. package/lib/routes/afr/navigation.ts +75 -0
  20. package/lib/routes/afr/query.ts +349 -0
  21. package/lib/routes/afr/utils.ts +80 -0
  22. package/lib/routes/aibase/discover.ts +1 -1
  23. package/lib/routes/aibase/news.ts +1 -1
  24. package/lib/routes/aibase/topic.ts +1 -1
  25. package/lib/routes/air-level/index.ts +49 -0
  26. package/lib/routes/air-level/levelrank.ts +65 -0
  27. package/lib/routes/air-level/namespace.ts +12 -0
  28. package/lib/routes/ajcass/namespace.ts +11 -0
  29. package/lib/routes/ajcass/shxyj.ts +73 -0
  30. package/lib/routes/alpinelinux/pkgs.ts +2 -2
  31. package/lib/routes/anime1/anime.ts +1 -1
  32. package/lib/routes/apnews/utils.ts +6 -2
  33. package/lib/routes/appleinsider/index.ts +1 -1
  34. package/lib/routes/aqara/region.ts +1 -1
  35. package/lib/routes/asus/bios.ts +0 -1
  36. package/lib/routes/baoyu/index.ts +57 -0
  37. package/lib/routes/baoyu/namespace.ts +8 -0
  38. package/lib/routes/bilibili/article.ts +37 -14
  39. package/lib/routes/bilibili/dynamic.ts +15 -7
  40. package/lib/routes/bilibili/followings-dynamic.ts +2 -2
  41. package/lib/routes/bilibili/manga-update.ts +3 -0
  42. package/lib/routes/bilibili/ranking.ts +188 -117
  43. package/lib/routes/bilibili/reply.ts +2 -0
  44. package/lib/routes/bilibili/templates/description.art +2 -0
  45. package/lib/routes/bing/daily-wallpaper.ts +5 -1
  46. package/lib/routes/bsky/posts.ts +0 -1
  47. package/lib/routes/bsky/templates/post.art +8 -1
  48. package/lib/routes/buaa/lib/space/newbook.ts +1 -1
  49. package/lib/routes/c114/namespace.ts +2 -0
  50. package/lib/routes/c114/roll.ts +71 -42
  51. package/lib/routes/cags/edu/index.ts +84 -0
  52. package/lib/routes/cags/namespace.ts +9 -0
  53. package/lib/routes/caixin/article.ts +1 -1
  54. package/lib/routes/caixin/blog.ts +2 -3
  55. package/lib/routes/caixin/category.ts +1 -1
  56. package/lib/routes/caixin/latest.ts +12 -16
  57. package/lib/routes/caixin/namespace.ts +1 -1
  58. package/lib/routes/caixin/utils-fulltext.ts +51 -0
  59. package/lib/routes/caixin/utils.ts +37 -37
  60. package/lib/routes/cara/likes.ts +1 -1
  61. package/lib/routes/cara/portfolio.ts +1 -1
  62. package/lib/routes/cara/timeline.ts +1 -1
  63. package/lib/routes/ccfa/index.ts +11 -11
  64. package/lib/routes/chub/characters.ts +1 -1
  65. package/lib/routes/cnbeta/namespace.ts +1 -1
  66. package/lib/routes/cngold/index.ts +195 -0
  67. package/lib/routes/cngold/namespace.ts +9 -0
  68. package/lib/routes/cnki/author.ts +120 -48
  69. package/lib/routes/cnki/utils.ts +4 -4
  70. package/lib/routes/coomer/artist.ts +1 -1
  71. package/lib/routes/coomer/namespace.ts +1 -1
  72. package/lib/routes/coomer/posts.ts +2 -2
  73. package/lib/routes/coomer/utils.ts +1 -1
  74. package/lib/routes/cpcaauto/index.ts +22 -22
  75. package/lib/routes/cs/zzkx.ts +1 -1
  76. package/lib/routes/csdn/blog.ts +17 -13
  77. package/lib/routes/cybersecurityventures/namespace.ts +7 -0
  78. package/lib/routes/cybersecurityventures/news.ts +121 -0
  79. package/lib/routes/cybersecurityventures/types.ts +17 -0
  80. package/lib/routes/daily/discussed.ts +22 -21
  81. package/lib/routes/daily/index.ts +14 -11
  82. package/lib/routes/daily/namespace.ts +1 -1
  83. package/lib/routes/daily/source.ts +186 -0
  84. package/lib/routes/daily/upvoted.ts +17 -17
  85. package/lib/routes/daily/user.ts +6 -23
  86. package/lib/routes/daily/utils.ts +27 -32
  87. package/lib/routes/dataguidance/index.ts +19 -30
  88. package/lib/routes/dcfever/news.ts +1 -1
  89. package/lib/routes/dcfever/reviews.ts +1 -1
  90. package/lib/routes/dcfever/trading-search.ts +1 -1
  91. package/lib/routes/dcfever/trading.ts +1 -1
  92. package/lib/routes/deeplearning/namespace.ts +3 -1
  93. package/lib/routes/deeplearning/templates/description.art +21 -0
  94. package/lib/routes/deeplearning/the-batch.ts +296 -0
  95. package/lib/routes/deepmind/blog.ts +1 -1
  96. package/lib/routes/digitalcameraworld/news.ts +1 -1
  97. package/lib/routes/discord/discord-api.ts +44 -2
  98. package/lib/routes/discord/search.ts +106 -0
  99. package/lib/routes/dn/news.ts +1 -1
  100. package/lib/routes/dockerhub/repositories.ts +42 -0
  101. package/lib/routes/dongqiudi/daily.ts +1 -1
  102. package/lib/routes/dw/namespace.ts +6 -0
  103. package/lib/routes/dw/news.ts +89 -0
  104. package/lib/routes/dw/rss.ts +62 -0
  105. package/lib/routes/dw/templates/description.art +23 -0
  106. package/lib/routes/dw/templates/liveblog.art +13 -0
  107. package/lib/routes/dw/templates/video.art +14 -0
  108. package/lib/routes/dw/utils.ts +172 -0
  109. package/lib/routes/ecnu/jwc.ts +5 -1
  110. package/lib/routes/espn/news.ts +1 -1
  111. package/lib/routes/fashionnetwork/namespace.ts +1 -1
  112. package/lib/routes/flyert/forum.ts +99 -0
  113. package/lib/routes/flyert/namespace.ts +1 -0
  114. package/lib/routes/flyert/templates/description.art +21 -0
  115. package/lib/routes/flyert/util.ts +188 -0
  116. package/lib/routes/follow/profile.ts +2 -2
  117. package/lib/routes/foresightnews/article.ts +1 -1
  118. package/lib/routes/foresightnews/column.ts +1 -1
  119. package/lib/routes/foresightnews/index.ts +3 -1
  120. package/lib/routes/foresightnews/news.ts +1 -1
  121. package/lib/routes/freecomputerbooks/index.ts +0 -10
  122. package/lib/routes/ftm/index.ts +1 -1
  123. package/lib/routes/furaffinity/art.ts +85 -0
  124. package/lib/routes/furaffinity/browse.ts +58 -0
  125. package/lib/routes/furaffinity/commissions.ts +55 -0
  126. package/lib/routes/furaffinity/home.ts +80 -0
  127. package/lib/routes/furaffinity/journal-comments.ts +64 -0
  128. package/lib/routes/furaffinity/journals.ts +56 -0
  129. package/lib/routes/furaffinity/namespace.ts +7 -0
  130. package/lib/routes/furaffinity/search.ts +72 -0
  131. package/lib/routes/furaffinity/shouts.ts +56 -0
  132. package/lib/routes/furaffinity/status.ts +58 -0
  133. package/lib/routes/furaffinity/submission-comments.ts +64 -0
  134. package/lib/{routes-deprecated/furaffinity/user.js → routes/furaffinity/user.ts} +53 -41
  135. package/lib/routes/furaffinity/watchers.ts +62 -0
  136. package/lib/routes/furaffinity/watching.ts +62 -0
  137. package/lib/routes/google/developers.ts +71 -0
  138. package/lib/routes/google/news.ts +26 -6
  139. package/lib/routes/gov/cbirc/index.ts +35 -35
  140. package/lib/routes/hamel/index.ts +81 -0
  141. package/lib/routes/hamel/namespace.ts +7 -0
  142. package/lib/routes/hellogithub/volume.ts +3 -0
  143. package/lib/routes/hket/index.ts +13 -1
  144. package/lib/routes/hostmonit/cloudflareyesv6.ts +1 -1
  145. package/lib/routes/hrbeu/sec/list.ts +80 -0
  146. package/lib/routes/hrbust/jwzx.ts +6 -0
  147. package/lib/routes/hunau/gfxy/index.ts +1 -1
  148. package/lib/routes/hunau/ied.ts +1 -1
  149. package/lib/routes/hunau/jwc.ts +1 -1
  150. package/lib/routes/hunau/xky/index.ts +1 -1
  151. package/lib/routes/hust/gs.ts +4 -3
  152. package/lib/routes/idolmaster/namespace.ts +7 -0
  153. package/lib/routes/idolmaster/news.ts +112 -0
  154. package/lib/routes/ieee/author.ts +95 -0
  155. package/lib/routes/ikea/cn/low-price.ts +2 -1
  156. package/lib/routes/imdb/chart.ts +1 -1
  157. package/lib/routes/inspirehep/author.ts +9 -1
  158. package/lib/routes/isct/namespace.ts +11 -0
  159. package/lib/routes/isct/news.ts +66 -0
  160. package/lib/routes/javtrailers/casts.ts +41 -0
  161. package/lib/routes/javtrailers/categories.ts +40 -0
  162. package/lib/routes/javtrailers/namespace.ts +7 -0
  163. package/lib/routes/javtrailers/studios.ts +39 -0
  164. package/lib/routes/javtrailers/templates/description.art +31 -0
  165. package/lib/routes/javtrailers/types.ts +59 -0
  166. package/lib/routes/javtrailers/utils.ts +48 -0
  167. package/lib/routes/jiemian/list.ts +1 -1
  168. package/lib/routes/jiuyangongshe/community.ts +1 -1
  169. package/lib/routes/jlu/phy/index.ts +55 -0
  170. package/lib/routes/joins/chinese.ts +13 -13
  171. package/lib/routes/kcna/news.ts +7 -5
  172. package/lib/routes/keep/user.ts +1 -1
  173. package/lib/routes/langchain/index.ts +74 -0
  174. package/lib/routes/langchain/namespace.ts +7 -0
  175. package/lib/routes/last-origin/namespace.ts +7 -0
  176. package/lib/routes/last-origin/news.ts +65 -0
  177. package/lib/routes/linkresearcher/index.ts +108 -46
  178. package/lib/routes/linkresearcher/namespace.ts +8 -2
  179. package/lib/routes/linkresearcher/templates/bilingual.art +7 -0
  180. package/lib/routes/linkresearcher/types.ts +103 -0
  181. package/lib/routes/liulinblog/itnews.ts +1 -1
  182. package/lib/routes/lofter/collection.ts +1 -1
  183. package/lib/routes/lofter/tag.ts +1 -1
  184. package/lib/routes/logrocket/index.ts +71 -0
  185. package/lib/routes/logrocket/namespace.ts +7 -0
  186. package/lib/routes/m-78/namespace.ts +7 -0
  187. package/lib/routes/m-78/news.ts +115 -0
  188. package/lib/routes/m-78/types.ts +13 -0
  189. package/lib/routes/mastodon/account-id.ts +1 -1
  190. package/lib/routes/mastodon/acct.ts +1 -1
  191. package/lib/routes/mastodon/timeline-local.ts +2 -2
  192. package/lib/routes/mastodon/timeline-remote.ts +2 -2
  193. package/lib/routes/mastodon/utils.ts +1 -1
  194. package/lib/routes/metacritic/index.ts +1 -1
  195. package/lib/routes/mi/utils.ts +1 -1
  196. package/lib/routes/mihoyo/bbs/official.ts +2 -1
  197. package/lib/routes/misskey/utils.ts +19 -1
  198. package/lib/routes/mittrchina/index.ts +2 -2
  199. package/lib/routes/natgeo/natgeo.ts +25 -24
  200. package/lib/routes/nbd/daily.ts +1 -1
  201. package/lib/routes/nielsberglund/index.ts +78 -0
  202. package/lib/routes/nielsberglund/namespace.ts +7 -0
  203. package/lib/routes/nytimes/rss.ts +57 -0
  204. package/lib/routes/openrice/chart.ts +68 -0
  205. package/lib/routes/openrice/templates/chart.art +9 -0
  206. package/lib/routes/openrice/voting.ts +84 -0
  207. package/lib/routes/oschina/news.ts +26 -7
  208. package/lib/routes/patreon/feed.ts +126 -0
  209. package/lib/routes/patreon/namespace.ts +7 -0
  210. package/lib/routes/patreon/templates/description.art +39 -0
  211. package/lib/routes/patreon/types.ts +387 -0
  212. package/lib/routes/pixiv/api/get-illust-detail.ts +22 -0
  213. package/lib/routes/pixiv/novel-api/content/nsfw.ts +73 -0
  214. package/lib/routes/pixiv/novel-api/content/sfw.ts +63 -0
  215. package/lib/routes/pixiv/novel-api/content/types.ts +254 -0
  216. package/lib/routes/pixiv/novel-api/content/utils.ts +133 -0
  217. package/lib/routes/pixiv/novel-api/series/nsfw.ts +84 -0
  218. package/lib/routes/pixiv/novel-api/series/sfw.ts +70 -0
  219. package/lib/routes/pixiv/novel-api/series/types.ts +94 -0
  220. package/lib/routes/pixiv/novel-api/user-novels/nsfw.ts +82 -0
  221. package/lib/routes/pixiv/novel-api/user-novels/sfw.ts +74 -0
  222. package/lib/routes/pixiv/novel-api/user-novels/types.ts +133 -0
  223. package/lib/routes/pixiv/novel-series.ts +52 -0
  224. package/lib/routes/pixiv/novels.ts +69 -44
  225. package/lib/routes/pixiv/utils.ts +3 -0
  226. package/lib/routes/plurk/anonymous.ts +1 -1
  227. package/lib/routes/plurk/hotlinks.ts +1 -1
  228. package/lib/routes/plurk/news.ts +1 -1
  229. package/lib/routes/plurk/search.ts +1 -1
  230. package/lib/routes/qstheory/index.ts +121 -0
  231. package/lib/routes/qstheory/magazine.ts +64 -0
  232. package/lib/routes/qstheory/namespace.ts +7 -0
  233. package/lib/routes/qstheory/utils.ts +25 -0
  234. package/lib/routes/ruc/ai.ts +1 -1
  235. package/lib/routes/scmp/coronavirus.ts +1 -1
  236. package/lib/routes/scu/jwc/tzgg.ts +75 -0
  237. package/lib/routes/scu/namespace.ts +7 -0
  238. package/lib/routes/scu/scupi/_utils.ts +62 -0
  239. package/lib/routes/scu/scupi/notice.ts +41 -0
  240. package/lib/routes/solidot/namespace.ts +1 -1
  241. package/lib/routes/stbu/jsjxy.ts +4 -1
  242. package/lib/routes/steam/search.ts +7 -0
  243. package/lib/routes/sycl/feeds.ts +1 -1
  244. package/lib/routes/syosetu/dev.ts +67 -0
  245. package/lib/routes/syosetu/index.ts +85 -0
  246. package/lib/routes/syosetu/namespace.ts +2 -2
  247. package/lib/routes/syosetu/ranking-isekai.ts +93 -0
  248. package/lib/routes/syosetu/ranking-r18.ts +192 -0
  249. package/lib/routes/syosetu/ranking.ts +285 -0
  250. package/lib/routes/syosetu/search.ts +161 -0
  251. package/lib/routes/syosetu/templates/description.art +73 -0
  252. package/lib/routes/syosetu/types/ranking-r18.ts +60 -0
  253. package/lib/routes/syosetu/types/ranking.ts +67 -0
  254. package/lib/routes/syosetu/types/search.ts +138 -0
  255. package/lib/routes/syosetu/utils.ts +50 -0
  256. package/lib/routes/telegram/channel.ts +31 -1
  257. package/lib/routes/telegram/scripts/get-telegram-session.mjs +16 -6
  258. package/lib/routes/telegram/stickerpack.ts +1 -1
  259. package/lib/routes/telegram/tglib/channel.ts +12 -9
  260. package/lib/routes/telegram/tglib/client.ts +13 -9
  261. package/lib/routes/test/index.ts +4 -0
  262. package/lib/routes/theblockbeats/index.ts +1 -1
  263. package/lib/routes/thegradient/index.ts +80 -0
  264. package/lib/routes/thegradient/namespace.ts +7 -0
  265. package/lib/routes/theinitium/app.ts +4 -0
  266. package/lib/routes/thepaper/channel.ts +1 -1
  267. package/lib/routes/thepaper/factpaper.ts +1 -1
  268. package/lib/routes/thepaper/featured.ts +1 -1
  269. package/lib/routes/thepaper/list.ts +1 -1
  270. package/lib/routes/thepaper/user.ts +174 -0
  271. package/lib/routes/tongji/sem/_utils.ts +65 -0
  272. package/lib/routes/tongji/sem/notice.ts +58 -0
  273. package/lib/routes/toutiao/a-bogus.ts +540 -0
  274. package/lib/routes/toutiao/namespace.ts +7 -0
  275. package/lib/routes/toutiao/templates/video.art +7 -0
  276. package/lib/routes/toutiao/types.ts +443 -0
  277. package/lib/routes/toutiao/user.ts +127 -0
  278. package/lib/routes/twitter/api/mobile-api/api.ts +8 -0
  279. package/lib/routes/twitter/api/web-api/utils.ts +21 -9
  280. package/lib/routes/twitter/namespace.ts +1 -0
  281. package/lib/routes/twitter/utils.ts +7 -1
  282. package/lib/routes/vertikal/latest.ts +73 -0
  283. package/lib/routes/vertikal/namespace.ts +7 -0
  284. package/lib/routes/vice/topic.ts +1 -1
  285. package/lib/routes/vocus/publication.ts +1 -1
  286. package/lib/routes/vocus/user.ts +1 -1
  287. package/lib/routes/wallstreetcn/calendar.ts +90 -0
  288. package/lib/routes/wallstreetcn/hot.ts +2 -2
  289. package/lib/routes/wallstreetcn/live.ts +1 -1
  290. package/lib/routes/wallstreetcn/news.ts +5 -3
  291. package/lib/routes/weibo/timeline.ts +3 -2
  292. package/lib/routes/wellcee/rent.ts +1 -1
  293. package/lib/routes/wufazhuce/namespace.ts +7 -0
  294. package/lib/routes/wufazhuce/one.ts +90 -0
  295. package/lib/routes/xiaoheihe/discount.ts +72 -28
  296. package/lib/routes/xiaohongshu/user.ts +40 -3
  297. package/lib/routes/xiaohongshu/util.ts +112 -105
  298. package/lib/routes/xsijishe/rank.ts +33 -7
  299. package/lib/routes/xueqiu/cookies.ts +13 -18
  300. package/lib/routes/yahoo/news/listid.ts +4 -1
  301. package/lib/routes/yahoo/news/provider-helper.ts +4 -1
  302. package/lib/routes/yahoo/news/provider.ts +4 -1
  303. package/lib/routes/yande/post.ts +13 -3
  304. package/lib/routes/youtube/user.ts +37 -25
  305. package/lib/routes/zhonglun/index.ts +5 -6
  306. package/lib/routes/zjut/cs/index.ts +1 -1
  307. package/lib/utils/got.ts +2 -1
  308. package/lib/utils/helpers.test.ts +13 -1
  309. package/lib/utils/helpers.ts +10 -0
  310. package/lib/utils/ofetch.ts +3 -0
  311. package/lib/utils/request-rewriter/fetch.test.ts +94 -0
  312. package/lib/utils/request-rewriter/fetch.ts +14 -1
  313. package/lib/views/error.tsx +1 -1
  314. package/package.json +40 -37
  315. package/lib/routes/78dm/templates/image.art +0 -1
  316. package/lib/routes/deeplearning/thebatch.ts +0 -74
  317. package/lib/routes/syosetu/chapter.ts +0 -87
  318. package/lib/routes/xiaohongshu/notes.ts +0 -39
  319. package/lib/routes-deprecated/furaffinity/browse.js +0 -44
  320. package/lib/routes-deprecated/furaffinity/commissions.js +0 -39
  321. package/lib/routes-deprecated/furaffinity/favorites.js +0 -56
  322. package/lib/routes-deprecated/furaffinity/gallery.js +0 -56
  323. package/lib/routes-deprecated/furaffinity/home.js +0 -72
  324. package/lib/routes-deprecated/furaffinity/journal-comments.js +0 -50
  325. package/lib/routes-deprecated/furaffinity/journals.js +0 -49
  326. package/lib/routes-deprecated/furaffinity/scraps.js +0 -56
  327. package/lib/routes-deprecated/furaffinity/search.js +0 -56
  328. package/lib/routes-deprecated/furaffinity/shouts.js +0 -40
  329. package/lib/routes-deprecated/furaffinity/status.js +0 -38
  330. package/lib/routes-deprecated/furaffinity/submission-comments.js +0 -50
  331. package/lib/routes-deprecated/furaffinity/watchers.js +0 -47
  332. package/lib/routes-deprecated/furaffinity/watching.js +0 -47
  333. package/lib/routes-deprecated/ieee/author.js +0 -30
  334. package/lib/routes-deprecated/qstheory/index.js +0 -122
@@ -0,0 +1,73 @@
1
+ {{ if novel.story }}
2
+ <p>{{@ novel.story.replaceAll('\n', '<br>') }}</p>
3
+ {{ /if }}
4
+
5
+ <h2>作品情報</h2>
6
+ <table>
7
+ <tr>
8
+ <td>状態</td>
9
+ <td>
10
+ {{ if novel.novel_type === 2 }}
11
+ 短編
12
+ {{ else }}
13
+ {{ if novel.end === 0 }}
14
+ 完結済
15
+ {{ else }}
16
+ 連載中
17
+ {{ /if }}
18
+ (全{{ novel.general_all_no }}エピソード)
19
+ {{ /if }}
20
+ </td>
21
+ </tr>
22
+ {{ if genreText }}
23
+ <tr>
24
+ <td>ジャンル</td>
25
+ <td>{{ genreText }}</td>
26
+ </tr>
27
+ {{ /if }}
28
+ <tr>
29
+ <td>キーワード</td>
30
+ <td>{{ novel.keyword.replaceAll(' ', '、') }}</td>
31
+ </tr>
32
+ <tr>
33
+ <td>最終掲載</td>
34
+ <td>{{ novel.general_lastup }}</td>
35
+ </tr>
36
+ <tr>
37
+ <td>Nコード</td>
38
+ <td>{{ novel.ncode }}</td>
39
+ </tr>
40
+ <tr>
41
+ <td>読了時間</td>
42
+ <td>約{{ novel.time }}分({{ novel.length }}文字)</td>
43
+ </tr>
44
+ </table>
45
+ <br>
46
+ <table>
47
+ {{ if novel.weekly_unique }}
48
+ <tr>
49
+ <td>週別ユニークユーザ</td>
50
+ <td>{{ novel.weekly_unique < 100 ? '100未満' : novel.weekly_unique }}</td>
51
+ </tr>
52
+ {{ /if }}
53
+ <tr>
54
+ <td>総合ポイント</td>
55
+ <td>{{ novel.global_point }} pt</td>
56
+ </tr>
57
+ <tr>
58
+ <td>評価人数</td>
59
+ <td>{{ novel.all_hyoka_cnt }} 人</td>
60
+ </tr>
61
+ <tr>
62
+ <td>評価ポイント</td>
63
+ <td>{{ novel.all_point }} pt</td>
64
+ </tr>
65
+ <tr>
66
+ <td>ブックマーク</td>
67
+ <td>{{ novel.fav_novel_cnt }} 件</td>
68
+ </tr>
69
+ </table>
70
+
71
+ {{ if novel.sasie_cnt > 0 }}
72
+ <p>挿絵数:{{ novel.sasie_cnt }}枚</p>
73
+ {{ /if }}
@@ -0,0 +1,60 @@
1
+ import { R18Site } from 'narou';
2
+
3
+ export enum SyosetuSub {
4
+ NOCTURNE = 'noc',
5
+ MOONLIGHT = 'mnlt',
6
+ MIDNIGHT = 'mid',
7
+ MOONLIGHT_BL = 'mnlt-bl',
8
+ }
9
+
10
+ export enum RankingPeriod {
11
+ DAILY = 'daily',
12
+ WEEKLY = 'weekly',
13
+ MONTHLY = 'monthly',
14
+ QUARTER = 'quarter',
15
+ YEARLY = 'yearly',
16
+ }
17
+
18
+ export enum NovelType {
19
+ TOTAL = 'total',
20
+ SHORT = 't',
21
+ ONGOING = 'r',
22
+ COMPLETE = 'er',
23
+ }
24
+
25
+ export const syosetuSubToNocgenre = {
26
+ [SyosetuSub.NOCTURNE]: R18Site.Nocturne,
27
+ [SyosetuSub.MOONLIGHT]: R18Site.MoonLight,
28
+ [SyosetuSub.MOONLIGHT_BL]: R18Site.MoonLightBL,
29
+ [SyosetuSub.MIDNIGHT]: R18Site.Midnight,
30
+ } as const;
31
+
32
+ export const syosetuSubToJapanese = {
33
+ [SyosetuSub.NOCTURNE]: 'ノクターン',
34
+ [SyosetuSub.MOONLIGHT]: 'ムーンライト',
35
+ [SyosetuSub.MOONLIGHT_BL]: 'ムーンライト BL',
36
+ [SyosetuSub.MIDNIGHT]: 'ミッドナイト',
37
+ } as const;
38
+
39
+ export const periodToOrder = {
40
+ [RankingPeriod.DAILY]: 'dailypoint',
41
+ [RankingPeriod.WEEKLY]: 'weeklypoint',
42
+ [RankingPeriod.MONTHLY]: 'monthlypoint',
43
+ [RankingPeriod.QUARTER]: 'quarterpoint',
44
+ [RankingPeriod.YEARLY]: 'yearlypoint',
45
+ } as const;
46
+
47
+ export const periodToJapanese = {
48
+ [RankingPeriod.DAILY]: '日間',
49
+ [RankingPeriod.WEEKLY]: '週間',
50
+ [RankingPeriod.MONTHLY]: '月間',
51
+ [RankingPeriod.QUARTER]: '四半期',
52
+ [RankingPeriod.YEARLY]: '年間',
53
+ } as const;
54
+
55
+ export const novelTypeToJapanese = {
56
+ [NovelType.TOTAL]: '総合',
57
+ [NovelType.SHORT]: '短編',
58
+ [NovelType.ONGOING]: '連載中',
59
+ [NovelType.COMPLETE]: '完結済',
60
+ } as const;
@@ -0,0 +1,67 @@
1
+ export enum RankingPeriod {
2
+ DAILY = 'daily',
3
+ WEEKLY = 'weekly',
4
+ MONTHLY = 'monthly',
5
+ QUARTER = 'quarter',
6
+ YEARLY = 'yearly',
7
+ TOTAL = 'total',
8
+ }
9
+
10
+ export enum NovelType {
11
+ TOTAL = 'total',
12
+ SHORT = 't',
13
+ ONGOING = 'r',
14
+ COMPLETE = 'er',
15
+ }
16
+
17
+ export enum RankingType {
18
+ LIST = 'list',
19
+ GENRE = 'genre',
20
+ ISEKAI = 'isekai',
21
+ }
22
+
23
+ export const periodToOrder = {
24
+ [RankingPeriod.DAILY]: 'dailypoint',
25
+ [RankingPeriod.WEEKLY]: 'weeklypoint',
26
+ [RankingPeriod.MONTHLY]: 'monthlypoint',
27
+ [RankingPeriod.QUARTER]: 'quarterpoint',
28
+ [RankingPeriod.YEARLY]: 'yearlypoint',
29
+ [RankingPeriod.TOTAL]: 'hyoka',
30
+ } as const;
31
+
32
+ export const periodToPointField = {
33
+ [RankingPeriod.DAILY]: 'pt',
34
+ [RankingPeriod.WEEKLY]: 'weekly_point',
35
+ [RankingPeriod.MONTHLY]: 'monthly_point',
36
+ [RankingPeriod.QUARTER]: 'quarter_point',
37
+ [RankingPeriod.YEARLY]: 'yearly_point',
38
+ [RankingPeriod.TOTAL]: 'global_point',
39
+ } as const;
40
+
41
+ export const periodToJapanese = {
42
+ [RankingPeriod.DAILY]: '日間',
43
+ [RankingPeriod.WEEKLY]: '週間',
44
+ [RankingPeriod.MONTHLY]: '月間',
45
+ [RankingPeriod.QUARTER]: '四半期',
46
+ [RankingPeriod.YEARLY]: '年間',
47
+ [RankingPeriod.TOTAL]: '累計',
48
+ } as const;
49
+
50
+ export const novelTypeToJapanese = {
51
+ [NovelType.TOTAL]: 'すべて',
52
+ [NovelType.SHORT]: '短編',
53
+ [NovelType.ONGOING]: '連載中',
54
+ [NovelType.COMPLETE]: '完結済',
55
+ } as const;
56
+
57
+ export enum IsekaiCategory {
58
+ RENAI = '1',
59
+ FANTASY = '2',
60
+ OTHER = 'o',
61
+ }
62
+
63
+ export const isekaiCategoryToJapanese = {
64
+ [IsekaiCategory.RENAI]: '〔恋愛〕',
65
+ [IsekaiCategory.FANTASY]: '〔ファンタジー〕',
66
+ [IsekaiCategory.OTHER]: '〔文芸・SF・その他〕',
67
+ } as const;
@@ -0,0 +1,138 @@
1
+ export enum SyosetuSub {
2
+ YOMOU = 'yomou',
3
+ NOCTURNE = 'noc',
4
+ MOONLIGHT = 'mnlt',
5
+ MIDNIGHT = 'mid',
6
+ }
7
+
8
+ export const syosetuSubToJapanese = {
9
+ [SyosetuSub.YOMOU]: '小説を読もう',
10
+ [SyosetuSub.NOCTURNE]: 'ノクターン',
11
+ [SyosetuSub.MOONLIGHT]: 'ムーンライト',
12
+ [SyosetuSub.MIDNIGHT]: 'ミッドナイト',
13
+ } as const;
14
+
15
+ export interface NarouSearchParams {
16
+ /**
17
+ * 作品種別の絞り込み Work Type Filter
18
+ *
19
+ * t 短編 Short
20
+ * r 連載中 Ongoing Series
21
+ * er 完結済連載作品 Completed Series
22
+ * re すべての連載作品 (連載中および完結済) Series and Completed Series
23
+ * ter 短編と完結済連載作品 Completed Works (Including Short and Series)
24
+ *
25
+ * tr 短編と連載中小説 Short and Ongoing Series
26
+ * all 全ての種別 (Default) All Types
27
+ *
28
+ * Note: While the official documentation describes 5 values, all 7 values above are functional.
29
+ */
30
+ type?: 't' | 'r' | 'er' | 're' | 'ter' | 'tr' | 'all';
31
+
32
+ /** 検索ワード Search Keywords */
33
+ word?: string;
34
+
35
+ /** 除外ワード Excluded Keywords */
36
+ notword?: string;
37
+
38
+ /**
39
+ * 検索範囲指定 Search Range Specifications
40
+ *
41
+ * - 読了時間 Reading Time
42
+ * - 文字数 Character Count
43
+ * - 総合ポイント Total Points
44
+ * - 最新掲載日(年月日)Latest Update Date (Year/Month/Day)
45
+ * - 初回掲載日(年月日)First Publication Date (Year/Month/Day)
46
+ */
47
+ mintime?: number;
48
+ maxtime?: number;
49
+ minlen?: number;
50
+ maxlen?: number;
51
+ min_globalpoint?: number;
52
+ max_globalpoint?: number;
53
+ minlastup?: string;
54
+ maxlastup?: string;
55
+ minfirstup?: string;
56
+ maxfirstup?: string;
57
+
58
+ /**
59
+ * 抽出条件の指定 Extraction Conditions
60
+ *
61
+ * - 挿絵のある作品 Works with Illustrations
62
+ * - 小説 PickUp!対象作品 Featured Novels
63
+ *
64
+ * 作品に含まれる要素:Elements Included in Works:
65
+ * - 残酷な描写あり Contains Cruel Content
66
+ * - ボーイズラブ Boys' Love
67
+ * - ガールズラブ Girls' Love
68
+ * - 異世界転生 Reincarnation in Another World
69
+ * - 異世界転移 Transportation to Another World
70
+ */
71
+ sasie?: string;
72
+ ispickup?: boolean;
73
+ iszankoku?: boolean;
74
+ isbl?: boolean;
75
+ isgl?: boolean;
76
+ istensei?: boolean;
77
+ istenni?: boolean;
78
+
79
+ /**
80
+ * 除外条件の指定 Exclusion Conditions
81
+ *
82
+ * - 長期連載停止中の作品 Works on Long-term Hiatus
83
+ *
84
+ * 作品に含まれる要素:Elements to Exclude:
85
+ * - 残酷な描写あり Cruel Content
86
+ * - ボーイズラブ Boys' Love
87
+ * - ガールズラブ Girls' Love
88
+ * - 異世界転生 Reincarnation in Another World
89
+ * - 異世界転移 Transportation to Another World
90
+ */
91
+ stop?: boolean;
92
+ notzankoku?: boolean;
93
+ notbl?: boolean;
94
+ notgl?: boolean;
95
+ nottensei?: boolean;
96
+ nottenni?: boolean;
97
+
98
+ /**
99
+ * ワード検索範囲指定 Word Search Scope
100
+ * すべてのチェックを解除した場合、すべての項目がワード検索の対象となります。
101
+ * If all boxes are unchecked, all items will become targets for word search.
102
+ *
103
+ * 作品タイトル Work Title
104
+ * あらすじ Synopsis
105
+ * キーワード Keywords
106
+ * 作者名 Author Name
107
+ */
108
+ title?: boolean;
109
+ ex?: boolean;
110
+ keyword?: boolean;
111
+ wname?: boolean;
112
+
113
+ /**
114
+ * 並び順 Sort Order
115
+ * - new: 新着更新順 (Default) Latest Updates
116
+ * - weekly: 週間ユニークアクセスが多い順 Most Weekly Unique Access
117
+ * - favnovelcnt: ブックマーク登録の多い順 Most Bookmarks
118
+ * - reviewcnt: レビューの多い順 Most Reviews
119
+ * - hyoka: 総合ポイントの高い順 Highest Total Points
120
+ * - dailypoint: 日間ポイントの高い順 Highest Daily Points
121
+ * - weeklypoint: 週間ポイントの高い順 Highest Weekly Points
122
+ * - monthlypoint: 月間ポイントの高い順 Highest Monthly Points
123
+ * - quarterpoint: 四半期ポイントの高い順 Highest Quarterly Points
124
+ * - yearlypoint: 年間ポイントの高い順 Highest Yearly Points
125
+ * - hyokacnt: 評価者数の多い順 Most Ratings
126
+ * - lengthdesc: 文字数の多い順 Most Characters
127
+ * - generalfirstup: 初回掲載順 First Publication Order
128
+ * - ncodedesc: N コード降順 Ncode Descending
129
+ * - old: 更新が古い順 Oldest Updates
130
+ */
131
+ order?: 'new' | 'weekly' | 'favnovelcnt' | 'reviewcnt' | 'hyoka' | 'dailypoint' | 'weeklypoint' | 'monthlypoint' | 'quarterpoint' | 'yearlypoint' | 'hyokacnt' | 'lengthdesc' | 'generalfirstup' | 'ncodedesc' | 'old';
132
+
133
+ /** ジャンル Genre */
134
+ genre?: string;
135
+
136
+ /** 掲載サイト指定 Site */
137
+ nocgenre?: number;
138
+ }
@@ -0,0 +1,50 @@
1
+ import { DataItem } from '@/types';
2
+ import cache from '@/utils/cache';
3
+ import ofetch from '@/utils/ofetch';
4
+ import { load } from 'cheerio';
5
+ import InvalidParameterError from '@/errors/types/invalid-parameter';
6
+ import { config } from '@/config';
7
+ import { NarouNovelFetch, NarouSearchResult, SearchBuilder, SearchBuilderR18 } from 'narou';
8
+
9
+ export async function fetchNovelInfo(ncode: string): Promise<{ baseUrl: string; novel: NarouSearchResult }> {
10
+ const api = new NarouNovelFetch();
11
+ const [generalRes, r18Res] = await Promise.all([new SearchBuilder({ gzip: 5, of: 't-s-k-ga-nt-nu' }, api).ncode(ncode).execute(), new SearchBuilderR18({ gzip: 5, of: 't-s-k-ga-nt-nu' }, api).ncode(ncode).execute()]);
12
+
13
+ const isGeneral = generalRes.allcount !== 0;
14
+ const novelData = isGeneral ? generalRes : r18Res;
15
+ const baseUrl = isGeneral ? 'https://ncode.syosetu.com' : 'https://novel18.syosetu.com';
16
+
17
+ if (novelData.allcount === 0) {
18
+ throw new InvalidParameterError('Novel not found in both APIs');
19
+ }
20
+
21
+ return {
22
+ baseUrl,
23
+ novel: novelData.values[0] as NarouSearchResult,
24
+ };
25
+ }
26
+
27
+ export async function fetchChapterContent(chapterUrl: string, chapter?: number): Promise<DataItem> {
28
+ return (await cache.tryGet(chapterUrl, async () => {
29
+ const response = await ofetch(chapterUrl, {
30
+ headers: {
31
+ Cookie: 'over18=yes',
32
+ 'User-Agent': config.ua,
33
+ },
34
+ });
35
+
36
+ const $ = load(response);
37
+
38
+ const title = `${chapter ? `#${chapter} ` : ''}${$('.p-novel__title').html() || ''}`;
39
+ const description = $('.p-novel__body').html() || '';
40
+ const pubDate = $('meta[name=WWWC]').attr('content');
41
+
42
+ return {
43
+ title,
44
+ description,
45
+ link: chapterUrl,
46
+ pubDate,
47
+ language: 'ja',
48
+ };
49
+ })) as DataItem;
50
+ }
@@ -98,6 +98,36 @@ For backward compatibility reasons, invalid \`routeParams\` will be treated as \
98
98
  optional: true,
99
99
  description: 'Telegram API Authentication',
100
100
  },
101
+ {
102
+ name: 'TELEGRAM_API_ID',
103
+ optional: true,
104
+ description: 'Telegram API ID',
105
+ },
106
+ {
107
+ name: 'TELEGRAM_API_HASH',
108
+ optional: true,
109
+ description: 'Telegram API Hash',
110
+ },
111
+ {
112
+ name: 'TELEGRAM_MAX_CONCURRENT_DOWNLOADS',
113
+ optional: true,
114
+ description: 'Telegram Max Concurrent Downloads',
115
+ },
116
+ {
117
+ name: 'TELEGRAM_PROXY_HOST',
118
+ optional: true,
119
+ description: 'Telegram Proxy Host',
120
+ },
121
+ {
122
+ name: 'TELEGRAM_PROXY_PORT',
123
+ optional: true,
124
+ description: 'Telegram Proxy Port',
125
+ },
126
+ {
127
+ name: 'TELEGRAM_PROXY_SECRET',
128
+ optional: true,
129
+ description: 'Telegram Proxy Secret',
130
+ },
101
131
  ],
102
132
  requirePuppeteer: false,
103
133
  antiCrawler: false,
@@ -112,7 +142,7 @@ For backward compatibility reasons, invalid \`routeParams\` will be treated as \
112
142
  },
113
143
  ],
114
144
  name: 'Channel',
115
- maintainers: ['DIYgod', 'Rongronggg9', 'pseudoyu'],
145
+ maintainers: ['DIYgod', 'Rongronggg9', 'synchrone', 'pseudoyu'],
116
146
  handler,
117
147
  description: `
118
148
  :::tip
@@ -1,11 +1,12 @@
1
1
  import { TelegramClient } from 'telegram';
2
2
  import { StringSession } from 'telegram/sessions/index.js';
3
3
  import readline from 'readline';
4
+ import winston from 'winston';
4
5
 
5
6
  function userInput(question) {
6
7
  const rl = readline.createInterface({
7
8
  input: process.stdin,
8
- output: process.stdout
9
+ output: process.stdout,
9
10
  });
10
11
  return new Promise((resolve) => {
11
12
  rl.question(question, (answer) => {
@@ -15,8 +16,17 @@ function userInput(question) {
15
16
  });
16
17
  }
17
18
 
19
+ const logger = winston.createLogger({
20
+ level: 'info',
21
+ format: winston.format.combine(
22
+ winston.format.timestamp(),
23
+ winston.format.printf(({ level, message, timestamp }) => `${timestamp} ${level}: ${message}`)
24
+ ),
25
+ transports: [new winston.transports.Console()],
26
+ });
27
+
18
28
  async function getSessionString() {
19
- const apiId = parseInt(await userInput('Please enter your API ID: '));
29
+ const apiId = Number.parseInt(await userInput('Please enter your API ID: '));
20
30
  const apiHash = await userInput('Please enter your API Hash: ');
21
31
  const stringSession = new StringSession('');
22
32
  const client = new TelegramClient(stringSession, apiId, apiHash, {
@@ -26,16 +36,16 @@ async function getSessionString() {
26
36
  phoneNumber: async () => await userInput('Please enter your phone number: '),
27
37
  password: async () => await userInput('Please enter your password: '),
28
38
  phoneCode: async () => await userInput('Please enter the code you received: '),
29
- onError: (err) => console.log(err),
39
+ onError: (err) => logger.error(err),
30
40
  });
31
41
 
32
- console.log('You are now connected.');
42
+ logger.info('You are now connected.');
33
43
  const sessionString = client.session.save();
44
+ logger.info(`Your session string is: ${sessionString}`);
34
45
 
35
- console.log('Your session string is:', sessionString);
36
46
  await client.disconnect();
37
47
  return sessionString;
38
48
  }
39
49
 
40
50
  // Run the function
41
- getSessionString().catch(console.error);
51
+ getSessionString().catch((error) => logger.error(error));
@@ -5,7 +5,7 @@ import ConfigNotFoundError from '@/errors/types/config-not-found';
5
5
 
6
6
  export const route: Route = {
7
7
  path: '/stickerpack/:name',
8
- categories: ['social-media', 'popular'],
8
+ categories: ['social-media'],
9
9
  view: ViewType.Pictures,
10
10
  example: '/telegram/stickerpack/DIYgod',
11
11
  parameters: { name: 'Sticker Pack name, available in the sharing URL' },
@@ -2,6 +2,8 @@ import InvalidParameterError from '@/errors/types/invalid-parameter';
2
2
  import { client, decodeMedia, getClient, getFilename, getMediaLink, streamDocument, streamThumbnail } from './client';
3
3
  import { returnBigInt as bigInt } from 'telegram/Helpers';
4
4
  import { HTMLParser } from 'telegram/extensions/html';
5
+ import { DataItem } from '@/types';
6
+ import type { Api } from 'telegram';
5
7
 
6
8
  function parseRange(range, length) {
7
9
  if (!range) {
@@ -111,24 +113,25 @@ async function getMedia(ctx) {
111
113
  }
112
114
 
113
115
  export default async function handler(ctx) {
116
+ const { username } = ctx.req.param();
114
117
  const client = await getClient();
115
118
 
116
- const item = [];
117
- const chat = await client.getInputEntity(ctx.req.param('username'));
119
+ const item: DataItem[] = [];
120
+ const chat = (await client.getInputEntity(username)) as Api.InputPeerChannel;
118
121
  const channelInfo = await client.getEntity(chat);
119
122
 
120
123
  if (channelInfo.className !== 'Channel') {
121
- throw new Error(`${ctx.req.param('username')} is not a channel`);
124
+ throw new Error(`${username} is not a channel`);
122
125
  }
123
126
 
124
- let attachments = [];
127
+ let attachments: string[] = [];
125
128
  const messages = await client.getMessages(chat, { limit: 50 });
126
129
 
127
130
  for (const message of messages) {
128
131
  if (message.media) {
129
132
  // messages that have no text are shown as if they're one post
130
133
  // because in TG only 1 attachment per message is possible
131
- attachments.push(getMediaLink(ctx, chat, ctx.req.param('username'), message));
134
+ attachments.push(getMediaLink(ctx, chat, username, message));
132
135
  }
133
136
  if (message.text !== '') {
134
137
  let description = attachments.join('\n');
@@ -144,8 +147,8 @@ export default async function handler(ctx) {
144
147
  title,
145
148
  description,
146
149
  pubDate: new Date(message.date * 1000).toUTCString(),
147
- link: `https://t.me/s/${ctx.req.param('username')}/${message.id}`,
148
- author: `${channelInfo.title} (@${ctx.req.param('username')})`,
150
+ link: `https://t.me/s/${username}/${message.id}`,
151
+ author: `${channelInfo.title} (@${username})`,
149
152
  });
150
153
  }
151
154
  }
@@ -153,10 +156,10 @@ export default async function handler(ctx) {
153
156
  return {
154
157
  title: channelInfo.title,
155
158
  language: null,
156
- link: `https://t.me/${ctx.req.param('username')}`,
159
+ link: `https://t.me/${username}`,
157
160
  item,
158
161
  allowEmpty: ctx.req.param('id') === 'allow_empty',
159
- description: `@${ctx.req.param('username')} on Telegram`,
162
+ description: `@${username} on Telegram`,
160
163
  };
161
164
  }
162
165
 
@@ -23,14 +23,18 @@ export async function getClient(authParams?: UserAuthParams, session?: string) {
23
23
  autoReconnect: true,
24
24
  retryDelay: 3000,
25
25
  maxConcurrentDownloads: Number(config.telegram.maxConcurrentDownloads ?? 10),
26
+ proxy:
27
+ config.telegram.proxy?.host && config.telegram.proxy.port && config.telegram.proxy.secret
28
+ ? {
29
+ ip: config.telegram.proxy.host,
30
+ port: Number(config.telegram.proxy.port),
31
+ MTProxy: true,
32
+ secret: config.telegram.proxy.secret,
33
+ }
34
+ : undefined,
26
35
  });
27
- await client.start(
28
- Object.assign(authParams ?? {}, {
29
- onError: (err) => {
30
- throw new Error('Cannot start TG: ' + err);
31
- },
32
- }) as any
33
- );
36
+
37
+ await client.connect();
34
38
  return client;
35
39
  }
36
40
 
@@ -77,7 +81,7 @@ function ExpandInlineBytes(bytes) {
77
81
  return real;
78
82
  }
79
83
 
80
- function getMediaLink(ctx, channel, channelName, message) {
84
+ function getMediaLink(ctx, channel: Api.InputPeerChannel, channelName: string, message: Api.Message) {
81
85
  const base = `${ctx.protocol}://${ctx.host}/telegram/channel/${channelName}`;
82
86
  const src = base + `${channel.channelId}_${message.id}`;
83
87
 
@@ -98,7 +102,7 @@ function getMediaLink(ctx, channel, channelName, message) {
98
102
  linkText += ` (${humanFileSize(x.document.size)})`;
99
103
  return `<a href="${src}" target="_blank"><img src="${src}?thumb" alt=""/><br/>${linkText}</a>`;
100
104
  }
101
- return;
105
+ return '';
102
106
  }
103
107
  function getFilename(x) {
104
108
  if (x instanceof Api.MessageMediaDocument) {
@@ -32,6 +32,10 @@ async function handler(ctx) {
32
32
  if (ctx.req.param('id') === 'invalid-parameter-error') {
33
33
  throw new InvalidParameterError('Test invalid parameter error');
34
34
  }
35
+ if (ctx.req.param('id') === 'redirect') {
36
+ ctx.set('redirect', '/test/1');
37
+ return;
38
+ }
35
39
  let item: DataItem[] = [];
36
40
  let image: string | null = null;
37
41
  switch (ctx.req.param('id')) {
@@ -3,7 +3,7 @@ import cache from '@/utils/cache';
3
3
  import ofetch from '@/utils/ofetch';
4
4
  import { load } from 'cheerio';
5
5
  import { parseDate } from '@/utils/parse-date';
6
- import path from 'path';
6
+ import path from 'node:path';
7
7
  import { art } from '@/utils/render';
8
8
  import { getCurrentPath } from '@/utils/helpers';
9
9