koishi-plugin-kkk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (702) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/LICENSE +674 -0
  3. package/README.md +98 -0
  4. package/assets/web/assets/CronEditor-CYgFpX-g.js +1 -0
  5. package/assets/web/assets/DesktopLayout-iI43ij11.js +1 -0
  6. package/assets/web/assets/MobileLayout-CziU8MCR.js +1 -0
  7. package/assets/web/assets/ThemeSwitch-DFohhwd9.js +1 -0
  8. package/assets/web/assets/index-BRROK0vh.js +47 -0
  9. package/assets/web/assets/index-Dj-StEiS.css +2 -0
  10. package/assets/web/assets/separator-CxcFlCzz.js +1 -0
  11. package/assets/web/favicon.svg +1 -0
  12. package/assets/web/icons.svg +24 -0
  13. package/assets/web/index.html +15 -0
  14. package/assets/webui.html +115 -0
  15. package/client/index.ts +63 -0
  16. package/config/default_config/app.yaml +64 -0
  17. package/config/default_config/bilibili.yaml +116 -0
  18. package/config/default_config/config.json +157 -0
  19. package/config/default_config/cookies.yaml +11 -0
  20. package/config/default_config/douyin.yaml +99 -0
  21. package/config/default_config/kuaishou.yaml +8 -0
  22. package/config/default_config/pushlist.yaml +37 -0
  23. package/config/default_config/request.yaml +22 -0
  24. package/config/default_config/upload.yaml +50 -0
  25. package/config/default_config/xiaohongshu.yaml +23 -0
  26. package/dist/index.js +1 -0
  27. package/lib/compat/axios.js +23 -0
  28. package/lib/compat/cron.js +77 -0
  29. package/lib/compat/esm.js +15 -0
  30. package/lib/compat/express.js +23 -0
  31. package/lib/compat/heroui.js +12 -0
  32. package/lib/compat/lodash.js +33 -0
  33. package/lib/compat/logger.js +118 -0
  34. package/lib/compat/node-karin.js +1053 -0
  35. package/lib/compat/phosphor-icons.js +27 -0
  36. package/lib/compat/qqcard.js +256 -0
  37. package/lib/compat/root.js +44 -0
  38. package/lib/compat/runtime.js +87 -0
  39. package/lib/compat/segment.js +167 -0
  40. package/lib/compat/sqlite3.js +117 -0
  41. package/lib/compat/start.js +7 -0
  42. package/lib/compat/syncConfig.js +65 -0
  43. package/lib/compat/template-react.js +30 -0
  44. package/lib/compat/text.js +65 -0
  45. package/lib/compat/yaml.js +13 -0
  46. package/lib/configBridge.js +91 -0
  47. package/lib/index.js +775 -0
  48. package/lib/karin/app.js +34 -0
  49. package/lib/karin/apps/__ready.js +9 -0
  50. package/lib/karin/apps/admin.js +136 -0
  51. package/lib/karin/apps/help.js +233 -0
  52. package/lib/karin/apps/push.js +291 -0
  53. package/lib/karin/apps/qrlogin.js +176 -0
  54. package/lib/karin/apps/statistics.js +209 -0
  55. package/lib/karin/apps/testPush.js +247 -0
  56. package/lib/karin/apps/tools.js +473 -0
  57. package/lib/karin/apps/update.js +252 -0
  58. package/lib/karin/index.js +37 -0
  59. package/lib/karin/module/db/bilibili.js +831 -0
  60. package/lib/karin/module/db/douyin.js +918 -0
  61. package/lib/karin/module/db/index.js +165 -0
  62. package/lib/karin/module/db/migration.js +199 -0
  63. package/lib/karin/module/db/statistics.js +559 -0
  64. package/lib/karin/module/index.js +94 -0
  65. package/lib/karin/module/server/constants/routes.js +48 -0
  66. package/lib/karin/module/server/controllers/bots.js +230 -0
  67. package/lib/karin/module/server/controllers/config.js +75 -0
  68. package/lib/karin/module/server/controllers/video.js +208 -0
  69. package/lib/karin/module/server/index.js +26 -0
  70. package/lib/karin/module/server/middlewares/auth.js +133 -0
  71. package/lib/karin/module/server/routes/amagi.js +57 -0
  72. package/lib/karin/module/server/routes/api.js +40 -0
  73. package/lib/karin/module/server/routes/index.js +97 -0
  74. package/lib/karin/module/server/routes/ssr.js +16 -0
  75. package/lib/karin/module/server/routes/static.js +43 -0
  76. package/lib/karin/module/utils/Base.js +403 -0
  77. package/lib/karin/module/utils/CardParser.js +487 -0
  78. package/lib/karin/module/utils/Common.js +418 -0
  79. package/lib/karin/module/utils/Config.js +434 -0
  80. package/lib/karin/module/utils/EmojiReaction.js +242 -0
  81. package/lib/karin/module/utils/ErrorHandler/handler.js +114 -0
  82. package/lib/karin/module/utils/ErrorHandler/index.js +55 -0
  83. package/lib/karin/module/utils/ErrorHandler/render.js +182 -0
  84. package/lib/karin/module/utils/ErrorHandler/sender.js +206 -0
  85. package/lib/karin/module/utils/ErrorHandler/strategy.js +41 -0
  86. package/lib/karin/module/utils/ErrorHandler/types.js +2 -0
  87. package/lib/karin/module/utils/ErrorHandler/utils.js +108 -0
  88. package/lib/karin/module/utils/FFmpeg.js +298 -0
  89. package/lib/karin/module/utils/ImageHelper.js +91 -0
  90. package/lib/karin/module/utils/ImageSlice.js +429 -0
  91. package/lib/karin/module/utils/MotionPhoto.js +250 -0
  92. package/lib/karin/module/utils/Network/Downloader.js +413 -0
  93. package/lib/karin/module/utils/Network/ImageDownloader.js +250 -0
  94. package/lib/karin/module/utils/Network/Network.js +332 -0
  95. package/lib/karin/module/utils/Network/ThrottleStream.js +71 -0
  96. package/lib/karin/module/utils/Network/constants.js +129 -0
  97. package/lib/karin/module/utils/Network/helpers.js +174 -0
  98. package/lib/karin/module/utils/Network/index.js +34 -0
  99. package/lib/karin/module/utils/Network/types.js +12 -0
  100. package/lib/karin/module/utils/Networks.js +17 -0
  101. package/lib/karin/module/utils/ParseLock.js +34 -0
  102. package/lib/karin/module/utils/ParseOverride.js +88 -0
  103. package/lib/karin/module/utils/QqCardResolve.js +114 -0
  104. package/lib/karin/module/utils/QqPanel.js +879 -0
  105. package/lib/karin/module/utils/Render/coverTheme.js +256 -0
  106. package/lib/karin/module/utils/Render/index.js +582 -0
  107. package/lib/karin/module/utils/amagiClient.js +338 -0
  108. package/lib/karin/module/utils/avatar.js +201 -0
  109. package/lib/karin/module/utils/bot.js +141 -0
  110. package/lib/karin/module/utils/build-metadata.js +50 -0
  111. package/lib/karin/module/utils/changelog.js +166 -0
  112. package/lib/karin/module/utils/index.js +26 -0
  113. package/lib/karin/module/utils/loginSession.js +259 -0
  114. package/lib/karin/module/utils/parseTip.js +93 -0
  115. package/lib/karin/module/utils/runtime-report.js +140 -0
  116. package/lib/karin/module/utils/semver.js +72 -0
  117. package/lib/karin/module/utils/statisticsAggregate.js +415 -0
  118. package/lib/karin/platform/bilibili/bilibili.js +1805 -0
  119. package/lib/karin/platform/bilibili/comments.js +294 -0
  120. package/lib/karin/platform/bilibili/danmaku.js +555 -0
  121. package/lib/karin/platform/bilibili/dynamic-text.js +827 -0
  122. package/lib/karin/platform/bilibili/genParams.js +37 -0
  123. package/lib/karin/platform/bilibili/getID.js +159 -0
  124. package/lib/karin/platform/bilibili/index.js +24 -0
  125. package/lib/karin/platform/bilibili/live-status.js +40 -0
  126. package/lib/karin/platform/bilibili/login.js +132 -0
  127. package/lib/karin/platform/bilibili/push.js +1397 -0
  128. package/lib/karin/platform/bilibili/riskControl.js +133 -0
  129. package/lib/karin/platform/bilibili/search.js +299 -0
  130. package/lib/karin/platform/common/danmaku-types.js +12 -0
  131. package/lib/karin/platform/douyin/comments.js +310 -0
  132. package/lib/karin/platform/douyin/danmaku.js +893 -0
  133. package/lib/karin/platform/douyin/douyin.js +1145 -0
  134. package/lib/karin/platform/douyin/getID.js +94 -0
  135. package/lib/karin/platform/douyin/index.js +24 -0
  136. package/lib/karin/platform/douyin/login.js +230 -0
  137. package/lib/karin/platform/douyin/push/favorite.js +75 -0
  138. package/lib/karin/platform/douyin/push/index.js +21 -0
  139. package/lib/karin/platform/douyin/push/live.js +69 -0
  140. package/lib/karin/platform/douyin/push/post.js +60 -0
  141. package/lib/karin/platform/douyin/push/recommend.js +74 -0
  142. package/lib/karin/platform/douyin/push/render.js +621 -0
  143. package/lib/karin/platform/douyin/push/types.js +2 -0
  144. package/lib/karin/platform/douyin/push.js +1128 -0
  145. package/lib/karin/platform/douyin/types.js +13 -0
  146. package/lib/karin/platform/douyin/videoQuality.js +222 -0
  147. package/lib/karin/platform/douyin/workType.js +182 -0
  148. package/lib/karin/platform/index.js +20 -0
  149. package/lib/karin/platform/kuaishou/comments.js +91 -0
  150. package/lib/karin/platform/kuaishou/getID.js +43 -0
  151. package/lib/karin/platform/kuaishou/getdata.js +41 -0
  152. package/lib/karin/platform/kuaishou/index.js +20 -0
  153. package/lib/karin/platform/kuaishou/kuaishou.js +122 -0
  154. package/lib/karin/platform/xiaohongshu/comments.js +162 -0
  155. package/lib/karin/platform/xiaohongshu/getID.js +129 -0
  156. package/lib/karin/platform/xiaohongshu/index.js +18 -0
  157. package/lib/karin/platform/xiaohongshu/xiaohongshu.js +643 -0
  158. package/lib/karin/root.js +73 -0
  159. package/lib/karin/setup.js +99 -0
  160. package/lib/karin/types/config/amagi.js +2 -0
  161. package/lib/karin/types/config/app.js +2 -0
  162. package/lib/karin/types/config/bilibili.js +2 -0
  163. package/lib/karin/types/config/cookies.js +2 -0
  164. package/lib/karin/types/config/douyin.js +2 -0
  165. package/lib/karin/types/config/index.js +2 -0
  166. package/lib/karin/types/config/kuaishou.js +2 -0
  167. package/lib/karin/types/config/pushlist.js +2 -0
  168. package/lib/karin/types/config/request.js +2 -0
  169. package/lib/karin/types/config/upload.js +2 -0
  170. package/lib/karin/types/config/xiaohongshu.js +2 -0
  171. package/lib/karin/types/datatypes.js +2 -0
  172. package/lib/karin/types/index.js +18 -0
  173. package/lib/karin/types/netrorks/NetworksConfigType.js +2 -0
  174. package/lib/karin/types/netrorks/index.js +17 -0
  175. package/lib/karin/web.config.js +49 -0
  176. package/lib/ktr/registry.js +82 -0
  177. package/lib/ktr/template/_preview/components/PreviewInfoCard.js +10 -0
  178. package/lib/ktr/template/_preview/components/PreviewLayout.js +10 -0
  179. package/lib/ktr/template/_preview/components/PreviewVideoCard.js +8 -0
  180. package/lib/ktr/template/_preview/render.js +142 -0
  181. package/lib/ktr/template/_preview/types.js +2 -0
  182. package/lib/ktr/template/_preview/utils/status.js +31 -0
  183. package/lib/ktr/template/_preview/utils/time.js +12 -0
  184. package/lib/ktr/template/bilibili/bangumi/components/bangumi.js +127 -0
  185. package/lib/ktr/template/bilibili/bangumi/components/types.js +2 -0
  186. package/lib/ktr/template/bilibili/bangumi/index.js +12 -0
  187. package/lib/ktr/template/bilibili/comment/components/Comment.js +193 -0
  188. package/lib/ktr/template/bilibili/comment/components/types.js +2 -0
  189. package/lib/ktr/template/bilibili/comment/index.js +10 -0
  190. package/lib/ktr/template/bilibili/components/Icons.js +66 -0
  191. package/lib/ktr/template/bilibili/components/shared.js +93 -0
  192. package/lib/ktr/template/bilibili/components/types.js +2 -0
  193. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_ARTICLE/components/DYNAMIC_TYPE_ARTICLE.js +66 -0
  194. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_ARTICLE/components/types.js +2 -0
  195. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_ARTICLE/index.js +10 -0
  196. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_AV/components/DYNAMIC_TYPE_AV.js +87 -0
  197. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_AV/components/types.js +2 -0
  198. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_AV/index.js +10 -0
  199. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_DRAW/components/DYNAMIC_TYPE_DRAW.js +93 -0
  200. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_DRAW/components/types.js +2 -0
  201. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_DRAW/index.js +10 -0
  202. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_FORWARD/components/DYNAMIC_TYPE_FORWARD.js +132 -0
  203. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_FORWARD/components/types.js +2 -0
  204. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_FORWARD/index.js +10 -0
  205. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_LIVE_RCMD/components/DYNAMIC_TYPE_LIVE_RCMD.js +84 -0
  206. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_LIVE_RCMD/components/types.js +2 -0
  207. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_LIVE_RCMD/index.js +10 -0
  208. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_WORD/components/DYNAMIC_TYPE_WORD.js +38 -0
  209. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_WORD/components/types.js +2 -0
  210. package/lib/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_WORD/index.js +10 -0
  211. package/lib/ktr/template/bilibili/dynamic/components/AdditionalCard.js +59 -0
  212. package/lib/ktr/template/bilibili/dynamic/components/CommonComponents.js +30 -0
  213. package/lib/ktr/template/bilibili/dynamic/types.js +2 -0
  214. package/lib/ktr/template/bilibili/qrcodeImg/components/qrcodeImg.js +48 -0
  215. package/lib/ktr/template/bilibili/qrcodeImg/components/types.js +3 -0
  216. package/lib/ktr/template/bilibili/qrcodeImg/index.js +10 -0
  217. package/lib/ktr/template/bilibili/userlist/components/UserList.js +53 -0
  218. package/lib/ktr/template/bilibili/userlist/components/types.js +3 -0
  219. package/lib/ktr/template/bilibili/userlist/index.js +13 -0
  220. package/lib/ktr/template/bilibili/videoInfo/components/types.js +2 -0
  221. package/lib/ktr/template/bilibili/videoInfo/components/videoInfo.js +62 -0
  222. package/lib/ktr/template/bilibili/videoInfo/index.js +10 -0
  223. package/lib/ktr/template/components/AmbientCover.js +36 -0
  224. package/lib/ktr/template/components/DefaultLayout.js +33 -0
  225. package/lib/ktr/template/components/GlowImage.js +276 -0
  226. package/lib/ktr/template/components/QRCodeWithAvatar.js +34 -0
  227. package/lib/ktr/template/components/RolldownLogo.js +6 -0
  228. package/lib/ktr/template/components/ViteLogo.js +6 -0
  229. package/lib/ktr/template/components/iconRegistry.js +173 -0
  230. package/lib/ktr/template/douyin/article-work/components/ArticleWork.js +99 -0
  231. package/lib/ktr/template/douyin/article-work/components/types.js +3 -0
  232. package/lib/ktr/template/douyin/article-work/index.js +10 -0
  233. package/lib/ktr/template/douyin/comment/components/Comment.js +189 -0
  234. package/lib/ktr/template/douyin/comment/components/types.js +2 -0
  235. package/lib/ktr/template/douyin/comment/index.js +10 -0
  236. package/lib/ktr/template/douyin/components/Icons.js +29 -0
  237. package/lib/ktr/template/douyin/components/types.js +3 -0
  238. package/lib/ktr/template/douyin/dynamic/components/Dynamic.js +90 -0
  239. package/lib/ktr/template/douyin/dynamic/components/types.js +3 -0
  240. package/lib/ktr/template/douyin/dynamic/index.js +10 -0
  241. package/lib/ktr/template/douyin/favorite-list/components/FavoriteList.js +30 -0
  242. package/lib/ktr/template/douyin/favorite-list/components/types.js +3 -0
  243. package/lib/ktr/template/douyin/favorite-list/index.js +10 -0
  244. package/lib/ktr/template/douyin/image-work/components/ImageWork.js +136 -0
  245. package/lib/ktr/template/douyin/image-work/components/types.js +2 -0
  246. package/lib/ktr/template/douyin/image-work/index.js +10 -0
  247. package/lib/ktr/template/douyin/live/components/Live.js +51 -0
  248. package/lib/ktr/template/douyin/live/components/types.js +3 -0
  249. package/lib/ktr/template/douyin/live/index.js +10 -0
  250. package/lib/ktr/template/douyin/musicinfo/components/MusicInfo.js +60 -0
  251. package/lib/ktr/template/douyin/musicinfo/components/types.js +3 -0
  252. package/lib/ktr/template/douyin/musicinfo/index.js +10 -0
  253. package/lib/ktr/template/douyin/qrcodeImg/components/qrcodeImg.js +39 -0
  254. package/lib/ktr/template/douyin/qrcodeImg/components/types.js +3 -0
  255. package/lib/ktr/template/douyin/qrcodeImg/index.js +9 -0
  256. package/lib/ktr/template/douyin/recommend-list/components/RecommendList.js +30 -0
  257. package/lib/ktr/template/douyin/recommend-list/components/types.js +3 -0
  258. package/lib/ktr/template/douyin/recommend-list/index.js +10 -0
  259. package/lib/ktr/template/douyin/user_profile/components/UserVideoList.js +54 -0
  260. package/lib/ktr/template/douyin/user_profile/components/types.js +3 -0
  261. package/lib/ktr/template/douyin/user_profile/index.js +9 -0
  262. package/lib/ktr/template/douyin/userlist/components/UserList.js +50 -0
  263. package/lib/ktr/template/douyin/userlist/components/types.js +3 -0
  264. package/lib/ktr/template/douyin/userlist/index.js +13 -0
  265. package/lib/ktr/template/douyin/video-work/components/VideoWork.js +127 -0
  266. package/lib/ktr/template/douyin/video-work/components/types.js +2 -0
  267. package/lib/ktr/template/douyin/video-work/index.js +10 -0
  268. package/lib/ktr/template/kuaishou/comment/components/Comment.js +88 -0
  269. package/lib/ktr/template/kuaishou/comment/components/types.js +2 -0
  270. package/lib/ktr/template/kuaishou/comment/index.js +10 -0
  271. package/lib/ktr/template/other/changelog/components/changelog.js +117 -0
  272. package/lib/ktr/template/other/changelog/components/types.js +3 -0
  273. package/lib/ktr/template/other/changelog/index.js +9 -0
  274. package/lib/ktr/template/other/handlerError/components/errorTitles.js +227 -0
  275. package/lib/ktr/template/other/handlerError/components/handlerError.js +392 -0
  276. package/lib/ktr/template/other/handlerError/components/stackHighlight.js +109 -0
  277. package/lib/ktr/template/other/handlerError/components/types.js +2 -0
  278. package/lib/ktr/template/other/handlerError/index.js +9 -0
  279. package/lib/ktr/template/other/help/components/Help.js +79 -0
  280. package/lib/ktr/template/other/help/components/types.js +3 -0
  281. package/lib/ktr/template/other/help/index.js +12 -0
  282. package/lib/ktr/template/other/live-photo-tip/components/LivePhotoTip.js +80 -0
  283. package/lib/ktr/template/other/live-photo-tip/components/types.js +3 -0
  284. package/lib/ktr/template/other/live-photo-tip/index.js +9 -0
  285. package/lib/ktr/template/other/qrlogin/components/qrlogin.js +58 -0
  286. package/lib/ktr/template/other/qrlogin/components/types.js +3 -0
  287. package/lib/ktr/template/other/qrlogin/index.js +9 -0
  288. package/lib/ktr/template/other/runtime/components/runtime.js +101 -0
  289. package/lib/ktr/template/other/runtime/components/types.js +3 -0
  290. package/lib/ktr/template/other/runtime/index.js +9 -0
  291. package/lib/ktr/template/other/version_warning/components/VersionWarning.js +38 -0
  292. package/lib/ktr/template/other/version_warning/components/types.js +3 -0
  293. package/lib/ktr/template/other/version_warning/index.js +9 -0
  294. package/lib/ktr/template/statistics/components/BoxplotGuide.js +17 -0
  295. package/lib/ktr/template/statistics/components/ChartCard.js +15 -0
  296. package/lib/ktr/template/statistics/components/KpiCard.js +14 -0
  297. package/lib/ktr/template/statistics/components/PlatformTable.js +20 -0
  298. package/lib/ktr/template/statistics/components/RankList.js +61 -0
  299. package/lib/ktr/template/statistics/components/SSRChart.js +22 -0
  300. package/lib/ktr/template/statistics/components/chartPresets.js +630 -0
  301. package/lib/ktr/template/statistics/components/chartTheme.js +226 -0
  302. package/lib/ktr/template/statistics/components/format.js +38 -0
  303. package/lib/ktr/template/statistics/components/types.js +9 -0
  304. package/lib/ktr/template/statistics/global/components/GlobalStatistics.js +246 -0
  305. package/lib/ktr/template/statistics/global/components/types.js +3 -0
  306. package/lib/ktr/template/statistics/global/index.js +9 -0
  307. package/lib/ktr/template/statistics/group/components/GroupStatistics.js +181 -0
  308. package/lib/ktr/template/statistics/group/components/types.js +3 -0
  309. package/lib/ktr/template/statistics/group/index.js +9 -0
  310. package/lib/ktr/template/types/ctx.js +2 -0
  311. package/lib/ktr/template/xiaohongshu/comment/components/Comment.js +99 -0
  312. package/lib/ktr/template/xiaohongshu/comment/components/types.js +3 -0
  313. package/lib/ktr/template/xiaohongshu/comment/index.js +9 -0
  314. package/lib/ktr/template/xiaohongshu/noteInfo/components/noteInfo.js +93 -0
  315. package/lib/ktr/template/xiaohongshu/noteInfo/components/types.js +2 -0
  316. package/lib/ktr/template/xiaohongshu/noteInfo/index.js +9 -0
  317. package/lib/ktr/utils/QRCodeAvatar.js +99 -0
  318. package/lib/ktr/utils/QRcode.js +56 -0
  319. package/lib/ktr/utils/avatarProxy.js +45 -0
  320. package/lib/ktr/utils/cn.js +11 -0
  321. package/lib/ktr/utils/theme.js +12 -0
  322. package/lib/qqFields.json +75 -0
  323. package/lib/qqOptions.js +44 -0
  324. package/lib/richtext/index.js +25 -0
  325. package/lib/richtext/parse/index.js +232 -0
  326. package/lib/richtext/react/cn.js +11 -0
  327. package/lib/richtext/react/index.js +221 -0
  328. package/lib/richtext/types.js +2 -0
  329. package/lib/schema.js +352 -0
  330. package/lib/webui.js +341 -0
  331. package/package.json +88 -0
  332. package/resources/image/bilibili/RICH_TEXT_NODE_TYPE/RICH_TEXT_NODE_TYPE_BV.svg +1 -0
  333. package/resources/image/bilibili/RICH_TEXT_NODE_TYPE/RICH_TEXT_NODE_TYPE_GOODS.svg +1 -0
  334. package/resources/image/bilibili/RICH_TEXT_NODE_TYPE/RICH_TEXT_NODE_TYPE_LOTTERY.svg +1 -0
  335. package/resources/image/bilibili/RICH_TEXT_NODE_TYPE/RICH_TEXT_NODE_TYPE_VIEW_PICTURE.svg +1 -0
  336. package/resources/image/bilibili/RICH_TEXT_NODE_TYPE/RICH_TEXT_NODE_TYPE_VOTE.svg +1 -0
  337. package/resources/image/bilibili/RICH_TEXT_NODE_TYPE/RICH_TEXT_NODE_TYPE_WEB.svg +1 -0
  338. package/resources/image/bilibili/bilibili-dark.png +0 -0
  339. package/resources/image/bilibili/bilibili-light.png +0 -0
  340. package/resources/image/bilibili/bilibili.png +0 -0
  341. package/resources/image/bilibili/id-dark.svg +1 -0
  342. package/resources/image/bilibili/id-light.svg +1 -0
  343. package/resources/image/bilibili/level/lv0.svg +1 -0
  344. package/resources/image/bilibili/level/lv1.svg +1 -0
  345. package/resources/image/bilibili/level/lv2.svg +1 -0
  346. package/resources/image/bilibili/level/lv3.svg +1 -0
  347. package/resources/image/bilibili/level/lv4.svg +1 -0
  348. package/resources/image/bilibili/level/lv5.svg +1 -0
  349. package/resources/image/bilibili/level/lv6.svg +1 -0
  350. package/resources/image/bilibili/level/lv7.svg +1 -0
  351. package/resources/image/bilibili/like-dark.svg +6 -0
  352. package/resources/image/bilibili/like-light.svg +6 -0
  353. package/resources/image/bilibili/play.svg +28 -0
  354. package/resources/image/bilibili/res-local1.png +0 -0
  355. package/resources/image/bilibili/up_pb.svg +1 -0
  356. package/resources/image/bilibili//347/233/264/346/222/255/344/270/255.png +0 -0
  357. package/resources/image/douyin/douyin.png +0 -0
  358. package/resources/image/douyin/dylogo-dark.svg +23 -0
  359. package/resources/image/douyin/dylogo-light.svg +38 -0
  360. package/resources/image/douyin/search-dark.svg +1 -0
  361. package/resources/image/douyin/search-light.svg +3 -0
  362. package/resources/image/douyin//346/212/226/351/237/263-/347/233/264/346/222/255/344/270/255.png +0 -0
  363. package/resources/image/frame-logo.png +0 -0
  364. package/resources/image/kuaishou/logo.png +0 -0
  365. package/resources/image/other/handlerError/Milky.png +0 -0
  366. package/resources/image/other/handlerError/chronocat.svg +43 -0
  367. package/resources/image/other/handlerError/conwechat.webp +0 -0
  368. package/resources/image/other/handlerError/gocq-http.webp +0 -0
  369. package/resources/image/other/handlerError/lagrange.webp +0 -0
  370. package/resources/image/other/handlerError/llonebot.webp +0 -0
  371. package/resources/image/other/handlerError/napcat.webp +0 -0
  372. package/resources/image/other/handlerError/onebot.png +0 -0
  373. package/resources/image/other/handlerError/satori.png +0 -0
  374. package/resources/image/xiaohongshu/logo.png +0 -0
  375. package/resources/template/style.css +23708 -0
  376. package/resources/vite.svg +130 -0
  377. package/scripts/build.mjs +129 -0
  378. package/scripts/check-schema.cjs +55 -0
  379. package/scripts/deploy.mjs +78 -0
  380. package/scripts/make-demo-placeholders.mjs +112 -0
  381. package/scripts/patch-deps.mjs +46 -0
  382. package/scripts/patch-webui.mjs +112 -0
  383. package/scripts/smoke-commands.cjs +39 -0
  384. package/scripts/smoke-config.cjs +122 -0
  385. package/scripts/smoke-douyin.cjs +170 -0
  386. package/scripts/smoke-koishi-commands.cjs +210 -0
  387. package/scripts/smoke-login.cjs +110 -0
  388. package/scripts/smoke-parse.cjs +54 -0
  389. package/scripts/smoke-push-mock.cjs +114 -0
  390. package/scripts/smoke-push.cjs +104 -0
  391. package/scripts/smoke-qq.cjs +147 -0
  392. package/scripts/smoke-qqcard.cjs +108 -0
  393. package/scripts/smoke-qqpanel.cjs +205 -0
  394. package/scripts/smoke-render.cjs +106 -0
  395. package/scripts/smoke-server.cjs +94 -0
  396. package/src/compat/axios.ts +5 -0
  397. package/src/compat/cron.ts +86 -0
  398. package/src/compat/esm.ts +13 -0
  399. package/src/compat/express.ts +5 -0
  400. package/src/compat/heroui.tsx +53 -0
  401. package/src/compat/lodash.ts +32 -0
  402. package/src/compat/logger.ts +121 -0
  403. package/src/compat/node-karin.ts +1064 -0
  404. package/src/compat/phosphor-icons.tsx +25 -0
  405. package/src/compat/qqcard.ts +251 -0
  406. package/src/compat/root.ts +44 -0
  407. package/src/compat/runtime.ts +120 -0
  408. package/src/compat/segment.ts +161 -0
  409. package/src/compat/sqlite3.ts +123 -0
  410. package/src/compat/start.ts +3 -0
  411. package/src/compat/syncConfig.ts +64 -0
  412. package/src/compat/template-react.ts +54 -0
  413. package/src/compat/text.ts +58 -0
  414. package/src/compat/yaml.ts +6 -0
  415. package/src/configBridge.ts +94 -0
  416. package/src/index.ts +769 -0
  417. package/src/karin/app.ts +1 -0
  418. package/src/karin/apps/__ready.ts +14 -0
  419. package/src/karin/apps/admin.ts +127 -0
  420. package/src/karin/apps/help.ts +228 -0
  421. package/src/karin/apps/push.ts +327 -0
  422. package/src/karin/apps/qrlogin.ts +160 -0
  423. package/src/karin/apps/statistics.ts +203 -0
  424. package/src/karin/apps/testPush.ts +226 -0
  425. package/src/karin/apps/tools.ts +510 -0
  426. package/src/karin/apps/update.ts +239 -0
  427. package/src/karin/index.ts +9 -0
  428. package/src/karin/module/db/bilibili.ts +1089 -0
  429. package/src/karin/module/db/douyin.ts +1218 -0
  430. package/src/karin/module/db/index.ts +159 -0
  431. package/src/karin/module/db/migration.ts +249 -0
  432. package/src/karin/module/db/statistics.ts +817 -0
  433. package/src/karin/module/index.ts +37 -0
  434. package/src/karin/module/server/constants/routes.ts +53 -0
  435. package/src/karin/module/server/controllers/bots.ts +289 -0
  436. package/src/karin/module/server/controllers/config.ts +85 -0
  437. package/src/karin/module/server/controllers/video.ts +212 -0
  438. package/src/karin/module/server/index.ts +11 -0
  439. package/src/karin/module/server/middlewares/auth.ts +147 -0
  440. package/src/karin/module/server/routes/amagi.ts +57 -0
  441. package/src/karin/module/server/routes/api.ts +42 -0
  442. package/src/karin/module/server/routes/index.ts +68 -0
  443. package/src/karin/module/server/routes/ssr.ts +14 -0
  444. package/src/karin/module/server/routes/static.ts +43 -0
  445. package/src/karin/module/utils/Base.ts +497 -0
  446. package/src/karin/module/utils/CardParser.ts +503 -0
  447. package/src/karin/module/utils/Common.ts +448 -0
  448. package/src/karin/module/utils/Config.ts +443 -0
  449. package/src/karin/module/utils/EmojiReaction.ts +268 -0
  450. package/src/karin/module/utils/ErrorHandler/handler.ts +124 -0
  451. package/src/karin/module/utils/ErrorHandler/index.ts +48 -0
  452. package/src/karin/module/utils/ErrorHandler/render.ts +180 -0
  453. package/src/karin/module/utils/ErrorHandler/sender.ts +192 -0
  454. package/src/karin/module/utils/ErrorHandler/strategy.ts +41 -0
  455. package/src/karin/module/utils/ErrorHandler/types.ts +122 -0
  456. package/src/karin/module/utils/ErrorHandler/utils.ts +108 -0
  457. package/src/karin/module/utils/FFmpeg.ts +357 -0
  458. package/src/karin/module/utils/ImageHelper.ts +90 -0
  459. package/src/karin/module/utils/ImageSlice.ts +383 -0
  460. package/src/karin/module/utils/MotionPhoto.ts +297 -0
  461. package/src/karin/module/utils/Network/Downloader.ts +481 -0
  462. package/src/karin/module/utils/Network/ImageDownloader.ts +291 -0
  463. package/src/karin/module/utils/Network/Network.ts +344 -0
  464. package/src/karin/module/utils/Network/ThrottleStream.ts +76 -0
  465. package/src/karin/module/utils/Network/constants.ts +135 -0
  466. package/src/karin/module/utils/Network/helpers.ts +183 -0
  467. package/src/karin/module/utils/Network/index.ts +28 -0
  468. package/src/karin/module/utils/Network/types.ts +46 -0
  469. package/src/karin/module/utils/Networks.ts +20 -0
  470. package/src/karin/module/utils/ParseLock.ts +33 -0
  471. package/src/karin/module/utils/ParseOverride.ts +128 -0
  472. package/src/karin/module/utils/QqCardResolve.ts +116 -0
  473. package/src/karin/module/utils/QqPanel.ts +880 -0
  474. package/src/karin/module/utils/Render/coverTheme.ts +294 -0
  475. package/src/karin/module/utils/Render/index.ts +574 -0
  476. package/src/karin/module/utils/amagiClient.ts +368 -0
  477. package/src/karin/module/utils/avatar.ts +220 -0
  478. package/src/karin/module/utils/bot.ts +115 -0
  479. package/src/karin/module/utils/build-metadata.ts +60 -0
  480. package/src/karin/module/utils/changelog.ts +175 -0
  481. package/src/karin/module/utils/index.ts +10 -0
  482. package/src/karin/module/utils/loginSession.ts +291 -0
  483. package/src/karin/module/utils/parseTip.ts +59 -0
  484. package/src/karin/module/utils/runtime-report.ts +142 -0
  485. package/src/karin/module/utils/semver.ts +60 -0
  486. package/src/karin/module/utils/statisticsAggregate.ts +507 -0
  487. package/src/karin/platform/bilibili/bilibili.ts +2004 -0
  488. package/src/karin/platform/bilibili/comments.ts +397 -0
  489. package/src/karin/platform/bilibili/danmaku.ts +653 -0
  490. package/src/karin/platform/bilibili/dynamic-text.ts +926 -0
  491. package/src/karin/platform/bilibili/genParams.ts +30 -0
  492. package/src/karin/platform/bilibili/getID.ts +163 -0
  493. package/src/karin/platform/bilibili/index.ts +8 -0
  494. package/src/karin/platform/bilibili/live-status.ts +36 -0
  495. package/src/karin/platform/bilibili/login.ts +130 -0
  496. package/src/karin/platform/bilibili/push.ts +1615 -0
  497. package/src/karin/platform/bilibili/riskControl.ts +114 -0
  498. package/src/karin/platform/bilibili/search.ts +305 -0
  499. package/src/karin/platform/common/danmaku-types.ts +18 -0
  500. package/src/karin/platform/douyin/comments.ts +404 -0
  501. package/src/karin/platform/douyin/danmaku.ts +1187 -0
  502. package/src/karin/platform/douyin/douyin.ts +1244 -0
  503. package/src/karin/platform/douyin/getID.ts +101 -0
  504. package/src/karin/platform/douyin/index.ts +8 -0
  505. package/src/karin/platform/douyin/login.ts +251 -0
  506. package/src/karin/platform/douyin/push/favorite.ts +97 -0
  507. package/src/karin/platform/douyin/push/index.ts +5 -0
  508. package/src/karin/platform/douyin/push/live.ts +86 -0
  509. package/src/karin/platform/douyin/push/post.ts +75 -0
  510. package/src/karin/platform/douyin/push/recommend.ts +96 -0
  511. package/src/karin/platform/douyin/push/render.ts +768 -0
  512. package/src/karin/platform/douyin/push/types.ts +41 -0
  513. package/src/karin/platform/douyin/push.ts +1241 -0
  514. package/src/karin/platform/douyin/types.ts +151 -0
  515. package/src/karin/platform/douyin/videoQuality.ts +234 -0
  516. package/src/karin/platform/douyin/workType.ts +238 -0
  517. package/src/karin/platform/index.ts +4 -0
  518. package/src/karin/platform/kuaishou/comments.ts +114 -0
  519. package/src/karin/platform/kuaishou/getID.ts +48 -0
  520. package/src/karin/platform/kuaishou/getdata.ts +78 -0
  521. package/src/karin/platform/kuaishou/index.ts +4 -0
  522. package/src/karin/platform/kuaishou/kuaishou.ts +130 -0
  523. package/src/karin/platform/xiaohongshu/comments.ts +227 -0
  524. package/src/karin/platform/xiaohongshu/getID.ts +127 -0
  525. package/src/karin/platform/xiaohongshu/index.ts +2 -0
  526. package/src/karin/platform/xiaohongshu/xiaohongshu.ts +733 -0
  527. package/src/karin/root.ts +78 -0
  528. package/src/karin/setup.ts +77 -0
  529. package/src/karin/types/config/amagi.ts +46 -0
  530. package/src/karin/types/config/app.ts +129 -0
  531. package/src/karin/types/config/bilibili.ts +121 -0
  532. package/src/karin/types/config/cookies.ts +11 -0
  533. package/src/karin/types/config/douyin.ts +93 -0
  534. package/src/karin/types/config/index.ts +41 -0
  535. package/src/karin/types/config/kuaishou.ts +10 -0
  536. package/src/karin/types/config/pushlist.ts +55 -0
  537. package/src/karin/types/config/request.ts +27 -0
  538. package/src/karin/types/config/upload.ts +49 -0
  539. package/src/karin/types/config/xiaohongshu.ts +24 -0
  540. package/src/karin/types/datatypes.ts +42 -0
  541. package/src/karin/types/index.ts +4 -0
  542. package/src/karin/types/netrorks/NetworksConfigType.ts +61 -0
  543. package/src/karin/types/netrorks/index.ts +1 -0
  544. package/src/karin/web.config.ts +48 -0
  545. package/src/ktr/registry.ts +55 -0
  546. package/src/ktr/template/_preview/components/PreviewInfoCard.tsx +33 -0
  547. package/src/ktr/template/_preview/components/PreviewLayout.tsx +65 -0
  548. package/src/ktr/template/_preview/components/PreviewVideoCard.tsx +22 -0
  549. package/src/ktr/template/_preview/render.ts +158 -0
  550. package/src/ktr/template/_preview/types.ts +15 -0
  551. package/src/ktr/template/_preview/utils/status.ts +29 -0
  552. package/src/ktr/template/_preview/utils/time.ts +8 -0
  553. package/src/ktr/template/bilibili/bangumi/components/bangumi.tsx +462 -0
  554. package/src/ktr/template/bilibili/bangumi/components/types.ts +36 -0
  555. package/src/ktr/template/bilibili/bangumi/index.tsx +9 -0
  556. package/src/ktr/template/bilibili/comment/components/Comment.tsx +657 -0
  557. package/src/ktr/template/bilibili/comment/components/types.ts +26 -0
  558. package/src/ktr/template/bilibili/comment/index.tsx +11 -0
  559. package/src/ktr/template/bilibili/components/Icons.tsx +209 -0
  560. package/src/ktr/template/bilibili/components/shared.tsx +162 -0
  561. package/src/ktr/template/bilibili/components/types.ts +388 -0
  562. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_ARTICLE/components/DYNAMIC_TYPE_ARTICLE.tsx +251 -0
  563. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_ARTICLE/components/types.ts +67 -0
  564. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_ARTICLE/index.tsx +12 -0
  565. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_AV/components/DYNAMIC_TYPE_AV.tsx +238 -0
  566. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_AV/components/types.ts +39 -0
  567. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_AV/index.tsx +12 -0
  568. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_DRAW/components/DYNAMIC_TYPE_DRAW.tsx +205 -0
  569. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_DRAW/components/types.ts +20 -0
  570. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_DRAW/index.tsx +11 -0
  571. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_FORWARD/components/DYNAMIC_TYPE_FORWARD.tsx +348 -0
  572. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_FORWARD/components/types.ts +16 -0
  573. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_FORWARD/index.tsx +12 -0
  574. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_LIVE_RCMD/components/DYNAMIC_TYPE_LIVE_RCMD.tsx +264 -0
  575. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_LIVE_RCMD/components/types.ts +32 -0
  576. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_LIVE_RCMD/index.tsx +12 -0
  577. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_WORD/components/DYNAMIC_TYPE_WORD.tsx +68 -0
  578. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_WORD/components/types.ts +14 -0
  579. package/src/ktr/template/bilibili/dynamic/DYNAMIC_TYPE_WORD/index.tsx +12 -0
  580. package/src/ktr/template/bilibili/dynamic/components/AdditionalCard.tsx +165 -0
  581. package/src/ktr/template/bilibili/dynamic/components/CommonComponents.tsx +142 -0
  582. package/src/ktr/template/bilibili/dynamic/types.ts +382 -0
  583. package/src/ktr/template/bilibili/qrcodeImg/components/qrcodeImg.tsx +179 -0
  584. package/src/ktr/template/bilibili/qrcodeImg/components/types.ts +9 -0
  585. package/src/ktr/template/bilibili/qrcodeImg/index.tsx +12 -0
  586. package/src/ktr/template/bilibili/userlist/components/UserList.tsx +246 -0
  587. package/src/ktr/template/bilibili/userlist/components/types.ts +35 -0
  588. package/src/ktr/template/bilibili/userlist/index.tsx +11 -0
  589. package/src/ktr/template/bilibili/videoInfo/components/types.ts +28 -0
  590. package/src/ktr/template/bilibili/videoInfo/components/videoInfo.tsx +217 -0
  591. package/src/ktr/template/bilibili/videoInfo/index.tsx +12 -0
  592. package/src/ktr/template/components/AmbientCover.tsx +50 -0
  593. package/src/ktr/template/components/DefaultLayout.tsx +166 -0
  594. package/src/ktr/template/components/GlowImage.tsx +572 -0
  595. package/src/ktr/template/components/QRCodeWithAvatar.tsx +52 -0
  596. package/src/ktr/template/components/RolldownLogo.tsx +110 -0
  597. package/src/ktr/template/components/ViteLogo.tsx +134 -0
  598. package/src/ktr/template/components/iconRegistry.ts +294 -0
  599. package/src/ktr/template/douyin/article-work/components/ArticleWork.tsx +301 -0
  600. package/src/ktr/template/douyin/article-work/components/types.ts +53 -0
  601. package/src/ktr/template/douyin/article-work/index.tsx +12 -0
  602. package/src/ktr/template/douyin/comment/components/Comment.tsx +612 -0
  603. package/src/ktr/template/douyin/comment/components/types.ts +85 -0
  604. package/src/ktr/template/douyin/comment/index.tsx +11 -0
  605. package/src/ktr/template/douyin/components/Icons.tsx +75 -0
  606. package/src/ktr/template/douyin/components/types.ts +83 -0
  607. package/src/ktr/template/douyin/dynamic/components/Dynamic.tsx +283 -0
  608. package/src/ktr/template/douyin/dynamic/components/types.ts +46 -0
  609. package/src/ktr/template/douyin/dynamic/index.tsx +11 -0
  610. package/src/ktr/template/douyin/favorite-list/components/FavoriteList.tsx +201 -0
  611. package/src/ktr/template/douyin/favorite-list/components/types.ts +38 -0
  612. package/src/ktr/template/douyin/favorite-list/index.tsx +12 -0
  613. package/src/ktr/template/douyin/image-work/components/ImageWork.tsx +437 -0
  614. package/src/ktr/template/douyin/image-work/components/types.ts +78 -0
  615. package/src/ktr/template/douyin/image-work/index.tsx +11 -0
  616. package/src/ktr/template/douyin/live/components/Live.tsx +229 -0
  617. package/src/ktr/template/douyin/live/components/types.ts +47 -0
  618. package/src/ktr/template/douyin/live/index.tsx +11 -0
  619. package/src/ktr/template/douyin/musicinfo/components/MusicInfo.tsx +187 -0
  620. package/src/ktr/template/douyin/musicinfo/components/types.ts +31 -0
  621. package/src/ktr/template/douyin/musicinfo/index.tsx +11 -0
  622. package/src/ktr/template/douyin/qrcodeImg/components/qrcodeImg.tsx +170 -0
  623. package/src/ktr/template/douyin/qrcodeImg/components/types.ts +9 -0
  624. package/src/ktr/template/douyin/qrcodeImg/index.tsx +9 -0
  625. package/src/ktr/template/douyin/recommend-list/components/RecommendList.tsx +201 -0
  626. package/src/ktr/template/douyin/recommend-list/components/types.ts +37 -0
  627. package/src/ktr/template/douyin/recommend-list/index.tsx +12 -0
  628. package/src/ktr/template/douyin/user_profile/components/UserVideoList.tsx +225 -0
  629. package/src/ktr/template/douyin/user_profile/components/types.ts +71 -0
  630. package/src/ktr/template/douyin/user_profile/index.tsx +9 -0
  631. package/src/ktr/template/douyin/userlist/components/UserList.tsx +229 -0
  632. package/src/ktr/template/douyin/userlist/components/types.ts +35 -0
  633. package/src/ktr/template/douyin/userlist/index.tsx +11 -0
  634. package/src/ktr/template/douyin/video-work/components/VideoWork.tsx +398 -0
  635. package/src/ktr/template/douyin/video-work/components/types.ts +80 -0
  636. package/src/ktr/template/douyin/video-work/index.tsx +11 -0
  637. package/src/ktr/template/font.css +6071 -0
  638. package/src/ktr/template/global.d.ts +69 -0
  639. package/src/ktr/template/kuaishou/comment/components/Comment.tsx +207 -0
  640. package/src/ktr/template/kuaishou/comment/components/types.ts +47 -0
  641. package/src/ktr/template/kuaishou/comment/index.tsx +11 -0
  642. package/src/ktr/template/other/changelog/components/changelog.tsx +411 -0
  643. package/src/ktr/template/other/changelog/components/types.ts +21 -0
  644. package/src/ktr/template/other/changelog/index.tsx +9 -0
  645. package/src/ktr/template/other/handlerError/components/errorTitles.ts +224 -0
  646. package/src/ktr/template/other/handlerError/components/handlerError.tsx +1076 -0
  647. package/src/ktr/template/other/handlerError/components/stackHighlight.ts +127 -0
  648. package/src/ktr/template/other/handlerError/components/types.ts +124 -0
  649. package/src/ktr/template/other/handlerError/index.tsx +9 -0
  650. package/src/ktr/template/other/help/components/Help.tsx +249 -0
  651. package/src/ktr/template/other/help/components/types.ts +47 -0
  652. package/src/ktr/template/other/help/index.tsx +9 -0
  653. package/src/ktr/template/other/live-photo-tip/components/LivePhotoTip.tsx +295 -0
  654. package/src/ktr/template/other/live-photo-tip/components/types.ts +8 -0
  655. package/src/ktr/template/other/live-photo-tip/index.tsx +9 -0
  656. package/src/ktr/template/other/qrlogin/components/qrlogin.tsx +295 -0
  657. package/src/ktr/template/other/qrlogin/components/types.ts +11 -0
  658. package/src/ktr/template/other/qrlogin/index.tsx +9 -0
  659. package/src/ktr/template/other/runtime/components/runtime.tsx +347 -0
  660. package/src/ktr/template/other/runtime/components/types.ts +75 -0
  661. package/src/ktr/template/other/runtime/index.tsx +9 -0
  662. package/src/ktr/template/other/version_warning/components/VersionWarning.tsx +392 -0
  663. package/src/ktr/template/other/version_warning/components/types.ts +8 -0
  664. package/src/ktr/template/other/version_warning/index.tsx +9 -0
  665. package/src/ktr/template/statistics/components/BoxplotGuide.tsx +57 -0
  666. package/src/ktr/template/statistics/components/ChartCard.tsx +40 -0
  667. package/src/ktr/template/statistics/components/KpiCard.tsx +39 -0
  668. package/src/ktr/template/statistics/components/PlatformTable.tsx +83 -0
  669. package/src/ktr/template/statistics/components/RankList.tsx +127 -0
  670. package/src/ktr/template/statistics/components/SSRChart.tsx +41 -0
  671. package/src/ktr/template/statistics/components/chartPresets.ts +700 -0
  672. package/src/ktr/template/statistics/components/chartTheme.ts +234 -0
  673. package/src/ktr/template/statistics/components/format.ts +33 -0
  674. package/src/ktr/template/statistics/components/types.ts +92 -0
  675. package/src/ktr/template/statistics/global/components/GlobalStatistics.tsx +597 -0
  676. package/src/ktr/template/statistics/global/components/types.ts +138 -0
  677. package/src/ktr/template/statistics/global/index.tsx +9 -0
  678. package/src/ktr/template/statistics/group/components/GroupStatistics.tsx +468 -0
  679. package/src/ktr/template/statistics/group/components/types.ts +113 -0
  680. package/src/ktr/template/statistics/group/index.tsx +9 -0
  681. package/src/ktr/template/style.css +65 -0
  682. package/src/ktr/template/types/ctx.ts +42 -0
  683. package/src/ktr/template/xiaohongshu/comment/components/Comment.tsx +264 -0
  684. package/src/ktr/template/xiaohongshu/comment/components/types.ts +119 -0
  685. package/src/ktr/template/xiaohongshu/comment/index.tsx +9 -0
  686. package/src/ktr/template/xiaohongshu/noteInfo/components/noteInfo.tsx +271 -0
  687. package/src/ktr/template/xiaohongshu/noteInfo/components/types.ts +66 -0
  688. package/src/ktr/template/xiaohongshu/noteInfo/index.tsx +9 -0
  689. package/src/ktr/utils/QRCodeAvatar.ts +102 -0
  690. package/src/ktr/utils/QRcode.ts +65 -0
  691. package/src/ktr/utils/avatarProxy.ts +42 -0
  692. package/src/ktr/utils/cn.ts +6 -0
  693. package/src/ktr/utils/theme.ts +10 -0
  694. package/src/qqFields.json +75 -0
  695. package/src/qqOptions.ts +64 -0
  696. package/src/richtext/index.ts +9 -0
  697. package/src/richtext/parse/index.ts +271 -0
  698. package/src/richtext/react/cn.ts +6 -0
  699. package/src/richtext/react/index.tsx +582 -0
  700. package/src/richtext/types.ts +320 -0
  701. package/src/schema.ts +372 -0
  702. package/src/webui.ts +352 -0
