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,1053 @@
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.syncUpstreamToKoishi = exports.segment = exports.logger = exports.karin = exports.app = exports.isFfmpegAvailable = exports.ffprobe = exports.ffmpeg = exports.createServerErrorResponse = exports.createNotFoundResponse = exports.createBadRequestResponse = exports.createSuccessResponse = exports.authMiddleware = exports.defineConfig = exports.checkPort = exports.isDocker = exports.mkdirSync = exports.updatePkg = exports.checkPkgUpdate = exports.restart = exports.watch = exports.hooks = exports.config = exports.common = exports.render = exports.db = exports.contactFriend = exports.contactGroup = exports.ForwardPayload = exports.Message = exports.KkkBot = exports.NEXT = exports.BOT_READY = exports.BOT_DISCONNECT = exports.BOT_CONNECT = exports.getKoishiContext = void 0;
7
+ exports.makeForward = makeForward;
8
+ exports.logs = logs;
9
+ exports.parseChangelog = parseChangelog;
10
+ exports.range = range;
11
+ /**
12
+ * `node-karin` 的 Koishi 兼容实现(迁移核心)。
13
+ *
14
+ * 目标:让 packages/core/src 里的业务代码几乎原样运行 —— 只把框架 API 换成 Koishi 的实现。
15
+ * 覆盖范围按原插件的真实调用面收敛:
16
+ * karin.command / task / getBot / getAllBot(ID|List) / contactGroup / sendMsg / sendMaster / on / ctx
17
+ * logger(见 ./logger)、segment(见 ./segment)、common.makeForward、config.master、db(KV)、render、sqlite3、root
18
+ */
19
+ const node_child_process_1 = require("node:child_process");
20
+ const node_url_1 = require("node:url");
21
+ const node_fs_1 = __importDefault(require("node:fs"));
22
+ const node_path_1 = __importDefault(require("node:path"));
23
+ const koishi_1 = require("koishi");
24
+ const logger_1 = require("./logger");
25
+ Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_1.logger; } });
26
+ const runtime_1 = require("./runtime");
27
+ const segment_1 = require("./segment");
28
+ Object.defineProperty(exports, "segment", { enumerable: true, get: function () { return segment_1.segment; } });
29
+ const syncConfig_1 = require("./syncConfig");
30
+ Object.defineProperty(exports, "syncUpstreamToKoishi", { enumerable: true, get: function () { return syncConfig_1.syncUpstreamToKoishi; } });
31
+ const text_1 = require("./text");
32
+ /** 取当前 Koishi 上下文(移植代码访问 Koishi 服务用) */
33
+ const getKoishiContext = () => (0, runtime_1.getRuntime)().ctx;
34
+ exports.getKoishiContext = getKoishiContext;
35
+ exports.BOT_CONNECT = 'bot-connect';
36
+ exports.BOT_DISCONNECT = 'bot-disconnect';
37
+ exports.BOT_READY = 'bot-ready';
38
+ /** 命令处理器调用 next() 时返回的哨兵,表示继续走后续中间件 */
39
+ exports.NEXT = Symbol('kkk.next');
40
+ /* ------------------------------------------------------------------ *
41
+ * Bot 适配
42
+ * ------------------------------------------------------------------ */
43
+ const MIME_BY_EXT = {
44
+ '.png': 'image/png',
45
+ '.jpg': 'image/jpeg',
46
+ '.jpeg': 'image/jpeg',
47
+ '.gif': 'image/gif',
48
+ '.webp': 'image/webp',
49
+ '.mp4': 'video/mp4',
50
+ '.mp3': 'audio/mpeg',
51
+ '.amr': 'audio/amr',
52
+ '.silk': 'audio/silk',
53
+ '.bin': 'application/octet-stream'
54
+ };
55
+ function guessMime(filePath) {
56
+ const ext = node_path_1.default.extname(filePath).toLowerCase();
57
+ return MIME_BY_EXT[ext] ?? 'application/octet-stream';
58
+ }
59
+ /** 仿 karin 的 AdapterType(机器人实例) */
60
+ class KkkBot {
61
+ bot;
62
+ constructor(bot) {
63
+ this.bot = bot;
64
+ }
65
+ get selfId() {
66
+ return this.bot.selfId;
67
+ }
68
+ get account() {
69
+ return {
70
+ selfId: this.bot.selfId,
71
+ uid: this.bot.user?.id ?? this.bot.selfId,
72
+ uin: this.bot.selfId,
73
+ name: this.bot.user?.name ?? this.bot.selfId,
74
+ avatar: this.bot.user?.avatar
75
+ };
76
+ }
77
+ get adapter() {
78
+ const platform = String(this.bot.platform ?? '');
79
+ const raw = this.bot.adapter || {};
80
+ const cfg = raw.config ?? {};
81
+ return {
82
+ name: platform,
83
+ protocol: platform,
84
+ standard: platform,
85
+ // 错误卡片模板还会读这三项,之前没给 → 卡片上显示 undefined 和一个空的「v」
86
+ platform: String(raw.platform ?? cfg.platform ?? (platform || '未知')),
87
+ communication: String(raw.communication ?? cfg.communication ?? cfg.protocol ?? '未知'),
88
+ version: String(raw.version ?? cfg.version ?? ''),
89
+ raw: this.bot.adapter
90
+ };
91
+ }
92
+ get ctx() {
93
+ return this.bot.ctx;
94
+ }
95
+ /** 好友列表 */
96
+ /**
97
+ * 好友列表。
98
+ *
99
+ * Koishi 的 Bot 没有统一的 getFriendList,拿不到就返回空数组 ——
100
+ * 上游用它来「找能给主人发消息的 bot」,空数组会自然走到后面的兜底逻辑(getAllBotID),
101
+ * 所以这里**不能抛错**,否则整条推送链路会断在第一步。
102
+ */
103
+ async getFriendList() {
104
+ try {
105
+ return await this.bot.getFriendList();
106
+ }
107
+ catch (error) {
108
+ logger_1.logger.debug('getFriendList 失败: ' + String(error));
109
+ return [];
110
+ }
111
+ }
112
+ /** 群信息,karin 侧字段为 groupName */
113
+ async getGroupInfo(groupId) {
114
+ try {
115
+ const guild = await this.bot.getGuild(groupId);
116
+ return { ...guild, groupId, groupName: guild?.name ?? '' };
117
+ }
118
+ catch (error) {
119
+ logger_1.logger.debug('getGroupInfo 失败: ' + String(error));
120
+ return undefined;
121
+ }
122
+ }
123
+ async getGroupAvatarUrl(groupId) {
124
+ try {
125
+ return await this.bot.getGroupAvatarUrl?.(groupId) ?? '';
126
+ }
127
+ catch {
128
+ return '';
129
+ }
130
+ }
131
+ async getAvatarUrl(userId) {
132
+ try {
133
+ return await this.bot.getAvatarUrl?.(userId) ?? '';
134
+ }
135
+ catch {
136
+ return '';
137
+ }
138
+ }
139
+ /**
140
+ * 合并转发。
141
+ *
142
+ * 上游是把内容装进「合并转发」发出去;但**部分适配器根本没有合并转发能力**
143
+ * (例如 QQ 官方适配器 koishi-plugin-adapter-qq-crack,platform=\`qqguild\`,
144
+ * 整个包里没有一处 forward),硬发 \`<message>\` 元素只会失败或变成一条空消息。
145
+ * 所以这里先问适配器支不支持,不支持就**退化成直接发送这些元素**(视觉上是普通消息)。
146
+ */
147
+ async sendForwardMsg(contact, elements, _options) {
148
+ const channelId = typeof contact === 'string' ? contact : contact.peer;
149
+ const payload = elements instanceof ForwardPayload ? elements : new ForwardPayload(normalizeContent(elements));
150
+ if (supportsForward(this.bot)) {
151
+ try {
152
+ const ids = await this.bot.sendMessage(channelId, [(0, koishi_1.h)('message', ...payload.elements)]);
153
+ return { messageId: ids[ids.length - 1] ?? '' };
154
+ }
155
+ catch (error) {
156
+ logger_1.logger.warn('合并转发发送失败,改为直接发送内容: ' + String(error?.message ?? error));
157
+ }
158
+ }
159
+ else {
160
+ logger_1.logger.debug('当前适配器(' + this.bot.platform + ')不支持合并转发,改为直接发送内容');
161
+ }
162
+ // 退化路径:整条发一次;失败再逐个元素发,尽量把内容送出去
163
+ try {
164
+ const ids = await this.bot.sendMessage(channelId, payload.elements);
165
+ return { messageId: ids[ids.length - 1] ?? '' };
166
+ }
167
+ catch (error) {
168
+ logger_1.logger.warn('整条发送失败,改为逐个元素发送: ' + String(error?.message ?? error));
169
+ let lastId = '';
170
+ for (const item of payload.elements) {
171
+ const ids = await this.bot.sendMessage(channelId, [item]);
172
+ lastId = ids[ids.length - 1] ?? lastId;
173
+ }
174
+ return { messageId: lastId };
175
+ }
176
+ }
177
+ /**
178
+ * 上传群文件。
179
+ *
180
+ * 上游会把「文件」写成各种形式:本地路径、`file://`、`base64://xxx`(Base.ts 生成视频文件时就是这种)。
181
+ * 之前这里只认路径,base64 串会直接抛「上传文件不存在」或者被当成 URL 交给适配器去 fetch
182
+ * (日志表现:`QQ 消息发送失败 fetch base64://AAAAHGZ0eXBpc29t…`)。
183
+ * 现在统一交给 `segment.file` 处理:它能吃路径 / file:// / base64:// / Buffer。
184
+ */
185
+ async uploadFile(contact, file, name) {
186
+ const channelId = typeof contact === 'string' ? contact : contact.peer;
187
+ let element;
188
+ if (Buffer.isBuffer(file)) {
189
+ element = segment_1.segment.file(file, name);
190
+ }
191
+ else if (typeof file === 'string' && (file.startsWith('base64://') || file.startsWith('data:'))) {
192
+ element = segment_1.segment.file(file, name);
193
+ }
194
+ else {
195
+ const filePath = String(file).startsWith('file://') ? String(file).slice('file://'.length) : String(file);
196
+ if (!node_fs_1.default.existsSync(filePath))
197
+ throw new Error('上传文件不存在: ' + filePath);
198
+ element = segment_1.segment.file(node_fs_1.default.readFileSync(filePath), name ?? node_path_1.default.basename(filePath));
199
+ }
200
+ return this.bot.sendMessage(channelId, [element]);
201
+ }
202
+ /** 群成员信息,karin 侧字段:userId/nick/card/role */
203
+ async getGroupMemberInfo(groupId, userId) {
204
+ const bot = this.bot;
205
+ try {
206
+ const member = await bot.getGuildMember?.(groupId, userId);
207
+ if (!member)
208
+ return undefined;
209
+ return { ...member, userId: member.user?.id ?? userId, nick: member.user?.name ?? member.nick ?? '', card: member.nick ?? '' };
210
+ }
211
+ catch (error) {
212
+ logger_1.logger.debug('getGroupMemberInfo 失败: ' + String(error));
213
+ return undefined;
214
+ }
215
+ }
216
+ /** 群列表,karin 侧字段:group_id/group_name */
217
+ async getGroupList() {
218
+ const bot = this.bot;
219
+ try {
220
+ const list = await bot.getGuildList?.();
221
+ return (list ?? []).map((item) => ({ ...item, group_id: item.id, group_name: item.name }));
222
+ }
223
+ catch (error) {
224
+ logger_1.logger.debug('getGroupList 失败: ' + String(error));
225
+ return [];
226
+ }
227
+ }
228
+ /** 取消息(karin 的 bot.getMsg),结果按 karin 的 elements 形状返回 */
229
+ async getMsg(contact, messageId) {
230
+ const channelId = typeof contact === 'string' ? contact : contact.peer;
231
+ try {
232
+ const message = await this.bot.getMessage(channelId, messageId);
233
+ if (!message)
234
+ return { message_id: messageId, elements: [], raw_message: '' };
235
+ const elements = (message.elements ?? []).map((el) => {
236
+ switch (el.type) {
237
+ case 'text': return { type: 'text', text: el.attrs?.content ?? '' };
238
+ case 'image': return { type: 'image', file: el.attrs?.src ?? '' };
239
+ case 'at': return { type: 'at', qq: el.attrs?.id ?? '' };
240
+ case 'quote': return { type: 'reply', id: el.attrs?.id ?? '' };
241
+ default: return { type: el.type, data: JSON.stringify(el.attrs ?? {}) };
242
+ }
243
+ });
244
+ return { message_id: message.id ?? messageId, raw_message: message.content ?? '', elements };
245
+ }
246
+ catch (error) {
247
+ logger_1.logger.debug('getMsg 失败: ' + String(error));
248
+ return { message_id: messageId, elements: [], raw_message: '' };
249
+ }
250
+ }
251
+ /** 发送消息(karin 的 bot.sendMsg) */
252
+ async sendMsg(contact, content, _options) {
253
+ const channelId = typeof contact === 'string' ? contact : contact.peer;
254
+ const ids = await this.bot.sendMessage(channelId, normalizeContent(content));
255
+ return { messageId: ids[ids.length - 1] ?? '' };
256
+ }
257
+ /**
258
+ * 消息表情回应(karin 的 bot.setMsgReaction)。
259
+ * Satori 机器人没有统一接口,能调则调,不能调就静默返回 false —— 原插件只用它做「处理中/成功」提示。
260
+ */
261
+ async setMsgReaction(_contact, messageId, emojiId, isAdd = true) {
262
+ const bot = this.bot;
263
+ const fn = bot.setMessageReaction ?? bot.setMsgReaction;
264
+ if (typeof fn !== 'function')
265
+ return false;
266
+ try {
267
+ await fn.call(bot, messageId, String(emojiId), isAdd);
268
+ return true;
269
+ }
270
+ catch {
271
+ return false;
272
+ }
273
+ }
274
+ /**
275
+ * 撤回消息。
276
+ *
277
+ * 必须带上频道号:QQ 适配器的 `deleteMessage(channelId, messageId)` 会在内部对
278
+ * channelId 调 `.startsWith`,传 undefined 直接抛
279
+ * `TypeError: Cannot read properties of undefined (reading 'startsWith')`(撤回全部失败)。
280
+ * @param messageId 要撤回的消息 id
281
+ * @param channelId 频道/群 id(karin 侧调用一般不带,这时用最近一次事件的频道)
282
+ */
283
+ async recallMsg(messageId, channelId) {
284
+ try {
285
+ const channel = channelId || this.lastChannelId || '';
286
+ return await this.bot.deleteMessage(channel, messageId);
287
+ }
288
+ catch (error) {
289
+ logger_1.logger.debug('recallMsg 失败: ' + String(error));
290
+ return undefined;
291
+ }
292
+ }
293
+ }
294
+ exports.KkkBot = KkkBot;
295
+ /* ------------------------------------------------------------------ *
296
+ * Message 适配
297
+ * ------------------------------------------------------------------ */
298
+ /** 仿 karin 的 Message(事件对象) */
299
+ class Message {
300
+ /** 消息文本(原插件会直接改写这个字段) */
301
+ msg;
302
+ selfId;
303
+ userId;
304
+ groupId;
305
+ isGroup;
306
+ sender;
307
+ contact;
308
+ bot;
309
+ messageId;
310
+ /** 引用的消息 ID(karin 的 e.replyId) */
311
+ replyId;
312
+ session;
313
+ /** 原始 satori 事件载荷 */
314
+ raw;
315
+ constructor(init) {
316
+ this.msg = init.msg ?? '';
317
+ this.selfId = init.selfId ?? '';
318
+ this.userId = init.userId ?? '';
319
+ this.groupId = init.groupId ?? '';
320
+ this.isGroup = init.isGroup ?? false;
321
+ this.sender = init.sender ?? { userId: this.userId, nick: '' };
322
+ this.contact = init.contact ?? { peer: this.groupId || ('private:' + this.userId), isGroup: this.isGroup };
323
+ this.bot = init.bot instanceof KkkBot ? init.bot : new KkkBot(init.bot);
324
+ this.messageId = init.messageId ?? '';
325
+ this.replyId = init.replyId ?? '';
326
+ this.session = init.session;
327
+ this.raw = init.raw;
328
+ }
329
+ /**
330
+ * 由 Koishi 会话构造。
331
+ * @param session Koishi 会话
332
+ * @param msg 已经归一化过的消息文本(QQ 卡片链路会在匹配前先做异步还原,见 karin/module/utils/QqCardResolve.ts);
333
+ * 不传时退回同步归一化(还原 JSON 转义 + 提取已有链接)
334
+ */
335
+ static fromSession(session, msg) {
336
+ const isGroup = !!session.guildId;
337
+ const userId = session.userId ?? '';
338
+ return new Message({
339
+ // QQ 分享卡片在适配器里是「带 JSON 转义的一整段文本」,这里还原转义并补上挖出来的链接,
340
+ // 否则各平台的链接正则匹配不到(详见 compat/text.ts)
341
+ msg: msg ?? (0, text_1.normalizeMessageText)(session.content ?? ''),
342
+ selfId: session.selfId,
343
+ userId,
344
+ groupId: session.guildId ?? session.channelId ?? '',
345
+ isGroup,
346
+ sender: { userId, nick: session.author?.nick ?? session.username ?? '' },
347
+ contact: {
348
+ peer: session.channelId ?? (isGroup ? session.guildId : 'private:' + userId),
349
+ guildId: session.guildId ?? undefined,
350
+ userId,
351
+ isGroup
352
+ },
353
+ bot: session.bot,
354
+ messageId: session.messageId ?? '',
355
+ replyId: session.quote?.id ?? session.event?.message?.quote?.id ?? '',
356
+ session,
357
+ raw: session.event
358
+ });
359
+ }
360
+ /**
361
+ * 回复消息。
362
+ *
363
+ * **被动回复兜底**:QQ 官方 bot 的「被动回复」有硬限制(一条消息只能回几次、还有时间窗),
364
+ * 而弹幕烧录这种操作动辄几分钟 —— 回来再 reply 就会撞
365
+ * `[40034128] 回复消息失败,被动回复时间或者次数超过限制`,视频明明下好了却发不出去。
366
+ * 这时自动改用**主动消息**(不带引用,直接往频道里发),失败才把原错误抛出去。
367
+ */
368
+ async reply(content, _options) {
369
+ const elements = normalizeContent(content);
370
+ /**
371
+ * 主动消息兜底(重点)。
372
+ *
373
+ * QQ 适配器在「被动回复超限」时**不一定抛异常**:它只是发不出去、返回空数组,
374
+ * 于是 await send() 看起来是成功的 —— 视频就静默丢了。所以这里除了 catch,
375
+ * 还要看**有没有拿到消息 ID**:没拿到就换主动消息(不带引用)重发一次。
376
+ */
377
+ const sendActive = async () => {
378
+ const activeIds = await this.bot.bot.sendMessage(this.contact.peer, elements);
379
+ return { messageId: activeIds?.[activeIds.length - 1] ?? '' };
380
+ };
381
+ try {
382
+ if (this.session) {
383
+ const ids = await this.session.send(elements);
384
+ const id = ids?.[ids.length - 1] ?? '';
385
+ if (!id) {
386
+ logger_1.logger.mark('[compat] 回复没有返回消息 ID(多为被动回复超限),改用主动消息重发');
387
+ return await sendActive();
388
+ }
389
+ return { messageId: id };
390
+ }
391
+ const ids = await this.bot.bot.sendMessage(this.contact.peer, elements);
392
+ return { messageId: ids?.[ids.length - 1] ?? '' };
393
+ }
394
+ catch (error) {
395
+ const text = String(error?.message ?? error);
396
+ // 被动回复额度/时间窗超了:换成主动消息再试一次
397
+ if (!/被动回复|40034128|timeout|次数超过/.test(text))
398
+ throw error;
399
+ // 用 mark 级别:这是「视频明明下好了却发不出去」的关键兜底,日志里要看得见
400
+ logger_1.logger.mark('[compat] 被动回复受限,改用主动消息发送: ' + text);
401
+ return await sendActive();
402
+ }
403
+ }
404
+ /** karin 的 e.bot 直接就是发送者 */
405
+ async sendMsg(content) {
406
+ return this.reply(content);
407
+ }
408
+ }
409
+ exports.Message = Message;
410
+ function normalizeContent(content) {
411
+ if (content === undefined || content === null)
412
+ return [];
413
+ return Array.isArray(content) ? content : [content];
414
+ }
415
+ /**
416
+ * 合并转发的载荷。
417
+ *
418
+ * 上游 \`common.makeForward(elements, botId, botName)\` 的返回值只被 \`bot.sendForwardMsg()\` 消费,
419
+ * 所以这里用一个带类型的对象承载「哪些元素要转发」,由 sendForwardMsg 决定真转发还是退化成直发。
420
+ */
421
+ class ForwardPayload {
422
+ elements;
423
+ botId;
424
+ botName;
425
+ constructor(elements, botId, botName) {
426
+ this.elements = elements;
427
+ this.botId = botId;
428
+ this.botName = botName;
429
+ }
430
+ }
431
+ exports.ForwardPayload = ForwardPayload;
432
+ /** karin 的 common.makeForward */
433
+ function makeForward(elements, botId, botName) {
434
+ return new ForwardPayload(normalizeContent(elements), botId, botName);
435
+ }
436
+ /**
437
+ * 适配器是否支持「合并转发」。
438
+ *
439
+ * OneBot 系(platform 为 onebot / red / chronocat…)支持 Satori 的 \`<message>\` 元素;
440
+ * QQ 官方 API(qqguild / qq / qqbot)没有这个能力,必须退化。
441
+ */
442
+ function supportsForward(bot) {
443
+ const platform = String(bot?.platform ?? '');
444
+ if (!platform)
445
+ return false;
446
+ return !/qqguild|qqbot|^qq$|official/i.test(platform);
447
+ }
448
+ /* ------------------------------------------------------------------ *
449
+ * karin 门面
450
+ * ------------------------------------------------------------------ */
451
+ let commandOrder = 0;
452
+ const contactGroup = (groupId) => ({ peer: groupId, guildId: groupId, isGroup: true });
453
+ exports.contactGroup = contactGroup;
454
+ const contactFriend = (userId) => ({ peer: 'private:' + userId, userId, isGroup: false });
455
+ exports.contactFriend = contactFriend;
456
+ function resolveBot(selfId) {
457
+ const runtime = (0, runtime_1.tryGetRuntime)();
458
+ if (!runtime)
459
+ return undefined;
460
+ const bots = runtime.ctx.bots;
461
+ if (!bots?.length)
462
+ return undefined;
463
+ const matched = selfId ? bots.find((bot) => bot.selfId === selfId || bot.user?.id === selfId) : undefined;
464
+ return new KkkBot(matched ?? bots[0]);
465
+ }
466
+ function command(reg, handler, options) {
467
+ const registration = { reg, handler, options, order: commandOrder++ };
468
+ runtime_1.commandQueue.push(registration);
469
+ return registration;
470
+ }
471
+ function task(name, cron, handler, options) {
472
+ const registration = { name, cron, handler, options };
473
+ runtime_1.taskQueue.push(registration);
474
+ return registration;
475
+ }
476
+ function on(event, handler) {
477
+ runtime_1.eventQueue.push({ event, handler });
478
+ return () => {
479
+ const index = runtime_1.eventQueue.findIndex((item) => item.handler === handler);
480
+ if (index >= 0)
481
+ runtime_1.eventQueue.splice(index, 1);
482
+ };
483
+ }
484
+ async function sendMsg(selfId, contact, content, _options) {
485
+ const bot = resolveBot(selfId);
486
+ if (!bot)
487
+ throw new Error('[kkk] 没有可用的机器人实例,无法发送消息');
488
+ const channelId = typeof contact === 'string' ? contact : contact.peer;
489
+ const ids = await bot.bot.sendMessage(channelId, normalizeContent(content));
490
+ return { messageId: ids[ids.length - 1] ?? '', rawData: ids };
491
+ }
492
+ async function sendMaster(botId, master, content, _options) {
493
+ const bot = resolveBot(botId);
494
+ if (!bot)
495
+ throw new Error('[kkk] 没有可用的机器人实例,无法发送消息');
496
+ const elements = normalizeContent(content);
497
+ const target = bot.bot;
498
+ // Satori 的 Bot 有 sendPrivateMessage;个别适配器没有,退化成私聊频道 id
499
+ const ids = typeof target.sendPrivateMessage === 'function'
500
+ ? await target.sendPrivateMessage(master, elements)
501
+ : await target.sendMessage('private:' + master, elements);
502
+ return { messageId: ids?.[ids.length - 1] ?? '', rawData: ids };
503
+ }
504
+ /**
505
+ * 等待同一会话中的下一条消息(karin 的 karin.ctx)。
506
+ */
507
+ function waitContext(event, options = {}) {
508
+ const runtime = (0, runtime_1.getRuntime)();
509
+ const timeout = options.time ?? 60 * 1000;
510
+ return new Promise((resolve, reject) => {
511
+ let settled = false;
512
+ const dispose = runtime.ctx.on('message', (session) => {
513
+ if (settled)
514
+ return;
515
+ if (session.channelId !== event.contact.peer)
516
+ return;
517
+ if (event.userId && session.userId !== event.userId)
518
+ return;
519
+ settled = true;
520
+ dispose();
521
+ clearTimeout(timer);
522
+ resolve(Message.fromSession(session));
523
+ });
524
+ const timer = setTimeout(() => {
525
+ if (settled)
526
+ return;
527
+ settled = true;
528
+ dispose();
529
+ if (options.throwOnTimeout)
530
+ reject(new Error('等待用户输入超时'));
531
+ else
532
+ resolve(undefined);
533
+ }, timeout);
534
+ });
535
+ }
536
+ /* ------------------------------------------------------------------ *
537
+ * KV 存储(karin 的 db.get/set/del)
538
+ * ------------------------------------------------------------------ */
539
+ const kvCache = new Map();
540
+ let kvLoaded = false;
541
+ function kvFile() {
542
+ return node_path_1.default.resolve((0, runtime_1.getRuntime)().dataRoot, 'koishi-plugin-kkk', 'data', 'kv.json');
543
+ }
544
+ function loadKv() {
545
+ if (kvLoaded)
546
+ return;
547
+ kvLoaded = true;
548
+ try {
549
+ const file = kvFile();
550
+ if (node_fs_1.default.existsSync(file)) {
551
+ const data = JSON.parse(node_fs_1.default.readFileSync(file, 'utf8'));
552
+ for (const [key, value] of Object.entries(data))
553
+ kvCache.set(key, value);
554
+ }
555
+ }
556
+ catch (error) {
557
+ logger_1.logger.warn('读取 KV 存储失败: ' + String(error));
558
+ }
559
+ }
560
+ function saveKv() {
561
+ try {
562
+ const file = kvFile();
563
+ node_fs_1.default.mkdirSync(node_path_1.default.dirname(file), { recursive: true });
564
+ node_fs_1.default.writeFileSync(file, JSON.stringify(Object.fromEntries(kvCache), null, 2));
565
+ }
566
+ catch (error) {
567
+ logger_1.logger.warn('写入 KV 存储失败: ' + String(error));
568
+ }
569
+ }
570
+ exports.db = {
571
+ async get(key) {
572
+ loadKv();
573
+ return kvCache.get(key);
574
+ },
575
+ async set(key, value) {
576
+ loadKv();
577
+ kvCache.set(key, value);
578
+ saveKv();
579
+ },
580
+ async del(key) {
581
+ loadKv();
582
+ kvCache.delete(key);
583
+ saveKv();
584
+ },
585
+ async all() {
586
+ loadKv();
587
+ return Object.fromEntries(kvCache);
588
+ },
589
+ async clear() {
590
+ kvCache.clear();
591
+ saveKv();
592
+ }
593
+ };
594
+ /* ------------------------------------------------------------------ *
595
+ * render / app / 其它零散 API
596
+ * ------------------------------------------------------------------ */
597
+ exports.render = {
598
+ /**
599
+ * karin 的 render.render:给 HTML 文件截图。
600
+ * 这里走 koishi-plugin-puppeteer(可选依赖)。
601
+ */
602
+ async render(options) {
603
+ const runtime = (0, runtime_1.getRuntime)();
604
+ const puppeteer = runtime.ctx.puppeteer;
605
+ if (!puppeteer)
606
+ throw new Error('[kkk] 渲染失败:未安装 koishi-plugin-puppeteer');
607
+ const screenshotOptions = {
608
+ file: options.file,
609
+ selector: options.selector ?? '#container',
610
+ fullPage: options.fullPage ?? false,
611
+ omitBackground: options.omitBackground ?? true,
612
+ type: options.type ?? 'png',
613
+ pageGotoParams: options.pageGotoParams
614
+ };
615
+ /**
616
+ * 自己开页面对 HTML 文件截图。
617
+ *
618
+ * 不能走 `puppeteer.render(html, options)` —— 那个 API 的第二个参数是**回调函数**,
619
+ * 传截图配置进去会直接报 `callback is not a function`
620
+ * (抖音弹幕条渲染就是这么挂的,日志里一堆「弹幕条渲染失败,将按纯文字处理」)。
621
+ */
622
+ const target = options.selector ?? '#container';
623
+ const newPage = async () => {
624
+ if (typeof puppeteer.page === 'function')
625
+ return await puppeteer.page();
626
+ if (puppeteer.browser && typeof puppeteer.browser.newPage === 'function')
627
+ return await puppeteer.browser.newPage();
628
+ return null;
629
+ };
630
+ const page = await newPage();
631
+ if (!page)
632
+ throw new Error('[kkk] 渲染失败:puppeteer 服务没有可用的页面');
633
+ try {
634
+ if (page.setViewport)
635
+ await page.setViewport({ width: 1200, height: 900, deviceScaleFactor: 2 });
636
+ await page.goto((0, node_url_1.pathToFileURL)(options.file).href, {
637
+ waitUntil: options.pageGotoParams?.waitUntil ?? 'load',
638
+ timeout: options.pageGotoParams?.timeout ?? 15000
639
+ });
640
+ const handle = (await page.$(target)) ?? (await page.$('body'));
641
+ const box = handle ? await handle.boundingBox() : null;
642
+ if (box && box.height > 900 && page.setViewport) {
643
+ await page.setViewport({ width: Math.ceil(box.width) + 4, height: Math.ceil(box.height) + 4, deviceScaleFactor: 2 });
644
+ }
645
+ const buffer = await page.screenshot({
646
+ clip: box ?? undefined,
647
+ omitBackground: options.omitBackground ?? true,
648
+ type: options.type ?? 'png'
649
+ });
650
+ return buffer.toString('base64');
651
+ }
652
+ finally {
653
+ try {
654
+ await page.close();
655
+ }
656
+ catch { /* 忽略 */ }
657
+ }
658
+ if (Buffer.isBuffer(result))
659
+ return result.toString('base64');
660
+ if (typeof result === 'string')
661
+ return result.replace(/^data:image\/\w+;base64,/, '');
662
+ if (result?.data)
663
+ return String(result.data).replace(/^data:image\/\w+;base64,/, '');
664
+ throw new Error('[kkk] 渲染失败:截图结果为空');
665
+ }
666
+ };
667
+ exports.common = {
668
+ makeForward,
669
+ async sleep(ms) {
670
+ return new Promise((resolve) => setTimeout(resolve, ms));
671
+ },
672
+ get karinVersion() {
673
+ return exports.karin.version;
674
+ }
675
+ };
676
+ exports.config = {
677
+ /** 主人账号列表 */
678
+ master() {
679
+ return (0, runtime_1.getRuntime)().config.masters;
680
+ },
681
+ /** 读取任意目录下的配置文件(兼容占位) */
682
+ json(dir) {
683
+ const runtime = (0, runtime_1.getRuntime)();
684
+ const file = dir ? node_path_1.default.resolve(runtime.dataRoot, dir) : node_path_1.default.resolve(runtime.dataRoot, 'config.json');
685
+ try {
686
+ return JSON.parse(node_fs_1.default.readFileSync(file, 'utf8'));
687
+ }
688
+ catch {
689
+ return undefined;
690
+ }
691
+ }
692
+ };
693
+ /**
694
+ * karin 的 hooks 是内置插件(更新检测等)暴露的钩子集合。
695
+ * Koishi 侧没有对应实现,这里做成深度空实现:任何属性都是可调用的 no-op,
696
+ * 避免移植代码在 import 阶段直接崩掉。
697
+ */
698
+ const noopProxy = new Proxy(function () { }, {
699
+ get: (_target, prop) => (prop === 'then' ? undefined : noopProxy),
700
+ apply: () => noopProxy
701
+ });
702
+ exports.hooks = new Proxy({}, {
703
+ get: (_target, prop) => (prop === 'on' || prop === 'once'
704
+ ? (event, handler) => on(event, handler)
705
+ : noopProxy)
706
+ });
707
+ const watch = (_paths, _options, _handler) => () => { };
708
+ exports.watch = watch;
709
+ const restart = async () => {
710
+ logger_1.logger.warn('[kkk] Koishi 环境下不支持插件重启,请手动重启进程');
711
+ };
712
+ exports.restart = restart;
713
+ /**
714
+ * 检查 npm 上的最新版本(对应 karin 的 checkPkgUpdate)。
715
+ * 返回 karin 约定的三种形状:yes(有更新) / no(无更新) / error。
716
+ * 未发布到 npm 的包(例如本地开发时的 koishi-plugin-kkk)会走到 error 分支,调用方按「无更新」处理。
717
+ */
718
+ const checkPkgUpdate = async (name, _options) => {
719
+ const local = readLocalVersion();
720
+ try {
721
+ const response = await fetch('https://registry.npmmirror.com/' + name, { signal: AbortSignal.timeout(10000) });
722
+ if (!response.ok)
723
+ return { status: 'error', error: new Error('HTTP ' + response.status) };
724
+ const meta = await response.json();
725
+ const remote = meta?.['dist-tags']?.latest;
726
+ if (!remote)
727
+ return { status: 'error', error: new Error('响应缺少 dist-tags.latest') };
728
+ if (remote === local)
729
+ return { status: 'no', local };
730
+ return { status: 'yes', local, remote };
731
+ }
732
+ catch (error) {
733
+ return { status: 'error', error: error };
734
+ }
735
+ };
736
+ exports.checkPkgUpdate = checkPkgUpdate;
737
+ /** 读取插件自身 package.json 的版本号 */
738
+ function readLocalVersion() {
739
+ try {
740
+ const file = node_path_1.default.resolve((0, runtime_1.getRuntime)().pluginRoot, 'package.json');
741
+ return JSON.parse(node_fs_1.default.readFileSync(file, 'utf8')).version ?? '0.0.0';
742
+ }
743
+ catch {
744
+ return '0.0.0';
745
+ }
746
+ }
747
+ const updatePkg = async (_name) => {
748
+ logger_1.logger.warn('[kkk] Koishi 环境下请使用包管理器更新插件');
749
+ return false;
750
+ };
751
+ exports.updatePkg = updatePkg;
752
+ exports.mkdirSync = node_fs_1.default.mkdirSync;
753
+ const isDocker = () => false;
754
+ exports.isDocker = isDocker;
755
+ /**
756
+ * 提取 CHANGELOG 中指定数量的版本记录(karin 的 \`logs\`)。
757
+ * 上游用法:\`logs({ version, data, length })\` → 返回最近 \`length\` 个版本的 markdown 片段。
758
+ */
759
+ function logs(options) {
760
+ const { data, length, version } = options ?? {};
761
+ if (typeof data !== 'string' || !data)
762
+ return '';
763
+ const versions = parseChangelog(data);
764
+ const keys = Object.keys(versions);
765
+ if (!keys.length)
766
+ return '';
767
+ let start = 0;
768
+ if (version) {
769
+ const index = keys.findIndex((key) => compareVersion(key, version) === 0);
770
+ if (index >= 0)
771
+ start = index;
772
+ }
773
+ const take = Math.max(1, Number(length) || 1);
774
+ return keys.slice(start, start + take).map((key) => '## [' + key + ']\n' + versions[key]).join('\n\n');
775
+ }
776
+ /** 版本号比较(仅用于 changelog 过滤,够用即可) */
777
+ function compareVersion(a, b) {
778
+ const pa = String(a).replace(/^v/i, '').split('-')[0].split('.').map((item) => Number(item) || 0);
779
+ const pb = String(b).replace(/^v/i, '').split('-')[0].split('.').map((item) => Number(item) || 0);
780
+ for (let i = 0; i < 3; i++) {
781
+ if ((pa[i] ?? 0) !== (pb[i] ?? 0))
782
+ return (pa[i] ?? 0) - (pb[i] ?? 0);
783
+ }
784
+ return 0;
785
+ }
786
+ /**
787
+ * 解析 CHANGELOG.md:\`{ '1.2.3': '该版本的正文' }\`(karin 的 parseChangelog)。
788
+ * 标题形如 \`## [1.2.3](...) (2024-01-01)\` 或 \`## 1.2.3\`。
789
+ */
790
+ function parseChangelog(text) {
791
+ const result = {};
792
+ if (typeof text !== 'string' || !text)
793
+ return result;
794
+ const lines = text.split(/\r?\n/);
795
+ let current = null;
796
+ let buffer = [];
797
+ const flush = () => {
798
+ if (current)
799
+ result[current] = buffer.join('\n').trim();
800
+ buffer = [];
801
+ };
802
+ for (const line of lines) {
803
+ const matched = line.match(/^#{1,4}\s*\[?v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\]?/);
804
+ if (matched) {
805
+ flush();
806
+ current = matched[1];
807
+ continue;
808
+ }
809
+ if (current)
810
+ buffer.push(line);
811
+ }
812
+ flush();
813
+ return result;
814
+ }
815
+ /**
816
+ * 按版本区间裁剪 changelog(karin 的 range)。
817
+ * 上游用法:\`range({ data, startVersion, endVersion, compare: 'semver' })\`,返回裁剪后的 markdown 文本。
818
+ * 区间语义:\`startVersion < v <= endVersion\`;解析不出任何版本时原样返回。
819
+ */
820
+ function range(options) {
821
+ const { data, startVersion, endVersion } = options ?? {};
822
+ if (typeof data !== 'string')
823
+ return data;
824
+ const parsed = parseChangelog(data);
825
+ const versions = Object.keys(parsed);
826
+ if (!versions.length)
827
+ return data;
828
+ const selected = versions.filter((version) => {
829
+ if (startVersion && compareVersion(version, startVersion) <= 0)
830
+ return false;
831
+ if (endVersion && compareVersion(version, endVersion) > 0)
832
+ return false;
833
+ return true;
834
+ });
835
+ if (!selected.length)
836
+ return data;
837
+ return selected.map((version) => '## [' + version + ']\n' + parsed[version]).join('\n\n');
838
+ }
839
+ const checkPort = async (port) => port;
840
+ exports.checkPort = checkPort;
841
+ const defineConfig = (config) => config;
842
+ exports.defineConfig = defineConfig;
843
+ /**
844
+ * 控制台 API 的鉴权(替代 karin 的 WebUI 会话鉴权)。
845
+ *
846
+ * - 插件配置里设了 \`apiToken\`:要求 \`Authorization: Bearer <token>\`(或 \`?token=\`);
847
+ * - 没设 token:只放行本机请求,避免把配置接口裸奔到公网。
848
+ */
849
+ const authMiddleware = (req, res, next) => {
850
+ const expected = String((0, runtime_1.getRuntime)().config.apiToken ?? '');
851
+ const provided = String(req?.headers?.authorization ?? '').replace(/^Bearer\s+/i, '')
852
+ || String(req?.query?.token ?? '');
853
+ if (expected) {
854
+ if (provided === expected)
855
+ return next();
856
+ return respond(401, res, { code: 401, message: '未授权:apiToken 不正确' });
857
+ }
858
+ const address = String(req?.socket?.remoteAddress ?? req?.ip ?? '');
859
+ if (/^(::1|::ffff:127\.0\.0\.1|127\.0\.0\.1)$/.test(address))
860
+ return next();
861
+ return respond(401, res, { code: 401, message: '未授权:请在插件配置中设置 apiToken' });
862
+ };
863
+ exports.authMiddleware = authMiddleware;
864
+ /**
865
+ * karin 的响应助手:**第一个参数是 express 的 res**,会直接把响应写出去。
866
+ * 例如 `createSuccessResponse(res, data, 'ok')` / `createBadRequestResponse(res, '参数错误')`。
867
+ * 移植过来的 controllers 就是这么用的,签名必须对齐(否则请求会一直挂着不返回)。
868
+ */
869
+ const respond = (status, res, payload) => {
870
+ try {
871
+ if (res && typeof res.status === 'function' && typeof res.json === 'function') {
872
+ res.status(status).json(payload);
873
+ }
874
+ else if (res && typeof res.send === 'function') {
875
+ res.status?.(status).send?.(payload);
876
+ }
877
+ }
878
+ catch (error) {
879
+ logger_1.logger.debug('[kkk] 写响应失败: ' + String(error));
880
+ }
881
+ return payload;
882
+ };
883
+ const createSuccessResponse = (res, data, message = 'success') => respond(200, res, { code: 200, message, data });
884
+ exports.createSuccessResponse = createSuccessResponse;
885
+ const createBadRequestResponse = (res, message = '请求参数错误') => respond(400, res, { code: 400, message });
886
+ exports.createBadRequestResponse = createBadRequestResponse;
887
+ const createNotFoundResponse = (res, message = '资源不存在') => respond(404, res, { code: 404, message });
888
+ exports.createNotFoundResponse = createNotFoundResponse;
889
+ const createServerErrorResponse = (res, message = '服务器内部错误') => respond(500, res, { code: 500, message });
890
+ exports.createServerErrorResponse = createServerErrorResponse;
891
+ /* ------------------------------------------------------------------ *
892
+ * FFmpeg / ffprobe
893
+ *
894
+ * 上游 karin 直接调它的 ffmpeg 封装;Koishi 兼容层原先是个**抛错的占位实现**,
895
+ * 结果所有要拼流/改封装的解析(登录态 B站 视频要先把 m4s 修成 mp4 再和音频合成)
896
+ * 都在第一步就炸/哑掉 —— 用户看到的就是「提示开始解析,然后没下文」。
897
+ *
898
+ * 这里给它一个真实现:子进程直接跑 ffmpeg / ffprobe,返回值形状保持 karin 的
899
+ * `{ status, stdout, stderr }`(`status` 为真表示成功,kkk 里到处这么判断)。
900
+ * 可执行文件来源优先级:karin 传入的 options.ffmpegPath → koishi-plugin-ffmpeg-path 服务
901
+ * → 环境变量 FFMPEG_PATH/FFPROBE_PATH → PATH 里的 ffmpeg/ffprobe。
902
+ * ------------------------------------------------------------------ */
903
+ function ffmpegRuntimeCtx() {
904
+ try {
905
+ return (0, runtime_1.tryGetRuntime)()?.ctx;
906
+ }
907
+ catch {
908
+ return null;
909
+ }
910
+ }
911
+ /** 由 ffmpeg 路径推出同目录的 ffprobe(找不到就交给 PATH) */
912
+ function siblingFfprobe(ffmpegPath) {
913
+ try {
914
+ if (!ffmpegPath || ffmpegPath === 'ffmpeg')
915
+ return 'ffprobe';
916
+ const dir = node_path_1.default.dirname(ffmpegPath);
917
+ const name = process.platform === 'win32' ? 'ffprobe.exe' : 'ffprobe';
918
+ const candidate = node_path_1.default.join(dir, name);
919
+ return node_fs_1.default.existsSync(candidate) ? candidate : 'ffprobe';
920
+ }
921
+ catch {
922
+ return 'ffprobe';
923
+ }
924
+ }
925
+ function resolveFfmpegBin(options = {}) {
926
+ if (typeof options?.ffmpegPath === 'string' && options.ffmpegPath)
927
+ return options.ffmpegPath;
928
+ const ctx = ffmpegRuntimeCtx();
929
+ const servicePath = ctx?.ffmpeg?.executable ?? ctx?.ffmpeg?.path;
930
+ if (typeof servicePath === 'string' && servicePath)
931
+ return servicePath;
932
+ return process.env.FFMPEG_PATH || process.env.FFMPEG_BIN || 'ffmpeg';
933
+ }
934
+ /** 把 karin 那种「一整条参数串」拆成 argv(引号内的空格要保留) */
935
+ function splitCommandArgs(input) {
936
+ const args = [];
937
+ const pattern = /"([^"]*)"|'([^']*)'|(\S+)/g;
938
+ let match;
939
+ while ((match = pattern.exec(String(input ?? '')))) {
940
+ args.push(match[1] ?? match[2] ?? match[3]);
941
+ }
942
+ return args;
943
+ }
944
+ function runFfmpegBinary(bin, args, options = {}) {
945
+ return new Promise((resolve) => {
946
+ let child;
947
+ try {
948
+ child = (0, node_child_process_1.spawn)(bin, args, { windowsHide: true });
949
+ }
950
+ catch (error) {
951
+ resolve({ status: false, stdout: '', stderr: String(error?.message ?? error), code: null });
952
+ return;
953
+ }
954
+ let stdout = '';
955
+ let stderr = '';
956
+ // 默认 10 分钟兜底,避免遇到损坏文件 / 网络流时永远挂着(kkk 里都是 await 调用)
957
+ const timeout = Number(options?.timeout ?? 600000);
958
+ const timer = timeout > 0 ? setTimeout(() => {
959
+ try {
960
+ child.kill('SIGKILL');
961
+ }
962
+ catch { /* 忽略 */ }
963
+ }, timeout) : null;
964
+ const done = (result) => {
965
+ if (timer)
966
+ clearTimeout(timer);
967
+ resolve(result);
968
+ };
969
+ child.stdout?.on('data', (chunk) => {
970
+ const text = String(chunk);
971
+ stdout += text;
972
+ options?.onStdout?.(text);
973
+ });
974
+ child.stderr?.on('data', (chunk) => {
975
+ const text = String(chunk);
976
+ stderr += text;
977
+ options?.onStderr?.(text);
978
+ });
979
+ child.on('error', (error) => {
980
+ done({ status: false, stdout, stderr: stderr + String(error?.message ?? error), code: null });
981
+ });
982
+ child.on('close', (code) => {
983
+ done({ status: code === 0, stdout, stderr, code });
984
+ });
985
+ });
986
+ }
987
+ const ffmpeg = (input, options = {}) => runFfmpegBinary(resolveFfmpegBin(options), splitCommandArgs(input), options);
988
+ exports.ffmpeg = ffmpeg;
989
+ const ffprobe = (input, options = {}) => {
990
+ const bin = typeof options?.ffprobePath === 'string' && options.ffprobePath
991
+ ? options.ffprobePath
992
+ : (process.env.FFPROBE_PATH || siblingFfprobe(resolveFfmpegBin(options)));
993
+ return runFfmpegBinary(bin, splitCommandArgs(input), options);
994
+ };
995
+ exports.ffprobe = ffprobe;
996
+ /** 是否真的能用 ffmpeg(弹幕烧录 / 转码相关功能用它决定要不要提示「未接入」) */
997
+ const isFfmpegAvailable = () => {
998
+ try {
999
+ const bin = resolveFfmpegBin();
1000
+ if (bin === 'ffmpeg') {
1001
+ // PATH 里的 ffmpeg:查一下常见位置即可,不为了探测去启动进程
1002
+ return true;
1003
+ }
1004
+ return node_fs_1.default.existsSync(bin);
1005
+ }
1006
+ catch {
1007
+ return false;
1008
+ }
1009
+ };
1010
+ exports.isFfmpegAvailable = isFfmpegAvailable;
1011
+ /** express 应用实例(模块级懒加载,供 module/server 使用) */
1012
+ let expressApp;
1013
+ exports.app = new Proxy({}, {
1014
+ get(_target, prop) {
1015
+ if (!expressApp) {
1016
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
1017
+ const express = require('express');
1018
+ expressApp = express();
1019
+ }
1020
+ return expressApp[prop];
1021
+ }
1022
+ });
1023
+ exports.karin = {
1024
+ version: '1.16.3-koishi-compat',
1025
+ command,
1026
+ task,
1027
+ on,
1028
+ getBot: (selfId) => resolveBot(selfId),
1029
+ /**
1030
+ * 取所有在线 bot 的 id。
1031
+ *
1032
+ * 不能只读 `bot.selfId` —— 实测 `ctx.bots` 里混着 console / sandbox 这类
1033
+ * selfId 为 null 的实例,过滤前会得到 `[null, null]`,推送任务就永远"找不到可用 bot"。
1034
+ * 这里把几种可能的来源都兜上,并且丢掉空值。
1035
+ */
1036
+ getAllBotID: () => {
1037
+ const bots = (0, runtime_1.tryGetRuntime)()?.ctx.bots ?? [];
1038
+ const ids = bots.map((bot) => bot?.selfId ?? bot?.user?.id ?? bot?.internal?.selfId ?? '');
1039
+ return [...new Set(ids.map((id) => String(id ?? '')).filter((id) => id && id !== 'undefined'))];
1040
+ },
1041
+ getAllBotList: () => ((0, runtime_1.tryGetRuntime)()?.ctx.bots ?? []).map((bot) => ({ bot: new KkkBot(bot), status: 1 })),
1042
+ contactGroup: exports.contactGroup,
1043
+ contactFriend: exports.contactFriend,
1044
+ sendMsg,
1045
+ sendMaster,
1046
+ ctx: waitContext,
1047
+ /** karin.template 在 Koishi 侧无对应实现 */
1048
+ template: (_name) => undefined,
1049
+ logger: logger_1.logger,
1050
+ segment: segment_1.segment,
1051
+ root: {}
1052
+ };
1053
+ exports.default = exports.karin;