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,1076 @@
1
+ import { Chip } from '@heroui/react'
2
+ import { formatDistanceToNow, parse } from 'date-fns'
3
+ import { zhCN } from 'date-fns/locale'
4
+ import {
5
+ AlertCircle,
6
+ Braces,
7
+ Clock,
8
+ FileText,
9
+ Fingerprint,
10
+ Gauge,
11
+ GitBranch,
12
+ ListChecks,
13
+ Puzzle,
14
+ QrCode,
15
+ Radio,
16
+ Repeat,
17
+ Route,
18
+ ShieldAlert,
19
+ Terminal,
20
+ Timer
21
+ } from 'lucide-react'
22
+ import _ from 'node-karin/lodash'
23
+ import React from 'react'
24
+ import { MdSchedule } from 'react-icons/md'
25
+
26
+ import { DefaultLayout } from '../../../components/DefaultLayout'
27
+ import type { PosterProps } from '../../../types/ctx'
28
+ import { generateQRCode } from '../../../../utils/QRcode'
29
+ import { isDark } from '../../../../utils/theme'
30
+
31
+ import { getRandomErrorTitle } from './errorTitles'
32
+ import { highlightStack } from './stackHighlight'
33
+ import type { AmagiErrorDetail, ApiErrorData } from './types'
34
+
35
+ /** 业务错误类型:从总数据类型里取,不再单独导出。 */
36
+ type BusinessError = ApiErrorData['error']
37
+ /** 日志等级:从总数据类型里逐步取。 */
38
+ type LogLevel = NonNullable<ApiErrorData['logs']>[number]['level']
39
+
40
+ /**
41
+ * 取「最后一次 `node_modules/` 之后的那一段」——包名,供调用栈的归属判定使用。
42
+ *
43
+ * 不能只看帧的路径里有没有 `node_modules`:发布后插件**自己**就装在 `node_modules` 里,
44
+ * 帧形如 `…/node_modules/.pnpm/koishi-plugin-kkk@…/node_modules/koishi-plugin-kkk/lib/core_chunk/main.js:…`,
45
+ * `node_modules` 出现两次 —— 只看文本特征会把每一帧都当成依赖压暗,整块图失去分层。
46
+ * 所以改问「这一帧和本模块是不是同一个包」:模块自身的位置就是包根的答案,两边各取包名比对即可。
47
+ * 源码树(开发态)里取不到包名,返回 `undefined`,此时凡进了 `node_modules` 的帧一律算外部帧。
48
+ *
49
+ * 只做字符串切分,**不做 URL→路径转换**:模板在 ktr dev 的 iframe 沙箱里由浏览器求值,
50
+ * `import.meta.url` 是 `http://localhost:5174/@fs/D:/…`,生产 bundle 里是 `file:///…`,
51
+ * 折算成文件系统路径要同时处理协议、主机、`/@fs` 与前导斜杠四种差异,漏一样就会把所有帧
52
+ * 都判成外部帧、整块压暗;而这两种形态都原样带着 `node_modules` 这一段,直接切更稳。
53
+ * 也**不能**为图省事引入 `node:*` 内置模块:模板会被 vite 当浏览器代码打包,`node:url`
54
+ * 这类会被 externalize 成空壳,模块求值期直接抛错,整个判定失效。
55
+ * @param input - 模块 URL 或帧里的路径原文
56
+ * @returns 包名,形如 `koishi-plugin-kkk`;不在 `node_modules` 里时返回 `undefined`
57
+ */
58
+ const packageSegmentOf = (input: string): string | undefined => {
59
+ const path = input.replace(/\\/g, '/')
60
+ const marker = '/node_modules/'
61
+ const at = path.lastIndexOf(marker)
62
+ if (at < 0) return undefined
63
+ return path.slice(at + marker.length).split('/')[0]
64
+ }
65
+
66
+ /**
67
+ * 本模块所在的包名;开发态跑源码树时为 `undefined`。
68
+ *
69
+ * Koishi 移植:上游用 `import.meta.url`(模板在 ktr dev 的浏览器沙箱里求值)。
70
+ * 我们的产物是 CJS,`import.meta` 会让 Node 把整个文件当 ESM(报 "exports is not defined"),
71
+ * 因此改用 `__filename` 拼一个 file:// URL —— 这里只做字符串切分找 `node_modules`,语义一致。
72
+ */
73
+ const selfModuleUrl =
74
+ typeof __filename === 'string' ? 'file:///' + __filename.replace(/\\/g, '/') : ''
75
+ const selfPackageSegment = packageSegmentOf(selfModuleUrl)
76
+
77
+ /**
78
+ * 判断一个调用帧的位置是否属于本插件自己的代码。
79
+ * @param location - 帧里的位置原文,形如 `路径:行:列` 或 `node:internal/…`
80
+ * @returns 是否属于本插件自己的代码
81
+ */
82
+ const isOwnFrameLocation = (location: string): boolean => {
83
+ const path = location.replace(/\\/g, '/')
84
+ // node 内部帧没有包名可言,直接算外部帧(与 stackHighlight 的兜底判定同款)
85
+ if (/^node:|\(node:/.test(path)) return false
86
+ // 没进 node_modules 的帧就是源码树里的自己(开发态)
87
+ if (!path.includes('/node_modules/')) return true
88
+ // 进了 node_modules:只有和本模块同属一个包才算自己的代码
89
+ return packageSegmentOf(path) === selfPackageSegment
90
+ }
91
+
92
+ /**
93
+ * ANSI 颜色代码映射
94
+ */
95
+ const ansiColorMap: Record<number, string> = {
96
+ 30: 'text-foreground',
97
+ 31: 'text-danger',
98
+ 32: 'text-success',
99
+ 33: 'text-warning',
100
+ 34: 'text-accent',
101
+ 35: 'text-accent',
102
+ 36: 'text-cyan-600',
103
+ 37: 'text-muted',
104
+ 90: 'text-foreground/70',
105
+ 91: 'text-danger',
106
+ 92: 'text-success',
107
+ 93: 'text-warning',
108
+ 94: 'text-accent',
109
+ 95: 'text-accent',
110
+ 96: 'text-muted',
111
+ 97: 'text-background/80'
112
+ }
113
+
114
+ const ansi256ToColor = (colorCode: number): string => {
115
+ const standardColors = [
116
+ '#000000',
117
+ '#800000',
118
+ '#008000',
119
+ '#808000',
120
+ '#000080',
121
+ '#800080',
122
+ '#008080',
123
+ '#c0c0c0',
124
+ '#808080',
125
+ '#ff0000',
126
+ '#00ff00',
127
+ '#ffff00',
128
+ '#0000ff',
129
+ '#ff00ff',
130
+ '#00ffff',
131
+ '#ffffff'
132
+ ]
133
+ if (colorCode < 16) return standardColors[colorCode]
134
+ if (colorCode < 232) {
135
+ const index = colorCode - 16
136
+ const r = Math.floor(index / 36),
137
+ g = Math.floor((index % 36) / 6),
138
+ b = index % 6
139
+ const toHex = (v: number) => (v === 0 ? 0 : 55 + v * 40).toString(16).padStart(2, '0')
140
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`
141
+ }
142
+ const gray = (colorCode - 232) * 10 + 8
143
+ const hex = gray.toString(16).padStart(2, '0')
144
+ return `#${hex}${hex}${hex}`
145
+ }
146
+
147
+ const convertAnsiToHtml = (text: string): string => {
148
+ // 完全避免在正则字面量中出现任何转义
149
+ const ESC = String.fromCharCode(27)
150
+ const ansiRegex = new RegExp(ESC + '\\[([0-9;]+)m', 'g')
151
+ let result = '',
152
+ lastIndex = 0
153
+ let currentStyles: { classes: string[]; inlineColor?: string } = { classes: [] }
154
+ let match
155
+
156
+ const escapeHtml = (str: string) =>
157
+ str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;')
158
+ const formatLogContent = (content: string) =>
159
+ escapeHtml(content).replace(
160
+ /([\u3400-\u9fff\uf900-\ufaff\u3000-\u303f\uff00-\uffef]+)/g,
161
+ '<span class="font-[HarmonyOSHans-Regular]">$1</span>'
162
+ )
163
+ const makeSpan = (content: string) => {
164
+ const hasClass = currentStyles.classes.length > 0,
165
+ hasInline = currentStyles.inlineColor
166
+ if (!hasClass && !hasInline) return formatLogContent(content)
167
+ const classAttr = hasClass ? ` class="${currentStyles.classes.join(' ')}"` : ''
168
+ const styleAttr = hasInline ? ` style="color: ${currentStyles.inlineColor}"` : ''
169
+ return `<span${classAttr}${styleAttr}>${formatLogContent(content)}</span>`
170
+ }
171
+
172
+ while ((match = ansiRegex.exec(text)) !== null) {
173
+ if (match.index > lastIndex) result += makeSpan(text.substring(lastIndex, match.index))
174
+ const codes = match[1].split(';').map(Number)
175
+ let i = 0
176
+ while (i < codes.length) {
177
+ const code = codes[i]
178
+ if (code === 90 && codes[i + 1] === 2) {
179
+ currentStyles.classes = currentStyles.classes.filter((c) => !c.startsWith('text-'))
180
+ currentStyles.inlineColor = undefined
181
+ currentStyles.classes.push('text-muted')
182
+ i++
183
+ } else if (code === 0 || code === 39 || code === 49) {
184
+ currentStyles.classes = currentStyles.classes.filter(
185
+ (c) => !c.startsWith('text-') && !c.startsWith('bg-') && !c.startsWith('dark:')
186
+ )
187
+ currentStyles.inlineColor = undefined
188
+ } else if (code === 1) {
189
+ if (!currentStyles.classes.includes('font-bold')) currentStyles.classes.push('font-bold')
190
+ } else if (code === 22) {
191
+ currentStyles.classes = currentStyles.classes.filter((c) => c !== 'font-bold')
192
+ } else if (code === 38 && codes[i + 1] === 5) {
193
+ const colorCode = codes[i + 2]
194
+ if (colorCode !== undefined) {
195
+ currentStyles.classes = currentStyles.classes.filter((c) => !c.startsWith('text-') && !c.startsWith('dark:'))
196
+ currentStyles.inlineColor = ansi256ToColor(colorCode)
197
+ i += 2
198
+ }
199
+ } else if (ansiColorMap[code]) {
200
+ currentStyles.classes = currentStyles.classes.filter((c) => !c.startsWith('text-') && !c.startsWith('dark:'))
201
+ currentStyles.inlineColor = undefined
202
+ currentStyles.classes.push(ansiColorMap[code])
203
+ }
204
+ i++
205
+ }
206
+ lastIndex = ansiRegex.lastIndex
207
+ }
208
+ if (lastIndex < text.length) result += makeSpan(text.substring(lastIndex))
209
+ return result
210
+ }
211
+
212
+ /** 把请求 URL 拆成「主体」与「查询参数名」两截:签名 URL 动辄上千字符,全印没法看 */
213
+ const splitRequestUrl = (raw: string): { head: string; names: string[]; queryLength: number } => {
214
+ try {
215
+ const u = new URL(raw)
216
+ const names = [...u.searchParams.keys()]
217
+ return { head: `${u.origin}${u.pathname}`, names, queryLength: u.search.length }
218
+ } catch {
219
+ return { head: raw, names: [], queryLength: 0 }
220
+ }
221
+ }
222
+
223
+ /** trace 里 reason 的中文名 */
224
+ const TRACE_REASON_LABELS: Record<string, string> = {
225
+ initial: '首次',
226
+ retry: '重试',
227
+ page: '翻页',
228
+ segment: '分段',
229
+ prepare: '前置'
230
+ }
231
+
232
+ const getLogLevelTheme = (level: LogLevel, dark: boolean) => {
233
+ const themeMap: Record< LogLevel,
234
+ {
235
+ bgClass: string
236
+ borderClass: string
237
+ textClass: string
238
+ iconClass: string
239
+ levelClass: string
240
+ dotClass: string
241
+ }
242
+ > = {
243
+ TRAC: {
244
+ bgClass: dark ? 'bg-muted/10' : 'bg-muted/5',
245
+ borderClass: 'border-muted/20',
246
+ textClass: 'text-muted',
247
+ iconClass: 'text-muted',
248
+ levelClass: dark ? 'text-muted/10' : 'text-muted/10',
249
+ dotClass: 'bg-muted/40'
250
+ },
251
+ DEBU: {
252
+ bgClass: dark ? 'bg-cyan-400/10' : 'bg-cyan-500/5',
253
+ borderClass: dark ? 'border-cyan-400/20' : 'border-cyan-500/20',
254
+ textClass: dark ? 'text-cyan-400' : 'text-cyan-600',
255
+ iconClass: dark ? 'text-cyan-400' : 'text-cyan-600',
256
+ levelClass: dark ? 'text-cyan-400/10' : 'text-cyan-600/10',
257
+ dotClass: dark ? 'bg-cyan-400/40' : 'bg-cyan-500/40'
258
+ },
259
+ MARK: {
260
+ bgClass: dark ? 'bg-muted/10' : 'bg-muted/5',
261
+ borderClass: 'border-muted/20',
262
+ textClass: 'text-muted',
263
+ iconClass: 'text-muted',
264
+ levelClass: dark ? 'text-muted/10' : 'text-muted/10',
265
+ dotClass: 'bg-muted/40'
266
+ },
267
+ INFO: {
268
+ bgClass: 'bg-success-soft',
269
+ borderClass: 'border-success/25',
270
+ textClass: 'text-success',
271
+ iconClass: 'text-success',
272
+ levelClass: dark ? 'text-success/10' : 'text-success/10',
273
+ dotClass: 'bg-success/40'
274
+ },
275
+ WARN: {
276
+ bgClass: 'bg-warning-soft',
277
+ borderClass: 'border-warning/25',
278
+ textClass: 'text-warning',
279
+ iconClass: 'text-warning',
280
+ levelClass: dark ? 'text-warning/10' : 'text-warning-soft',
281
+ dotClass: 'bg-warning/40'
282
+ },
283
+ ERRO: {
284
+ bgClass: 'bg-danger-soft',
285
+ borderClass: 'border-danger/25',
286
+ textClass: 'text-danger',
287
+ iconClass: 'text-danger',
288
+ levelClass: dark ? 'text-danger/10' : 'text-danger/10',
289
+ dotClass: 'bg-danger/40'
290
+ },
291
+ FATA: {
292
+ bgClass: dark ? 'bg-pink-400/10' : 'bg-pink-500/5',
293
+ borderClass: dark ? 'border-pink-400/25' : 'border-pink-500/25',
294
+ textClass: dark ? 'text-pink-400' : 'text-pink-500',
295
+ iconClass: dark ? 'text-pink-400' : 'text-pink-500',
296
+ levelClass: dark ? 'text-pink-400/10' : 'text-pink-500/10',
297
+ dotClass: dark ? 'bg-pink-400/40' : 'bg-pink-500/40'
298
+ }
299
+ }
300
+ return themeMap[level] || themeMap['TRAC']
301
+ }
302
+
303
+ const ADAPTER_LOGO_MAP: Record<string, string> = {
304
+ napcat: '/image/other/handlerError/napcat.webp',
305
+ lagrange: '/image/other/handlerError/lagrange.webp',
306
+ chronocat: '/image/other/handlerError/chronocat.svg',
307
+ llonebot: '/image/other/handlerError/llonebot.webp',
308
+ lltwobot: '/image/other/handlerError/llonebot.webp',
309
+ conwechat: '/image/other/handlerError/conwechat.webp',
310
+ gocq: '/image/other/handlerError/gocq-http.webp'
311
+ }
312
+
313
+ const getAdapterLogo = (adapterName: string): React.ReactNode => {
314
+ const nameLower = adapterName.toLowerCase()
315
+ for (const [key, logoPath] of Object.entries(ADAPTER_LOGO_MAP)) {
316
+ if (nameLower.includes(key)) return <img src={logoPath} className="h-20 w-auto" alt={adapterName} />
317
+ }
318
+ return <Puzzle size={64} className="text-danger/80" />
319
+ }
320
+
321
+ /**
322
+ * amagi 12 个错误大类的中文名与「该怎么办」。
323
+ *
324
+ * 印 `kind` 本身对看图的人没用 —— 有用的是它指向哪一类处置:改配置、等一会儿、
325
+ * 还是提 issue。所以每一类都带一句处置提示。
326
+ */
327
+ /** 未知 kind 的兜底(表里找不到时用它,避免整张错误卡片渲染失败) */
328
+ const FALLBACK_KIND_META = { zh: '接口错误', hint: '接口没有返回预期数据,可能是登录凭证过期或被风控拦截。' }
329
+
330
+ const ERROR_KIND_META: Record<AmagiErrorDetail['kind'], { zh: string; hint: string }> = {
331
+ validation: { zh: '参数校验', hint: '调用参数不合法,通常是插件自身的问题' },
332
+ auth: { zh: '身份失效', hint: 'Cookie 缺失或已过期,重新扫码登录即可' },
333
+ rate_limit: { zh: '触发限流', hint: '请求太频繁,等一会儿再试' },
334
+ risk: { zh: '命中风控', hint: '平台要求人机验证,或需要换一个账号的 Cookie' },
335
+ not_found: { zh: '内容不存在', hint: '作品可能已删除、被设为私密或仅粉丝可见' },
336
+ forbidden: { zh: '无权访问', hint: '当前账号看不到这份内容(付费 / 地区 / 权限)' },
337
+ unavailable: { zh: '服务不可用', hint: '平台侧临时故障,稍后重试' },
338
+ network: { zh: '网络错误', hint: '检查代理配置与出口网络' },
339
+ timeout: { zh: '请求超时', hint: '调大 amagi.timeout,或检查代理链路' },
340
+ parse: { zh: '响应解析失败', hint: '平台改了协议,或返回的是反爬页面' },
341
+ internal: { zh: 'amagi 内部错误', hint: '解析库内部异常,建议反馈' },
342
+ unknown: { zh: '未分类错误', hint: '平台返回了未被识别的错误码' }
343
+ }
344
+
345
+ /** 诊断区的一格:小标签 + 大值,值缺失时整格不渲染 */
346
+ const DetailCell: React.FC<{
347
+ icon: React.ReactNode
348
+ label: string
349
+ value?: string | number
350
+ color: string
351
+ valueColor: string
352
+ }> = ({ icon, label, value, color, valueColor }) => {
353
+ if (value === undefined || value === null || value === '') return null
354
+ return (
355
+ <div className="flex flex-col gap-2">
356
+ <div className="flex items-center gap-3 opacity-70">
357
+ {icon}
358
+ <span className="text-xl font-semibold tracking-[0.12em]" style={{ color }}>
359
+ {label}
360
+ </span>
361
+ </div>
362
+ <span className="text-3xl font-bold font-mono break-all" style={{ color: valueColor }}>
363
+ {value}
364
+ </span>
365
+ </div>
366
+ )
367
+ }
368
+
369
+ const SectionTitle: React.FC<{ icon: React.ReactNode; en: string; zh: string; color: string }> = ({ icon, en, zh, color }) => (
370
+ <div className="flex items-center gap-5 mb-6">
371
+ {icon}
372
+ <div className="flex flex-col leading-tight">
373
+ <span className="text-xl font-semibold tracking-[0.2em] uppercase" style={{ color }}>
374
+ {en}
375
+ </span>
376
+ <span className="text-base font-medium tracking-[0.08em] opacity-80" style={{ color }}>
377
+ {zh}
378
+ </span>
379
+ </div>
380
+ </div>
381
+ )
382
+
383
+ /**
384
+ * API错误显示组件 - 手机端 Apple 风格
385
+ */
386
+ export const handlerError: React.FC<PosterProps<ApiErrorData>> = (props) => {
387
+ const { data } = props
388
+ const dark = isDark(props.ctx)
389
+ const isBusinessError = data.type === 'business_error'
390
+ const businessError = isBusinessError ? (data.error as BusinessError) : null
391
+ const displayMethod = businessError?.businessName || data.method
392
+
393
+ // 高亮方式看文本本身有没有 ANSI,而不是看错误来源:amagi 与非 amagi 现在都只印
394
+ // 纯文本调用帧,走结构上色;只有调用方显式覆盖进来的 util.inspect 转储仍走 ANSI 那条。
395
+ // 归属判定必须由本包给出:插件发布后自己就装在 node_modules 里,只看路径特征会把
396
+ // 每一帧都当成依赖压暗(构建产物整块图失去分层)。
397
+ const stackText = String(businessError?.stack || data.error?.stack || '')
398
+ const stackHtml = stackText.includes(String.fromCharCode(27))
399
+ ? convertAnsiToHtml(stackText)
400
+ : highlightStack(stackText, dark, { isOwnFrame: isOwnFrameLocation })
401
+
402
+ // 631 配色 - 红/珊瑚色系
403
+ const bgColor = dark ? '#0f0a0a' : '#faf5f5'
404
+ const primaryColor = dark ? '#f87171' : '#dc2626'
405
+ const secondaryColor = dark ? '#fca5a5' : '#b91c1c'
406
+ const mutedColor = dark ? 'rgba(248,113,113,0.7)' : '#991b1b'
407
+ const accentColor = dark ? '#fecaca' : '#7f1d1d'
408
+
409
+ return (
410
+ <DefaultLayout
411
+ {...props}
412
+ // version={undefined}
413
+ className="relative overflow-hidden"
414
+ style={{ backgroundColor: bgColor, width: '1440px', minHeight: '1800px' }}
415
+ >
416
+ {/* 弥散光背景 - 深浅模式完全适配 */}
417
+ <div className="absolute inset-0 pointer-events-none">
418
+ {/* 左上主光斑 */}
419
+ <div
420
+ className="absolute rounded-full w-300 h-350 -top-75 -left-50 blur-[120px] -rotate-15"
421
+ style={{
422
+ background: dark
423
+ ? 'radial-gradient(ellipse at 40% 40%, rgba(220,38,38,0.35) 0%, rgba(185,28,28,0.18) 50%, transparent 100%)'
424
+ : 'radial-gradient(ellipse at 40% 40%, rgba(248,113,113,0.45) 0%, rgba(252,165,165,0.22) 50%, transparent 100%)'
425
+ }}
426
+ />
427
+ {/* 右侧光斑 */}
428
+ <div
429
+ className="absolute rounded-full w-225 h-250 top-100 -right-25 blur-[100px] rotate-20"
430
+ style={{
431
+ background: dark
432
+ ? 'radial-gradient(ellipse at 50% 50%, rgba(127,29,29,0.3) 0%, rgba(69,10,10,0.15) 50%, transparent 100%)'
433
+ : 'radial-gradient(ellipse at 50% 50%, rgba(254,202,202,0.4) 0%, rgba(254,226,226,0.2) 50%, transparent 100%)'
434
+ }}
435
+ />
436
+ {/* 底部光斑 */}
437
+ <div
438
+ className="absolute rounded-full w-250 h-200 -bottom-50 left-50 blur-[140px] -rotate-10"
439
+ style={{
440
+ background: dark
441
+ ? 'radial-gradient(ellipse at 50% 60%, rgba(153,27,27,0.3) 0%, rgba(127,29,29,0.15) 50%, transparent 100%)'
442
+ : 'radial-gradient(ellipse at 50% 60%, rgba(252,165,165,0.35) 0%, rgba(254,202,202,0.18) 50%, transparent 100%)'
443
+ }}
444
+ />
445
+ </div>
446
+
447
+ {/* 单色噪点层 - 明显颗粒感 */}
448
+ <div className="absolute inset-0 pointer-events-none" style={{ opacity: dark ? 0.12 : 0.18 }}>
449
+ <svg className="w-full h-full" xmlns="http://www.w3.org/2000/svg">
450
+ <filter id="errorPixelNoise" x="0%" y="0%" width="100%" height="100%">
451
+ <feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="1" stitchTiles="stitch" result="noise" />
452
+ <feColorMatrix type="saturate" values="0" result="gray" />
453
+ <feComponentTransfer>
454
+ <feFuncR type="discrete" tableValues="0 1" />
455
+ <feFuncG type="discrete" tableValues="0 1" />
456
+ <feFuncB type="discrete" tableValues="0 1" />
457
+ </feComponentTransfer>
458
+ </filter>
459
+ <rect width="100%" height="100%" filter="url(#errorPixelNoise)" />
460
+ </svg>
461
+ </div>
462
+
463
+ {/* 背景大字装饰 */}
464
+ <div className="absolute bottom-20 right-15 pointer-events-none select-none opacity-[0.03]">
465
+ <span
466
+ className="text-[180px] font-black tracking-tighter leading-none block text-right"
467
+ style={{ color: dark ? '#fff' : '#7f1d1d' }}
468
+ >
469
+ ERROR
470
+ </span>
471
+ </div>
472
+
473
+ {/* 四周装饰性图形点缀 */}
474
+ <div className="absolute inset-0 pointer-events-none overflow-hidden z-0">
475
+ {/* 右上角:实心方块阵列 */}
476
+ <div className="absolute top-10 right-10 grid grid-cols-2 gap-3 opacity-20">
477
+ <div className="w-4 h-4" style={{ backgroundColor: primaryColor }} />
478
+ <div className="w-4 h-4" style={{ backgroundColor: secondaryColor }} />
479
+ <div className="w-4 h-4" style={{ backgroundColor: secondaryColor }} />
480
+ <div className="w-4 h-4" style={{ backgroundColor: primaryColor }} />
481
+ </div>
482
+
483
+ {/* 左下角:对角线条纹 */}
484
+ <div
485
+ className="absolute bottom-0 left-0 w-125 h-125 opacity-[0.06] pointer-events-none"
486
+ style={{
487
+ backgroundImage: `repeating-linear-gradient(45deg, ${primaryColor}, ${primaryColor} 4px, transparent 2px, transparent 12px)`,
488
+ maskImage: 'linear-gradient(to top right, black, transparent 70%)',
489
+ WebkitMaskImage: 'linear-gradient(to top right, black, transparent 70%)'
490
+ }}
491
+ />
492
+
493
+ {/* 右下角:同心圆弧 */}
494
+ <div className="absolute -bottom-20 -right-20 w-150 h-150 opacity-10 pointer-events-none">
495
+ <div className="absolute bottom-0 right-0 w-full h-full border-40 rounded-full" style={{ borderColor: primaryColor }} />
496
+ <div
497
+ className="absolute bottom-20 right-20 w-[calc(100%-160px)] h-[calc(100%-160px)] border-20 rounded-full"
498
+ style={{ borderColor: secondaryColor }}
499
+ />
500
+ <div
501
+ className="absolute bottom-35 right-35 w-[calc(100%-280px)] h-[calc(100%-280px)] border-10 rounded-full"
502
+ style={{ borderColor: mutedColor }}
503
+ />
504
+ </div>
505
+ </div>
506
+
507
+ {/* 内容层 */}
508
+ <div className="relative z-10 flex flex-col h-full p-16">
509
+ {/* 顶部状态栏 */}
510
+ <div className="flex items-center justify-between mb-14">
511
+ {/* 优化后的左侧状态标签 */}
512
+ <div className="flex items-center">
513
+ {/* 左侧装饰竖条 */}
514
+ <div
515
+ className="h-16 w-3 mr-4 opacity-80"
516
+ style={{
517
+ backgroundColor: primaryColor,
518
+ backgroundImage: 'repeating-linear-gradient(45deg, transparent, transparent 2px, rgba(0,0,0,0.2) 2px, rgba(0,0,0,0.2) 4px)'
519
+ }}
520
+ />
521
+
522
+ {/* 主标签容器 */}
523
+ <div
524
+ className="relative px-8 py-3 backdrop-blur-md"
525
+ style={{
526
+ backgroundColor: dark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.02)',
527
+ border: `1px solid ${dark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'}`
528
+ }}
529
+ >
530
+ {/* 四角装饰钉 */}
531
+ <div className="absolute top-0 left-0 w-2 h-2 border-t-2 border-l-2" style={{ borderColor: primaryColor }} />
532
+ <div className="absolute top-0 right-0 w-2 h-2 border-t-2 border-r-2" style={{ borderColor: primaryColor }} />
533
+ <div className="absolute bottom-0 left-0 w-2 h-2 border-b-2 border-l-2" style={{ borderColor: primaryColor }} />
534
+ <div className="absolute bottom-0 right-0 w-2 h-2 border-b-2 border-r-2" style={{ borderColor: primaryColor }} />
535
+
536
+ <div className="flex items-center gap-6">
537
+ {/* 状态指示器 */}
538
+ <div
539
+ className="flex flex-col items-center justify-center border-r pr-6"
540
+ style={{ borderColor: dark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)' }}
541
+ >
542
+ <div
543
+ className="w-4 h-4 rounded-full shadow-[0_0_15px_currentColor] animate-pulse"
544
+ style={{ backgroundColor: primaryColor, color: primaryColor }}
545
+ />
546
+ <span className="text-[10px] font-mono mt-2 tracking-wider opacity-50" style={{ color: mutedColor }}>
547
+ ERR.01
548
+ </span>
549
+ </div>
550
+
551
+ {/* 文字信息 */}
552
+ <div className="flex flex-col">
553
+ <span
554
+ className="text-xs font-mono font-bold tracking-[0.4em] uppercase mb-1 opacity-50"
555
+ style={{ color: secondaryColor }}
556
+ >
557
+ System Alert
558
+ </span>
559
+ <span className="text-2xl font-black tracking-[0.25em] uppercase" style={{ color: primaryColor }}>
560
+ Runtime Exception
561
+ </span>
562
+ </div>
563
+ </div>
564
+ </div>
565
+ </div>
566
+ {/* 优化后的时间显示模块 */}
567
+ <div className="flex items-center gap-8 pr-12">
568
+ {/* 装饰线条组 */}
569
+ <div className="flex flex-col gap-1 items-end opacity-40">
570
+ <div className="w-16 h-0.5" style={{ backgroundColor: primaryColor }} />
571
+ <div className="w-8 h-0.5" style={{ backgroundColor: secondaryColor }} />
572
+ </div>
573
+
574
+ {/* 时间数字显示 */}
575
+ <div className="text-right">
576
+ <div className="flex items-center justify-end gap-3 mb-1">
577
+ <span className="text-xs font-black tracking-[0.3em] uppercase opacity-60" style={{ color: mutedColor }}>
578
+ System Time
579
+ </span>
580
+ <span className="w-2 h-2 rounded-full animate-pulse" style={{ backgroundColor: primaryColor }} />
581
+ </div>
582
+ <div className="font-mono text-5xl font-black tracking-widest leading-none" style={{ color: mutedColor }}>
583
+ {new Date(data.timestamp).toLocaleTimeString('en-GB', { hour12: false })}
584
+ </div>
585
+ </div>
586
+
587
+ {/* 分割线 */}
588
+ <div className="h-12 w-0.5 opacity-20" style={{ backgroundColor: mutedColor }} />
589
+
590
+ {/* 日期显示 */}
591
+ <div className="text-right">
592
+ <div className="text-xs font-black tracking-[0.3em] uppercase opacity-60 mb-1" style={{ color: mutedColor }}>
593
+ Date
594
+ </div>
595
+ <div className="font-mono text-3xl font-bold tracking-[0.2em]" style={{ color: secondaryColor }}>
596
+ {new Date(data.timestamp)
597
+ .toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' })
598
+ .replaceAll('/', '-')}
599
+ </div>
600
+ </div>
601
+ </div>
602
+ </div>
603
+
604
+ {/* 主标题 */}
605
+ <div className="mb-20">
606
+ <h1 className="text-[120px] font-black leading-none tracking-tight mb-10" style={{ color: accentColor }}>
607
+ {getRandomErrorTitle()}
608
+ </h1>
609
+ <p className="text-5xl font-semibold" style={{ color: primaryColor }}>
610
+ {displayMethod}
611
+ </p>
612
+ </div>
613
+
614
+ {/* amagi 错误诊断:只有失败来自解析库时才有这一块 */}
615
+ {data.amagi && (
616
+ <div className="mb-16">
617
+ <SectionTitle
618
+ icon={<ShieldAlert size={36} style={{ color: mutedColor }} />}
619
+ en="Amagi Diagnosis"
620
+ zh="解析库错误诊断"
621
+ color={mutedColor}
622
+ />
623
+ <div
624
+ className="p-12 rounded-[36px]"
625
+ style={{
626
+ backgroundColor: dark ? 'rgba(0,0,0,0.22)' : 'rgba(255,255,255,0.55)',
627
+ border: `1px solid ${dark ? 'rgba(248,113,113,0.18)' : 'rgba(252,165,165,0.45)'}`
628
+ }}
629
+ >
630
+ {/* 第一行:错误大类 + 是否可重试。这两个决定「现在该做什么」 */}
631
+ <div className="flex items-center gap-6 flex-wrap mb-4">
632
+ <span
633
+ className="px-8 py-3 rounded-full text-3xl font-black tracking-wide"
634
+ style={{
635
+ backgroundColor: dark ? 'rgba(248,113,113,0.18)' : 'rgba(220,38,38,0.12)',
636
+ color: primaryColor
637
+ }}
638
+ >
639
+ {(ERROR_KIND_META[data.amagi.kind] ?? FALLBACK_KIND_META).zh}
640
+ </span>
641
+ <span
642
+ className="px-6 py-3 rounded-full text-2xl font-bold tracking-wide"
643
+ style={{
644
+ backgroundColor: data.amagi.retryable
645
+ ? dark
646
+ ? 'rgba(74,222,128,0.16)'
647
+ : 'rgba(22,163,74,0.12)'
648
+ : dark
649
+ ? 'rgba(148,163,184,0.16)'
650
+ : 'rgba(100,116,139,0.12)',
651
+ color: data.amagi.retryable ? (dark ? '#4ade80' : '#15803d') : dark ? '#cbd5e1' : '#475569'
652
+ }}
653
+ >
654
+ {data.amagi.retryable ? '可以重试' : '重试无用'}
655
+ </span>
656
+ <span className="font-mono text-2xl opacity-70" style={{ color: mutedColor }}>
657
+ {data.amagi.kind}
658
+ </span>
659
+ </div>
660
+
661
+ <p className="text-3xl mb-10" style={{ color: secondaryColor }}>
662
+ {(ERROR_KIND_META[data.amagi.kind] ?? FALLBACK_KIND_META).hint}
663
+ </p>
664
+
665
+ {/* 平台返回的原文:与堆栈里那份 inspect 转储不同,这里是干净的一句话 */}
666
+ <div
667
+ className="p-8 rounded-7xl mb-10"
668
+ style={{ backgroundColor: dark ? 'rgba(220,38,38,0.12)' : 'rgba(254,202,202,0.35)' }}
669
+ >
670
+ <div className="text-xl font-semibold tracking-[0.12em] opacity-70 mb-3" style={{ color: mutedColor }}>
671
+ 平台原文
672
+ </div>
673
+ <p className="text-3xl leading-relaxed break-all" style={{ color: accentColor }}>
674
+ {data.amagi.reason || '(平台未给出说明)'}
675
+ </p>
676
+ </div>
677
+
678
+ {/* 分层错误码与请求归因 */}
679
+ <div className="grid grid-cols-3 gap-x-12 gap-y-10">
680
+ <DetailCell
681
+ icon={<AlertCircle size={26} style={{ color: mutedColor }} />}
682
+ label="AMAGI 码"
683
+ value={data.amagi.code}
684
+ color={mutedColor}
685
+ valueColor={accentColor}
686
+ />
687
+ <DetailCell
688
+ icon={<Radio size={26} style={{ color: mutedColor }} />}
689
+ label="平台业务码"
690
+ value={data.amagi.platformCode}
691
+ color={mutedColor}
692
+ valueColor={accentColor}
693
+ />
694
+ <DetailCell
695
+ icon={<Gauge size={26} style={{ color: mutedColor }} />}
696
+ label="HTTP 状态"
697
+ value={data.amagi.httpStatus}
698
+ color={mutedColor}
699
+ valueColor={accentColor}
700
+ />
701
+ <DetailCell
702
+ icon={<Fingerprint size={26} style={{ color: mutedColor }} />}
703
+ label="请求 ID"
704
+ value={data.amagi.requestId}
705
+ color={mutedColor}
706
+ valueColor={accentColor}
707
+ />
708
+ <DetailCell
709
+ icon={<Repeat size={26} style={{ color: mutedColor }} />}
710
+ label="实际请求次数"
711
+ value={data.amagi.attempts}
712
+ color={mutedColor}
713
+ valueColor={accentColor}
714
+ />
715
+ <DetailCell
716
+ icon={<Timer size={26} style={{ color: mutedColor }} />}
717
+ label="耗时"
718
+ value={data.amagi.durationMs === undefined ? undefined : `${data.amagi.durationMs} ms`}
719
+ color={mutedColor}
720
+ valueColor={accentColor}
721
+ />
722
+ </div>
723
+
724
+ {/* 参数校验的字段级错误,只有 kind === 'validation' 时有 */}
725
+ {data.amagi.issues && data.amagi.issues.length > 0 && (
726
+ <div className="mt-12">
727
+ <div className="flex items-center gap-3 mb-5 opacity-70">
728
+ <ListChecks size={26} style={{ color: mutedColor }} />
729
+ <span className="text-xl font-semibold tracking-[0.12em]" style={{ color: mutedColor }}>
730
+ 参数问题
731
+ </span>
732
+ </div>
733
+ <ul className="space-y-4">
734
+ {data.amagi.issues.map((issue, index) => (
735
+ <li key={`${issue.path}-${index}`} className="flex gap-5 text-2xl leading-relaxed">
736
+ <span className="font-mono font-bold shrink-0" style={{ color: primaryColor }}>
737
+ {issue.path || '(根)'}
738
+ </span>
739
+ <span style={{ color: accentColor }}>{issue.message}</span>
740
+ </li>
741
+ ))}
742
+ </ul>
743
+ </div>
744
+ )}
745
+
746
+ {/* 逐个请求的明细。一次「翻 3 页 + 重试 1 次」在这里就是 4 行 */}
747
+ {data.amagi.trace && data.amagi.trace.length > 0 && (
748
+ <div className="mt-12">
749
+ <div className="flex items-center gap-3 mb-6 opacity-70">
750
+ <Route size={26} style={{ color: mutedColor }} />
751
+ <span className="text-xl font-semibold tracking-[0.12em]" style={{ color: mutedColor }}>
752
+ 请求轨迹({data.amagi.trace.length} 次)
753
+ </span>
754
+ </div>
755
+ <div className="space-y-6">
756
+ {data.amagi.trace.map((entry, index) => {
757
+ const { head, names, queryLength } = splitRequestUrl(entry.url)
758
+ const ok = entry.status !== undefined && entry.status >= 200 && entry.status < 300
759
+ return (
760
+ <div
761
+ key={`${entry.url}-${index}`}
762
+ className="p-8 rounded-7xl"
763
+ style={{ backgroundColor: dark ? 'rgba(0,0,0,0.2)' : 'rgba(255,255,255,0.5)' }}
764
+ >
765
+ <div className="flex items-center gap-4 flex-wrap mb-4">
766
+ <span
767
+ className="px-4 py-1 rounded-full text-xl font-bold"
768
+ style={{
769
+ backgroundColor: dark ? 'rgba(148,163,184,0.18)' : 'rgba(100,116,139,0.14)',
770
+ color: dark ? '#cbd5e1' : '#475569'
771
+ }}
772
+ >
773
+ {TRACE_REASON_LABELS[entry.reason] ?? entry.reason}
774
+ </span>
775
+ <span className="font-mono text-2xl font-bold" style={{ color: accentColor }}>
776
+ {entry.method}
777
+ </span>
778
+ <span
779
+ className="font-mono text-2xl font-bold"
780
+ style={{ color: entry.status === undefined ? mutedColor : ok ? (dark ? '#4ade80' : '#15803d') : primaryColor }}
781
+ >
782
+ {entry.status ?? '未发出'}
783
+ </span>
784
+ <span className="font-mono text-xl opacity-70" style={{ color: mutedColor }}>
785
+ {entry.durationMs} ms
786
+ </span>
787
+ {entry.retryOf && (
788
+ <span className="font-mono text-xl" style={{ color: primaryColor }}>
789
+ 重试于 {entry.retryOf}
790
+ </span>
791
+ )}
792
+ </div>
793
+ <p className="font-mono text-xl break-all leading-relaxed" style={{ color: secondaryColor }}>
794
+ {head}
795
+ </p>
796
+ {names.length > 0 && (
797
+ <p className="font-mono text-lg break-all mt-3 opacity-60" style={{ color: mutedColor }}>
798
+ {names.length} 个查询参数 / {queryLength} 字符:{names.slice(0, 12).join(' ')}
799
+ {names.length > 12 ? ` …+${names.length - 12}` : ''}
800
+ </p>
801
+ )}
802
+ </div>
803
+ )
804
+ })}
805
+ </div>
806
+ </div>
807
+ )}
808
+ </div>
809
+ </div>
810
+ )}
811
+
812
+ {/* 验证二维码 */}
813
+ {data.isVerification && data.verificationUrl && (
814
+ <div className="mb-16 p-12 rounded-[40px]" style={{ backgroundColor: dark ? 'rgba(0,0,0,0.25)' : 'rgba(255,255,255,0.6)' }}>
815
+ <div className="flex items-center gap-6 mb-10">
816
+ <QrCode size={40} className="text-warning" />
817
+ <span className="text-3xl font-semibold" style={{ color: accentColor }}>
818
+ 人机验证
819
+ </span>
820
+ </div>
821
+ <div className="flex gap-16 items-center">
822
+ <img src={generateQRCode(data.verificationUrl, dark)} alt="验证二维码" className="w-64 h-64 rounded-3xl" />
823
+ <div className="space-y-6">
824
+ <p className="text-3xl" style={{ color: secondaryColor }}>
825
+ 请在 120 秒内完成验证
826
+ </p>
827
+ <ol className="space-y-4 text-2xl" style={{ color: mutedColor }}>
828
+ <li>1. 使用手机扫描二维码</li>
829
+ <li>2. 在网页中完成人机验证</li>
830
+ <li>3. 将验证结果发送至此对话</li>
831
+ </ol>
832
+ {data.verificationUrl && (
833
+ <p className="text-xl break-all mt-8" style={{ color: mutedColor }}>
834
+ {data.verificationUrl}
835
+ </p>
836
+ )}
837
+ </div>
838
+ </div>
839
+ </div>
840
+ )}
841
+
842
+ {/* 触发命令 */}
843
+ {data.triggerCommand && (
844
+ <div className="mb-14">
845
+ <SectionTitle
846
+ icon={<Terminal size={36} style={{ color: mutedColor }} />}
847
+ en="Trigger Command"
848
+ zh="触发命令"
849
+ color={mutedColor}
850
+ />
851
+ <div className="p-10 rounded-[36px]" style={{ backgroundColor: dark ? 'rgba(0,0,0,0.2)' : 'rgba(255,255,255,0.5)' }}>
852
+ <pre
853
+ className="text-3xl leading-relaxed whitespace-pre-wrap break-all font-mono"
854
+ style={{ color: accentColor }}
855
+ dangerouslySetInnerHTML={{ __html: convertAnsiToHtml(data.triggerCommand) }}
856
+ />
857
+ </div>
858
+ </div>
859
+ )}
860
+
861
+ {/* 错误堆栈 */}
862
+ <div className="mb-14">
863
+ <SectionTitle
864
+ icon={<AlertCircle size={36} style={{ color: mutedColor }} />}
865
+ en="Stack Trace"
866
+ zh={data.amagi ? '调用栈(结构化上下文见上)' : data.error?.dump ? '调用栈(对象转储见下)' : '错误堆栈'}
867
+ color={mutedColor}
868
+ />
869
+ <div
870
+ className="p-10 rounded-[36px]"
871
+ style={{
872
+ backgroundColor: dark ? 'rgba(220,38,38,0.1)' : 'rgba(254,202,202,0.4)',
873
+ border: `1px solid ${dark ? 'rgba(248,113,113,0.2)' : 'rgba(252,165,165,0.5)'}`
874
+ }}
875
+ >
876
+ <pre
877
+ className="text-2xl leading-relaxed whitespace-pre-wrap break-all font-mono"
878
+ style={{ color: dark ? 'rgba(255,255,255,0.85)' : 'rgba(127,29,29,0.9)' }}
879
+ dangerouslySetInnerHTML={{ __html: stackHtml }}
880
+ />
881
+ </div>
882
+ </div>
883
+
884
+ {/* 对象转储:非 amagi 异常的自有属性,帧已经在上面单独高亮了 */}
885
+ {data.error?.dump && (
886
+ <div className="mb-14">
887
+ <SectionTitle icon={<Braces size={36} style={{ color: mutedColor }} />} en="Object Dump" zh="对象转储" color={mutedColor} />
888
+ <div className="p-10 rounded-[36px]" style={{ backgroundColor: dark ? 'rgba(0,0,0,0.2)' : 'rgba(255,255,255,0.5)' }}>
889
+ <pre
890
+ className="text-2xl leading-relaxed whitespace-pre-wrap break-all font-mono"
891
+ style={{ color: dark ? 'rgba(255,255,255,0.85)' : 'rgba(127,29,29,0.9)' }}
892
+ dangerouslySetInnerHTML={{ __html: convertAnsiToHtml(data.error.dump) }}
893
+ />
894
+ </div>
895
+ </div>
896
+ )}
897
+
898
+ {/* 执行日志 */}
899
+ {data.logs && data.logs.length > 0 && (
900
+ <div className="mb-14">
901
+ <SectionTitle
902
+ icon={<FileText size={36} style={{ color: mutedColor }} />}
903
+ en="Execution Logs"
904
+ zh="执行日志"
905
+ color={mutedColor}
906
+ />
907
+ <div className="space-y-6">
908
+ {data.logs.map((log, index) => {
909
+ const theme = getLogLevelTheme(log.level, dark)
910
+ return (
911
+ <fieldset key={index} className={`relative rounded-3xl ${theme.bgClass} border-2 ${theme.borderClass} p-6`}>
912
+ {/* 时间戳 */}
913
+ <legend className="flex items-center gap-2 ml-4">
914
+ {/* 左侧圆角装饰 */}
915
+ <span className={`w-2 h-6 rounded-full -mr-1.5 ${theme.dotClass}`} />
916
+ <span className="flex items-center gap-2 px-3">
917
+ <Clock size={18} className={theme.iconClass} />
918
+ <span className={`text-xl font-mono font-medium ${theme.textClass}`}>{log.timestamp}</span>
919
+ </span>
920
+ {/* 右侧圆角装饰 */}
921
+ <span className={`w-2 h-6 rounded-full -ml-1.5 ${theme.dotClass}`} />
922
+ </legend>
923
+
924
+ {/* 日志等级 */}
925
+ <div className="absolute bottom-2 right-6 pointer-events-none">
926
+ <span className={`text-6xl font-black uppercase leading-none tracking-tight ${theme.levelClass}`}>{log.level}」</span>
927
+ </div>
928
+
929
+ {/* 日志内容 */}
930
+ <div
931
+ className="relative z-1 text-2xl font-mono whitespace-pre-wrap break-all leading-relaxed"
932
+ style={{ color: dark ? 'rgba(255,255,255,0.88)' : 'rgba(0,0,0,0.82)' }}
933
+ dangerouslySetInnerHTML={{ __html: convertAnsiToHtml(log.message) }}
934
+ />
935
+ </fieldset>
936
+ )
937
+ })}
938
+ </div>
939
+ </div>
940
+ )}
941
+
942
+ {/* 底部版本信息 */}
943
+ <div className="mt-auto pt-12" style={{ borderTop: `2px solid ${dark ? 'rgba(248,113,113,0.15)' : 'rgba(252,165,165,0.3)'}` }}>
944
+ {/* 版本信息:框架版本 / 插件版本 / 适配器 —— 合并成一行,适配器只显示名称 */}
945
+ <div className="flex items-center flex-wrap gap-x-16 gap-y-6 mb-12">
946
+ <div className="flex items-center gap-6">
947
+ <img src={(data as any).frameworkLogo ?? '/image/frame-logo.png'} className="h-16 w-auto" alt="Framework" />
948
+ <div>
949
+ <p className="text-xl" style={{ color: mutedColor }}>Framework / 框架版本</p>
950
+ <p className="text-3xl font-bold" style={{ color: accentColor }}>{data.frameworkVersion}</p>
951
+ </div>
952
+ </div>
953
+ <div className="flex items-center gap-6">
954
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 230 221" className="h-16 w-auto" style={{ color: accentColor }}>
955
+ <path
956
+ d="M132.75,87.37l-53.72-53.37c-4.66-4.63-1.38-12.58,5.18-12.58h115.13c6.57,0,9.84,7.95,5.18,12.58l-53.72,53.37c-4.99,4.96-13.06,4.96-18.05,0Z"
957
+ fill="currentColor"
958
+ />
959
+ <path
960
+ d="M28.49,186.89l.03-51.42c-.02-6.57,7.92-9.87,12.56-5.23l57.02,57.02c4.64,4.64,1.34,12.41-5.23,12.39h-51.42c-7.04-.02-12.94-5.72-12.96-12.76Z"
961
+ fill="currentColor"
962
+ />
963
+ <path
964
+ d="M41.54,23.68l163.04,163.05c4.78,4.78,1.39,12.95-5.36,12.94h-47.88c-9.69,0-18.99-3.86-25.84-10.71L39.3,102.75c-6.85-6.85-10.7-16.15-10.7-25.84V29.04c0-6.76,8.16-10.14,12.94-5.36Z"
965
+ fill="currentColor"
966
+ />
967
+ </svg>
968
+ <div>
969
+ <p className="text-xl" style={{ color: mutedColor }}>Plugin / 插件版本</p>
970
+ <p className="text-3xl font-bold" style={{ color: accentColor }}>{data.pluginVersion}</p>
971
+ </div>
972
+ </div>
973
+ {data.adapterInfo && (
974
+ <div className="flex items-center gap-6">
975
+ {getAdapterLogo(data.adapterInfo.name)}
976
+ <div>
977
+ <p className="text-xl" style={{ color: mutedColor }}>Adapter / 适配器</p>
978
+ <p className="text-3xl font-bold truncate" style={{ color: accentColor }}>{data.adapterInfo.name}</p>
979
+ </div>
980
+ </div>
981
+ )}
982
+ </div>
983
+ {/* 次要信息 */}
984
+ <div className="flex items-center gap-10 text-xl mb-12" style={{ color: mutedColor }}>
985
+ {data.buildTime && (
986
+ <div className="flex items-center gap-3">
987
+ <MdSchedule size={24} />
988
+ <span>
989
+ Built Time: {data.buildTime} 于{' '}
990
+ {formatDistanceToNow(parse(data.buildTime, 'yyyy年MM月dd日 HH:mm', new Date()), { locale: zhCN })}前
991
+ </span>
992
+ </div>
993
+ )}
994
+ {data.commitHash && (
995
+ <div className="flex items-center gap-3">
996
+ <GitBranch size={24} />
997
+ <span>Commit Hash: {data.commitHash}</span>
998
+ </div>
999
+ )}
1000
+ </div>
1001
+
1002
+ {/* 帮助提示 */}
1003
+ <div className="p-10 rounded-[36px]" style={{ backgroundColor: dark ? 'rgba(0,0,0,0.2)' : 'rgba(255,255,255,0.5)' }}>
1004
+ <div className="flex items-end justify-between mb-6">
1005
+ <div>
1006
+ <p className="text-3xl font-semibold mb-2" style={{ color: accentColor }}>
1007
+ Need Help? / 需要帮助?
1008
+ </p>
1009
+ <p className="text-2xl" style={{ color: secondaryColor }}>
1010
+ 提交问题时请附上完整报错截图、复现步骤和环境版本信息。
1011
+ </p>
1012
+ </div>
1013
+ <span
1014
+ className="text-xs font-black tracking-[0.2em] uppercase px-3 py-1 rounded-full"
1015
+ style={{
1016
+ color: primaryColor,
1017
+ backgroundColor: dark ? 'rgba(248,113,113,0.12)' : 'rgba(220,38,38,0.08)'
1018
+ }}
1019
+ >
1020
+ Support
1021
+ </span>
1022
+ </div>
1023
+ <div
1024
+ className="grid grid-cols-2 gap-x-6 gap-y-6 text-2xl leading-relaxed py-6"
1025
+ style={{
1026
+ borderTop: `1px solid ${dark ? 'rgba(248,113,113,0.2)' : 'rgba(220,38,38,0.12)'}`,
1027
+ borderBottom: `1px solid ${dark ? 'rgba(248,113,113,0.2)' : 'rgba(220,38,38,0.12)'}`
1028
+ }}
1029
+ >
1030
+ <div>
1031
+ <p className="font-semibold mb-1" style={{ color: accentColor }}>
1032
+ GitHub Issue
1033
+ </p>
1034
+ <p className="text-xl break-all" style={{ color: secondaryColor }}>
1035
+ https://github.com/maimai993/koishi-plugin-kkk/issues/new/choose
1036
+ </p>
1037
+ </div>
1038
+ <div>
1039
+ <p className="font-semibold mb-1" style={{ color: accentColor }}>
1040
+ GitHub Repository
1041
+ </p>
1042
+ <p className="text-xl break-all" style={{ color: secondaryColor }}>
1043
+ https://github.com/maimai993/koishi-plugin-kkk
1044
+ </p>
1045
+ </div>
1046
+ <div>
1047
+ <p className="font-semibold mb-1" style={{ color: accentColor }}>
1048
+ QQ 群
1049
+ </p>
1050
+ <p className="text-xl" style={{ color: secondaryColor }}>
1051
+ 1050229473
1052
+ </p>
1053
+ </div>
1054
+ <div>
1055
+ <p className="font-semibold mb-1" style={{ color: accentColor }}>
1056
+ 附带信息
1057
+ </p>
1058
+ <p className="text-xl" style={{ color: secondaryColor }}>
1059
+ 此图片 + 触发命令 + 对应配置(自行脱敏处理)
1060
+ </p>
1061
+ </div>
1062
+ </div>
1063
+ <div className="flex items-center gap-4 mt-6 text-xl" style={{ color: mutedColor }}>
1064
+ <span className="font-mono">Tips:</span>
1065
+ <span>信息越完整,定位越快。</span>
1066
+ </div>
1067
+ </div>
1068
+ </div>
1069
+ </div>
1070
+ </DefaultLayout>
1071
+ )
1072
+ }
1073
+
1074
+ handlerError.displayName = 'handlerError'
1075
+
1076
+ export default handlerError