@@ -0,0 +1,582 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Render = exports.getImageMetadata = void 0;
7
+ exports.buildFallbackHtml = buildFallbackHtml;
8
+ exports.resolveFrameLogo = resolveFrameLogo;
9
+ exports.buildPosterContext = buildPosterContext;
10
+ exports.renderTemplateHtml = renderTemplateHtml;
11
+ /**
12
+ * 渲染模块(Koishi 移植版)。
13
+ *
14
+ * 上游链路:ktr(\`@karinjs/template-react\`)把 \`template/**\` 打成 SSR 外壳 → 出 HTML → Karin render 截图。
15
+ * Koishi 侧不引入 ktr 的构建管线(需要 vite/tailwind 打包),改为:
16
+ * 1. 直接用 **react-dom/server** 对上游模板组件做 SSR(模板只依赖 \`{ data, ctx }\` props);
17
+ * 2. 内联上游构建产物 \`resources/template/style.css\`(tailwind 编译结果,省掉 tailwind 构建);
18
+ * 3. 用 koishi-plugin-puppeteer 截图。
19
+ * 路由不在注册表里、或 SSR 失败时,回退到内置通用信息卡片,保证解析结果始终有图。
20
+ */
21
+ const node_fs_1 = __importDefault(require("node:fs"));
22
+ const node_path_1 = __importDefault(require("node:path"));
23
+ const node_url_1 = require("node:url");
24
+ const node_karin_1 = require("../../../../compat/node-karin.js");
25
+ const root_1 = require("../../../../compat/root.js");
26
+ const node_stream_1 = require("node:stream");
27
+ const react_1 = __importDefault(require("react"));
28
+ const server_1 = require("react-dom/server");
29
+ const esm_1 = require("../../../../compat/esm");
30
+ const registry_1 = require("../../../../ktr/registry");
31
+ const utils_1 = require("../../../module/utils");
32
+ const Config_1 = require("../../../module/utils/Config");
33
+ const coverTheme_1 = require("./coverTheme");
34
+ /* ------------------------------------------------------------------ *
35
+ * 样式
36
+ * ------------------------------------------------------------------ */
37
+ let cachedCss = null;
38
+ /** 读取并修正模板样式(上游产物里的字体指向 Karin 本地服务,换成相对路径,加载失败则回退系统字体) */
39
+ function loadTemplateCss() {
40
+ if (cachedCss !== null)
41
+ return cachedCss;
42
+ try {
43
+ const cssPath = node_path_1.default.resolve(utils_1.Root.pluginPath, 'resources', 'template', 'style.css');
44
+ const raw = node_fs_1.default.readFileSync(cssPath, 'utf8');
45
+ cachedCss = raw.replace(/url\("?http:\/\/localhost:\d+\/config\/commonResource\//g, 'url("./template-fonts/');
46
+ }
47
+ catch (error) {
48
+ node_karin_1.logger.debug('[Render] 读取模板样式失败,将使用无样式渲染: ' + String(error?.message ?? error));
49
+ cachedCss = '';
50
+ }
51
+ return cachedCss;
52
+ }
53
+ /* ------------------------------------------------------------------ *
54
+ * 兜底卡片
55
+ * ------------------------------------------------------------------ */
56
+ const escapeHtml = (input) => String(input ?? '')
57
+ .replace(/&/g, '&')
58
+ .replace(/</g, '&lt;')
59
+ .replace(/>/g, '&gt;')
60
+ .replace(/"/g, '&quot;');
61
+ /** 递归时不往里看的键(Koishi 的 ctx / 适配器实例等,读属性会触发「未注册」警告且毫无意义) */
62
+ const PICK_SKIP_KEYS = new Set([
63
+ 'ctx', 'app', 'root', 'scope', 'bot', 'session', 'event', 'logger', 'config',
64
+ '_events', '_eventsCount', 'adapter', 'http', 'internal', 'socket', 'parser',
65
+ 'target', 'parent', 'children', 'prototype', 'constructor'
66
+ ]);
67
+ /** 只递归纯对象与数组:类实例(ctx / Bot / Session…)一律不深入 */
68
+ const isPlainSource = (value) => {
69
+ if (Array.isArray(value))
70
+ return true;
71
+ if (!value || typeof value !== 'object')
72
+ return false;
73
+ const proto = Object.getPrototypeOf(value);
74
+ return proto === Object.prototype || proto === null;
75
+ };
76
+ const pickFirst = (source, keys, depth = 3, seen = new Set()) => {
77
+ if (!source || typeof source !== 'object' || depth < 0)
78
+ return undefined;
79
+ // 防环(对象互相引用时会无限递归)
80
+ if (seen.has(source))
81
+ return undefined;
82
+ seen.add(source);
83
+ for (const key of keys) {
84
+ if (PICK_SKIP_KEYS.has(key))
85
+ continue;
86
+ const value = source[key];
87
+ if (value !== undefined && value !== null && value !== '')
88
+ return value;
89
+ }
90
+ for (const [key, value] of Object.entries(source)) {
91
+ if (PICK_SKIP_KEYS.has(key))
92
+ continue;
93
+ if (isPlainSource(value)) {
94
+ const found = pickFirst(value, keys, depth - 1, seen);
95
+ if (found !== undefined)
96
+ return found;
97
+ }
98
+ }
99
+ return undefined;
100
+ };
101
+ const asText = (value) => {
102
+ if (value === undefined || value === null)
103
+ return '';
104
+ if (typeof value === 'string' || typeof value === 'number')
105
+ return String(value);
106
+ if (Array.isArray(value)) {
107
+ const parts = value.map((item) => (item && typeof item === 'object' ? item.text ?? item.desc ?? '' : item)).filter(Boolean);
108
+ return parts.join('');
109
+ }
110
+ return String(value.text ?? value.desc ?? value.title ?? '');
111
+ };
112
+ const formatCount = (value) => {
113
+ const num = Number(value);
114
+ if (!Number.isFinite(num))
115
+ return '';
116
+ if (num >= 100000000)
117
+ return (num / 100000000).toFixed(1) + '亿';
118
+ if (num >= 10000)
119
+ return (num / 10000).toFixed(1) + '万';
120
+ return String(num);
121
+ };
122
+ /** 从渲染数据里尽力提取通用卡片需要的字段 */
123
+ function extractCardData(data) {
124
+ const title = asText(pickFirst(data, ['title', 'desc', 'dynamicTitle', 'name']));
125
+ const author = asText(pickFirst(data, ['nickname', 'nick', 'author', 'name', 'uname']));
126
+ const avatar = asText(pickFirst(data, ['avatar', 'face', 'avatarUrl', 'head_url']));
127
+ const cover = asText(pickFirst(data, ['cover', 'coverUrl', 'originCover', 'pic', 'dynamicCover', 'image']));
128
+ const description = asText(pickFirst(data, ['desc', 'description', 'dynamicText', 'summary', 'content']));
129
+ const stats = [
130
+ ['点赞', pickFirst(data, ['digg_count', 'like', 'likes'])],
131
+ ['评论', pickFirst(data, ['comment_count', 'comments', 'reply'])],
132
+ ['收藏', pickFirst(data, ['collect_count', 'favorite', 'favorites'])],
133
+ ['分享', pickFirst(data, ['share_count', 'share', 'repost'])],
134
+ ['播放', pickFirst(data, ['play', 'view', 'views', 'playCount'])]
135
+ ]
136
+ .map(([label, value]) => [label, formatCount(value)])
137
+ .filter(([, value]) => !!value);
138
+ return { title, author, avatar, cover, description, stats };
139
+ }
140
+ /** 兜底卡片:不依赖模板,直接用通用字段渲染一张信息卡 */
141
+ function buildFallbackHtml(route, data, dark, scale) {
142
+ const card = extractCardData(data);
143
+ const bg = dark ? '#101014' : '#f4f5f7';
144
+ const fg = dark ? '#f7f8fa' : '#1c1f23';
145
+ const sub = dark ? '#a7abb3' : '#6b7280';
146
+ const coverHtml = card.cover ? '<div class="cover" style="background-image:url(' + escapeHtml(card.cover) + ')"></div>' : '';
147
+ const statsHtml = card.stats.length
148
+ ? '<div class="stats">' + card.stats.map(([label, value]) => '<span><b>' + escapeHtml(value) + '</b>' + escapeHtml(label) + '</span>').join('') + '</div>'
149
+ : '';
150
+ return '<!DOCTYPE html>\n<html lang="zh-CN"><head><meta charset="utf-8"><style>\n' +
151
+ ' * { box-sizing: border-box; margin: 0; padding: 0; }\n' +
152
+ ' body { background: ' + bg + '; color: ' + fg + '; font-family: "Microsoft YaHei", "PingFang SC", system-ui, sans-serif; }\n' +
153
+ ' #container { width: 720px; padding: 20px; }\n' +
154
+ ' .card { border-radius: 18px; background: ' + (dark ? '#1b1c20' : '#ffffff') + '; overflow: hidden; box-shadow: 0 12px 32px rgba(0,0,0,.12); zoom: ' + scale + '; }\n' +
155
+ ' .cover { width: 100%; height: 380px; background-size: cover; background-position: center; background-color: #2a2c31; }\n' +
156
+ ' .body { padding: 20px 24px 26px; }\n' +
157
+ ' .route { font-size: 13px; color: ' + sub + '; letter-spacing: .08em; text-transform: uppercase; margin-bottom: 10px; }\n' +
158
+ ' .title { font-size: 26px; font-weight: 700; line-height: 1.35; word-break: break-word; }\n' +
159
+ ' .author { display: flex; align-items: center; gap: 10px; margin-top: 14px; color: ' + sub + '; font-size: 16px; }\n' +
160
+ ' .author img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; }\n' +
161
+ ' .desc { margin-top: 16px; font-size: 16px; line-height: 1.7; color: ' + sub + '; white-space: pre-wrap; word-break: break-word; }\n' +
162
+ ' .stats { display: flex; gap: 26px; margin-top: 20px; font-size: 14px; color: ' + sub + '; }\n' +
163
+ ' .stats b { display: block; font-size: 20px; color: ' + fg + '; }\n' +
164
+ ' .footer { margin-top: 18px; font-size: 12px; color: ' + sub + '; }\n' +
165
+ '</style></head>\n<body><div id="container"><div class="card">\n' +
166
+ coverHtml +
167
+ '\n <div class="body">\n' +
168
+ ' <div class="route">' + escapeHtml(route) + '</div>\n' +
169
+ ' <div class="title">' + escapeHtml(card.title || '解析结果') + '</div>\n' +
170
+ (card.author
171
+ ? ' <div class="author">' + (card.avatar ? '<img src="' + escapeHtml(card.avatar) + '" />' : '') + '<span>' + escapeHtml(card.author) + '</span></div>\n'
172
+ : '') +
173
+ (card.description ? ' <div class="desc">' + escapeHtml(card.description.slice(0, 600)) + '</div>\n' : '') +
174
+ (statsHtml ? ' ' + statsHtml + '\n' : '') +
175
+ ' <div class="footer">koishi-plugin-kkk v' + escapeHtml(utils_1.Root.pluginVersion) + ' · 模板渲染未启用,当前为内置通用卡片</div>\n' +
176
+ ' </div>\n</div></div></body></html>';
177
+ }
178
+ /* ------------------------------------------------------------------ *
179
+ * 模板 SSR
180
+ * ------------------------------------------------------------------ */
181
+ /**
182
+ * 页脚那个「框架 logo」。
183
+ *
184
+ * 上游 karin 是起 HTTP 服务把 `/image/frame-logo.png` 喂给浏览器的;
185
+ * Koishi 移植版渲染的是**本地 HTML 文件**,绝对路径 `/image/...` 会指向磁盘根目录,
186
+ * 于是卡片页脚只剩下一个裂图(alt 文字 `logo`)。这里直接内联成 data URI。
187
+ */
188
+ let frameLogoCache = null;
189
+ function resolveFrameLogo() {
190
+ if (frameLogoCache !== null)
191
+ return frameLogoCache;
192
+ /**
193
+ * 页脚 logo:用 **Koishi 自己的图标**(@koishijs/plugin-console 里那张,
194
+ * 也就是控制台左上角那个),而不是上游 karin 的 frame-logo。
195
+ */
196
+ const candidates = [
197
+ node_path_1.default.join(utils_1.Root.pluginPath, '..', '@koishijs', 'plugin-console', 'dist', 'logo.png'),
198
+ node_path_1.default.join(utils_1.Root.pluginPath, '..', '@koishijs', 'client', 'app', 'assets', 'logo.png'),
199
+ node_path_1.default.join(utils_1.Root.pluginPath, 'resources', 'image', 'frame-logo.png')
200
+ ];
201
+ for (const filePath of candidates) {
202
+ try {
203
+ if (!node_fs_1.default.existsSync(filePath))
204
+ continue;
205
+ frameLogoCache = 'data:image/png;base64,' + node_fs_1.default.readFileSync(filePath).toString('base64');
206
+ return frameLogoCache;
207
+ }
208
+ catch { /* 换下一个 */ }
209
+ }
210
+ frameLogoCache = '';
211
+ return frameLogoCache;
212
+ }
213
+ /** 组装模板上下文(与上游 Render/index.ts 一致) */
214
+ function buildPosterContext(dark) {
215
+ return {
216
+ scale: Math.min(2, Math.max(0.5, Number(Config_1.Config.app?.renderScale ?? 100) / 100)),
217
+ theme: { mode: dark ? 'dark' : 'light' },
218
+ version: {
219
+ plugin: 'koishi-plugin',
220
+ pluginName: 'kkk',
221
+ pluginVersion: utils_1.Root.pluginVersion,
222
+ releaseType: /^\d+\.\d+\.\d+$/.test(utils_1.Root.pluginVersion) ? 'Stable' : 'Preview',
223
+ poweredBy: 'Koishi',
224
+ frameworkVersion: utils_1.Root.karinVersion,
225
+ // 页脚 logo(data URI,见 resolveFrameLogo)
226
+ frameLogo: resolveFrameLogo(),
227
+ hasUpdate: false
228
+ },
229
+ ambientCover: {
230
+ coverOpacity: Config_1.Config.app?.ambientCover?.coverOpacity,
231
+ overlayEdgeOpacity: Config_1.Config.app?.ambientCover?.overlayEdgeOpacity,
232
+ overlayMiddleOpacity: Config_1.Config.app?.ambientCover?.overlayMiddleOpacity
233
+ }
234
+ };
235
+ }
236
+ /** 二维码生成器只加载一次(ESM-only 包,只能在 SSR 前异步 import) */
237
+ let qrcodeReady = null;
238
+ async function ensureQrcodeGenerator() {
239
+ if (!qrcodeReady) {
240
+ qrcodeReady = (async () => {
241
+ const [qrcode, utils] = await Promise.all([
242
+ (0, esm_1.importEsm)('@ikenxuan/qrcode'),
243
+ Promise.resolve(require('../../../../ktr/utils/QRcode'))
244
+ ]);
245
+ if (typeof qrcode.generateSync === 'function') {
246
+ utils.setQrcodeGenerator(qrcode.generateSync);
247
+ }
248
+ })().catch((error) => {
249
+ node_karin_1.logger.debug('[Render] 二维码生成器加载失败: ' + String(error?.message ?? error));
250
+ });
251
+ }
252
+ return qrcodeReady;
253
+ }
254
+ /**
255
+ * 把 React 元素渲染成 HTML 字符串。
256
+ *
257
+ * 用流式 API 而不是同步的 renderToStaticMarkup:部分上游模板会 suspend
258
+ * (React 19 的 `use()` / 异步资源),同步渲染会直接抛
259
+ * "A component suspended while responding to synchronous input" 而整块回退成通用卡片。
260
+ * 流式渲染会等挂起的内容就绪(onAllReady)再产出完整 HTML。
261
+ */
262
+ async function renderToHtml(element, timeoutMs = 15000) {
263
+ return await new Promise((resolve, reject) => {
264
+ let html = '';
265
+ const stream = new node_stream_1.PassThrough();
266
+ stream.on('data', (chunk) => { html += chunk.toString(); });
267
+ stream.on('end', () => resolve(html));
268
+ stream.on('error', reject);
269
+ let settled = false;
270
+ const fail = (error) => {
271
+ if (settled)
272
+ return;
273
+ settled = true;
274
+ reject(error instanceof Error ? error : new Error(String(error)));
275
+ };
276
+ const { pipe, abort } = (0, server_1.renderToPipeableStream)(element, {
277
+ onError: (error) => node_karin_1.logger.debug('[Render] SSR 渲染期错误: ' + String(error?.message ?? error)),
278
+ onShellError: fail,
279
+ onAllReady: () => {
280
+ if (settled)
281
+ return;
282
+ settled = true;
283
+ pipe(stream);
284
+ }
285
+ });
286
+ setTimeout(() => {
287
+ if (settled)
288
+ return;
289
+ abort();
290
+ fail(new Error('SSR 渲染超时'));
291
+ }, timeoutMs).unref?.();
292
+ });
293
+ }
294
+ /** 用上游模板做 SSR;路由不支持或失败时返回 null */
295
+ async function renderTemplateHtml(route, data, dark) {
296
+ await ensureQrcodeGenerator();
297
+ let template;
298
+ try {
299
+ template = await (0, registry_1.loadTemplate)(route);
300
+ }
301
+ catch (error) {
302
+ node_karin_1.logger.debug('[Render] 模板 ' + route + ' 加载失败(可能缺少依赖): ' + String(error?.message ?? error));
303
+ return null;
304
+ }
305
+ if (!template?.component)
306
+ return null;
307
+ if (typeof template.validate === 'function' && !template.validate(data)) {
308
+ node_karin_1.logger.debug('[Render] 模板 ' + route + ' 的数据校验未通过,回退通用卡片');
309
+ return null;
310
+ }
311
+ try {
312
+ const ctx = buildPosterContext(dark);
313
+ const element = react_1.default.createElement(template.component, { data, ctx });
314
+ const body = await renderToHtml(react_1.default.createElement('div', { id: 'container' }, element));
315
+ const css = loadTemplateCss();
316
+ const themeClass = dark ? 'dark' : '';
317
+ /**
318
+ * 截图专用的覆盖样式:
319
+ * - 页面不要外边距/内边距,也不要白色背景(否则卡片圆角外面会透出白边、底部会多一条空白);
320
+ * - 卡片**不要圆角** —— 圆角会让四个角露出页面底色,看起来就是卡片缺了一角。
321
+ * 只压掉最外层的圆角,内部小元素(头像、标签)保持原样。
322
+ */
323
+ const shotCss = 'html,body{margin:0!important;padding:0!important;background:transparent!important;overflow:hidden!important}'
324
+ + '#container{margin:0!important;padding:0!important;border-radius:0!important}'
325
+ + '#container>div,#container>div>div{border-radius:0!important}'
326
+ + 'body{display:inline-block}';
327
+ return '<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><style>' + css + shotCss + '</style></head>'
328
+ + '<body class="' + themeClass + '">' + body + '</body></html>';
329
+ }
330
+ catch (error) {
331
+ node_karin_1.logger.warn('[Render] 模板 ' + route + ' SSR 失败,回退通用卡片: ' + String(error?.message ?? error));
332
+ return null;
333
+ }
334
+ }
335
+ /* ------------------------------------------------------------------ *
336
+ * 截图
337
+ * ------------------------------------------------------------------ */
338
+ /**
339
+ * 用 koishi-plugin-puppeteer 对一个 HTML 文件截图,返回 base64。
340
+ *
341
+ * `scale` 会作为 deviceScaleFactor(配置项 `app.renderScale`,100 = 1x,200 = 2x):
342
+ * 不设的话高分辨率卡片会被截成 1x,群里看着又小又糊;顺带把视口撑到整张卡片大小,
343
+ * 否则比视口高的卡片会被裁掉一截(表现就是「截图只有一部分」)。
344
+ */
345
+ async function screenshot(htmlPath, selector, timeout, scale = 1, format = 'jpeg') {
346
+ const puppeteer = (0, node_karin_1.getKoishiContext)()?.puppeteer;
347
+ if (!puppeteer)
348
+ throw new Error('未安装 koishi-plugin-puppeteer,无法渲染图片');
349
+ // 卡片是给手机看的:**低于 2x 会明显发虚**,所以下限锁 2(上限 3)。
350
+ // 想更大更清晰就调 `app.renderScale`(100 → 2x,150 → 3x),配 100 时保持 2x 不出错。
351
+ const requested = Number.isFinite(scale) && scale > 0 ? scale * 2 : 2;
352
+ let deviceScaleFactor = Math.min(3, Math.max(2, requested));
353
+ // 安全阀:超大页面降一档缩放,避免单次渲染吃掉几 GB 内存(曾经把实例 OOM 崩掉)
354
+ try {
355
+ if (node_fs_1.default.statSync(htmlPath).size > 6 * 1024 * 1024)
356
+ deviceScaleFactor = Math.max(1, deviceScaleFactor - 1);
357
+ }
358
+ catch { /* 忽略 */ }
359
+ /**
360
+ * 视口用卡片的**设计宽度**(模板都按 1440 排版),高度按内容量一次。
361
+ *
362
+ * 之前试过「量出内容自然尺寸再把视口撑到那么大」:Chrome 会为此分配超大帧缓冲,
363
+ * 单次渲染把 node 堆吃到 3GB+ 并直接 OOM 崩掉实例。现在宽度固定、高度只增不减,
364
+ * 并且不再用 `captureBeyondViewport`(它在大页面上内存表现同样很差)。
365
+ */
366
+ const DESIGN_WIDTH = 1440;
367
+ /** 在给定页面上完成「导航 → 量高度 → 截图」,返回 base64 */
368
+ const capture = async (page) => {
369
+ if (page.setViewport) {
370
+ // 宽度就用卡片设计宽度:多给 24px 会多出一条白边(用户看到的「右边超出去一点」)
371
+ await page.setViewport({ width: DESIGN_WIDTH, height: 900, deviceScaleFactor });
372
+ }
373
+ await page.goto((0, node_url_1.pathToFileURL)(htmlPath).href, { waitUntil: 'networkidle0', timeout });
374
+ const metrics = await page.evaluate((sel) => {
375
+ const node = document.querySelector(sel) || document.body;
376
+ const rect = node.getBoundingClientRect ? node.getBoundingClientRect() : null;
377
+ return {
378
+ // 用**元素自己的盒子**而不是整页 scrollHeight:整页量出来的高度会带上 body 边距,
379
+ // 截图底部就多一条空白
380
+ width: Math.ceil(rect?.width || node.scrollWidth || document.body.scrollWidth || 0),
381
+ height: Math.ceil(rect?.height || node.scrollHeight || document.body.scrollHeight || 0)
382
+ };
383
+ }, selector).catch(() => ({ width: 0, height: 0 }));
384
+ if (page.setViewport) {
385
+ /**
386
+ * 宽度按**内容实测**来:正常模板是 1440 宽,而兜底卡片只有 720 ——
387
+ * 固定 1440 会让兜底卡片右边留一大片白。这里两者都能贴合,
388
+ * 同时高度按内容撑够,避免长卡片被裁。
389
+ */
390
+ const width = Math.min(Math.max(metrics.width || DESIGN_WIDTH, 320), 1600);
391
+ /**
392
+ * 高度按卡片实际盒子取整(不留容差)。
393
+ * 另外把 **页面底色设成卡片自己的底色** —— 视口哪怕只比卡片高一两个像素,
394
+ * JPEG 里那一条也会是白色页面底,看起来就是「下面有个小白边」。
395
+ */
396
+ const height = Math.min(Math.max(Math.round(metrics.height), 200), 20000);
397
+ await page.setViewport({ width, height, deviceScaleFactor });
398
+ await page.evaluate((sel) => {
399
+ try {
400
+ const node = document.querySelector(sel);
401
+ if (!node)
402
+ return;
403
+ const card = node.firstElementChild || node;
404
+ const bg = getComputedStyle(card).backgroundColor;
405
+ if (bg && bg !== 'rgba(0, 0, 0, 0)' && bg !== 'transparent') {
406
+ document.documentElement.style.background = bg;
407
+ document.body.style.background = bg;
408
+ }
409
+ }
410
+ catch { /* 取不到就算了 */ }
411
+ }, selector).catch(() => undefined);
412
+ await page.evaluate(() => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve))));
413
+ }
414
+ /**
415
+ * 用「卡片元素自己的范围」裁切,而不是整屏截图。
416
+ *
417
+ * 视口宽度比卡片设计宽度多了 24px(给滚动条留余量),整屏截图会在右边多出一条白边,
418
+ * 用户看到的就是「卡片右边超出了/有白边」。clip 只取 #container 的盒子,正好贴合卡片。
419
+ */
420
+ const handle = (await page.$(selector)) ?? (await page.$('body'));
421
+ const clip = handle ? await handle.boundingBox() : null;
422
+ /**
423
+ * 默认输出 JPEG:2x 的卡片 PNG 动辄十几 MB(带照片背景时尤其夸张),
424
+ * 超过 QQ 的图片上传限制就会被**当成文件**发出去(用户看到的是「[文件]」而不是图片)。
425
+ * 二维码那类需要像素级清晰的场景仍用 PNG(见 Render 里的判断)。
426
+ */
427
+ const buffer = await page.screenshot({
428
+ omitBackground: format === 'png',
429
+ type: format,
430
+ quality: format === 'jpeg' ? 92 : undefined
431
+ });
432
+ return buffer.toString('base64');
433
+ };
434
+ /**
435
+ * 自己开一个页面截图,**不要走插件的 render() 包装**。
436
+ *
437
+ * 实测:1440x4895 的运行环境诊断卡片,走 `puppeteer.render()` 时仅导航一步
438
+ * 就让 node 堆从 206MB 涨到 1407MB(首次渲染累计 +3GB,直接把宿主 OOM 崩掉);
439
+ * 自己 newPage + goto + 截图只涨几十 MB。所以这里优先直连浏览器,用完关掉页面。
440
+ */
441
+ const newPage = async () => {
442
+ try {
443
+ if (typeof puppeteer.page === 'function')
444
+ return await puppeteer.page();
445
+ if (puppeteer.browser && typeof puppeteer.browser.newPage === 'function')
446
+ return await puppeteer.browser.newPage();
447
+ }
448
+ catch (error) {
449
+ node_karin_1.logger.debug('[Render] 直连浏览器失败,退回插件 render(): ' + (error?.message ?? error));
450
+ }
451
+ return null;
452
+ };
453
+ const page = await newPage();
454
+ if (page) {
455
+ try {
456
+ return await capture(page);
457
+ }
458
+ finally {
459
+ try {
460
+ await page.close();
461
+ }
462
+ catch { /* 页面可能已被插件关掉,忽略 */ }
463
+ }
464
+ }
465
+ node_karin_1.logger.debug('[Render] 插件未暴露 page/browser,退回 puppeteer.render()');
466
+ return await puppeteer.render('', async (page) => capture(page));
467
+ }
468
+ const getImageMetadata = (buffer) => {
469
+ if (buffer.length >= 24 && buffer.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))) {
470
+ return { width: buffer.readUInt32BE(16), height: buffer.readUInt32BE(20) };
471
+ }
472
+ // JPEG:QQ 的 markdown 图片要写死「#宽px #高px」,所以必须能读出来
473
+ if (buffer.length > 4 && buffer[0] === 0xff && buffer[1] === 0xd8) {
474
+ let offset = 2;
475
+ while (offset + 9 < buffer.length) {
476
+ if (buffer[offset] !== 0xff) {
477
+ offset++;
478
+ continue;
479
+ }
480
+ const marker = buffer[offset + 1];
481
+ // SOF0..SOF15(跳过 DHT/DAC 等非 SOF 标记)
482
+ if (marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc) {
483
+ return { height: buffer.readUInt16BE(offset + 5), width: buffer.readUInt16BE(offset + 7) };
484
+ }
485
+ const length = buffer.readUInt16BE(offset + 2);
486
+ if (length <= 0)
487
+ break;
488
+ offset += 2 + length;
489
+ }
490
+ }
491
+ return {};
492
+ };
493
+ exports.getImageMetadata = getImageMetadata;
494
+ /**
495
+ * 渲染函数(上游签名):\`Render(event, '平台/模板', data)\` → 图片消息段数组。
496
+ */
497
+ /**
498
+ * 把模板里的第三方图床代理换回原图地址。
499
+ *
500
+ * 上游模板给头像/装扮这类图套了一层 images.weserv.nl/?url=<encoded>(本意是绕开 B站的防盗链),
501
+ * 但那个代理在有些网络下**根本连不上** —— 表现就是卡片里 UP 主头像是个裂图。
502
+ * 实测 B站原图直连(i0/i2.hdslb.com)不带 Referer 也是 200,所以这里直接还原成原地址。
503
+ */
504
+ /**
505
+ * 把模板里 `src="/image/xxx"` 这种**本地绝对路径**的图片内联成 data URI。
506
+ *
507
+ * 上游是 karin 的 HTTP 服务在提供 `/image/*`(插件 resources/image 目录);Koishi 移植版渲染的是
508
+ * 本地 HTML 文件,绝对路径会指向磁盘根目录 → 裂图。评论卡片里的 B站 logo、大会员标记、等级图标
509
+ * 就是这么丢的(页脚 logo 之前也踩过同一个坑)。
510
+ */
511
+ function inlineLocalImages(html) {
512
+ const imageRoot = node_path_1.default.join(utils_1.Root.pluginPath, 'resources');
513
+ const mimeOf = (file) => {
514
+ const ext = node_path_1.default.extname(file).toLowerCase();
515
+ if (ext === '.svg')
516
+ return 'image/svg+xml';
517
+ if (ext === '.jpg' || ext === '.jpeg')
518
+ return 'image/jpeg';
519
+ if (ext === '.webp')
520
+ return 'image/webp';
521
+ if (ext === '.gif')
522
+ return 'image/gif';
523
+ return 'image/png';
524
+ };
525
+ return html.replace(/(src=")(\/image\/[^"]+)(")/g, (all, head, url, tail) => {
526
+ try {
527
+ const relative = decodeURIComponent(url.replace(/^\/+/, ''));
528
+ const full = node_path_1.default.join(imageRoot, relative);
529
+ if (!full.startsWith(node_path_1.default.resolve(imageRoot)))
530
+ return all;
531
+ if (!node_fs_1.default.existsSync(full))
532
+ return all;
533
+ const buffer = node_fs_1.default.readFileSync(full);
534
+ const mime = mimeOf(full);
535
+ // svg 是文本,用 utf8 base64 也一样能显示,这里统一 base64 省事
536
+ return head + 'data:' + mime + ';base64,' + buffer.toString('base64') + tail;
537
+ }
538
+ catch {
539
+ return all;
540
+ }
541
+ });
542
+ }
543
+ function unwrapImageProxy(html) {
544
+ return html.replace(/https:\/\/images\.weserv\.nl\/\?url=([^"'&\s]+)/gi, (all, encoded) => {
545
+ try {
546
+ const decoded = decodeURIComponent(encoded);
547
+ return /^https?:\/\//i.test(decoded) ? decoded : all;
548
+ }
549
+ catch {
550
+ return all;
551
+ }
552
+ });
553
+ }
554
+ const Render = async (_event, route, data) => {
555
+ const dark = await (0, coverTheme_1.resolveUseDarkTheme)(route, data).catch(() => false);
556
+ const scale = Math.min(2, Math.max(0.5, Number(Config_1.Config.app?.renderScale ?? 100) / 100));
557
+ let html = await renderTemplateHtml(route, data, dark);
558
+ if (!html) {
559
+ html = buildFallbackHtml(route, data, dark, scale);
560
+ }
561
+ html = inlineLocalImages(unwrapImageProxy(html));
562
+ const htmlPath = node_path_1.default.resolve(root_1.karinPathHtml, utils_1.Root.pluginName, route.replace(/[\\/]/g, '_') + '.html');
563
+ try {
564
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(htmlPath), { recursive: true });
565
+ node_fs_1.default.writeFileSync(htmlPath, html, 'utf8');
566
+ // 二维码:必须像素级清晰(JPEG 压缩会影响扫码),继续用 PNG;其它卡片用 JPEG 压体积
567
+ const isQrCode = /qrcode/i.test(route);
568
+ const format = isQrCode ? 'png' : 'jpeg';
569
+ const base64 = await screenshot(htmlPath, '#container', Number(Config_1.Config.app?.RenderWaitTime ?? 10) * 1000, scale, format);
570
+ const buffer = Buffer.from(base64, 'base64');
571
+ const meta = (0, exports.getImageMetadata)(buffer);
572
+ node_karin_1.logger.debug('[Render] ' + route + ' 渲染完成 ' + format + ' ' + (meta.width ?? '?') + 'x' + (meta.height ?? '?') + ' ' + Math.round(buffer.length / 1024) + 'KB');
573
+ // 用带 mime 的 data URL,适配器才知道按 JPEG 上传(base64:// 会被当成 PNG)
574
+ return [node_karin_1.segment.image('data:image/' + format + ';base64,' + base64)];
575
+ }
576
+ catch (error) {
577
+ node_karin_1.logger.warn('[Render] ' + route + ' 渲染失败:' + (error?.message ?? error));
578
+ return [];
579
+ }
580
+ };
581
+ exports.Render = Render;
582
+ exports.default = exports.Render;