node-karin 1.7.10 → 1.7.12

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 (231) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +32 -0
  3. package/dist/index.d.ts +388 -259
  4. package/dist/index.js +2247 -1398
  5. package/dist/root.d.ts +86 -21
  6. package/dist/root.js +68 -22
  7. package/dist/web/assets/{404-ROM-5vaV.js → 404-C9u_NlJi.js} +1 -1
  8. package/dist/web/assets/Item-pd96GKIG.js.br +0 -0
  9. package/dist/web/assets/SelectionManager-BlXTH2VC.js.br +0 -0
  10. package/dist/web/assets/about-BwlDpX-c.js.br +0 -0
  11. package/dist/web/assets/accordion-Bj06RlD-.js.br +0 -0
  12. package/dist/web/assets/adapter-Du42CYBT.js.br +0 -0
  13. package/dist/web/assets/{bot-DAG7M5q-.js → bot-DdYIqTVP.js} +1 -1
  14. package/dist/web/assets/chunk-2C6KNKEU-CBJmVWyn.js.br +0 -0
  15. package/dist/web/assets/chunk-2QAN2V2R-BulY1jfw.js.br +0 -0
  16. package/dist/web/assets/chunk-3TCFMHK3-BpJf4Q9f.js.br +0 -0
  17. package/dist/web/assets/chunk-4EXC76WE-DWVJR0TX.js.br +0 -0
  18. package/dist/web/assets/chunk-6JWJ7CFW-BDAlVmIQ.js.br +0 -0
  19. package/dist/web/assets/chunk-6NGXL2PC-DIPEMSmA.js.br +0 -0
  20. package/dist/web/assets/chunk-6VC6TS2O-sjq9IySl.js.br +0 -0
  21. package/dist/web/assets/chunk-736YWA4T-BK_z11TK.js.br +0 -0
  22. package/dist/web/assets/chunk-A6PX3NG3-BsGR2bWZ.js.br +0 -0
  23. package/dist/web/assets/{chunk-B75B6XQK-DEU248fD.js → chunk-B75B6XQK-B0VUBvt8.js} +1 -1
  24. package/dist/web/assets/chunk-BWXGEJBS-DvCShJym.js.br +0 -0
  25. package/dist/web/assets/{chunk-D5XJWRAV-Hwzbrfsb.js → chunk-D5XJWRAV-9uH2CwV1.js} +1 -1
  26. package/dist/web/assets/chunk-HAJUSXOG-6BFBENy1.js.br +0 -0
  27. package/dist/web/assets/chunk-IHO36JMK-DKnKLDmu.js.br +0 -0
  28. package/dist/web/assets/chunk-J6JGI6RM-DKmnXtnU.js.br +0 -0
  29. package/dist/web/assets/chunk-J7I6W5JF-IqR8CF_Q.js.br +0 -0
  30. package/dist/web/assets/chunk-KCYYJJH4-BdofC4qA.js.br +0 -0
  31. package/dist/web/assets/chunk-KHLLQ6W4-CpyZzH4q.js.br +0 -0
  32. package/dist/web/assets/chunk-KQ5CH2X7-MWuUq5gI.js.br +0 -0
  33. package/dist/web/assets/{chunk-LAX3QLKM-CBYOkqco.js → chunk-LAX3QLKM-B0tE0BjZ.js} +1 -1
  34. package/dist/web/assets/{chunk-LGSBTEIA-TCuFLh0L.js → chunk-LGSBTEIA--Gvr91gm.js} +1 -1
  35. package/dist/web/assets/{chunk-M3MASYO7-Cf1ct4AJ.js → chunk-M3MASYO7-BVjxibqV.js} +1 -1
  36. package/dist/web/assets/chunk-ML27DD5T-BjYAog8d.js.br +0 -0
  37. package/dist/web/assets/chunk-MSDKUXDP-DKkJKxM-.js.br +0 -0
  38. package/dist/web/assets/chunk-MW56SEHC-CTlcS-O4.js.br +0 -0
  39. package/dist/web/assets/chunk-MZRCPRP2-BBG21hp8.js.br +0 -0
  40. package/dist/web/assets/{chunk-OH2E76JR-ChR4CzW6.js → chunk-OH2E76JR-BYurMayl.js} +1 -1
  41. package/dist/web/assets/{chunk-OTWYT2HS-D-5Sw7yY.js → chunk-OTWYT2HS-cQ8QQNDY.js} +1 -1
  42. package/dist/web/assets/chunk-RRTOIK23-CSPsT46O.js.br +0 -0
  43. package/dist/web/assets/chunk-SLABUSGS-s9w3Zt5w.js.br +0 -0
  44. package/dist/web/assets/{chunk-TE6SZS6W-DVjNRMW1.js → chunk-TE6SZS6W-1UK_YAGg.js} +1 -1
  45. package/dist/web/assets/{chunk-UX7UMZL5-DNrr8yIE.js → chunk-UX7UMZL5-DHf8C-o1.js} +1 -1
  46. package/dist/web/assets/chunk-WQVQ7P2I-C4kbg9VI.js.br +0 -0
  47. package/dist/web/assets/config-CEElyPBT.js.br +0 -0
  48. package/dist/web/assets/config-DVn1FaJ-.js.br +0 -0
  49. package/dist/web/assets/cssMode-CXyVPoom.js.br +0 -0
  50. package/dist/web/assets/{default_page-C-I5cIoe.js → default_page-BKgpdS-e.js} +1 -1
  51. package/dist/web/assets/detail-C5769b6q.js.br +0 -0
  52. package/dist/web/assets/detail-COuw3J9r.js.br +0 -0
  53. package/dist/web/assets/env-CSYJHsPf.js.br +0 -0
  54. package/dist/web/assets/{eye-CHCoGrQg.js → eye-DEh2Pgsu.js} +1 -1
  55. package/dist/web/assets/features-animation-F-pzovue.js +1 -0
  56. package/dist/web/assets/focusSafely-DOspV_xj.js.br +0 -0
  57. package/dist/web/assets/freemarker2-BV0OzS9F.js.br +0 -0
  58. package/dist/web/assets/friend_request-DfiA7sPM.js.br +0 -0
  59. package/dist/web/assets/{github-B60g1t4F.js → github-nVmhSG0k.js} +1 -1
  60. package/dist/web/assets/group-CfWIxZ1S.js.br +0 -0
  61. package/dist/web/assets/{group_notice-B5gSbmBW.js → group_notice-XufgXVhG.js} +1 -1
  62. package/dist/web/assets/handlebars-DSMVNR0n.js.br +0 -0
  63. package/dist/web/assets/html-ClQau7kT.js.br +0 -0
  64. package/dist/web/assets/htmlMode-CN2HUcKJ.js.br +0 -0
  65. package/dist/web/assets/iconBase-BbDMq9Lm.js.br +0 -0
  66. package/dist/web/assets/index-B2KKfeyN.js.br +0 -0
  67. package/dist/web/assets/index-B59L0CDQ.js.br +0 -0
  68. package/dist/web/assets/index-BRJPOEf0.js.br +0 -0
  69. package/dist/web/assets/index-BSQ_9cWz.js.br +0 -0
  70. package/dist/web/assets/index-BTn745-y.js.br +0 -0
  71. package/dist/web/assets/index-Bl5YOuTR.js.br +0 -0
  72. package/dist/web/assets/{index-DwRqexnd.js → index-Bm-03b92.js} +1 -1
  73. package/dist/web/assets/index-CNKcljeW.js +1 -0
  74. package/dist/web/assets/index-CSkzWqtN.js.br +0 -0
  75. package/dist/web/assets/index-CY-NVVkv.js.br +0 -0
  76. package/dist/web/assets/index-CeBvj3ZH.js.br +0 -0
  77. package/dist/web/assets/index-DCzNSkJn.js.br +0 -0
  78. package/dist/web/assets/{index-CvJYXohb.js → index-DNKbYZlM.js} +1 -1
  79. package/dist/web/assets/index-DVsvetQP.js.br +0 -0
  80. package/dist/web/assets/index-D_816BTl.js.br +0 -0
  81. package/dist/web/assets/index-Db1iHKoe.js.br +0 -0
  82. package/dist/web/assets/{index-WTooMED4.js → index-DjU-NtVQ.js} +1 -1
  83. package/dist/web/assets/index-Drqc4ASm.js.br +0 -0
  84. package/dist/web/assets/index-Dwnb7Xtz.js.br +0 -0
  85. package/dist/web/assets/index-EGWrH2j2.js +1 -0
  86. package/dist/web/assets/{index-BAoYlZHZ.js → index-IUy6p99y.js} +1 -1
  87. package/dist/web/assets/index-k_Cd4_SW.js.br +0 -0
  88. package/dist/web/assets/index-nZMp9MWB.js.br +0 -0
  89. package/dist/web/assets/index.esm-BSKygSH-.js.br +0 -0
  90. package/dist/web/assets/inputGroup-CJGuoYUx.js.br +0 -0
  91. package/dist/web/assets/isSymbol-BShv9ove.js.br +0 -0
  92. package/dist/web/assets/javascript-BegoFNre.js.br +0 -0
  93. package/dist/web/assets/jsonMode-Dxf_RJRO.js.br +0 -0
  94. package/dist/web/assets/layout-al9rnD7b.js.br +0 -0
  95. package/dist/web/assets/liquid-bFSovgkX.js.br +0 -0
  96. package/dist/web/assets/loading-Czh_ivNv.js.br +0 -0
  97. package/dist/web/assets/login-DpjAzjKU.js.br +0 -0
  98. package/dist/web/assets/mdx-DGviX4hR.js.br +0 -0
  99. package/dist/web/assets/{message-BNFpim4r.js → message-mTjTgeaM.js} +1 -1
  100. package/dist/web/assets/message.model-B1qK1MiE.js.br +0 -0
  101. package/dist/web/assets/number-7W8NeZVk.js.br +0 -0
  102. package/dist/web/assets/pm2-CniXkaeu.js.br +0 -0
  103. package/dist/web/assets/private-CfG8JI8L.js.br +0 -0
  104. package/dist/web/assets/python-D0ZD_k1N.js.br +0 -0
  105. package/dist/web/assets/razor-DRYiVyDt.js.br +0 -0
  106. package/dist/web/assets/react-resizable-panels.browser.esm-DubqLJ4h.js.br +0 -0
  107. package/dist/web/assets/redis-BJLUr1tG.js.br +0 -0
  108. package/dist/web/assets/render-DEylqIUg.js.br +0 -0
  109. package/dist/web/assets/{save-DMaHHFuO.js → save-D6wQsuGT.js} +1 -1
  110. package/dist/web/assets/server-CRdhk2Wy.js.br +0 -0
  111. package/dist/web/assets/{terminal-Zxtnjvkh.js → terminal-CfCQe79-.js} +1 -1
  112. package/dist/web/assets/terminal-bNIVjrPM.js.br +0 -0
  113. package/dist/web/assets/test-url-CZXnW7jp.js.br +0 -0
  114. package/dist/web/assets/theme-switch-Bz2l2CwF.js.br +0 -0
  115. package/dist/web/assets/tsMode-DKGjerkd.js.br +0 -0
  116. package/dist/web/assets/typescript-CsEXAEHs.js.br +0 -0
  117. package/dist/web/assets/use-dialog-BrR6Szrb.js +1 -0
  118. package/dist/web/assets/{useEvent-Db-ky4me.js → useEvent-DaW3_jZI.js} +1 -1
  119. package/dist/web/assets/useFocusable-CtLTcLFV.js.br +0 -0
  120. package/dist/web/assets/{useFormReset-dmnhOTNk.js → useFormReset-CBBc4OFV.js} +1 -1
  121. package/dist/web/assets/useHover-NCfDbwX0.js.br +0 -0
  122. package/dist/web/assets/{useKeyboard-Cge6c6KY.js → useKeyboard-BZ4YtCxw.js} +1 -1
  123. package/dist/web/assets/{useLabel-B4NXQBW4.js → useLabel-DBycc4Nu.js} +1 -1
  124. package/dist/web/assets/useNumberFormatter-DhAgwXM6.js.br +0 -0
  125. package/dist/web/assets/useRequest-BWEdMIz7.js.br +0 -0
  126. package/dist/web/assets/useToggle-Wuq-KqyX.js.br +0 -0
  127. package/dist/web/assets/{users-rI_NwA1Q.js → users-_IqQqJDb.js} +1 -1
  128. package/dist/web/assets/video_insert-Bj2IxuYI.js.br +0 -0
  129. package/dist/web/assets/webui-B6dfxJX4.js.br +0 -0
  130. package/dist/web/assets/xml-BHQFK9Jh.js.br +0 -0
  131. package/dist/web/assets/yaml-2He2eI3V.js.br +0 -0
  132. package/dist/web/index.html +1 -1
  133. package/package.json +2 -2
  134. package/dist/web/assets/Item-BSnj9N-S.js.br +0 -0
  135. package/dist/web/assets/SelectionManager-BSGyCPB6.js.br +0 -0
  136. package/dist/web/assets/about-Dn7SmYD5.js.br +0 -0
  137. package/dist/web/assets/accordion-yx6m6E4c.js.br +0 -0
  138. package/dist/web/assets/adapter-BE6Ejj32.js.br +0 -0
  139. package/dist/web/assets/chunk-2C6KNKEU-8uJ8XP-i.js.br +0 -0
  140. package/dist/web/assets/chunk-2QAN2V2R-DV7L5QFL.js.br +0 -0
  141. package/dist/web/assets/chunk-3TCFMHK3-CUCMPqK0.js.br +0 -0
  142. package/dist/web/assets/chunk-4EXC76WE-BQZeyUq0.js.br +0 -0
  143. package/dist/web/assets/chunk-6JWJ7CFW-Bj3QHecF.js.br +0 -0
  144. package/dist/web/assets/chunk-6NGXL2PC-AftDQVX_.js.br +0 -0
  145. package/dist/web/assets/chunk-6VC6TS2O-D4EHcS9B.js.br +0 -0
  146. package/dist/web/assets/chunk-736YWA4T-B2h7YdK3.js.br +0 -0
  147. package/dist/web/assets/chunk-A6PX3NG3-BicU5fh6.js.br +0 -0
  148. package/dist/web/assets/chunk-BWXGEJBS-DeDOUu0R.js.br +0 -0
  149. package/dist/web/assets/chunk-HAJUSXOG-Drgjv-QD.js.br +0 -0
  150. package/dist/web/assets/chunk-IHO36JMK-BNYnWSoy.js.br +0 -0
  151. package/dist/web/assets/chunk-J6JGI6RM-CcxhCy3w.js.br +0 -0
  152. package/dist/web/assets/chunk-J7I6W5JF-0wSc07EW.js.br +0 -0
  153. package/dist/web/assets/chunk-KCYYJJH4-CeaLdnyN.js.br +0 -0
  154. package/dist/web/assets/chunk-KHLLQ6W4-DAQe5Hoo.js.br +0 -0
  155. package/dist/web/assets/chunk-KQ5CH2X7-BkOtCub0.js.br +0 -0
  156. package/dist/web/assets/chunk-ML27DD5T-B4MSKmX3.js.br +0 -0
  157. package/dist/web/assets/chunk-MSDKUXDP-Drw51uob.js.br +0 -0
  158. package/dist/web/assets/chunk-MW56SEHC-C3P_Uzcs.js.br +0 -0
  159. package/dist/web/assets/chunk-MZRCPRP2-C2ypITZg.js.br +0 -0
  160. package/dist/web/assets/chunk-RRTOIK23-D9N-soNs.js.br +0 -0
  161. package/dist/web/assets/chunk-SLABUSGS-JnrNRAbY.js.br +0 -0
  162. package/dist/web/assets/chunk-WQVQ7P2I-BiwI21H_.js.br +0 -0
  163. package/dist/web/assets/config-BDdIlQFb.js.br +0 -0
  164. package/dist/web/assets/config-DF-6BWhc.js.br +0 -0
  165. package/dist/web/assets/cssMode-B9RzJoGx.js.br +0 -0
  166. package/dist/web/assets/detail-CP4CI5uQ.js.br +0 -0
  167. package/dist/web/assets/detail-D3_esqOW.js.br +0 -0
  168. package/dist/web/assets/env-K7kL0HI8.js.br +0 -0
  169. package/dist/web/assets/features-animation-DQ6MKzWa.js +0 -1
  170. package/dist/web/assets/focusSafely-JJUVNIhy.js.br +0 -0
  171. package/dist/web/assets/freemarker2-COvAb8cQ.js.br +0 -0
  172. package/dist/web/assets/friend_request-I3sxhcox.js.br +0 -0
  173. package/dist/web/assets/group-D2VEsO_B.js.br +0 -0
  174. package/dist/web/assets/handlebars-nx4hotnj.js.br +0 -0
  175. package/dist/web/assets/html-CsiNnsxH.js.br +0 -0
  176. package/dist/web/assets/htmlMode-BLYL8DCC.js.br +0 -0
  177. package/dist/web/assets/iconBase-CNF-KpIB.js.br +0 -0
  178. package/dist/web/assets/index-0Gm3jP6_.js.br +0 -0
  179. package/dist/web/assets/index-AnPeObV4.js.br +0 -0
  180. package/dist/web/assets/index-B0Fd8xnC.js.br +0 -0
  181. package/dist/web/assets/index-BMPHtvAN.js.br +0 -0
  182. package/dist/web/assets/index-BeRyyzC-.js.br +0 -0
  183. package/dist/web/assets/index-BvXvYx9J.js.br +0 -0
  184. package/dist/web/assets/index-Bz-Rb7E1.js.br +0 -0
  185. package/dist/web/assets/index-C-BzIWSp.js.br +0 -0
  186. package/dist/web/assets/index-C0_1_AeC.js.br +0 -0
  187. package/dist/web/assets/index-CU_PqmHL.js.br +0 -0
  188. package/dist/web/assets/index-CkbJgG04.js.br +0 -0
  189. package/dist/web/assets/index-CqJOpW7i.js.br +0 -0
  190. package/dist/web/assets/index-DDxSDMSZ.js.br +0 -0
  191. package/dist/web/assets/index-DYk8Wuvm.js.br +0 -0
  192. package/dist/web/assets/index-DobBTFkc.js +0 -1
  193. package/dist/web/assets/index-DqRTH1kA.js.br +0 -0
  194. package/dist/web/assets/index-cAqdVtC6.js.br +0 -0
  195. package/dist/web/assets/index-cb3EnRup.js.br +0 -0
  196. package/dist/web/assets/index-cbFoOFFD.js +0 -1
  197. package/dist/web/assets/index.esm-Cz228LMZ.js.br +0 -0
  198. package/dist/web/assets/inputGroup-wf-bbSCC.js.br +0 -0
  199. package/dist/web/assets/isSymbol-BYn5WlEE.js.br +0 -0
  200. package/dist/web/assets/javascript-bfBKpoLI.js.br +0 -0
  201. package/dist/web/assets/jsonMode-ChsocM0N.js.br +0 -0
  202. package/dist/web/assets/layout-BjsKGQWu.js.br +0 -0
  203. package/dist/web/assets/liquid-Co0J5pAR.js.br +0 -0
  204. package/dist/web/assets/loading-CCRi9hXp.js.br +0 -0
  205. package/dist/web/assets/login-CRhbMteV.js.br +0 -0
  206. package/dist/web/assets/mdx-C2ycXLg9.js.br +0 -0
  207. package/dist/web/assets/message.model-Lda63gEP.js.br +0 -0
  208. package/dist/web/assets/number-hR31MZlh.js.br +0 -0
  209. package/dist/web/assets/pm2-DKIyr5_a.js.br +0 -0
  210. package/dist/web/assets/private-BZ5KhwbS.js.br +0 -0
  211. package/dist/web/assets/python-ChrT3a_m.js.br +0 -0
  212. package/dist/web/assets/razor-Cs-u95op.js.br +0 -0
  213. package/dist/web/assets/react-resizable-panels.browser.esm-F8N05kqq.js.br +0 -0
  214. package/dist/web/assets/redis-DH6rAkqL.js.br +0 -0
  215. package/dist/web/assets/render-Vlnps6rd.js.br +0 -0
  216. package/dist/web/assets/server-BxGTIM1m.js.br +0 -0
  217. package/dist/web/assets/terminal-BIa8L1VQ.js.br +0 -0
  218. package/dist/web/assets/test-url-CgPWVEZv.js.br +0 -0
  219. package/dist/web/assets/theme-switch-CHsM6_Qw.js.br +0 -0
  220. package/dist/web/assets/tsMode-Df8Mkd5P.js.br +0 -0
  221. package/dist/web/assets/typescript-Cv120TyN.js.br +0 -0
  222. package/dist/web/assets/use-dialog-B0SmQMV8.js +0 -1
  223. package/dist/web/assets/useFocusable-CCFlkkgl.js.br +0 -0
  224. package/dist/web/assets/useHover-B-NdY18h.js.br +0 -0
  225. package/dist/web/assets/useNumberFormatter-DmWB9RgU.js.br +0 -0
  226. package/dist/web/assets/useRequest-BMjtEA4i.js.br +0 -0
  227. package/dist/web/assets/useToggle-svCuJzdq.js.br +0 -0
  228. package/dist/web/assets/video_insert-DB6rbTaT.js.br +0 -0
  229. package/dist/web/assets/webui-CHFIalLA.js.br +0 -0
  230. package/dist/web/assets/xml-BrYdQdcP.js.br +0 -0
  231. package/dist/web/assets/yaml-DxpbnXfn.js.br +0 -0
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import YAML, { isMap, isSeq, isPair } from 'yaml';
8
8
  import path4 from 'node:path';
9
9
  import chokidar from 'chokidar';
10
10
  import { pipeline, Readable } from 'node:stream';
11
- import axios8, { AxiosError } from 'axios';
11
+ import axios10, { AxiosError } from 'axios';
12
12
  import lodash3 from 'lodash';
13
13
  import { URL as URL$1, fileURLToPath as fileURLToPath$1, pathToFileURL } from 'node:url';
14
14
  import { createRequire } from 'module';
@@ -22,13 +22,13 @@ import sqlite3 from 'sqlite3';
22
22
  import WebSocket, { WebSocketServer, WebSocket as WebSocket$1 } from 'ws';
23
23
  import jwt from 'jsonwebtoken';
24
24
  import dotenv from 'dotenv';
25
+ import template from 'art-template';
26
+ import schedule from 'node-schedule';
25
27
  import moment2 from 'moment';
26
28
  import express2, { Router } from 'express';
27
29
  import { createServer } from 'node:http';
28
30
  import { createBrotliDecompress } from 'node:zlib';
29
- import schedule from 'node-schedule';
30
31
  import { createClient } from 'redis';
31
- import template from 'art-template';
32
32
 
33
33
  var __defProp = Object.defineProperty;
34
34
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -86,32 +86,76 @@ var init_debug2 = __esm({
86
86
  global.debug = debug2;
87
87
  }
88
88
  });
89
- var filename, karinDir, karinMain, pluginDir, isPkg, defaultConfigPath, defaultViewPath, commentPath, basePath, configPath, dataPath, tempPath, resourcePath, dbPath, redisSqlite3Path, kvPath, logsPath, htmlPath, pm2Path, consolePath, sandboxDataPath, sandboxTempPath, root_default;
89
+ var filename, karinPathRoot, karinPathMain, karinPathPlugins, isPackaged, karinPathDefaultConfig, karinPathDefaultView, karinPathComment, karinPathBase, karinPathConfig, karinPathData, karinPathTemp, karinPathResource, karinPathDb, karinPathRedisSqlite3, karinPathKv, karinPathLogs, karinPathHtml, karinPathPm2Config, karinPathConsole, karinPathSandboxData, karinPathSandboxTemp, karinDir, karinMain, pluginDir, isPkg, defaultConfigPath, defaultViewPath, commentPath, basePath, configPath, dataPath, tempPath, resourcePath, dbPath, redisSqlite3Path, kvPath, logsPath, htmlPath, pm2Path, consolePath, sandboxDataPath, sandboxTempPath, root_default;
90
90
  var init_root = __esm({
91
91
  "src/root.ts"() {
92
92
  filename = fileURLToPath(import.meta.url);
93
- karinDir = Object.freeze(path.join(filename, "../..").replace(/\\/g, "/"));
94
- karinMain = Object.freeze(path.join(karinDir, "dist", "index.js"));
95
- pluginDir = Object.freeze(path.join(process.cwd(), "plugins"));
96
- isPkg = Object.freeze(filename.includes("node_modules"));
97
- defaultConfigPath = Object.freeze(path.join(karinDir, "default", "config"));
98
- defaultViewPath = Object.freeze(path.join(karinDir, "default", "view"));
99
- commentPath = Object.freeze(path.join(karinDir, "default", "comment"));
100
- basePath = Object.freeze(path.join(process.cwd(), "@karinjs"));
101
- configPath = Object.freeze(path.join(basePath, "config"));
102
- dataPath = Object.freeze(path.join(basePath, "data"));
103
- tempPath = Object.freeze(path.join(basePath, "temp"));
104
- resourcePath = Object.freeze(path.join(basePath, "resource"));
105
- dbPath = Object.freeze(path.join(dataPath, "db"));
106
- redisSqlite3Path = Object.freeze(path.join(dbPath, "redis-sqlite3"));
107
- kvPath = Object.freeze(path.join(dbPath, "kv"));
108
- logsPath = Object.freeze(path.join(basePath, "logs"));
109
- htmlPath = Object.freeze(path.join(tempPath, "html"));
110
- pm2Path = Object.freeze(path.join(configPath, "pm2.yaml"));
111
- consolePath = Object.freeze(path.join(tempPath, "console"));
112
- sandboxDataPath = Object.freeze(path.join(dataPath, "sandbox"));
113
- sandboxTempPath = Object.freeze(path.join(tempPath, "sandbox"));
93
+ karinPathRoot = Object.freeze(path.join(filename, "../..").replace(/\\/g, "/"));
94
+ karinPathMain = Object.freeze(path.join(karinPathRoot, "dist", "index.js"));
95
+ karinPathPlugins = Object.freeze(path.join(process.cwd(), "plugins"));
96
+ isPackaged = Object.freeze(filename.includes("node_modules"));
97
+ karinPathDefaultConfig = Object.freeze(path.join(karinPathRoot, "default", "config"));
98
+ karinPathDefaultView = Object.freeze(path.join(karinPathRoot, "default", "view"));
99
+ karinPathComment = Object.freeze(path.join(karinPathRoot, "default", "comment"));
100
+ karinPathBase = Object.freeze(path.join(process.cwd(), "@karinjs"));
101
+ karinPathConfig = Object.freeze(path.join(karinPathBase, "config"));
102
+ karinPathData = Object.freeze(path.join(karinPathBase, "data"));
103
+ karinPathTemp = Object.freeze(path.join(karinPathBase, "temp"));
104
+ karinPathResource = Object.freeze(path.join(karinPathBase, "resource"));
105
+ karinPathDb = Object.freeze(path.join(karinPathData, "db"));
106
+ karinPathRedisSqlite3 = Object.freeze(path.join(karinPathDb, "redis-sqlite3"));
107
+ karinPathKv = Object.freeze(path.join(karinPathDb, "kv"));
108
+ karinPathLogs = Object.freeze(path.join(karinPathBase, "logs"));
109
+ karinPathHtml = Object.freeze(path.join(karinPathTemp, "html"));
110
+ karinPathPm2Config = Object.freeze(path.join(karinPathConfig, "pm2.yaml"));
111
+ karinPathConsole = Object.freeze(path.join(karinPathTemp, "console"));
112
+ karinPathSandboxData = Object.freeze(path.join(karinPathData, "sandbox"));
113
+ karinPathSandboxTemp = Object.freeze(path.join(karinPathTemp, "sandbox"));
114
+ karinDir = karinPathRoot;
115
+ karinMain = karinPathMain;
116
+ pluginDir = karinPathPlugins;
117
+ isPkg = isPackaged;
118
+ defaultConfigPath = karinPathDefaultConfig;
119
+ defaultViewPath = karinPathDefaultView;
120
+ commentPath = karinPathComment;
121
+ basePath = karinPathBase;
122
+ configPath = karinPathConfig;
123
+ dataPath = karinPathData;
124
+ tempPath = karinPathTemp;
125
+ resourcePath = karinPathResource;
126
+ dbPath = karinPathDb;
127
+ redisSqlite3Path = karinPathRedisSqlite3;
128
+ kvPath = karinPathKv;
129
+ logsPath = karinPathLogs;
130
+ htmlPath = karinPathHtml;
131
+ pm2Path = karinPathPm2Config;
132
+ consolePath = karinPathConsole;
133
+ sandboxDataPath = karinPathSandboxData;
134
+ sandboxTempPath = karinPathSandboxTemp;
114
135
  root_default = {
136
+ // 新常量
137
+ karinPathRoot,
138
+ karinPathMain,
139
+ karinPathPlugins,
140
+ isPackaged,
141
+ karinPathDefaultConfig,
142
+ karinPathDefaultView,
143
+ karinPathComment,
144
+ karinPathBase,
145
+ karinPathConfig,
146
+ karinPathData,
147
+ karinPathTemp,
148
+ karinPathResource,
149
+ karinPathDb,
150
+ karinPathRedisSqlite3,
151
+ karinPathKv,
152
+ karinPathLogs,
153
+ karinPathHtml,
154
+ karinPathPm2Config,
155
+ karinPathConsole,
156
+ karinPathSandboxData,
157
+ karinPathSandboxTemp,
158
+ // 旧常量,保持兼容性
115
159
  karinDir,
116
160
  karinMain,
117
161
  pluginDir,
@@ -125,6 +169,8 @@ var init_root = __esm({
125
169
  tempPath,
126
170
  resourcePath,
127
171
  dbPath,
172
+ redisSqlite3Path,
173
+ kvPath,
128
174
  logsPath,
129
175
  htmlPath,
130
176
  pm2Path,
@@ -563,14 +609,18 @@ var init_default = __esm({
563
609
  {
564
610
  enable: false,
565
611
  url: "ws://127.0.0.1:7005",
566
- token: "123456"
612
+ token: "123456",
613
+ isSnapka: false,
614
+ reconnectTime: 5e3,
615
+ heartbeatTime: 3e4
567
616
  }
568
617
  ],
569
618
  http_server: [
570
619
  {
571
620
  enable: false,
572
621
  url: "http://127.0.0.1:7005",
573
- token: "123456"
622
+ token: "123456",
623
+ isSnapka: false
574
624
  }
575
625
  ]
576
626
  }
@@ -763,7 +813,7 @@ var init_file = __esm({
763
813
  downFile = async (fileUrl, savePath, param = {}) => {
764
814
  try {
765
815
  await fs5.promises.mkdir(path4.dirname(savePath), { recursive: true });
766
- const response = await axios8.get(fileUrl, { ...param, responseType: "stream" });
816
+ const response = await axios10.get(fileUrl, { ...param, responseType: "stream" });
767
817
  await streamPipeline(response.data, fs5.createWriteStream(savePath));
768
818
  return true;
769
819
  } catch (error) {
@@ -853,7 +903,7 @@ var init_file = __esm({
853
903
  }
854
904
  };
855
905
  getAllFilesSync = (dir2, options = {}) => {
856
- const { suffixs = [], exclude = [] } = options;
906
+ const { suffixs = [], exclude = [], returnType = "rel" } = options;
857
907
  const result = [];
858
908
  const readDirRecursive = (currentDir, prefix = "") => {
859
909
  const files = fs5.readdirSync(currentDir, { withFileTypes: true });
@@ -867,15 +917,15 @@ var init_file = __esm({
867
917
  if (suffixs.length > 0) {
868
918
  const normalizedSuffixs = suffixs.map((s) => s.startsWith(".") ? s : `.${s}`);
869
919
  if (normalizedSuffixs.includes(suffix)) {
870
- result.push(relativePath);
920
+ result.push(returnType === "abs" ? fullPath : relativePath);
871
921
  }
872
922
  } else if (exclude.length > 0) {
873
923
  const normalizedExclude = exclude.map((s) => s.startsWith(".") ? s : `.${s}`);
874
924
  if (!normalizedExclude.includes(suffix)) {
875
- result.push(relativePath);
925
+ result.push(returnType === "abs" ? fullPath : relativePath);
876
926
  }
877
927
  } else {
878
- result.push(relativePath);
928
+ result.push(returnType === "abs" ? fullPath : relativePath);
879
929
  }
880
930
  }
881
931
  }
@@ -887,7 +937,7 @@ var init_file = __esm({
887
937
  return result;
888
938
  };
889
939
  getAllFiles = async (dir2, options = {}) => {
890
- const { suffixs = [], exclude = [] } = options;
940
+ const { suffixs = [], exclude = [], returnType = "rel" } = options;
891
941
  const result = [];
892
942
  const readDirRecursive = async (currentDir, prefix = "") => {
893
943
  const files = await fs5.promises.readdir(currentDir, { withFileTypes: true });
@@ -901,15 +951,15 @@ var init_file = __esm({
901
951
  if (suffixs.length > 0) {
902
952
  const normalizedSuffixs = suffixs.map((s) => s.startsWith(".") ? s : `.${s}`);
903
953
  if (normalizedSuffixs.includes(suffix)) {
904
- result.push(relativePath);
954
+ result.push(returnType === "abs" ? fullPath : relativePath);
905
955
  }
906
956
  } else if (exclude.length > 0) {
907
957
  const normalizedExclude = exclude.map((s) => s.startsWith(".") ? s : `.${s}`);
908
958
  if (!normalizedExclude.includes(suffix)) {
909
- result.push(relativePath);
959
+ result.push(returnType === "abs" ? fullPath : relativePath);
910
960
  }
911
961
  } else {
912
- result.push(relativePath);
962
+ result.push(returnType === "abs" ? fullPath : relativePath);
913
963
  }
914
964
  }
915
965
  }));
@@ -936,7 +986,7 @@ var init_data = __esm({
936
986
  if (data.startsWith("base64://")) return data.replace("base64://", "");
937
987
  if (data.startsWith("http")) {
938
988
  if (options.http) return data;
939
- const response = await axios8.get(data, { responseType: "stream" });
989
+ const response = await axios10.get(data, { responseType: "stream" });
940
990
  const buffer2 = await stream(response.data);
941
991
  return buffer2.toString("base64");
942
992
  }
@@ -956,7 +1006,7 @@ var init_data = __esm({
956
1006
  }
957
1007
  if (data.startsWith("http")) {
958
1008
  if (options == null ? void 0 : options.http) return data;
959
- const response = await axios8.get(data, { responseType: "arraybuffer" });
1009
+ const response = await axios10.get(data, { responseType: "arraybuffer" });
960
1010
  return Buffer.from(response.data, "binary");
961
1011
  }
962
1012
  const files = data.replace(sep, "");
@@ -969,9 +1019,9 @@ var init_data = __esm({
969
1019
  stream3.on("end", () => resolve(Buffer.concat(chunks)));
970
1020
  stream3.on("error", (error) => reject(error));
971
1021
  });
972
- readFile = async (path31) => {
1022
+ readFile = async (path32) => {
973
1023
  try {
974
- const data = await fs5.promises.readFile(path31);
1024
+ const data = await fs5.promises.readFile(path32);
975
1025
  return data;
976
1026
  } catch (error) {
977
1027
  logger.error(error);
@@ -987,36 +1037,36 @@ var init_data = __esm({
987
1037
  var readJsonSync, writeJsonSync, readJson, writeJson, json;
988
1038
  var init_json = __esm({
989
1039
  "src/utils/fs/json.ts"() {
990
- readJsonSync = (path31, isThrow = false) => {
1040
+ readJsonSync = (path32, isThrow = false) => {
991
1041
  try {
992
- const data = fs5.readFileSync(path31, "utf8");
1042
+ const data = fs5.readFileSync(path32, "utf8");
993
1043
  return JSON.parse(data);
994
1044
  } catch (error) {
995
1045
  if (isThrow) throw error;
996
1046
  return null;
997
1047
  }
998
1048
  };
999
- writeJsonSync = (path31, data, isThrow = false) => {
1049
+ writeJsonSync = (path32, data, isThrow = false) => {
1000
1050
  try {
1001
- fs5.writeFileSync(path31, JSON.stringify(data, null, 2));
1051
+ fs5.writeFileSync(path32, JSON.stringify(data, null, 2));
1002
1052
  return true;
1003
1053
  } catch (error) {
1004
1054
  if (isThrow) throw error;
1005
1055
  return false;
1006
1056
  }
1007
1057
  };
1008
- readJson = async (path31, isThrow = false) => {
1058
+ readJson = async (path32, isThrow = false) => {
1009
1059
  try {
1010
- const data = await fs5.promises.readFile(path31, "utf8");
1060
+ const data = await fs5.promises.readFile(path32, "utf8");
1011
1061
  return JSON.parse(data);
1012
1062
  } catch (error) {
1013
1063
  if (isThrow) throw error;
1014
1064
  return null;
1015
1065
  }
1016
1066
  };
1017
- writeJson = async (path31, data, isThrow = false) => {
1067
+ writeJson = async (path32, data, isThrow = false) => {
1018
1068
  try {
1019
- await fs5.promises.writeFile(path31, JSON.stringify(data, null, 2));
1069
+ await fs5.promises.writeFile(path32, JSON.stringify(data, null, 2));
1020
1070
  return true;
1021
1071
  } catch (error) {
1022
1072
  if (isThrow) throw error;
@@ -1159,12 +1209,12 @@ var init_pkg2 = __esm({
1159
1209
  });
1160
1210
 
1161
1211
  // src/utils/fs/static.ts
1162
- var isStatic;
1212
+ var isPublic;
1163
1213
  var init_static = __esm({
1164
1214
  "src/utils/fs/static.ts"() {
1165
- init_cache();
1166
1215
  init_path();
1167
- isStatic = (filePath) => {
1216
+ init_cache();
1217
+ isPublic = (filePath) => {
1168
1218
  try {
1169
1219
  for (const item of cache3.static) {
1170
1220
  if (isSubPath(item, filePath)) {
@@ -1173,7 +1223,7 @@ var init_static = __esm({
1173
1223
  }
1174
1224
  return false;
1175
1225
  } catch (error) {
1176
- logger.error("isStatic", error);
1226
+ logger.error(error);
1177
1227
  return false;
1178
1228
  }
1179
1229
  };
@@ -1196,10 +1246,10 @@ var init_yaml = __esm({
1196
1246
  * 获取指定路径的值
1197
1247
  * @param path - 路径,多个路径使用`.`连接,例如:`a.b.c`
1198
1248
  */
1199
- get(path31) {
1249
+ get(path32) {
1200
1250
  try {
1201
- if (!path31) return this.document.toJSON();
1202
- return lodash3.get(this.document.toJSON(), path31);
1251
+ if (!path32) return this.document.toJSON();
1252
+ return lodash3.get(this.document.toJSON(), path32);
1203
1253
  } catch (error) {
1204
1254
  logger.error(`[YamlEditor] \u83B7\u53D6\u6570\u636E\u65F6\u51FA\u9519\uFF1A${error}`);
1205
1255
  return null;
@@ -1211,9 +1261,9 @@ var init_yaml = __esm({
1211
1261
  * @param value - 要设置的值 允许的类型:`string`, `boolean`, `number`, `object`, `array`
1212
1262
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1213
1263
  */
1214
- set(path31, value, isSplit = true) {
1264
+ set(path32, value, isSplit = true) {
1215
1265
  try {
1216
- const _path = typeof path31 === "string" ? isSplit ? path31.split(".") : [path31] : path31;
1266
+ const _path = typeof path32 === "string" ? isSplit ? path32.split(".") : [path32] : path32;
1217
1267
  this.document.setIn(_path, value);
1218
1268
  return true;
1219
1269
  } catch (error) {
@@ -1227,11 +1277,11 @@ var init_yaml = __esm({
1227
1277
  * @param value - 要添加的值
1228
1278
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1229
1279
  */
1230
- add(path31, value, isSplit = true) {
1280
+ add(path32, value, isSplit = true) {
1231
1281
  try {
1232
- const _path = typeof path31 === "string" ? isSplit ? path31.split(".") : [path31] : path31;
1282
+ const _path = typeof path32 === "string" ? isSplit ? path32.split(".") : [path32] : path32;
1233
1283
  this.document.addIn(_path, value);
1234
- logger.debug(`[YamlEditor] \u5DF2\u5728 ${path31} \u6DFB\u52A0\u65B0\u7684\u503C`);
1284
+ logger.debug(`[YamlEditor] \u5DF2\u5728 ${path32} \u6DFB\u52A0\u65B0\u7684\u503C`);
1235
1285
  return true;
1236
1286
  } catch (error) {
1237
1287
  logger.error(`[YamlEditor] \u6DFB\u52A0\u6570\u636E\u65F6\u51FA\u9519\uFF1A${error}`);
@@ -1244,9 +1294,9 @@ var init_yaml = __esm({
1244
1294
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1245
1295
  * @returns 是否删除成功
1246
1296
  */
1247
- del(path31, isSplit = true) {
1297
+ del(path32, isSplit = true) {
1248
1298
  try {
1249
- const _path = typeof path31 === "string" ? isSplit ? path31.split(".") : [path31] : path31;
1299
+ const _path = typeof path32 === "string" ? isSplit ? path32.split(".") : [path32] : path32;
1250
1300
  this.document.deleteIn(_path);
1251
1301
  return true;
1252
1302
  } catch (error) {
@@ -1261,9 +1311,9 @@ var init_yaml = __esm({
1261
1311
  * @param prepend - 如果为 true,则添加到数组的开头,否则添加到末尾
1262
1312
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1263
1313
  */
1264
- append(path31, value, prepend = false, isSplit = true) {
1314
+ append(path32, value, prepend = false, isSplit = true) {
1265
1315
  try {
1266
- const _path = typeof path31 === "string" ? isSplit ? path31.split(".") : [path31] : path31;
1316
+ const _path = typeof path32 === "string" ? isSplit ? path32.split(".") : [path32] : path32;
1267
1317
  let current = this.document.getIn(_path);
1268
1318
  if (!current) {
1269
1319
  current = new YAML.YAMLSeq();
@@ -1274,7 +1324,7 @@ var init_yaml = __esm({
1274
1324
  } else {
1275
1325
  prepend ? current.items.unshift(value) : current.add(value);
1276
1326
  }
1277
- logger.debug(`[YamlEditor] \u5DF2\u5411 ${path31} \u6570\u7EC4${prepend ? "\u5F00\u5934" : "\u672B\u5C3E"}\u6DFB\u52A0\u65B0\u5143\u7D20\uFF1A${value}`);
1327
+ logger.debug(`[YamlEditor] \u5DF2\u5411 ${path32} \u6570\u7EC4${prepend ? "\u5F00\u5934" : "\u672B\u5C3E"}\u6DFB\u52A0\u65B0\u5143\u7D20\uFF1A${value}`);
1278
1328
  return true;
1279
1329
  } catch (error) {
1280
1330
  logger.error(`[YamlEditor] \u5411\u6570\u7EC4\u6DFB\u52A0\u5143\u7D20\u65F6\u51FA\u9519\uFF1A${error}`);
@@ -1287,9 +1337,9 @@ var init_yaml = __esm({
1287
1337
  * @param value - 要删除的值
1288
1338
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1289
1339
  */
1290
- remove(path31, value, isSplit = true) {
1340
+ remove(path32, value, isSplit = true) {
1291
1341
  try {
1292
- const _path = typeof path31 === "string" ? isSplit ? path31.split(".") : [path31] : path31;
1342
+ const _path = typeof path32 === "string" ? isSplit ? path32.split(".") : [path32] : path32;
1293
1343
  const current = this.document.getIn(_path);
1294
1344
  if (!current) {
1295
1345
  logger.error("[YamlEditor] \u6307\u5B9A\u7684\u8DEF\u5F84\u4E0D\u5B58\u5728");
@@ -1305,7 +1355,7 @@ var init_yaml = __esm({
1305
1355
  return false;
1306
1356
  }
1307
1357
  current.items.splice(index5, 1);
1308
- logger.debug(`[YamlEditor] \u5DF2\u4ECE ${path31} \u6570\u7EC4\u5220\u9664\u5143\u7D20\uFF1A${value}`);
1358
+ logger.debug(`[YamlEditor] \u5DF2\u4ECE ${path32} \u6570\u7EC4\u5220\u9664\u5143\u7D20\uFF1A${value}`);
1309
1359
  return true;
1310
1360
  } catch (error) {
1311
1361
  logger.error(`[YamlEditor] \u4ECE\u6570\u7EC4\u5220\u9664\u5143\u7D20\u65F6\u51FA\u9519\uFF1A${error}`);
@@ -1317,9 +1367,9 @@ var init_yaml = __esm({
1317
1367
  * @param path - 路径,用点号分隔
1318
1368
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1319
1369
  */
1320
- has(path31, isSplit = true) {
1370
+ has(path32, isSplit = true) {
1321
1371
  try {
1322
- const _path = typeof path31 === "string" ? isSplit ? path31.split(".") : [path31] : path31;
1372
+ const _path = typeof path32 === "string" ? isSplit ? path32.split(".") : [path32] : path32;
1323
1373
  return this.document.hasIn(_path);
1324
1374
  } catch (error) {
1325
1375
  logger.error(`[YamlEditor] \u68C0\u67E5\u8DEF\u5F84\u662F\u5426\u5B58\u5728\u65F6\u51FA\u9519\uFF1A${error}`);
@@ -1332,9 +1382,9 @@ var init_yaml = __esm({
1332
1382
  * @param value - 要查询的值
1333
1383
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1334
1384
  */
1335
- hasval(path31, value, isSplit = true) {
1385
+ hasval(path32, value, isSplit = true) {
1336
1386
  try {
1337
- const _path = typeof path31 === "string" ? isSplit ? path31.split(".") : [path31] : path31;
1387
+ const _path = typeof path32 === "string" ? isSplit ? path32.split(".") : [path32] : path32;
1338
1388
  const current = this.document.getIn(_path);
1339
1389
  if (!current) return false;
1340
1390
  if (current instanceof YAML.YAMLSeq) {
@@ -1345,7 +1395,7 @@ var init_yaml = __esm({
1345
1395
  return lodash3.isEqual(current, value);
1346
1396
  }
1347
1397
  } catch (error) {
1348
- logger.error(`[YamlEditor] \u68C0\u67E5\u8DEF\u5F84 ${path31} \u662F\u5426\u5305\u542B\u503C\u65F6\u51FA\u9519\uFF1A${error}`);
1398
+ logger.error(`[YamlEditor] \u68C0\u67E5\u8DEF\u5F84 ${path32} \u662F\u5426\u5305\u542B\u503C\u65F6\u51FA\u9519\uFF1A${error}`);
1349
1399
  return false;
1350
1400
  }
1351
1401
  }
@@ -1355,8 +1405,8 @@ var init_yaml = __esm({
1355
1405
  * @param value - 要查询的值
1356
1406
  * @deprecated 请使用 `hasval` 代替
1357
1407
  */
1358
- hasVal(path31, value) {
1359
- return this.hasval(path31, value);
1408
+ hasVal(path32, value) {
1409
+ return this.hasval(path32, value);
1360
1410
  }
1361
1411
  /**
1362
1412
  * 向根节点新增元素,如果根节点不是数组,则将其转换为数组再新增元素
@@ -1401,9 +1451,9 @@ var init_yaml = __esm({
1401
1451
  * @param path - 路径,多个路径使用`.`连接,例如:`a.b.c`
1402
1452
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1403
1453
  */
1404
- getpair(path31, isSplit = true) {
1405
- if (!path31) throw new Error("path is required");
1406
- const keys = typeof path31 === "string" ? isSplit ? path31.split(".") : [path31] : path31;
1454
+ getpair(path32, isSplit = true) {
1455
+ if (!path32) throw new Error("path is required");
1456
+ const keys = typeof path32 === "string" ? isSplit ? path32.split(".") : [path32] : path32;
1407
1457
  let pair = this.document.contents;
1408
1458
  keys.forEach((key) => {
1409
1459
  if (isMap(pair)) {
@@ -1423,10 +1473,10 @@ var init_yaml = __esm({
1423
1473
  * @param prepend - 如果为 true,则添加注释到开头,否则添加到同一行的末尾
1424
1474
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1425
1475
  */
1426
- comment(path31, comment2, prepend = true, isSplit = true) {
1427
- if (!path31) throw new Error("[YamlEditor] path \u4E0D\u80FD\u4E3A\u7A7A");
1428
- const pair = this.getpair(path31, isSplit);
1429
- if (!pair) throw new Error(`[YamlEditor] \u672A\u627E\u5230\u8282\u70B9 ${path31}`);
1476
+ comment(path32, comment2, prepend = true, isSplit = true) {
1477
+ if (!path32) throw new Error("[YamlEditor] path \u4E0D\u80FD\u4E3A\u7A7A");
1478
+ const pair = this.getpair(path32, isSplit);
1479
+ if (!pair) throw new Error(`[YamlEditor] \u672A\u627E\u5230\u8282\u70B9 ${path32}`);
1430
1480
  comment2 = ` ${comment2}`;
1431
1481
  if (prepend) {
1432
1482
  pair.key.commentBefore = comment2;
@@ -1440,10 +1490,10 @@ var init_yaml = __esm({
1440
1490
  * @param type - 要删除的注释类型,`before` 为注释前,`after` 为注释后,`all` 为全部
1441
1491
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1442
1492
  */
1443
- uncomment(path31, type = "all", isSplit = true) {
1444
- if (!path31) throw new Error("[YamlEditor] path \u4E0D\u80FD\u4E3A\u7A7A");
1445
- const pair = this.getpair(path31, isSplit);
1446
- if (!pair) throw new Error(`[YamlEditor] \u672A\u627E\u5230\u8282\u70B9 ${path31}`);
1493
+ uncomment(path32, type = "all", isSplit = true) {
1494
+ if (!path32) throw new Error("[YamlEditor] path \u4E0D\u80FD\u4E3A\u7A7A");
1495
+ const pair = this.getpair(path32, isSplit);
1496
+ if (!pair) throw new Error(`[YamlEditor] \u672A\u627E\u5230\u8282\u70B9 ${path32}`);
1447
1497
  if (type === "all") {
1448
1498
  delete pair.key.comment;
1449
1499
  delete pair.key.commentBefore;
@@ -1459,10 +1509,10 @@ var init_yaml = __esm({
1459
1509
  * @param type - 要检查的注释类型,`before` 为注释前,`after` 为注释后
1460
1510
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1461
1511
  */
1462
- hascomment(path31, type, isSplit = true) {
1463
- if (!path31) throw new Error("[YamlEditor] path \u4E0D\u80FD\u4E3A\u7A7A");
1464
- const pair = this.getpair(path31, isSplit);
1465
- if (!pair) throw new Error(`[YamlEditor] \u672A\u627E\u5230\u8282\u70B9 ${path31}`);
1512
+ hascomment(path32, type, isSplit = true) {
1513
+ if (!path32) throw new Error("[YamlEditor] path \u4E0D\u80FD\u4E3A\u7A7A");
1514
+ const pair = this.getpair(path32, isSplit);
1515
+ if (!pair) throw new Error(`[YamlEditor] \u672A\u627E\u5230\u8282\u70B9 ${path32}`);
1466
1516
  if (type === "before") {
1467
1517
  return !!pair.key.commentBefore;
1468
1518
  } else if (type === "after") {
@@ -1475,10 +1525,10 @@ var init_yaml = __esm({
1475
1525
  * @param path - 路径,多个路径使用`.`连接,例如:`a.b.c`
1476
1526
  * @param isSplit - 是否使用分割路径路径,默认为 `true`
1477
1527
  */
1478
- getcomment(path31, isSplit = true) {
1479
- if (!path31) throw new Error("[YamlEditor] path \u4E0D\u80FD\u4E3A\u7A7A");
1480
- const pair = this.getpair(path31, isSplit);
1481
- if (!pair) throw new Error(`[YamlEditor] \u672A\u627E\u5230\u8282\u70B9 ${path31}`);
1528
+ getcomment(path32, isSplit = true) {
1529
+ if (!path32) throw new Error("[YamlEditor] path \u4E0D\u80FD\u4E3A\u7A7A");
1530
+ const pair = this.getpair(path32, isSplit);
1531
+ if (!pair) throw new Error(`[YamlEditor] \u672A\u627E\u5230\u8282\u70B9 ${path32}`);
1482
1532
  return pair.key.commentBefore || pair.key.comment;
1483
1533
  }
1484
1534
  /**
@@ -1490,11 +1540,11 @@ var init_yaml = __esm({
1490
1540
  logger.debug("[YamlEditor] \u6587\u4EF6\u5DF2\u4FDD\u5B58");
1491
1541
  }
1492
1542
  };
1493
- read = (path31) => {
1494
- const data = YAML.parse(fs5.readFileSync(path31, "utf-8"));
1543
+ read = (path32) => {
1544
+ const data = YAML.parse(fs5.readFileSync(path32, "utf-8"));
1495
1545
  read.save = (options) => {
1496
1546
  try {
1497
- save(path31, data, typeof options === "string" ? JSON.parse(options) : options);
1547
+ save(path32, data, typeof options === "string" ? JSON.parse(options) : options);
1498
1548
  return true;
1499
1549
  } catch (error) {
1500
1550
  logger.error("[YamlEditor] \u4FDD\u5B58\u6587\u4EF6\u65F6\u51FA\u9519");
@@ -1504,23 +1554,23 @@ var init_yaml = __esm({
1504
1554
  };
1505
1555
  return data;
1506
1556
  };
1507
- write = (path31, value) => {
1557
+ write = (path32, value) => {
1508
1558
  try {
1509
- fs5.writeFileSync(path31, YAML.stringify(value));
1559
+ fs5.writeFileSync(path32, YAML.stringify(value));
1510
1560
  return true;
1511
1561
  } catch {
1512
1562
  return false;
1513
1563
  }
1514
1564
  };
1515
- save = (path31, value, options) => {
1565
+ save = (path32, value, options) => {
1516
1566
  if (!options) {
1517
- fs5.writeFileSync(path31, YAML.stringify(value));
1567
+ fs5.writeFileSync(path32, YAML.stringify(value));
1518
1568
  return;
1519
1569
  }
1520
1570
  const editor = new YamlEditor(YAML.stringify(value));
1521
1571
  const comment2 = typeof options === "string" ? JSON.parse(fs5.readFileSync(options, "utf8")) : options;
1522
1572
  applyComments(editor, comment2);
1523
- fs5.writeFileSync(path31, editor.document.toString());
1573
+ fs5.writeFileSync(path32, editor.document.toString());
1524
1574
  };
1525
1575
  comment = (filePath, commentConfig) => {
1526
1576
  const editor = new YamlEditor(filePath);
@@ -1681,11 +1731,11 @@ __export(key_exports, {
1681
1731
  WS_CONNECTION: () => WS_CONNECTION,
1682
1732
  WS_CONNECTION_ONEBOT: () => WS_CONNECTION_ONEBOT,
1683
1733
  WS_CONNECTION_PUPPETEER: () => WS_CONNECTION_PUPPETEER,
1684
- WS_CONNECTION_PUPPETEER_2: () => WS_CONNECTION_PUPPETEER_2,
1685
1734
  WS_CONNECTION_SANDBOX: () => WS_CONNECTION_SANDBOX,
1686
- WS_CONNECTION_TERMINAL: () => WS_CONNECTION_TERMINAL
1735
+ WS_CONNECTION_TERMINAL: () => WS_CONNECTION_TERMINAL,
1736
+ WS_SNAPKA: () => WS_SNAPKA
1687
1737
  });
1688
- var RECV_MSG, SEND_MSG, EVENT_COUNT, FILE_CHANGE, WS_CONNECTION, WS_CONNECTION_ONEBOT, WS_CONNECTION_PUPPETEER, WS_CONNECTION_SANDBOX, WS_CONNECTION_TERMINAL, WS_CLOSE, WS_CLOSE_ONEBOT, WS_CLOSE_PUPPETEER, WS_CLOSE_SANDBOX, WS_CONNECTION_PUPPETEER_2;
1738
+ var RECV_MSG, SEND_MSG, EVENT_COUNT, FILE_CHANGE, WS_CONNECTION, WS_CONNECTION_ONEBOT, WS_CONNECTION_PUPPETEER, WS_CONNECTION_SANDBOX, WS_CONNECTION_TERMINAL, WS_CLOSE, WS_CLOSE_ONEBOT, WS_CLOSE_PUPPETEER, WS_CLOSE_SANDBOX, WS_SNAPKA;
1689
1739
  var init_key = __esm({
1690
1740
  "src/utils/fs/key.ts"() {
1691
1741
  RECV_MSG = "karin:count:recv";
@@ -1701,7 +1751,7 @@ var init_key = __esm({
1701
1751
  WS_CLOSE_ONEBOT = "ws:close:onebot";
1702
1752
  WS_CLOSE_PUPPETEER = "ws:close:puppeteer";
1703
1753
  WS_CLOSE_SANDBOX = "ws:close:sandbox";
1704
- WS_CONNECTION_PUPPETEER_2 = "ws:connection:puppeteer-2";
1754
+ WS_SNAPKA = "ws:connection:snapka";
1705
1755
  }
1706
1756
  });
1707
1757
 
@@ -1739,7 +1789,7 @@ __export(fs_exports, {
1739
1789
  isFile: () => isFile,
1740
1790
  isFileSync: () => isFileSync,
1741
1791
  isPlugin: () => isPlugin,
1742
- isStatic: () => isStatic,
1792
+ isPublic: () => isPublic,
1743
1793
  isSubPath: () => isSubPath,
1744
1794
  json: () => json,
1745
1795
  key: () => key_exports,
@@ -1806,9 +1856,9 @@ __export(fs_exports2, {
1806
1856
  WS_CONNECTION: () => WS_CONNECTION,
1807
1857
  WS_CONNECTION_ONEBOT: () => WS_CONNECTION_ONEBOT,
1808
1858
  WS_CONNECTION_PUPPETEER: () => WS_CONNECTION_PUPPETEER,
1809
- WS_CONNECTION_PUPPETEER_2: () => WS_CONNECTION_PUPPETEER_2,
1810
1859
  WS_CONNECTION_SANDBOX: () => WS_CONNECTION_SANDBOX,
1811
1860
  WS_CONNECTION_TERMINAL: () => WS_CONNECTION_TERMINAL,
1861
+ WS_SNAPKA: () => WS_SNAPKA,
1812
1862
  Watch: () => Watch,
1813
1863
  Watcher: () => Watcher,
1814
1864
  YamlEditor: () => YamlEditor,
@@ -1841,7 +1891,7 @@ __export(fs_exports2, {
1841
1891
  isFile: () => isFile,
1842
1892
  isFileSync: () => isFileSync,
1843
1893
  isPlugin: () => isPlugin,
1844
- isStatic: () => isStatic,
1894
+ isPublic: () => isPublic,
1845
1895
  isSubPath: () => isSubPath,
1846
1896
  json: () => json,
1847
1897
  key: () => key_exports,
@@ -2340,7 +2390,21 @@ var init_cache2 = __esm({
2340
2390
  message: [],
2341
2391
  forward: []
2342
2392
  },
2343
- emptyMessage: []
2393
+ empty: {
2394
+ message: [],
2395
+ notice: [],
2396
+ request: []
2397
+ },
2398
+ eventCall: {
2399
+ message: [],
2400
+ group: [],
2401
+ guild: [],
2402
+ groupTemp: [],
2403
+ friend: [],
2404
+ direct: [],
2405
+ notice: [],
2406
+ request: []
2407
+ }
2344
2408
  };
2345
2409
  }
2346
2410
  });
@@ -3600,6 +3664,336 @@ var init_internal = __esm({
3600
3664
  init_status_listener();
3601
3665
  }
3602
3666
  });
3667
+ var addHook2, eventCall, emitHooks2, eventCallEmit;
3668
+ var init_eventCall = __esm({
3669
+ "src/hooks/eventCall.ts"() {
3670
+ init_cache2();
3671
+ addHook2 = (list2, callback, options = {}) => {
3672
+ const id = createHookId();
3673
+ list2.push({
3674
+ id,
3675
+ priority: options.priority ?? 1e4,
3676
+ callback
3677
+ });
3678
+ return { id, list: lodash3.orderBy(list2, ["priority"], ["asc"]) };
3679
+ };
3680
+ eventCall = Object.assign(
3681
+ /**
3682
+ * 添加通用事件调用钩子
3683
+ * @param callback 事件处理回调函数
3684
+ * @param options 钩子配置项
3685
+ * @returns 钩子ID
3686
+ */
3687
+ (callback, options = {}) => {
3688
+ const { id, list: list2 } = addHook2(cache4.eventCall.message, callback, options);
3689
+ logger.mark(`[hooks] \u6DFB\u52A0\u901A\u7528\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3690
+ cache4.eventCall.message = list2;
3691
+ return id;
3692
+ },
3693
+ {
3694
+ /**
3695
+ * 添加群聊事件调用钩子
3696
+ * @param callback 事件处理回调函数
3697
+ * @param options 钩子配置项
3698
+ * @returns 钩子ID
3699
+ */
3700
+ group(callback, options = {}) {
3701
+ const { id, list: list2 } = addHook2(cache4.eventCall.group, callback, options);
3702
+ logger.mark(`[hooks] \u6DFB\u52A0\u7FA4\u804A\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3703
+ cache4.eventCall.group = list2;
3704
+ return id;
3705
+ },
3706
+ /**
3707
+ * 添加频道事件调用钩子
3708
+ * @param callback 事件处理回调函数
3709
+ * @param options 钩子配置项
3710
+ * @returns 钩子ID
3711
+ */
3712
+ guild(callback, options = {}) {
3713
+ const { id, list: list2 } = addHook2(cache4.eventCall.guild, callback, options);
3714
+ logger.mark(`[hooks] \u6DFB\u52A0\u9891\u9053\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3715
+ cache4.eventCall.guild = list2;
3716
+ return id;
3717
+ },
3718
+ /**
3719
+ * 添加群临时事件调用钩子
3720
+ * @param callback 事件处理回调函数
3721
+ * @param options 钩子配置项
3722
+ * @returns 钩子ID
3723
+ */
3724
+ groupTemp(callback, options = {}) {
3725
+ const { id, list: list2 } = addHook2(cache4.eventCall.groupTemp, callback, options);
3726
+ logger.mark(`[hooks] \u6DFB\u52A0\u7FA4\u4E34\u65F6\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3727
+ cache4.eventCall.groupTemp = list2;
3728
+ return id;
3729
+ },
3730
+ /**
3731
+ * 添加好友事件调用钩子
3732
+ * @param callback 事件处理回调函数
3733
+ * @param options 钩子配置项
3734
+ * @returns 钩子ID
3735
+ */
3736
+ friend(callback, options = {}) {
3737
+ const { id, list: list2 } = addHook2(cache4.eventCall.friend, callback, options);
3738
+ logger.mark(`[hooks] \u6DFB\u52A0\u597D\u53CB\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3739
+ cache4.eventCall.friend = list2;
3740
+ return id;
3741
+ },
3742
+ /**
3743
+ * 添加私聊事件调用钩子
3744
+ * @param callback 事件处理回调函数
3745
+ * @param options 钩子配置项
3746
+ * @returns 钩子ID
3747
+ */
3748
+ direct(callback, options = {}) {
3749
+ const { id, list: list2 } = addHook2(cache4.eventCall.direct, callback, options);
3750
+ logger.mark(`[hooks] \u6DFB\u52A0\u79C1\u804A\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3751
+ cache4.eventCall.direct = list2;
3752
+ return id;
3753
+ },
3754
+ /**
3755
+ * 添加通知事件调用钩子
3756
+ * @param callback 事件处理回调函数
3757
+ * @param options 钩子配置项
3758
+ * @returns 钩子ID
3759
+ */
3760
+ notice(callback, options = {}) {
3761
+ const { id, list: list2 } = addHook2(cache4.eventCall.notice, callback, options);
3762
+ logger.mark(`[hooks] \u6DFB\u52A0\u901A\u77E5\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3763
+ cache4.eventCall.notice = list2;
3764
+ return id;
3765
+ },
3766
+ /**
3767
+ * 添加请求事件调用钩子
3768
+ * @param callback 事件处理回调函数
3769
+ * @param options 钩子配置项
3770
+ * @returns 钩子ID
3771
+ */
3772
+ request(callback, options = {}) {
3773
+ const { id, list: list2 } = addHook2(cache4.eventCall.request, callback, options);
3774
+ logger.mark(`[hooks] \u6DFB\u52A0\u8BF7\u6C42\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3775
+ cache4.eventCall.request = list2;
3776
+ return id;
3777
+ },
3778
+ /**
3779
+ * 删除钩子
3780
+ * @param id 钩子ID
3781
+ */
3782
+ remove(id) {
3783
+ logger.mark(`[hooks] \u79FB\u9664\u4E8B\u4EF6\u8C03\u7528\u94A9\u5B50: ${id}`);
3784
+ cache4.eventCall.message = cache4.eventCall.message.filter((item) => item.id !== id);
3785
+ cache4.eventCall.group = cache4.eventCall.group.filter((item) => item.id !== id);
3786
+ cache4.eventCall.guild = cache4.eventCall.guild.filter((item) => item.id !== id);
3787
+ cache4.eventCall.groupTemp = cache4.eventCall.groupTemp.filter((item) => item.id !== id);
3788
+ cache4.eventCall.friend = cache4.eventCall.friend.filter((item) => item.id !== id);
3789
+ cache4.eventCall.direct = cache4.eventCall.direct.filter((item) => item.id !== id);
3790
+ cache4.eventCall.notice = cache4.eventCall.notice.filter((item) => item.id !== id);
3791
+ cache4.eventCall.request = cache4.eventCall.request.filter((item) => item.id !== id);
3792
+ }
3793
+ }
3794
+ );
3795
+ emitHooks2 = async (event, plugin, hooks2) => {
3796
+ let isNext = false;
3797
+ for (const hook of hooks2) {
3798
+ const result = hook.callback(event, plugin, () => {
3799
+ isNext = true;
3800
+ });
3801
+ if (isPromise(result)) await result;
3802
+ if (!isNext) return false;
3803
+ isNext = false;
3804
+ }
3805
+ return true;
3806
+ };
3807
+ eventCallEmit = {
3808
+ /**
3809
+ * 触发通用事件调用钩子
3810
+ * @param event 事件
3811
+ * @param plugin 插件对象
3812
+ * @returns 是否继续正常流程
3813
+ */
3814
+ message: (event, plugin) => emitHooks2(event, plugin, cache4.eventCall.message),
3815
+ /**
3816
+ * 触发群聊事件调用钩子
3817
+ * @param event 群聊事件
3818
+ * @param plugin 插件对象
3819
+ * @returns 是否继续正常流程
3820
+ */
3821
+ group: (event, plugin) => emitHooks2(event, plugin, cache4.eventCall.group),
3822
+ /**
3823
+ * 触发频道事件调用钩子
3824
+ * @param event 频道事件
3825
+ * @param plugin 插件对象
3826
+ * @returns 是否继续正常流程
3827
+ */
3828
+ guild: (event, plugin) => emitHooks2(event, plugin, cache4.eventCall.guild),
3829
+ /**
3830
+ * 触发群临时事件调用钩子
3831
+ * @param event 群临时事件
3832
+ * @param plugin 插件对象
3833
+ * @returns 是否继续正常流程
3834
+ */
3835
+ groupTemp: (event, plugin) => emitHooks2(event, plugin, cache4.eventCall.groupTemp),
3836
+ /**
3837
+ * 触发好友事件调用钩子
3838
+ * @param event 好友事件
3839
+ * @param plugin 插件对象
3840
+ * @returns 是否继续正常流程
3841
+ */
3842
+ friend: (event, plugin) => emitHooks2(event, plugin, cache4.eventCall.friend),
3843
+ /**
3844
+ * 触发私聊事件调用钩子
3845
+ * @param event 私聊事件
3846
+ * @param plugin 插件对象
3847
+ * @returns 是否继续正常流程
3848
+ */
3849
+ direct: (event, plugin) => emitHooks2(event, plugin, cache4.eventCall.direct),
3850
+ /**
3851
+ * 触发通知事件调用钩子
3852
+ * @param event 通知事件
3853
+ * @param plugin 插件对象
3854
+ * @returns 是否继续正常流程
3855
+ */
3856
+ notice: (event, plugin) => emitHooks2(event, plugin, cache4.eventCall.notice),
3857
+ /**
3858
+ * 触发请求事件调用钩子
3859
+ * @param event 请求事件
3860
+ * @param plugin 插件对象
3861
+ * @returns 是否继续正常流程
3862
+ */
3863
+ request: (event, plugin) => emitHooks2(event, plugin, cache4.eventCall.request)
3864
+ };
3865
+ }
3866
+ });
3867
+ var addMessageHook, addGeneralHook, empty, emitMessageHooks, emitGeneralHooks, emptyEmit;
3868
+ var init_empty = __esm({
3869
+ "src/hooks/empty.ts"() {
3870
+ init_cache2();
3871
+ addMessageHook = (list2, callback, options = {}) => {
3872
+ const id = createHookId();
3873
+ list2.push({
3874
+ id,
3875
+ priority: options.priority ?? 1e4,
3876
+ callback
3877
+ });
3878
+ return { id, list: lodash3.orderBy(list2, ["priority"], ["asc"]) };
3879
+ };
3880
+ addGeneralHook = (list2, callback, options = {}) => {
3881
+ const id = createHookId();
3882
+ list2.push({
3883
+ id,
3884
+ priority: options.priority ?? 1e4,
3885
+ callback
3886
+ });
3887
+ return { id, list: lodash3.orderBy(list2, ["priority"], ["asc"]) };
3888
+ };
3889
+ empty = Object.assign(
3890
+ /**
3891
+ * 添加未找到匹配插件消息钩子
3892
+ * @param callback 消息处理回调函数
3893
+ * @param options 钩子配置项
3894
+ * @returns 钩子ID
3895
+ */
3896
+ (callback, options = {}) => {
3897
+ const { id, list: list2 } = addMessageHook(cache4.empty.message, callback, options);
3898
+ logger.mark(`[hooks] \u6DFB\u52A0\u672A\u627E\u5230\u5339\u914D\u63D2\u4EF6\u6D88\u606F\u94A9\u5B50: ${id}`);
3899
+ cache4.empty.message = list2;
3900
+ return id;
3901
+ },
3902
+ {
3903
+ /**
3904
+ * 添加未找到匹配插件消息钩子
3905
+ * @param callback 消息处理回调函数
3906
+ * @param options 钩子配置项
3907
+ * @returns 钩子ID
3908
+ */
3909
+ message(callback, options = {}) {
3910
+ const { id, list: list2 } = addMessageHook(cache4.empty.message, callback, options);
3911
+ logger.mark(`[hooks] \u6DFB\u52A0\u672A\u627E\u5230\u5339\u914D\u63D2\u4EF6\u6D88\u606F\u94A9\u5B50: ${id}`);
3912
+ cache4.empty.message = list2;
3913
+ return id;
3914
+ },
3915
+ /**
3916
+ * 添加未找到匹配插件通知钩子
3917
+ * @param callback 通知处理回调函数
3918
+ * @param options 钩子配置项
3919
+ * @returns 钩子ID
3920
+ */
3921
+ notice(callback, options = {}) {
3922
+ const { id, list: list2 } = addGeneralHook(cache4.empty.notice, callback, options);
3923
+ logger.mark(`[hooks] \u6DFB\u52A0\u672A\u627E\u5230\u5339\u914D\u63D2\u4EF6\u901A\u77E5\u94A9\u5B50: ${id}`);
3924
+ cache4.empty.notice = list2;
3925
+ return id;
3926
+ },
3927
+ /**
3928
+ * 添加未找到匹配插件请求钩子
3929
+ * @param callback 请求处理回调函数
3930
+ * @param options 钩子配置项
3931
+ * @returns 钩子ID
3932
+ */
3933
+ request(callback, options = {}) {
3934
+ const { id, list: list2 } = addGeneralHook(cache4.empty.request, callback, options);
3935
+ logger.mark(`[hooks] \u6DFB\u52A0\u672A\u627E\u5230\u5339\u914D\u63D2\u4EF6\u8BF7\u6C42\u94A9\u5B50: ${id}`);
3936
+ cache4.empty.request = list2;
3937
+ return id;
3938
+ },
3939
+ /**
3940
+ * 删除未找到匹配插件钩子
3941
+ * @param id 钩子ID
3942
+ */
3943
+ remove(id) {
3944
+ logger.mark(`[hooks] \u79FB\u9664\u672A\u627E\u5230\u5339\u914D\u63D2\u4EF6\u94A9\u5B50: ${id}`);
3945
+ cache4.empty.message = cache4.empty.message.filter((item) => item.id !== id);
3946
+ cache4.empty.notice = cache4.empty.notice.filter((item) => item.id !== id);
3947
+ cache4.empty.request = cache4.empty.request.filter((item) => item.id !== id);
3948
+ }
3949
+ }
3950
+ );
3951
+ emitMessageHooks = async (event, hooks2) => {
3952
+ let isNext = false;
3953
+ for (const hook of hooks2) {
3954
+ const result = hook.callback(event, () => {
3955
+ isNext = true;
3956
+ });
3957
+ if (isPromise(result)) await result;
3958
+ if (!isNext) return false;
3959
+ isNext = false;
3960
+ }
3961
+ return true;
3962
+ };
3963
+ emitGeneralHooks = async (event, hooks2) => {
3964
+ let isNext = false;
3965
+ for (const hook of hooks2) {
3966
+ const result = hook.callback(event, () => {
3967
+ isNext = true;
3968
+ });
3969
+ if (isPromise(result)) await result;
3970
+ if (!isNext) return false;
3971
+ isNext = false;
3972
+ }
3973
+ return true;
3974
+ };
3975
+ emptyEmit = {
3976
+ /**
3977
+ * 触发未找到匹配插件消息钩子
3978
+ * @param event 消息事件
3979
+ * @returns 是否继续正常流程
3980
+ */
3981
+ message: (event) => emitMessageHooks(event, cache4.empty.message),
3982
+ /**
3983
+ * 触发未找到匹配插件通知钩子
3984
+ * @param event 通知事件
3985
+ * @returns 是否继续正常流程
3986
+ */
3987
+ notice: (event) => emitGeneralHooks(event, cache4.empty.notice),
3988
+ /**
3989
+ * 触发未找到匹配插件请求钩子
3990
+ * @param event 请求事件
3991
+ * @returns 是否继续正常流程
3992
+ */
3993
+ request: (event) => emitGeneralHooks(event, cache4.empty.request)
3994
+ };
3995
+ }
3996
+ });
3603
3997
 
3604
3998
  // src/event/handler/other/handler.ts
3605
3999
  var log2, initMsg, initRole, initAlias, initEmit, disableViaAdapter, disableViaPluginWhitelist, disableViaPluginBlacklist, privateFilterEvent, groupFilterEvent, groupPrint, guildPrint;
@@ -3908,6 +4302,8 @@ var init_other = __esm({
3908
4302
  "src/event/handler/other/other.ts"() {
3909
4303
  init_cache();
3910
4304
  init_internal();
4305
+ init_eventCall();
4306
+ init_empty();
3911
4307
  init_handler();
3912
4308
  initTips = (ctx3) => {
3913
4309
  switch (ctx3.subEvent) {
@@ -4000,10 +4396,22 @@ var init_other = __esm({
4000
4396
  if (plugin.event !== ctx3.event && plugin.event !== `${ctx3.event}.${ctx3.subEvent}`) {
4001
4397
  continue;
4002
4398
  }
4399
+ if (ctx3.event === "notice") {
4400
+ const result2 = await eventCallEmit.notice(ctx3, plugin);
4401
+ if (!result2) return;
4402
+ } else {
4403
+ const result2 = await eventCallEmit.request(ctx3, plugin);
4404
+ if (!result2) return;
4405
+ }
4003
4406
  const result = await fnc(ctx3, plugin, config2);
4004
4407
  if (!result) return;
4005
4408
  }
4006
4409
  log2(ctx3.userId, `\u672A\u627E\u5230\u5339\u914D\u5230\u76F8\u5E94\u63D2\u4EF6: ${ctx3.eventId}`);
4410
+ if (ctx3.event === "notice") {
4411
+ emptyEmit.notice(ctx3);
4412
+ } else {
4413
+ emptyEmit.request(ctx3);
4414
+ }
4007
4415
  };
4008
4416
  fnc = async (ctx3, plugin, config2) => {
4009
4417
  if (!disableViaAdapter(plugin, ctx3.bot.adapter.protocol)) return true;
@@ -4242,11 +4650,11 @@ var init_permission = __esm({
4242
4650
  };
4243
4651
  }
4244
4652
  });
4245
- var addHook2, message, emitHooks2, hooksMessageEmit;
4653
+ var addHook3, message, emitHooks3, hooksMessageEmit;
4246
4654
  var init_messaeg = __esm({
4247
4655
  "src/hooks/messaeg.ts"() {
4248
4656
  init_cache2();
4249
- addHook2 = (list2, callback, options = {}) => {
4657
+ addHook3 = (list2, callback, options = {}) => {
4250
4658
  const id = createHookId();
4251
4659
  list2.push({
4252
4660
  id,
@@ -4263,7 +4671,7 @@ var init_messaeg = __esm({
4263
4671
  * @returns 钩子ID
4264
4672
  */
4265
4673
  (callback, options = {}) => {
4266
- const { id, list: list2 } = addHook2(cache4.message.message, callback, options);
4674
+ const { id, list: list2 } = addHook3(cache4.message.message, callback, options);
4267
4675
  logger.mark(`[hooks] \u6DFB\u52A0\u5168\u90E8\u6D88\u606F\u94A9\u5B50: ${id}`);
4268
4676
  cache4.message.message = list2;
4269
4677
  return id;
@@ -4276,7 +4684,7 @@ var init_messaeg = __esm({
4276
4684
  * @returns 钩子ID
4277
4685
  */
4278
4686
  friend(callback, options = {}) {
4279
- const { id, list: list2 } = addHook2(cache4.message.friend, callback, options);
4687
+ const { id, list: list2 } = addHook3(cache4.message.friend, callback, options);
4280
4688
  logger.mark(`[hooks] \u6DFB\u52A0\u597D\u53CB\u6D88\u606F\u94A9\u5B50: ${id}`);
4281
4689
  cache4.message.friend = list2;
4282
4690
  return id;
@@ -4288,7 +4696,7 @@ var init_messaeg = __esm({
4288
4696
  * @returns 钩子ID
4289
4697
  */
4290
4698
  group(callback, options = {}) {
4291
- const { id, list: list2 } = addHook2(cache4.message.group, callback, options);
4699
+ const { id, list: list2 } = addHook3(cache4.message.group, callback, options);
4292
4700
  logger.mark(`[hooks] \u6DFB\u52A0\u7FA4\u6D88\u606F\u94A9\u5B50: ${id}`);
4293
4701
  cache4.message.group = list2;
4294
4702
  return id;
@@ -4300,7 +4708,7 @@ var init_messaeg = __esm({
4300
4708
  * @returns 钩子ID
4301
4709
  */
4302
4710
  guild(callback, options = {}) {
4303
- const { id, list: list2 } = addHook2(cache4.message.guild, callback, options);
4711
+ const { id, list: list2 } = addHook3(cache4.message.guild, callback, options);
4304
4712
  logger.mark(`[hooks] \u6DFB\u52A0\u9891\u9053\u6D88\u606F\u94A9\u5B50: ${id}`);
4305
4713
  cache4.message.guild = list2;
4306
4714
  return id;
@@ -4312,7 +4720,7 @@ var init_messaeg = __esm({
4312
4720
  * @returns 钩子ID
4313
4721
  */
4314
4722
  direct(callback, options = {}) {
4315
- const { id, list: list2 } = addHook2(cache4.message.direct, callback, options);
4723
+ const { id, list: list2 } = addHook3(cache4.message.direct, callback, options);
4316
4724
  logger.mark(`[hooks] \u6DFB\u52A0\u4E34\u65F6\u6D88\u606F\u94A9\u5B50: ${id}`);
4317
4725
  cache4.message.direct = list2;
4318
4726
  return id;
@@ -4324,7 +4732,7 @@ var init_messaeg = __esm({
4324
4732
  * @returns 钩子ID
4325
4733
  */
4326
4734
  groupTemp(callback, options = {}) {
4327
- const { id, list: list2 } = addHook2(cache4.message.groupTemp, callback, options);
4735
+ const { id, list: list2 } = addHook3(cache4.message.groupTemp, callback, options);
4328
4736
  logger.mark(`[hooks] \u6DFB\u52A0\u7FA4\u4E34\u65F6\u6D88\u606F\u94A9\u5B50: ${id}`);
4329
4737
  cache4.message.groupTemp = list2;
4330
4738
  return id;
@@ -4344,7 +4752,7 @@ var init_messaeg = __esm({
4344
4752
  }
4345
4753
  }
4346
4754
  );
4347
- emitHooks2 = async (event, hooks2) => {
4755
+ emitHooks3 = async (event, hooks2) => {
4348
4756
  let isNext = false;
4349
4757
  for (const hook of hooks2) {
4350
4758
  const result = hook.callback(event, () => {
@@ -4362,95 +4770,37 @@ var init_messaeg = __esm({
4362
4770
  * @param event 消息事件
4363
4771
  * @returns 是否继续正常流程
4364
4772
  */
4365
- message: (event) => emitHooks2(event, cache4.message.message),
4773
+ message: (event) => emitHooks3(event, cache4.message.message),
4366
4774
  /**
4367
4775
  * 触发好友消息钩子
4368
4776
  * @param event 好友消息事件
4369
4777
  * @returns 是否继续正常流程
4370
4778
  */
4371
- friend: (event) => emitHooks2(event, cache4.message.friend),
4779
+ friend: (event) => emitHooks3(event, cache4.message.friend),
4372
4780
  /**
4373
4781
  * 触发群消息钩子
4374
4782
  * @param event 群消息事件
4375
4783
  * @returns 是否继续正常流程
4376
4784
  */
4377
- group: (event) => emitHooks2(event, cache4.message.group),
4785
+ group: (event) => emitHooks3(event, cache4.message.group),
4378
4786
  /**
4379
4787
  * 触发频道消息钩子
4380
4788
  * @param event 频道消息事件
4381
4789
  * @returns 是否继续正常流程
4382
4790
  */
4383
- guild: (event) => emitHooks2(event, cache4.message.guild),
4791
+ guild: (event) => emitHooks3(event, cache4.message.guild),
4384
4792
  /**
4385
4793
  * 触发私聊消息钩子
4386
4794
  * @param event 私聊消息事件
4387
4795
  * @returns 是否继续正常流程
4388
4796
  */
4389
- direct: (event) => emitHooks2(event, cache4.message.direct),
4797
+ direct: (event) => emitHooks3(event, cache4.message.direct),
4390
4798
  /**
4391
4799
  * 触发群临时消息钩子
4392
4800
  * @param event 群临时消息事件
4393
4801
  * @returns 是否继续正常流程
4394
4802
  */
4395
- groupTemp: (event) => emitHooks2(event, cache4.message.groupTemp)
4396
- };
4397
- }
4398
- });
4399
- var addHook3, emptyMessage, emitHooks3, hooksEmptyMessageEmit;
4400
- var init_emptyMessage = __esm({
4401
- "src/hooks/emptyMessage.ts"() {
4402
- init_cache2();
4403
- addHook3 = (list2, callback, options = {}) => {
4404
- const id = createHookId();
4405
- list2.push({
4406
- id,
4407
- priority: options.priority ?? 1e4,
4408
- callback
4409
- });
4410
- return { id, list: lodash3.orderBy(list2, ["priority"], ["asc"]) };
4411
- };
4412
- emptyMessage = Object.assign(
4413
- /**
4414
- * 添加未找到匹配插件消息钩子
4415
- * @param callback 消息处理回调函数
4416
- * @param options 钩子配置项
4417
- * @returns 钩子ID
4418
- */
4419
- (callback, options = {}) => {
4420
- const { id, list: list2 } = addHook3(cache4.emptyMessage, callback, options);
4421
- logger.mark(`[hooks] \u6DFB\u52A0\u672A\u627E\u5230\u5339\u914D\u63D2\u4EF6\u6D88\u606F\u94A9\u5B50: ${id}`);
4422
- cache4.emptyMessage = list2;
4423
- return id;
4424
- },
4425
- {
4426
- /**
4427
- * 删除未找到匹配插件消息钩子
4428
- * @param id 钩子ID
4429
- */
4430
- remove(id) {
4431
- logger.mark(`[hooks] \u79FB\u9664\u672A\u627E\u5230\u5339\u914D\u63D2\u4EF6\u6D88\u606F\u94A9\u5B50: ${id}`);
4432
- cache4.emptyMessage = cache4.emptyMessage.filter((item) => item.id !== id);
4433
- }
4434
- }
4435
- );
4436
- emitHooks3 = async (event) => {
4437
- let isNext = false;
4438
- for (const hook of cache4.emptyMessage) {
4439
- const result = hook.callback(event, () => {
4440
- isNext = true;
4441
- });
4442
- if (isPromise(result)) await result;
4443
- if (!isNext) return false;
4444
- }
4445
- return isNext;
4446
- };
4447
- hooksEmptyMessageEmit = {
4448
- /**
4449
- * 触发未找到匹配插件消息钩子
4450
- * @param event 消息事件
4451
- * @returns 是否继续正常流程
4452
- */
4453
- emptyMessage: (event) => emitHooks3(event)
4803
+ groupTemp: (event) => emitHooks3(event, cache4.message.groupTemp)
4454
4804
  };
4455
4805
  }
4456
4806
  });
@@ -4463,7 +4813,8 @@ var init_groups3 = __esm({
4463
4813
  init_internal();
4464
4814
  init_permission();
4465
4815
  init_messaeg();
4466
- init_emptyMessage();
4816
+ init_empty();
4817
+ init_eventCall();
4467
4818
  init_config();
4468
4819
  init_handler();
4469
4820
  groupHandler = async (ctx3) => {
@@ -4474,7 +4825,7 @@ var init_groups3 = __esm({
4474
4825
  initRole(ctx3, config2);
4475
4826
  initAlias(ctx3, group.alias);
4476
4827
  initEmit(ctx3);
4477
- initPrint2(ctx3, "group", "\u7FA4\u6D88\u606F", isPrint ? "info" : "debug");
4828
+ initPrint2(ctx3, isPrint ? "info" : "debug");
4478
4829
  const hook = await hooksMessageEmit.group(ctx3);
4479
4830
  if (!hook) {
4480
4831
  logger.debug(`[${ctx3.logFnc}] \u7FA4\u6D88\u606F\u94A9\u5B50\u8FD4\u56DEfalse \u8DF3\u8FC7\u5F53\u524D\u4E8B\u4EF6: ${ctx3.eventId}`);
@@ -4511,7 +4862,7 @@ var init_groups3 = __esm({
4511
4862
  initRole(ctx3, config2);
4512
4863
  initAlias(ctx3, group.alias);
4513
4864
  initEmit(ctx3);
4514
- initPrint2(ctx3, "groupTemp", "\u7FA4\u4E34\u65F6\u6D88\u606F");
4865
+ initPrint2(ctx3);
4515
4866
  const hook = await hooksMessageEmit.groupTemp(ctx3);
4516
4867
  if (!hook) {
4517
4868
  logger.debug(`[${ctx3.logFnc}] \u7FA4\u4E34\u65F6\u6D88\u606F\u94A9\u5B50\u8FD4\u56DEfalse \u8DF3\u8FC7\u5F53\u524D\u4E8B\u4EF6: ${ctx3.eventId}`);
@@ -4542,7 +4893,7 @@ var init_groups3 = __esm({
4542
4893
  initRole(ctx3, config2);
4543
4894
  initAlias(ctx3, group.alias);
4544
4895
  initEmit(ctx3);
4545
- initPrint2(ctx3, "guild", "\u9891\u9053\u6D88\u606F");
4896
+ initPrint2(ctx3);
4546
4897
  const context2 = context(ctx3);
4547
4898
  if (context2) return ctx3;
4548
4899
  hooksMessageEmit.guild(ctx3);
@@ -4563,9 +4914,28 @@ var init_groups3 = __esm({
4563
4914
  });
4564
4915
  }
4565
4916
  };
4566
- initPrint2 = (ctx3, type, prefix, level = "info") => {
4567
- ctx3.logText = `[${type}:${ctx3.userId}(${ctx3.sender.nick || ""})]`;
4568
- logger.bot(level, ctx3.selfId, `${prefix}: [${ctx3.userId}(${ctx3.sender.nick || ""})] ${ctx3.rawMessage}`);
4917
+ initPrint2 = (ctx3, level = "info") => {
4918
+ let idPath;
4919
+ let msgType;
4920
+ if (ctx3.isFriend) {
4921
+ msgType = "\u597D\u53CB\u6D88\u606F";
4922
+ idPath = ctx3.userId;
4923
+ } else if (ctx3.isGroup) {
4924
+ msgType = "\u7FA4\u6D88\u606F";
4925
+ idPath = `${ctx3.groupId}-${ctx3.userId}`;
4926
+ } else if (ctx3.isGuild) {
4927
+ msgType = "\u9891\u9053\u6D88\u606F";
4928
+ idPath = `${ctx3.guildId}-${ctx3.channelId}-${ctx3.userId}`;
4929
+ } else if (ctx3.isGroupTemp) {
4930
+ msgType = "\u7FA4\u4E34\u65F6\u6D88\u606F";
4931
+ idPath = `${ctx3.groupId}-${ctx3.userId}`;
4932
+ } else {
4933
+ msgType = "\u79C1\u4FE1\u6D88\u606F";
4934
+ idPath = ctx3.userId;
4935
+ }
4936
+ const nick = ctx3.sender.nick || "";
4937
+ ctx3.logText = `[${ctx3.contact.scene}:${idPath}(${nick})]`;
4938
+ logger.bot(level, ctx3.selfId, `${msgType}: [${idPath}(${nick})] ${ctx3.rawMessage}`);
4569
4939
  };
4570
4940
  groupsDeal = async (ctx3, config2, isPrint, filter) => {
4571
4941
  for (const plugin of cache3.command) {
@@ -4574,7 +4944,7 @@ var init_groups3 = __esm({
4574
4944
  if (!result) return;
4575
4945
  }
4576
4946
  log2(ctx3.userId, `\u672A\u627E\u5230\u5339\u914D\u5230\u76F8\u5E94\u63D2\u4EF6: ${ctx3.messageId}`);
4577
- hooksEmptyMessageEmit.emptyMessage(ctx3);
4947
+ emptyEmit.message(ctx3);
4578
4948
  };
4579
4949
  groupsCmd = async (ctx3, plugin, config2, isPrint) => {
4580
4950
  const reg = plugin.reg;
@@ -4586,6 +4956,18 @@ var init_groups3 = __esm({
4586
4956
  const logFnc = logger.fnc(ctx3.logFnc);
4587
4957
  isPrint && plugin.log(ctx3.selfId, `${logFnc}${ctx3.logText} ${lodash3.truncate(ctx3.msg, { length: 100 })}`);
4588
4958
  const start3 = Date.now();
4959
+ if (ctx3.isGroup) {
4960
+ const result = await eventCallEmit.group(ctx3, plugin);
4961
+ if (!result) return false;
4962
+ } else if (ctx3.isGuild) {
4963
+ const result = await eventCallEmit.guild(ctx3, plugin);
4964
+ if (!result) return false;
4965
+ } else if (ctx3.isGroupTemp) {
4966
+ const result = await eventCallEmit.groupTemp(ctx3, plugin);
4967
+ if (!result) return false;
4968
+ }
4969
+ const hookResult = await eventCallEmit.message(ctx3, plugin);
4970
+ if (!hookResult) return false;
4589
4971
  try {
4590
4972
  if (!Permission.groups(ctx3, plugin)) return false;
4591
4973
  let next = false;
@@ -4633,7 +5015,8 @@ var init_private3 = __esm({
4633
5015
  init_config();
4634
5016
  init_permission();
4635
5017
  init_messaeg();
4636
- init_emptyMessage();
5018
+ init_eventCall();
5019
+ init_empty();
4637
5020
  init_handler();
4638
5021
  hasMethod = (obj, methodName) => {
4639
5022
  return typeof obj[methodName] === "function";
@@ -4708,7 +5091,7 @@ var init_private3 = __esm({
4708
5091
  if (!result) return;
4709
5092
  }
4710
5093
  log2(ctx3.userId, `\u672A\u627E\u5230\u5339\u914D\u5230\u76F8\u5E94\u63D2\u4EF6: ${ctx3.messageId}`);
4711
- hooksEmptyMessageEmit.emptyMessage(ctx3);
5094
+ emptyEmit.message(ctx3);
4712
5095
  };
4713
5096
  privateCmd = async (ctx3, plugin, config2) => {
4714
5097
  const reg = plugin.reg;
@@ -4720,6 +5103,15 @@ var init_private3 = __esm({
4720
5103
  const logFnc = logger.fnc(ctx3.logFnc);
4721
5104
  plugin.log(ctx3.selfId, `${logFnc}${ctx3.logText} ${lodash3.truncate(ctx3.msg, { length: 100 })}`);
4722
5105
  const start3 = Date.now();
5106
+ if (ctx3.isFriend) {
5107
+ const result = await eventCallEmit.friend(ctx3, plugin);
5108
+ if (!result) return false;
5109
+ } else if (ctx3.isDirect) {
5110
+ const result = await eventCallEmit.direct(ctx3, plugin);
5111
+ if (!result) return false;
5112
+ }
5113
+ const hookResult = await eventCallEmit.message(ctx3, plugin);
5114
+ if (!hookResult) return false;
4723
5115
  try {
4724
5116
  if (!Permission.private(ctx3, plugin)) return false;
4725
5117
  let next = false;
@@ -8843,11 +9235,12 @@ comment: ${comment2}`
8843
9235
  };
8844
9236
  }
8845
9237
  });
8846
- var cache5, getPlugins, getPluginsInfo, createPkg, getAppInfo, getGitInfo, getNpmInfo, isNpmPlugin, filterApp, filterGit, filterPkg;
9238
+ var cache5, getPlugins, getPluginsInfo, createPkg, getAppInfo, getGitInfo, getNpmInfo, filterApp, filterGit, filterPkg;
8847
9239
  var init_list = __esm({
8848
9240
  "src/plugin/list.ts"() {
8849
9241
  init_env();
8850
9242
  init_env2();
9243
+ init_system2();
8851
9244
  init_root();
8852
9245
  init_path();
8853
9246
  init_env3();
@@ -9014,15 +9407,6 @@ var init_list = __esm({
9014
9407
  }));
9015
9408
  info.push(createPkg("npm", name, dir2, apps, allApps, isForce));
9016
9409
  };
9017
- isNpmPlugin = async (name) => {
9018
- try {
9019
- const file = path4.join(process.cwd(), "node_modules", name, "package.json");
9020
- const pkg2 = await requireFile(file);
9021
- return !!pkg2.karin;
9022
- } catch {
9023
- return false;
9024
- }
9025
- };
9026
9410
  filterApp = async (files, list2) => {
9027
9411
  await Promise.all(files.map(async (v) => {
9028
9412
  if (!v.isDirectory()) return;
@@ -9033,9 +9417,16 @@ var init_list = __esm({
9033
9417
  };
9034
9418
  filterGit = async (files, list2) => {
9035
9419
  await Promise.all(files.map(async (v) => {
9420
+ var _a, _b;
9036
9421
  if (!v.isDirectory()) return;
9037
9422
  if (!v.name.startsWith("karin-plugin-")) return;
9038
9423
  if (!fs5.existsSync(path4.join(pluginDir, v.name, "package.json"))) return;
9424
+ const pkg2 = await requireFile(path4.join(pluginDir, v.name, "package.json"));
9425
+ if (((_b = (_a = pkg2 == null ? void 0 : pkg2.karin) == null ? void 0 : _a.engines) == null ? void 0 : _b.karin) && !satisfies(pkg2.karin.engines.karin, process.env.KARIN_VERSION)) {
9426
+ const msg = `[getPlugins][git] ${v.name} \u8981\u6C42 node-karin \u7248\u672C\u4E3A ${pkg2.karin.engines.karin}\uFF0C\u5F53\u524D\u4E0D\u7B26\u5408\u8981\u6C42\uFF0C\u8DF3\u8FC7\u52A0\u8F7D\u63D2\u4EF6`;
9427
+ setTimeout(() => logger.error(msg), 1e3);
9428
+ return;
9429
+ }
9039
9430
  list2.push(`git:${v.name}`);
9040
9431
  }));
9041
9432
  const root2 = await requireFile("./package.json");
@@ -9069,9 +9460,18 @@ var init_list = __esm({
9069
9460
  ...Object.keys(pkg2.dependencies || {}),
9070
9461
  ...Object.keys(pkg2.devDependencies || {})
9071
9462
  ].filter((name) => !exclude.includes(name) && !name.startsWith("@types"));
9072
- await Promise.all(dependencies.map(async (name) => {
9073
- const isPlugin2 = await isNpmPlugin(name);
9074
- if (isPlugin2) list2.push(`npm:${name}`);
9463
+ await Promise.allSettled(dependencies.map(async (name) => {
9464
+ var _a, _b;
9465
+ const file = path4.join(process.cwd(), "node_modules", name, "package.json");
9466
+ const pkg3 = await requireFile(file);
9467
+ if (!pkg3.karin) return;
9468
+ if ((_b = (_a = pkg3.karin) == null ? void 0 : _a.engines) == null ? void 0 : _b.karin) {
9469
+ if (!satisfies(pkg3.karin.engines.karin, process.env.KARIN_VERSION)) {
9470
+ logger.error(`[getPlugins][npm] ${name} \u8981\u6C42 node-karin \u7248\u672C\u4E3A ${pkg3.karin.engines.karin}\uFF0C\u5F53\u524D\u4E0D\u7B26\u5408\u8981\u6C42\uFF0C\u8DF3\u8FC7\u52A0\u8F7D\u63D2\u4EF6`);
9471
+ return;
9472
+ }
9473
+ list2.push(`npm:${name}`);
9474
+ }
9075
9475
  }));
9076
9476
  };
9077
9477
  }
@@ -9242,11 +9642,11 @@ var init_update = __esm({
9242
9642
  }
9243
9643
  };
9244
9644
  getCommit = async (options) => {
9245
- const { path: path31, count: count3 = 1, hash, branch } = options;
9645
+ const { path: path32, count: count3 = 1, hash, branch } = options;
9246
9646
  let cmd = `git log -${count3} --format="[%ad]%s %n" --date="format:%m-%d %H:%M"`;
9247
9647
  if (hash) cmd = `git log ${hash}..HEAD --format="[%ad] %s %n" --date="format:%m-%d %H:%M"`;
9248
9648
  if (branch) cmd = `git log -${count3} ${branch} --format="[%ad] %s %n" --date="format:%m-%d %H:%M"`;
9249
- const { stdout, error } = await exec(cmd, { cwd: path31 });
9649
+ const { stdout, error } = await exec(cmd, { cwd: path32 });
9250
9650
  if (error) {
9251
9651
  throw error;
9252
9652
  }
@@ -9983,6 +10383,156 @@ var init_fileToUrl = __esm({
9983
10383
  }
9984
10384
  });
9985
10385
 
10386
+ // src/utils/system/range.ts
10387
+ var parseVersion, compareVersions, matchesPattern, parseRangeCondition, satisfiesCondition, satisfies;
10388
+ var init_range = __esm({
10389
+ "src/utils/system/range.ts"() {
10390
+ parseVersion = (version) => {
10391
+ const [versionPart, prerelease] = version.split("-");
10392
+ const parts = versionPart.split(".");
10393
+ const isWildcard = (part) => part === "x" || part === "*" || part === "X";
10394
+ const majorWildcard = parts.length > 0 && isWildcard(parts[0]);
10395
+ const minorWildcard = parts.length > 1 && isWildcard(parts[1]);
10396
+ const patchWildcard = parts.length > 2 && isWildcard(parts[2]);
10397
+ const parseNumberOrNull = (part) => {
10398
+ if (!part || isWildcard(part)) return null;
10399
+ return Number(part) || 0;
10400
+ };
10401
+ return {
10402
+ major: parseNumberOrNull(parts[0]),
10403
+ minor: parseNumberOrNull(parts[1]),
10404
+ patch: parseNumberOrNull(parts[2]),
10405
+ prerelease: prerelease || null,
10406
+ majorWildcard,
10407
+ minorWildcard,
10408
+ patchWildcard
10409
+ };
10410
+ };
10411
+ compareVersions = (v1, v2) => {
10412
+ const version1 = parseVersion(v1);
10413
+ const version2 = parseVersion(v2);
10414
+ if (version1.major !== version2.major) {
10415
+ if (version1.major === null || version2.major === null) return 0;
10416
+ return version1.major > version2.major ? 1 : -1;
10417
+ }
10418
+ if (version1.minor !== version2.minor) {
10419
+ if (version1.minor === null || version2.minor === null) return 0;
10420
+ return version1.minor > version2.minor ? 1 : -1;
10421
+ }
10422
+ if (version1.patch !== version2.patch) {
10423
+ if (version1.patch === null || version2.patch === null) return 0;
10424
+ return version1.patch > version2.patch ? 1 : -1;
10425
+ }
10426
+ if (version1.prerelease === null && version2.prerelease !== null) {
10427
+ return 1;
10428
+ }
10429
+ if (version1.prerelease !== null && version2.prerelease === null) {
10430
+ return -1;
10431
+ }
10432
+ if (version1.prerelease !== null && version2.prerelease !== null) {
10433
+ const prereleaseOrder = {
10434
+ alpha: 1,
10435
+ beta: 2,
10436
+ rc: 3
10437
+ };
10438
+ const getPrereleaseOrder = (pre) => {
10439
+ const identifier = pre.split(".")[0];
10440
+ return prereleaseOrder[identifier] || 0;
10441
+ };
10442
+ const order1 = getPrereleaseOrder(version1.prerelease);
10443
+ const order2 = getPrereleaseOrder(version2.prerelease);
10444
+ if (order1 !== order2) {
10445
+ return order1 > order2 ? 1 : -1;
10446
+ }
10447
+ const getNumericSuffix = (pre) => {
10448
+ const parts = pre.split(".");
10449
+ return parts.length > 1 ? parseInt(parts[1], 10) || 0 : 0;
10450
+ };
10451
+ const num1 = getNumericSuffix(version1.prerelease);
10452
+ const num2 = getNumericSuffix(version2.prerelease);
10453
+ if (num1 !== num2) {
10454
+ return num1 > num2 ? 1 : -1;
10455
+ }
10456
+ }
10457
+ return 0;
10458
+ };
10459
+ matchesPattern = (version, pattern) => {
10460
+ const versionObj = parseVersion(version);
10461
+ const patternObj = parseVersion(pattern);
10462
+ if (!patternObj.majorWildcard && versionObj.major !== patternObj.major) {
10463
+ return false;
10464
+ }
10465
+ if (!patternObj.minorWildcard && versionObj.minor !== patternObj.minor) {
10466
+ return false;
10467
+ }
10468
+ if (!patternObj.patchWildcard && versionObj.patch !== patternObj.patch) {
10469
+ return false;
10470
+ }
10471
+ if (patternObj.prerelease === null) {
10472
+ return true;
10473
+ }
10474
+ if (patternObj.prerelease !== null && versionObj.prerelease === null) {
10475
+ return false;
10476
+ }
10477
+ if (patternObj.prerelease !== null && versionObj.prerelease !== null) {
10478
+ return compareVersions(version, pattern) === 0;
10479
+ }
10480
+ return true;
10481
+ };
10482
+ parseRangeCondition = (condition) => {
10483
+ const operators = [">=", "<=", ">", "<", "^"];
10484
+ let operator = "";
10485
+ let version = condition;
10486
+ for (const op of operators) {
10487
+ if (condition.startsWith(op)) {
10488
+ operator = op;
10489
+ version = condition.substring(op.length);
10490
+ break;
10491
+ }
10492
+ }
10493
+ return { operator, version };
10494
+ };
10495
+ satisfiesCondition = (version, condition) => {
10496
+ const { operator, version: rangeVersion } = parseRangeCondition(condition);
10497
+ if (rangeVersion.includes("x") || rangeVersion.includes("*") || rangeVersion.includes("X")) {
10498
+ if (operator === "") {
10499
+ return matchesPattern(version, rangeVersion);
10500
+ }
10501
+ return false;
10502
+ }
10503
+ const comparison = compareVersions(version, rangeVersion);
10504
+ const parsedRange = parseVersion(rangeVersion);
10505
+ let upperBound;
10506
+ switch (operator) {
10507
+ case ">":
10508
+ return comparison > 0;
10509
+ case ">=":
10510
+ return comparison >= 0;
10511
+ case "<":
10512
+ return comparison < 0;
10513
+ case "<=":
10514
+ return comparison <= 0;
10515
+ case "^":
10516
+ if (compareVersions(version, rangeVersion) < 0) {
10517
+ return false;
10518
+ }
10519
+ if (parsedRange.major === 0) {
10520
+ upperBound = `0.${parsedRange.minor + 1}.0`;
10521
+ } else {
10522
+ upperBound = `${parsedRange.major + 1}.0.0`;
10523
+ }
10524
+ return compareVersions(version, upperBound) < 0;
10525
+ default:
10526
+ return comparison === 0;
10527
+ }
10528
+ };
10529
+ satisfies = (range2, version) => {
10530
+ const conditions = range2.split(" ");
10531
+ return conditions.every((condition) => satisfiesCondition(version, condition));
10532
+ };
10533
+ }
10534
+ });
10535
+
9986
10536
  // src/utils/system/index.ts
9987
10537
  var system_exports = {};
9988
10538
  __export(system_exports, {
@@ -10016,6 +10566,7 @@ __export(system_exports, {
10016
10566
  isWin: () => isWin2,
10017
10567
  restart: () => restart,
10018
10568
  restartDirect: () => restartDirect,
10569
+ satisfies: () => satisfies,
10019
10570
  stringifyError: () => stringifyError,
10020
10571
  updateAllGitPlugin: () => updateAllGitPlugin,
10021
10572
  updateAllPkg: () => updateAllPkg,
@@ -10037,6 +10588,7 @@ var init_system2 = __esm({
10037
10588
  init_update();
10038
10589
  init_restart();
10039
10590
  init_fileToUrl();
10591
+ init_range();
10040
10592
  }
10041
10593
  });
10042
10594
 
@@ -10133,13 +10685,13 @@ var init_http = __esm({
10133
10685
  try {
10134
10686
  const token = getHttpBotApiToken(this.selfId);
10135
10687
  const headers = token ? { Authorization: `Bearer ${token}` } : {};
10136
- const { data } = await axios8.post(`${this.adapter.address}/${action}`, params, { headers, timeout: time2 * 1e3 });
10688
+ const { data } = await axios10.post(`${this.adapter.address}/${action}`, params, { headers, timeout: time2 * 1e3 });
10137
10689
  if (data.status === "ok") {
10138
10690
  return data.data;
10139
10691
  }
10140
10692
  throw buildError(this.selfId, action, request2, data);
10141
10693
  } catch (error) {
10142
- if (axios8.isAxiosError(error) && error.code === "ECONNABORTED") {
10694
+ if (axios10.isAxiosError(error) && error.code === "ECONNABORTED") {
10143
10695
  throw buildError(this.selfId, action, request2, "\u8BF7\u6C42\u8D85\u65F6");
10144
10696
  }
10145
10697
  buildError(this.selfId, action, request2);
@@ -10676,7 +11228,7 @@ __export(config_exports, {
10676
11228
  port: () => port,
10677
11229
  privates: () => privates,
10678
11230
  redis: () => redis,
10679
- render: () => render,
11231
+ render: () => render2,
10680
11232
  setConfig: () => setConfig,
10681
11233
  setEnv: () => setEnv,
10682
11234
  setYaml: () => setYaml,
@@ -10832,7 +11384,7 @@ var init_common = __esm({
10832
11384
  var _a;
10833
11385
  try {
10834
11386
  const config2 = typeof paramOrUrl === "string" ? { ...param, url: paramOrUrl, method: type } : paramOrUrl;
10835
- return await axios8(config2);
11387
+ return await axios10(config2);
10836
11388
  } catch (error) {
10837
11389
  if (error instanceof AxiosError) {
10838
11390
  if (((_a = error.response) == null ? void 0 : _a.status) === 401) return void 0;
@@ -11345,317 +11897,979 @@ var init_privates = __esm({
11345
11897
  }
11346
11898
  });
11347
11899
 
11348
- // src/utils/config/file/render.ts
11349
- var cache10, format4, initRender, render, getRenderCfg, render_default;
11350
- var init_render = __esm({
11351
- "src/utils/config/file/render.ts"() {
11352
- init_watch();
11353
- init_require();
11354
- init_fs2();
11355
- init_listeners();
11356
- format4 = (data) => {
11357
- return {
11358
- ws_server: data.ws_server,
11359
- ws_client: data.ws_client.map((v) => ({
11360
- ...v,
11361
- token: String(v.token)
11362
- })),
11363
- http_server: data.http_server.map((v) => ({
11364
- ...v,
11365
- token: String(v.token)
11366
- }))
11367
- };
11368
- };
11369
- initRender = (dir2) => {
11370
- const name = "render.json";
11371
- const file = `${dir2}/${name}`;
11372
- const data = requireFileSync(file, { type: "json" });
11373
- cache10 = format4(data);
11374
- watch(file, (old, data2) => {
11375
- cache10 = format4(data2);
11376
- const options = { file: name, old, data: cache10 };
11377
- listeners.emit(FILE_CHANGE, options);
11378
- listeners.emit(`${FILE_CHANGE}:${name}`, options);
11379
- }, { type: "json" });
11900
+ // src/adapter/snapka/key.ts
11901
+ var createWsResponseKey;
11902
+ var init_key2 = __esm({
11903
+ "src/adapter/snapka/key.ts"() {
11904
+ createWsResponseKey = (echo) => {
11905
+ return `_response:${echo}`;
11380
11906
  };
11381
- render = () => cache10;
11382
- getRenderCfg = () => cache10;
11383
- render_default = initRender;
11384
- }
11385
- });
11386
-
11387
- // src/utils/config/file/pm2.ts
11388
- var pm2;
11389
- var init_pm2 = __esm({
11390
- "src/utils/config/file/pm2.ts"() {
11391
- init_root();
11392
- init_require();
11393
- pm2 = () => requireFileSync(`${configPath}/pm2.json`, { ex: 30 });
11394
- }
11395
- });
11396
-
11397
- // src/utils/config/file/redis.ts
11398
- var redis;
11399
- var init_redis = __esm({
11400
- "src/utils/config/file/redis.ts"() {
11401
- init_root();
11402
- init_require();
11403
- redis = () => requireFileSync(`${configPath}/redis.json`, { ex: 30 });
11404
11907
  }
11405
11908
  });
11406
11909
 
11407
- // src/utils/config/file/index.ts
11408
- var initConfigCache;
11409
- var init_file2 = __esm({
11410
- "src/utils/config/file/index.ts"() {
11411
- init_adapter();
11412
- init_config2();
11413
- init_env3();
11414
- init_groups4();
11415
- init_privates();
11416
- init_render();
11417
- init_adapter();
11418
- init_config2();
11419
- init_env3();
11420
- init_groups4();
11421
- init_privates();
11422
- init_render();
11423
- init_pm2();
11424
- init_redis();
11425
- initConfigCache = (dir2) => {
11426
- env_default();
11427
- adapter_default(dir2);
11428
- config_default(dir2);
11429
- groups_default(dir2);
11430
- privates_default(dir2);
11431
- render_default(dir2);
11910
+ // src/adapter/snapka/request.ts
11911
+ var index2, createRequestError, sendWsRequest, sendWsScreenshotRequest;
11912
+ var init_request4 = __esm({
11913
+ "src/adapter/snapka/request.ts"() {
11914
+ init_internal();
11915
+ init_key2();
11916
+ index2 = 0;
11917
+ createRequestError = (options, errorType, cause) => {
11918
+ return new Error(
11919
+ `[sendRequest] \u8BF7\u6C42\u9519\u8BEF:
11920
+ options: ${options}
11921
+ error: ${errorType}`,
11922
+ { cause }
11923
+ );
11432
11924
  };
11433
- }
11434
- });
11435
- var env2, initConfig2;
11436
- var init_init = __esm({
11437
- "src/utils/config/init.ts"() {
11438
- init_env();
11439
- init_pkg();
11440
- init_default();
11441
- init_file2();
11442
- env2 = () => {
11443
- const list2 = [
11444
- {
11445
- key: "LOG_MAX_CONNECTIONS",
11446
- value: "5",
11447
- comment: "\u65E5\u5FD7\u5B9E\u65F6Api\u6700\u591A\u652F\u6301\u540C\u65F6\u8FDE\u63A5\u6570"
11925
+ sendWsRequest = (socket, data, options = { timeout: 60 * 1e3, onRequest: true }) => {
11926
+ return new Promise((resolve, reject) => {
11927
+ const timeout2 = (options == null ? void 0 : options.timeout) ?? 60 * 1e3;
11928
+ if (socket.readyState !== socket.OPEN) {
11929
+ return reject(createRequestError(
11930
+ JSON.stringify(data),
11931
+ `WebSocket\u672A\u8FDE\u63A5\uFF0C\u5F53\u524D\u72B6\u6001: ${socket.readyState}`
11932
+ ));
11448
11933
  }
11449
- ];
11450
- const file = `${process.cwd()}/${process.env.EBV_FILE}`;
11451
- const content = fs5.readFileSync(file, "utf-8");
11452
- list2.forEach((v) => {
11453
- if (!content.includes(v.key)) {
11454
- fs5.appendFileSync(file, `
11455
- ${v.comment}
11456
- ${v.key}=${v.value}`);
11457
- process.env[v.key] = v.value;
11934
+ if (options.onRequest) {
11935
+ if (index2 >= Number.MAX_SAFE_INTEGER) {
11936
+ index2 = 0;
11937
+ }
11938
+ const echo = (++index2).toString();
11939
+ const key = createWsResponseKey(echo);
11940
+ const str2 = JSON.stringify({ ...data, echo });
11941
+ const result = (data2) => {
11942
+ clearTimeout(timer);
11943
+ if ((data2 == null ? void 0 : data2.status) === "ok") {
11944
+ return resolve(data2.data);
11945
+ }
11946
+ reject(createRequestError(str2, "\u8BF7\u6C42\u5931\u8D25", data2));
11947
+ };
11948
+ const timer = setTimeout(() => {
11949
+ listeners.off(key, result);
11950
+ reject(createRequestError(str2, `\u8BF7\u6C42\u8D85\u65F6 ${timeout2}ms`));
11951
+ }, timeout2);
11952
+ listeners.once(key, result);
11953
+ try {
11954
+ socket.send(str2);
11955
+ } catch (error) {
11956
+ clearTimeout(timer);
11957
+ listeners.off(key, result);
11958
+ reject(createRequestError(str2, "\u53D1\u9001\u5931\u8D25", error));
11959
+ }
11960
+ return;
11961
+ }
11962
+ try {
11963
+ socket.send(JSON.stringify(data));
11964
+ resolve(void 0);
11965
+ } catch (error) {
11966
+ reject(createRequestError(JSON.stringify(data), "\u53D1\u9001\u5931\u8D25", error));
11458
11967
  }
11459
11968
  });
11460
11969
  };
11461
- initConfig2 = async (dir2) => {
11462
- const files = [
11463
- dir2.basePath,
11464
- dir2.configPath,
11465
- dir2.dataPath,
11466
- dir2.tempPath,
11467
- dir2.htmlPath,
11468
- dir2.consolePath,
11469
- dir2.resourcePath,
11470
- dir2.sandboxDataPath,
11471
- dir2.sandboxTempPath,
11472
- `${dir2.sandboxDataPath}/avatar`
11473
- ];
11474
- await Promise.all(files.map((v) => {
11475
- if (!fs5.existsSync(v)) fs5.mkdirSync(v, { recursive: true });
11476
- return Promise.resolve();
11477
- }));
11478
- setVersion(pkg().version);
11479
- env2();
11480
- if (process.env.pm_id) setRuntime("pm2");
11481
- const list2 = await fs5.promises.readdir(dir2.consolePath);
11482
- await Promise.all(list2.map((v) => {
11483
- if (fs5.statSync(`${dir2.consolePath}/${v}`).isDirectory()) {
11484
- fs5.rmdirSync(`${dir2.consolePath}/${v}`, { recursive: true });
11485
- } else {
11486
- fs5.unlinkSync(`${dir2.consolePath}/${v}`);
11970
+ sendWsScreenshotRequest = (socket, params, timeout2 = 60 * 1e3) => {
11971
+ return sendWsRequest(
11972
+ socket,
11973
+ {
11974
+ params,
11975
+ type: "request",
11976
+ action: params.data ? "render" : "screenshot"
11977
+ },
11978
+ {
11979
+ onRequest: true,
11980
+ timeout: timeout2
11487
11981
  }
11488
- return Promise.resolve();
11489
- }));
11490
- await Promise.all(Object.keys(defaultConfig).map(async (key) => {
11491
- const file = `${dir2.configPath}/${key}.json`;
11492
- if (fs5.existsSync(file)) return;
11493
- const data = JSON.stringify(defaultConfig[key], null, 2);
11494
- await fs5.promises.writeFile(file, data, "utf-8");
11495
- return true;
11496
- }));
11497
- initConfigCache(dir2.configPath);
11982
+ );
11498
11983
  };
11499
11984
  }
11500
11985
  });
11501
- var tips, request, checkProcess;
11502
- var init_check = __esm({
11503
- "src/service/process/check.ts"() {
11504
- init_sleep();
11505
- tips = (msg, isTrim = false) => `[process]${isTrim ? "" : " "}${msg}`;
11506
- request = async (url, path31, method, timeout2) => {
11507
- const client = axios8.create({
11508
- baseURL: url,
11509
- timeout: timeout2,
11510
- headers: { Authorization: `Bearer ${process.env.HTTP_AUTH_KEY}` },
11511
- validateStatus: () => true
11512
- });
11513
- try {
11514
- const result = await client[method](path31);
11515
- if (result.status === 200) {
11516
- logger.info(
11517
- tips(`[${method}] \u8BF7\u6C42\u6210\u529F:
11518
- `, true) + `path: ${path31}
11519
- body: ${JSON.stringify(result.data)}
11520
- `
11521
- );
11522
- return { code: result.status, success: true, data: result.data };
11523
- }
11524
- if (result.status === 401) {
11525
- logger.error(
11526
- tips(`[${method}] \u9274\u6743\u5931\u8D25:
11527
- `, true) + `path: ${path31}
11528
- body: ${JSON.stringify(result.data)}
11529
- `
11530
- );
11531
- return { code: result.status, success: false };
11986
+
11987
+ // src/adapter/render/admin/template.ts
11988
+ var template_exports = {};
11989
+ __export(template_exports, {
11990
+ renderTemplate: () => renderTemplate,
11991
+ renderTpl: () => renderTpl,
11992
+ startCleanExpiredFiles: () => startCleanExpiredFiles
11993
+ });
11994
+ var renderTpl, renderTemplate, getOutputPath, cleanExpiredFiles, startCleanExpiredFiles;
11995
+ var init_template = __esm({
11996
+ "src/adapter/render/admin/template.ts"() {
11997
+ init_root();
11998
+ init_fsSync();
11999
+ init_file();
12000
+ renderTpl = (options) => {
12001
+ if (typeof options.file !== "string") {
12002
+ throw TypeError("\u6A21\u677F\u6587\u4EF6\u8DEF\u5F84\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32");
12003
+ }
12004
+ if (!options.name) {
12005
+ options.name = path4.basename(options.file) || "render";
12006
+ }
12007
+ if (options.data) {
12008
+ if (options.file.startsWith("http")) {
12009
+ throw TypeError("\u4ED6\u55B5\u7684 \u4E0D\u4F1A\u771F\u7684\u6709\u7B28\u6BD4\u4F20\u4E2Ahttp\u6765\u5F53\u505A\u6A21\u677F\u5427...");
11532
12010
  }
11533
- (path31 === "/ping" ? logger.debug : logger.error).call(
11534
- logger,
11535
- tips(`[${method}] \u8BF7\u6C42\u5931\u8D25:
11536
- `, true) + `path: ${path31}
11537
- body: ${JSON.stringify(result.data)}
11538
- `
11539
- );
11540
- return { code: result.status, success: false };
11541
- } catch (error) {
11542
- logger.debug(
11543
- tips(`[${method}] \u8BF7\u6C42\u5F02\u5E38:
11544
- `, true) + `path: ${path31}
11545
- error: ${(error == null ? void 0 : error.message) || "\u672A\u77E5\u9519\u8BEF"}
11546
- `
11547
- );
11548
- return { code: 500, success: false };
12011
+ const file = path4.resolve(options.file);
12012
+ const tplData = fs5.readFileSync(file, "utf-8");
12013
+ const renderData = template.render(tplData, options.data);
12014
+ const outputPath = getOutputPath(options.file, renderData, options.name);
12015
+ fs5.writeFileSync(outputPath, renderData);
12016
+ delete options.data;
12017
+ options.file = `file://${outputPath}`;
12018
+ return options;
12019
+ }
12020
+ if (!options.file.startsWith("http") && !options.file.startsWith("file")) {
12021
+ options.file = `file://${path4.resolve(options.file)}`;
11549
12022
  }
12023
+ delete options.data;
12024
+ return options;
11550
12025
  };
11551
- checkProcess = async (port2) => {
11552
- var _a, _b;
11553
- const host2 = `http://127.0.0.1:${port2}/api/v1`;
11554
- const ping = await request(host2, "/ping", "get", 300);
11555
- if (!ping || !ping.success) {
11556
- logger.debug(logger.green("\u6CA1\u6709\u68C0\u6D4B\u5230\u540E\u53F0\u8FDB\u7A0B~"));
11557
- return;
12026
+ renderTemplate = (options) => {
12027
+ if (typeof options.file !== "string") {
12028
+ throw TypeError("\u6A21\u677F\u6587\u4EF6\u8DEF\u5F84\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32");
11558
12029
  }
11559
- const pid = await request(host2, "/status/karin", "get", 300);
11560
- console.log("pid:", pid);
11561
- if (pid && pid.success) {
11562
- if (((_b = (_a = pid.data) == null ? void 0 : _a.data) == null ? void 0 : _b.pid) === process.pid) {
11563
- logger.debug(logger.green(tips("\u540E\u53F0\u8FDB\u7A0Bpid\u4E0E\u5F53\u524D\u8FDB\u7A0Bpid\u4E00\u81F4 \u8DF3\u8FC7\u68C0\u67E5")));
11564
- return;
12030
+ if ("name" in options) {
12031
+ options.file_name = options.name;
12032
+ delete options.name;
12033
+ }
12034
+ if (!options.file_name) {
12035
+ options.file_name = path4.basename(options.file) || "render";
12036
+ }
12037
+ if (options.data) {
12038
+ if (options.file.startsWith("http")) {
12039
+ throw TypeError("\u4ED6\u55B5\u7684 \u4E0D\u4F1A\u771F\u7684\u6709\u7B28\u6BD4\u4F20\u4E2Ahttp\u6765\u5F53\u505A\u6A21\u677F\u5427...");
11565
12040
  }
12041
+ const file = path4.resolve(options.file);
12042
+ const tplData = fs5.readFileSync(file, "utf-8");
12043
+ const renderData = template.render(tplData, options.data);
12044
+ const outputPath = getOutputPath(options.file, renderData, options.file_name);
12045
+ fs5.writeFileSync(outputPath, renderData);
12046
+ delete options.data;
12047
+ options.file = `file://${outputPath}`;
12048
+ return options;
11566
12049
  }
11567
- logger.error(logger.yellow(tips("\u68C0\u6D4B\u5230\u540E\u53F0\u8FDB\u7A0B \u6B63\u5728\u5173\u95ED...")));
11568
- const exit = await request(host2, "/exit", "post", 500);
11569
- if (!exit || !exit.success) {
11570
- logger.fatal(logger.red(tips("\u540E\u53F0\u8FDB\u7A0B\u5173\u95ED\u5931\u8D25\uFF0C\u5982\u591A\u5F00Bot\u8BF7\u66F4\u6362\u7AEF\u53E3")));
11571
- process.exit(1);
12050
+ if (!options.file.startsWith("http") && !options.file.startsWith("file")) {
12051
+ options.file = `file://${path4.resolve(options.file)}`;
11572
12052
  }
11573
- for (let i = 0; i < 100; i++) {
11574
- const ping2 = await request(host2, "/ping", "get", 300);
11575
- if (ping2 && ping2.success) {
11576
- await sleep(50);
11577
- continue;
12053
+ delete options.data;
12054
+ return options;
12055
+ };
12056
+ getOutputPath = (file, data, name) => {
12057
+ const extname = path4.extname(file);
12058
+ const basename = path4.basename(file, extname);
12059
+ const fileDir = path4.join(htmlPath, name || "render");
12060
+ mkdirSync(fileDir);
12061
+ const contentHash = crypto.createHash("md5").update(data).digest("hex").substring(0, 8);
12062
+ const filePath = path4.join(fileDir, `${basename}-${contentHash}${extname}`);
12063
+ if (fs5.existsSync(filePath)) {
12064
+ const now = /* @__PURE__ */ new Date();
12065
+ try {
12066
+ fs5.utimesSync(filePath, now, now);
12067
+ } catch (err) {
12068
+ logger.error(`[\u6587\u4EF6\u66F4\u65B0] \u66F4\u65B0\u6587\u4EF6\u65F6\u51FA\u9519: ${filePath}, ${err}`);
11578
12069
  }
11579
- logger.mark(logger.green(tips("\u540E\u53F0\u8FDB\u7A0B\u5DF2\u5173\u95ED")));
11580
- return;
12070
+ return filePath;
11581
12071
  }
11582
- logger.error(logger.red(tips(`\u540E\u53F0\u8FDB\u7A0B\u5173\u95ED\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u662F\u5426\u6709\u8FDB\u7A0B\u6B63\u5728\u5360\u7528\u7AEF\u53E3 ${port2} `)));
11583
- process.exit(1);
12072
+ fs5.writeFileSync(filePath, data);
12073
+ return filePath;
11584
12074
  };
11585
- }
11586
- });
11587
-
11588
- // src/service/process/exit.ts
11589
- var exit_exports = {};
11590
- __export(exit_exports, {
11591
- processExit: () => processExit
11592
- });
11593
- var exitStatus, processExit;
11594
- var init_exit = __esm({
11595
- "src/service/process/exit.ts"() {
11596
- init_check();
11597
- init_exec();
11598
- init_uptime();
11599
- exitStatus = false;
11600
- processExit = async (code) => {
11601
- try {
11602
- if (exitStatus) return;
11603
- exitStatus = true;
11604
- const { redis: redis3 } = await Promise.resolve().then(() => (init_index(), index_exports));
11605
- await redis3.save();
11606
- logger.mark(tips(`\u8FD0\u884C\u7ED3\u675F \u8FD0\u884C\u65F6\u95F4\uFF1A${uptime2()} \u9000\u51FA\u7801\uFF1A${code ?? "\u672A\u77E5"}`));
11607
- if (process.env.pm_id) {
11608
- await exec(`pm2 delete ${process.env.pm_id}`);
12075
+ cleanExpiredFiles = async () => {
12076
+ let count3 = 0;
12077
+ const now = Date.now();
12078
+ const files = await getAllFiles(htmlPath, { suffixs: [".html"], returnType: "abs" });
12079
+ if (files.length === 0) return;
12080
+ const EXPIRE_TIME = 10 * 60 * 1e3;
12081
+ for (const file of files) {
12082
+ try {
12083
+ const stats = await fs5.promises.stat(file);
12084
+ const lastModified = stats.mtimeMs;
12085
+ if (now - lastModified > EXPIRE_TIME) {
12086
+ await fs5.promises.unlink(file);
12087
+ count3++;
12088
+ }
12089
+ } catch (err) {
12090
+ logger.error(`[\u6587\u4EF6\u6E05\u7406] \u5904\u7406\u6587\u4EF6\u65F6\u51FA\u9519: ${file}, ${err}`);
11609
12091
  }
11610
- } finally {
11611
- setTimeout(() => {
11612
- exitStatus = true;
11613
- }, 200);
11614
- process.exit();
11615
12092
  }
12093
+ logger.mark(`[\u6587\u4EF6\u6E05\u7406] \u6E05\u7406HTML\u5B8C\u6210: ${count3}/${files.length}`);
11616
12094
  };
11617
- }
11618
- });
11619
-
11620
- // src/service/process/signalCapture.ts
11621
- var processHandler;
11622
- var init_signalCapture = __esm({
11623
- "src/service/process/signalCapture.ts"() {
11624
- init_exit();
11625
- init_listeners();
11626
- processHandler = () => {
11627
- process.once("SIGHUP", (code) => processExit(code));
11628
- process.once("SIGINT", (code) => processExit(code));
11629
- process.once("SIGTERM", (code) => processExit(code));
11630
- process.once("SIGBREAK", (code) => processExit(code));
11631
- process.once("SIGQUIT", (code) => processExit(code));
11632
- process.on("warning", (warning) => listeners.emit("warn", warning));
11633
- process.on("uncaughtException", (error, origin) => {
11634
- listeners.emit("error", error, origin);
11635
- });
11636
- process.on("unhandledRejection", (error, promise) => {
11637
- listeners.emit("error", error, promise);
11638
- });
11639
- process.on("rejectionHandled", (error) => {
11640
- listeners.emit("error", error);
11641
- });
11642
- listeners.on("error", (...args) => {
11643
- logger.error(...args);
11644
- });
11645
- if (process.env.pm_id) process.env.RUNTIME = "pm2";
12095
+ startCleanExpiredFiles = () => {
12096
+ schedule.scheduleJob(process.env.CLEAN_HTML_CRON || "*/10 * * * *", cleanExpiredFiles);
11646
12097
  };
11647
12098
  }
11648
12099
  });
11649
12100
 
11650
- // src/service/process/index.ts
11651
- var initProcess;
11652
- var init_process = __esm({
11653
- "src/service/process/index.ts"() {
11654
- init_check();
11655
- init_signalCapture();
11656
- initProcess = async (port2) => {
11657
- processHandler();
11658
- await checkProcess(port2);
12101
+ // src/adapter/render/admin/cache.ts
12102
+ var index3, cache10, registerRender, unregisterRender, getRender, callRender, getRenderCount, getRenderList, renderHtml, renderMultiHtml, RenderCache, render, Renderer;
12103
+ var init_cache3 = __esm({
12104
+ "src/adapter/render/admin/cache.ts"() {
12105
+ index3 = 0;
12106
+ cache10 = [];
12107
+ registerRender = (id, render4) => {
12108
+ const i = ++index3;
12109
+ cache10.push({ index: i, id, render: render4 });
12110
+ logger.mark(`[render:${index3}] ${logger.green("\u6CE8\u518C\u6210\u529F")}: ${id}`);
12111
+ return i;
12112
+ };
12113
+ unregisterRender = (index5) => {
12114
+ const app2 = cache10.find((app3) => app3.index === index5);
12115
+ if (!app2) {
12116
+ logger.error(`[render] \u5378\u8F7D\u5931\u8D25: \u4E0D\u5B58\u5728\u7D22\u5F15 ${index5}`);
12117
+ return false;
12118
+ }
12119
+ cache10.splice(cache10.findIndex((app3) => app3.index === index5), 1);
12120
+ logger.mark(`[render] ${logger.yellow("\u5378\u8F7D\u6210\u529F")}: ${app2.id}`);
12121
+ return true;
12122
+ };
12123
+ getRender = (id) => {
12124
+ if (cache10.length === 0) throw new Error("[\u8C03\u7528\u6E32\u67D3\u5668\u5931\u8D25] \u6E32\u67D3\u5668\u5217\u8868\u4E3A\u7A7A");
12125
+ if (!id) {
12126
+ const app3 = cache10[Math.floor(Math.random() * cache10.length)];
12127
+ return app3;
12128
+ }
12129
+ if (typeof id === "number") {
12130
+ const app3 = cache10.find((app4) => app4.index === id);
12131
+ if (!app3) throw new Error(`[\u8C03\u7528\u6E32\u67D3\u5668\u5931\u8D25] \u672A\u627E\u5230\u6E32\u67D3\u5668\uFF1A${id}`);
12132
+ return app3;
12133
+ }
12134
+ const app2 = cache10.find((app3) => app3.id === id);
12135
+ if (!app2) throw new Error(`[\u8C03\u7528\u6E32\u67D3\u5668\u5931\u8D25] \u672A\u627E\u5230\u6E32\u67D3\u5668\uFF1A${id}`);
12136
+ return app2;
12137
+ };
12138
+ callRender = async (options, id) => {
12139
+ const res = getRender(id);
12140
+ const result = await res.render(Object.assign(options, { encoding: "base64" }));
12141
+ return result;
12142
+ };
12143
+ getRenderCount = () => cache10.length;
12144
+ getRenderList = () => {
12145
+ const list2 = cache10.map((app2) => app2);
12146
+ return list2;
12147
+ };
12148
+ renderHtml = (data) => {
12149
+ return callRender({
12150
+ file: data,
12151
+ name: "render",
12152
+ encoding: "base64",
12153
+ pageGotoParams: {
12154
+ waitUntil: "networkidle2"
12155
+ }
12156
+ });
12157
+ };
12158
+ renderMultiHtml = (file, multiPage) => {
12159
+ if (!multiPage && multiPage !== 0) multiPage = true;
12160
+ return callRender({
12161
+ file,
12162
+ name: "render",
12163
+ encoding: "base64",
12164
+ multiPage,
12165
+ pageGotoParams: {
12166
+ waitUntil: "networkidle2"
12167
+ }
12168
+ });
12169
+ };
12170
+ RenderCache = class {
12171
+ /**
12172
+ * 注册渲染器
12173
+ * @param data 渲染器数据
12174
+ * @param data.id 渲染器ID
12175
+ * @param data.type 渲染器类型
12176
+ * @param ata.render 渲染器标准方法
12177
+ * @returns 渲染器索引
12178
+ */
12179
+ app(data) {
12180
+ return registerRender(data.id, data.render);
12181
+ }
12182
+ /**
12183
+ * 卸载渲染器
12184
+ * @param index 渲染器索引
12185
+ * @returns 是否卸载成功
12186
+ */
12187
+ unapp(index5) {
12188
+ return unregisterRender(index5);
12189
+ }
12190
+ /**
12191
+ * 返回渲染器实例 未键入id返回第一个
12192
+ * @param id 渲染器ID
12193
+ * @returns 渲染器实例
12194
+ */
12195
+ App(id = "") {
12196
+ return getRender(id);
12197
+ }
12198
+ /**
12199
+ * 调用标准渲染器
12200
+ */
12201
+ async render(options, id) {
12202
+ return callRender(options, id);
12203
+ }
12204
+ /**
12205
+ * 快速渲染
12206
+ * @param data html路径、http地址
12207
+ * @returns 返回图片base64或数组
12208
+ */
12209
+ async renderHtml(data) {
12210
+ return renderHtml(data);
12211
+ }
12212
+ /**
12213
+ * 快速分片渲染
12214
+ * @param data html路径、http地址
12215
+ * @param multiPage 分片高度 自动计算传true
12216
+ */
12217
+ async renderMultiHtml(data, multiPage) {
12218
+ return renderMultiHtml(data, multiPage);
12219
+ }
12220
+ };
12221
+ render = new RenderCache();
12222
+ Renderer = render;
12223
+ }
12224
+ });
12225
+ var PREFIX, snapkaMap, createSnapkaClient, onMessage, initSnapkaClient, disconnectSnapkaClient, addSnapkaClient;
12226
+ var init_client2 = __esm({
12227
+ "src/adapter/snapka/client.ts"() {
12228
+ init_internal();
12229
+ init_request4();
12230
+ init_template();
12231
+ init_cache3();
12232
+ init_key2();
12233
+ init_static();
12234
+ PREFIX = "[snapka-ws-clinet] ";
12235
+ snapkaMap = /* @__PURE__ */ new Map();
12236
+ createSnapkaClient = (clientOptions) => {
12237
+ let index5 = -1;
12238
+ let isReconnect = true;
12239
+ let reconnectTimer;
12240
+ const { enable, url, token, reconnectTime = 5e3, heartbeatTime = 3e4, isSnapka = false } = clientOptions;
12241
+ if (!enable || !isSnapka) return;
12242
+ const authorization = token ? `Bearer ${crypto.createHash("sha256").update(token).digest("hex")}` : void 0;
12243
+ const close = () => {
12244
+ isReconnect = false;
12245
+ if (reconnectTimer) {
12246
+ clearTimeout(reconnectTimer);
12247
+ reconnectTimer = void 0;
12248
+ }
12249
+ client == null ? void 0 : client.close();
12250
+ snapkaMap.delete(url);
12251
+ };
12252
+ const client = token ? new WebSocket$1(url, {
12253
+ headers: {
12254
+ authorization: `Bearer ${crypto.createHash("sha256").update(token).digest("hex")}`
12255
+ }
12256
+ }) : new WebSocket$1(url);
12257
+ const fnc2 = (isPrint = true) => {
12258
+ client.removeAllListeners();
12259
+ client == null ? void 0 : client.close();
12260
+ index5 > 0 && unregisterRender(index5);
12261
+ if (!isReconnect) {
12262
+ isPrint && logger.error(`${PREFIX}\u8FDE\u63A5\u5173\u95ED: ${url}`);
12263
+ return;
12264
+ }
12265
+ isPrint && logger.error(`${PREFIX}\u8FDE\u63A5\u5173\u95ED: ${url} ${reconnectTime / 1e3}s \u540E\u91CD\u8FDE...`);
12266
+ reconnectTimer = setTimeout(() => createSnapkaClient(clientOptions), reconnectTime);
12267
+ };
12268
+ client.once("open", () => {
12269
+ var _a;
12270
+ const timer = setInterval(() => client.ping(), heartbeatTime);
12271
+ if (snapkaMap.has(url)) (_a = snapkaMap.get(url)) == null ? void 0 : _a.close();
12272
+ snapkaMap.set(url, { client, close });
12273
+ client.once("close", () => {
12274
+ clearInterval(timer);
12275
+ fnc2();
12276
+ });
12277
+ setTimeout(() => {
12278
+ if (client.readyState !== WebSocket$1.OPEN) return;
12279
+ logger.info(`${PREFIX}\u8FDE\u63A5\u6210\u529F: ${url}`);
12280
+ index5 = registerRender("snapka", render4);
12281
+ client.on("message", async (event) => onMessage(client, url, event, authorization));
12282
+ }, 3e3);
12283
+ });
12284
+ client.on("error", (error) => {
12285
+ logger.error(`${PREFIX}\u8FDE\u63A5\u9519\u8BEF: ${error}`);
12286
+ fnc2(false);
12287
+ });
12288
+ const render4 = (options) => {
12289
+ options = renderTemplate(options);
12290
+ return sendWsScreenshotRequest(client, options);
12291
+ };
12292
+ return {
12293
+ render: render4,
12294
+ close
12295
+ };
12296
+ };
12297
+ onMessage = async (client, url, event, authorization) => {
12298
+ const raw2 = event.toString();
12299
+ const options = JSON.parse(raw2);
12300
+ logger.debug(`${PREFIX}\u6536\u5230\u6D88\u606F: ${lodash3.truncate(raw2, { length: 300 })}`);
12301
+ if (options.type === "response") {
12302
+ const key = createWsResponseKey(options.echo);
12303
+ return listeners.emit(key, options);
12304
+ }
12305
+ if (options.type !== "request") {
12306
+ return logger.error(`${PREFIX}\u6536\u5230\u672A\u77E5\u6D88\u606F: ${raw2}`);
12307
+ }
12308
+ if (options.action === "uploadFile") {
12309
+ const file = fileURLToPath$1(options.params.path);
12310
+ logger.debug(`${PREFIX}\u6536\u5230\u4E0A\u4F20\u6587\u4EF6\u8BF7\u6C42: ${options.params.path}`);
12311
+ if (!isPublic(file)) {
12312
+ logger.error(`${PREFIX}\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25: \u975E\u6CD5\u7684\u8DEF\u5F84\uFF0C${file} \u6CA1\u6709\u5904\u4E8E\u5141\u8BB8\u9759\u6001\u8D44\u6E90\u76EE\u5F55\u4E0B`);
12313
+ client.send(JSON.stringify({
12314
+ type: "response",
12315
+ action: "uploadFile",
12316
+ echo: options.echo,
12317
+ status: "failed",
12318
+ data: "\u975E\u6CD5\u7684\u8DEF\u5F84\uFF0C\u6CA1\u6709\u5904\u4E8E\u5141\u8BB8\u9759\u6001\u8D44\u6E90\u76EE\u5F55\u4E0B"
12319
+ }));
12320
+ return;
12321
+ }
12322
+ const target = new URL$1(url);
12323
+ target.protocol = url.startsWith("wss") ? "https:" : "http:";
12324
+ target.pathname = options.params.uploadPath;
12325
+ try {
12326
+ await axios10.post(
12327
+ target.toString(),
12328
+ {
12329
+ echo: options.echo,
12330
+ file: `base64://${fs5.readFileSync(file, "base64")}`
12331
+ },
12332
+ {
12333
+ headers: {
12334
+ "Content-Type": "application/json",
12335
+ Authorization: authorization
12336
+ }
12337
+ }
12338
+ );
12339
+ } catch (error) {
12340
+ logger.error(new Error(`${PREFIX}\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25: ${error}`, { cause: error }));
12341
+ client.send(JSON.stringify({
12342
+ type: "response",
12343
+ action: "uploadFile",
12344
+ echo: options.echo,
12345
+ status: "failed",
12346
+ data: error.message
12347
+ }));
12348
+ }
12349
+ }
12350
+ };
12351
+ initSnapkaClient = async () => {
12352
+ const { getRenderCfg: getRenderCfg2 } = await Promise.resolve().then(() => (init_config(), config_exports));
12353
+ const cfg = getRenderCfg2();
12354
+ cfg.ws_client.forEach((item) => {
12355
+ createSnapkaClient(item);
12356
+ });
12357
+ };
12358
+ disconnectSnapkaClient = (url) => {
12359
+ const cache12 = snapkaMap.get(url);
12360
+ if (!cache12) return;
12361
+ cache12.close();
12362
+ snapkaMap.delete(url);
12363
+ };
12364
+ addSnapkaClient = (clientOptions) => {
12365
+ createSnapkaClient(clientOptions);
12366
+ };
12367
+ }
12368
+ });
12369
+ var auth;
12370
+ var init_auth = __esm({
12371
+ "src/adapter/snapka/auth.ts"() {
12372
+ auth = (token) => {
12373
+ if (!process.env.WS_SERVER_AUTH_KEY) return true;
12374
+ if (!token) return false;
12375
+ if (token === `Bearer ${process.env.WS_SERVER_AUTH_KEY}`) return true;
12376
+ const sha256 = crypto.createHash("sha256").update(process.env.WS_SERVER_AUTH_KEY).digest("hex");
12377
+ if (token === `Bearer ${sha256}`) return true;
12378
+ return false;
12379
+ };
12380
+ }
12381
+ });
12382
+
12383
+ // src/adapter/snapka/server.ts
12384
+ var WebSocketPuppeteerServer, initWebSocketPuppeteerServer;
12385
+ var init_server2 = __esm({
12386
+ "src/adapter/snapka/server.ts"() {
12387
+ init_auth();
12388
+ init_internal();
12389
+ init_key2();
12390
+ init_request4();
12391
+ init_key();
12392
+ init_template();
12393
+ init_cache3();
12394
+ WebSocketPuppeteerServer = async (socket, request2) => {
12395
+ let index5 = -1;
12396
+ const authorization = request2.headers["authorization"];
12397
+ if (!auth(authorization)) {
12398
+ socket.close();
12399
+ logger.error(`[WebSocket] \u9274\u6743\u5931\u8D25: authorization: ${authorization} url: ${request2.url}`);
12400
+ return;
12401
+ }
12402
+ const render4 = (options) => {
12403
+ options = renderTemplate(options);
12404
+ return sendWsScreenshotRequest(socket, options);
12405
+ };
12406
+ socket.on("close", () => {
12407
+ index5 > 0 && unregisterRender(index5);
12408
+ socket.removeAllListeners();
12409
+ socket.close();
12410
+ });
12411
+ socket.on("message", (event) => {
12412
+ const raw2 = event.toString();
12413
+ const { type, status, echo, data } = JSON.parse(raw2) || {};
12414
+ logger.debug(`[WebSocket] ${echo} ${type} ${status}`);
12415
+ logger.trace(`[WebSocket] ${echo} ${raw2}`);
12416
+ if (type !== "response") {
12417
+ logger.error(`[WebSocket] \u672A\u77E5\u7684\u8BF7\u6C42: ${raw2}`);
12418
+ return;
12419
+ }
12420
+ const key = createWsResponseKey(echo);
12421
+ listeners.emit(key, { status, data });
12422
+ });
12423
+ const name = request2.headers["x-client-name"] || "snapka";
12424
+ index5 = registerRender(name, render4);
12425
+ };
12426
+ initWebSocketPuppeteerServer = () => {
12427
+ listeners.on(WS_SNAPKA, (socket, request2, call2) => {
12428
+ call2();
12429
+ WebSocketPuppeteerServer(socket, request2);
12430
+ });
12431
+ };
12432
+ }
12433
+ });
12434
+ var snapkaMap2, createSnapkaHttp, initSnapkaHttp, disconnectSnapkaHttp;
12435
+ var init_http2 = __esm({
12436
+ "src/adapter/snapka/http.ts"() {
12437
+ init_config();
12438
+ init_template();
12439
+ init_cache3();
12440
+ snapkaMap2 = /* @__PURE__ */ new Map();
12441
+ createSnapkaHttp = async (options) => {
12442
+ if (!options.isSnapka || !options.enable) return;
12443
+ const authorization = `Bearer ${crypto.createHash("sha256").update(options.token).digest("hex")}`;
12444
+ const url = path4.dirname(options.url) + `/ping?token=${authorization}`;
12445
+ const test = async () => {
12446
+ try {
12447
+ const result = await axios10.get(url);
12448
+ return result.data;
12449
+ } catch (error) {
12450
+ return false;
12451
+ }
12452
+ };
12453
+ const pingResult = await test();
12454
+ if (!pingResult) {
12455
+ logger.error(`\u65E0\u6CD5\u8FDE\u63A5\u5230 Snapka-http \u670D\u52A1: ${options.url}\uFF0C\u5C06\u5728\u540E\u53F0\u7EE7\u7EED\u5C1D\u8BD5\u8FDE\u63A5`);
12456
+ }
12457
+ const render4 = async (data) => {
12458
+ var _a;
12459
+ data = renderTemplate(data);
12460
+ try {
12461
+ const result = await axios10.post(options.url, data, {
12462
+ headers: {
12463
+ Authorization: authorization
12464
+ }
12465
+ });
12466
+ if (result.status === 200 && ((_a = result.data) == null ? void 0 : _a.code) === 200) {
12467
+ return result.data.data;
12468
+ }
12469
+ throw new Error("\u8BF7\u6C42\u5931\u8D25:", { cause: result.data });
12470
+ } catch (error) {
12471
+ logger.error(`Snapka-http \u670D\u52A1\u8BF7\u6C42\u5F02\u5E38: ${options.url}`, error);
12472
+ throw error;
12473
+ }
12474
+ };
12475
+ let pingTimer;
12476
+ let consecutiveFailures = 0;
12477
+ const index5 = registerRender("snapka-http", render4);
12478
+ const close = () => {
12479
+ if (pingTimer) {
12480
+ clearInterval(pingTimer);
12481
+ pingTimer = void 0;
12482
+ }
12483
+ snapkaMap2.delete(options.url);
12484
+ unregisterRender(index5);
12485
+ };
12486
+ const startPingInterval = () => {
12487
+ pingTimer = setInterval(async () => {
12488
+ const isAlive = await test();
12489
+ if (isAlive) {
12490
+ if (consecutiveFailures > 0) {
12491
+ logger.log(`Snapka-http \u670D\u52A1 ${options.url} \u6062\u590D\u8FDE\u63A5`);
12492
+ consecutiveFailures = 0;
12493
+ }
12494
+ } else {
12495
+ consecutiveFailures++;
12496
+ logger.error(`Snapka-http \u670D\u52A1\u8FDE\u63A5\u5F02\u5E38 (${consecutiveFailures}\u6B21): ${options.url}\uFF0C\u5C06\u7EE7\u7EED\u5C1D\u8BD5\u91CD\u8FDE`);
12497
+ }
12498
+ }, 1e4);
12499
+ };
12500
+ startPingInterval();
12501
+ snapkaMap2.set(options.url, { close, pingTimer });
12502
+ return {
12503
+ render: render4,
12504
+ close
12505
+ };
12506
+ };
12507
+ initSnapkaHttp = async () => {
12508
+ const cfg = getRenderCfg();
12509
+ for (const options of cfg.http_server) {
12510
+ await createSnapkaHttp(options);
12511
+ }
12512
+ };
12513
+ disconnectSnapkaHttp = (url) => {
12514
+ const handler3 = snapkaMap2.get(url);
12515
+ if (handler3) {
12516
+ handler3.close();
12517
+ }
12518
+ };
12519
+ }
12520
+ });
12521
+
12522
+ // src/adapter/snapka/index.ts
12523
+ var snapka_exports = {};
12524
+ __export(snapka_exports, {
12525
+ addSnapkaClient: () => addSnapkaClient,
12526
+ createSnapkaClient: () => createSnapkaClient,
12527
+ createSnapkaHttp: () => createSnapkaHttp,
12528
+ disconnectSnapkaClient: () => disconnectSnapkaClient,
12529
+ disconnectSnapkaHttp: () => disconnectSnapkaHttp,
12530
+ initSnapkaClient: () => initSnapkaClient,
12531
+ initSnapkaHttp: () => initSnapkaHttp,
12532
+ initWebSocketPuppeteerServer: () => initWebSocketPuppeteerServer
12533
+ });
12534
+ var init_snapka = __esm({
12535
+ "src/adapter/snapka/index.ts"() {
12536
+ init_client2();
12537
+ init_server2();
12538
+ init_http2();
12539
+ }
12540
+ });
12541
+
12542
+ // src/utils/config/file/render.ts
12543
+ var cache11, format4, initRender, render2, getRenderCfg, render_default;
12544
+ var init_render = __esm({
12545
+ "src/utils/config/file/render.ts"() {
12546
+ init_watch();
12547
+ init_fs2();
12548
+ init_number();
12549
+ init_require();
12550
+ init_listeners();
12551
+ format4 = (data) => {
12552
+ return {
12553
+ ws_server: data.ws_server,
12554
+ ws_client: data.ws_client.map((v) => ({
12555
+ ...v,
12556
+ token: String(v.token)
12557
+ })),
12558
+ http_server: data.http_server.map((v) => ({
12559
+ ...v,
12560
+ token: String(v.token),
12561
+ isSnapka: v.isSnapka ?? false
12562
+ }))
12563
+ };
12564
+ };
12565
+ initRender = (dir2) => {
12566
+ const name = "render.json";
12567
+ const file = `${dir2}/${name}`;
12568
+ const data = requireFileSync(file, { type: "json" });
12569
+ cache11 = format4(data);
12570
+ watch(file, async (old, data2) => {
12571
+ cache11 = format4(data2);
12572
+ const wsClient = diffArray(
12573
+ Array.isArray(old == null ? void 0 : old.ws_client) ? old == null ? void 0 : old.ws_client : [],
12574
+ Array.isArray(data2 == null ? void 0 : data2.ws_client) ? data2 == null ? void 0 : data2.ws_client : []
12575
+ );
12576
+ const {
12577
+ disconnectSnapkaClient: disconnectSnapkaClient2,
12578
+ createSnapkaClient: createSnapkaClient2,
12579
+ disconnectSnapkaHttp: disconnectSnapkaHttp2,
12580
+ createSnapkaHttp: createSnapkaHttp2
12581
+ } = await Promise.resolve().then(() => (init_snapka(), snapka_exports));
12582
+ wsClient.removed.forEach((v) => disconnectSnapkaClient2(v.url));
12583
+ wsClient.added.forEach((v) => createSnapkaClient2(v));
12584
+ const httpServer = diffArray(
12585
+ Array.isArray(old == null ? void 0 : old.http_server) ? old == null ? void 0 : old.http_server : [],
12586
+ Array.isArray(data2 == null ? void 0 : data2.http_server) ? data2 == null ? void 0 : data2.http_server : []
12587
+ );
12588
+ httpServer.removed.forEach((v) => disconnectSnapkaHttp2(v.url));
12589
+ httpServer.added.forEach((v) => createSnapkaHttp2(v));
12590
+ const options = { file: name, old, data: cache11 };
12591
+ listeners.emit(FILE_CHANGE, options);
12592
+ listeners.emit(`${FILE_CHANGE}:${name}`, options);
12593
+ }, { type: "json" });
12594
+ };
12595
+ render2 = () => cache11;
12596
+ getRenderCfg = () => cache11;
12597
+ render_default = initRender;
12598
+ }
12599
+ });
12600
+
12601
+ // src/utils/config/file/pm2.ts
12602
+ var pm2;
12603
+ var init_pm2 = __esm({
12604
+ "src/utils/config/file/pm2.ts"() {
12605
+ init_root();
12606
+ init_require();
12607
+ pm2 = () => requireFileSync(`${configPath}/pm2.json`, { ex: 30 });
12608
+ }
12609
+ });
12610
+
12611
+ // src/utils/config/file/redis.ts
12612
+ var redis;
12613
+ var init_redis = __esm({
12614
+ "src/utils/config/file/redis.ts"() {
12615
+ init_root();
12616
+ init_require();
12617
+ redis = () => requireFileSync(`${configPath}/redis.json`, { ex: 30 });
12618
+ }
12619
+ });
12620
+
12621
+ // src/utils/config/file/index.ts
12622
+ var initConfigCache;
12623
+ var init_file2 = __esm({
12624
+ "src/utils/config/file/index.ts"() {
12625
+ init_adapter();
12626
+ init_config2();
12627
+ init_env3();
12628
+ init_groups4();
12629
+ init_privates();
12630
+ init_render();
12631
+ init_adapter();
12632
+ init_config2();
12633
+ init_env3();
12634
+ init_groups4();
12635
+ init_privates();
12636
+ init_render();
12637
+ init_pm2();
12638
+ init_redis();
12639
+ initConfigCache = (dir2) => {
12640
+ env_default();
12641
+ adapter_default(dir2);
12642
+ config_default(dir2);
12643
+ groups_default(dir2);
12644
+ privates_default(dir2);
12645
+ render_default(dir2);
12646
+ };
12647
+ }
12648
+ });
12649
+ var env2, initConfig2;
12650
+ var init_init = __esm({
12651
+ "src/utils/config/init.ts"() {
12652
+ init_env();
12653
+ init_pkg();
12654
+ init_default();
12655
+ init_file2();
12656
+ env2 = () => {
12657
+ const list2 = [
12658
+ {
12659
+ key: "LOG_MAX_CONNECTIONS",
12660
+ value: "5",
12661
+ comment: "\u65E5\u5FD7\u5B9E\u65F6Api\u6700\u591A\u652F\u6301\u540C\u65F6\u8FDE\u63A5\u6570"
12662
+ }
12663
+ ];
12664
+ const file = `${process.cwd()}/${process.env.EBV_FILE}`;
12665
+ const content = fs5.readFileSync(file, "utf-8");
12666
+ list2.forEach((v) => {
12667
+ if (!content.includes(v.key)) {
12668
+ fs5.appendFileSync(file, `
12669
+ ${v.comment}
12670
+ ${v.key}=${v.value}`);
12671
+ process.env[v.key] = v.value;
12672
+ }
12673
+ });
12674
+ };
12675
+ initConfig2 = async (dir2) => {
12676
+ const files = [
12677
+ dir2.basePath,
12678
+ dir2.configPath,
12679
+ dir2.dataPath,
12680
+ dir2.tempPath,
12681
+ dir2.htmlPath,
12682
+ dir2.consolePath,
12683
+ dir2.resourcePath,
12684
+ dir2.sandboxDataPath,
12685
+ dir2.sandboxTempPath,
12686
+ `${dir2.sandboxDataPath}/avatar`
12687
+ ];
12688
+ await Promise.all(files.map((v) => {
12689
+ if (!fs5.existsSync(v)) fs5.mkdirSync(v, { recursive: true });
12690
+ return Promise.resolve();
12691
+ }));
12692
+ setVersion(pkg().version);
12693
+ env2();
12694
+ if (process.env.pm_id) setRuntime("pm2");
12695
+ const list2 = await fs5.promises.readdir(dir2.consolePath);
12696
+ await Promise.all(list2.map((v) => {
12697
+ if (fs5.statSync(`${dir2.consolePath}/${v}`).isDirectory()) {
12698
+ fs5.rmdirSync(`${dir2.consolePath}/${v}`, { recursive: true });
12699
+ } else {
12700
+ fs5.unlinkSync(`${dir2.consolePath}/${v}`);
12701
+ }
12702
+ return Promise.resolve();
12703
+ }));
12704
+ await Promise.all(Object.keys(defaultConfig).map(async (key) => {
12705
+ const file = `${dir2.configPath}/${key}.json`;
12706
+ if (fs5.existsSync(file)) return;
12707
+ const data = JSON.stringify(defaultConfig[key], null, 2);
12708
+ await fs5.promises.writeFile(file, data, "utf-8");
12709
+ return true;
12710
+ }));
12711
+ initConfigCache(dir2.configPath);
12712
+ };
12713
+ }
12714
+ });
12715
+ var tips, request, checkProcess;
12716
+ var init_check = __esm({
12717
+ "src/service/process/check.ts"() {
12718
+ init_sleep();
12719
+ tips = (msg, isTrim = false) => `[process]${isTrim ? "" : " "}${msg}`;
12720
+ request = async (url, path32, method, timeout2) => {
12721
+ const client = axios10.create({
12722
+ baseURL: url,
12723
+ timeout: timeout2,
12724
+ headers: { Authorization: `Bearer ${process.env.HTTP_AUTH_KEY}` },
12725
+ validateStatus: () => true
12726
+ });
12727
+ try {
12728
+ const result = await client[method](path32);
12729
+ if (result.status === 200) {
12730
+ logger.info(
12731
+ tips(`[${method}] \u8BF7\u6C42\u6210\u529F:
12732
+ `, true) + `path: ${path32}
12733
+ body: ${JSON.stringify(result.data)}
12734
+ `
12735
+ );
12736
+ return { code: result.status, success: true, data: result.data };
12737
+ }
12738
+ if (result.status === 401) {
12739
+ logger.error(
12740
+ tips(`[${method}] \u9274\u6743\u5931\u8D25:
12741
+ `, true) + `path: ${path32}
12742
+ body: ${JSON.stringify(result.data)}
12743
+ `
12744
+ );
12745
+ return { code: result.status, success: false };
12746
+ }
12747
+ (path32 === "/ping" ? logger.debug : logger.error).call(
12748
+ logger,
12749
+ tips(`[${method}] \u8BF7\u6C42\u5931\u8D25:
12750
+ `, true) + `path: ${path32}
12751
+ body: ${JSON.stringify(result.data)}
12752
+ `
12753
+ );
12754
+ return { code: result.status, success: false };
12755
+ } catch (error) {
12756
+ logger.debug(
12757
+ tips(`[${method}] \u8BF7\u6C42\u5F02\u5E38:
12758
+ `, true) + `path: ${path32}
12759
+ error: ${(error == null ? void 0 : error.message) || "\u672A\u77E5\u9519\u8BEF"}
12760
+ `
12761
+ );
12762
+ return { code: 500, success: false };
12763
+ }
12764
+ };
12765
+ checkProcess = async (port2) => {
12766
+ var _a, _b;
12767
+ const host2 = `http://127.0.0.1:${port2}/api/v1`;
12768
+ const ping = await request(host2, "/ping", "get", 300);
12769
+ if (!ping || !ping.success) {
12770
+ logger.debug(logger.green("\u6CA1\u6709\u68C0\u6D4B\u5230\u540E\u53F0\u8FDB\u7A0B~"));
12771
+ return;
12772
+ }
12773
+ const pid = await request(host2, "/status/karin", "get", 300);
12774
+ console.log("pid:", pid);
12775
+ if (pid && pid.success) {
12776
+ if (((_b = (_a = pid.data) == null ? void 0 : _a.data) == null ? void 0 : _b.pid) === process.pid) {
12777
+ logger.debug(logger.green(tips("\u540E\u53F0\u8FDB\u7A0Bpid\u4E0E\u5F53\u524D\u8FDB\u7A0Bpid\u4E00\u81F4 \u8DF3\u8FC7\u68C0\u67E5")));
12778
+ return;
12779
+ }
12780
+ }
12781
+ logger.error(logger.yellow(tips("\u68C0\u6D4B\u5230\u540E\u53F0\u8FDB\u7A0B \u6B63\u5728\u5173\u95ED...")));
12782
+ const exit = await request(host2, "/exit", "post", 500);
12783
+ if (!exit || !exit.success) {
12784
+ logger.fatal(logger.red(tips("\u540E\u53F0\u8FDB\u7A0B\u5173\u95ED\u5931\u8D25\uFF0C\u5982\u591A\u5F00Bot\u8BF7\u66F4\u6362\u7AEF\u53E3")));
12785
+ process.exit(1);
12786
+ }
12787
+ for (let i = 0; i < 100; i++) {
12788
+ const ping2 = await request(host2, "/ping", "get", 300);
12789
+ if (ping2 && ping2.success) {
12790
+ await sleep(50);
12791
+ continue;
12792
+ }
12793
+ logger.mark(logger.green(tips("\u540E\u53F0\u8FDB\u7A0B\u5DF2\u5173\u95ED")));
12794
+ return;
12795
+ }
12796
+ logger.error(logger.red(tips(`\u540E\u53F0\u8FDB\u7A0B\u5173\u95ED\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u662F\u5426\u6709\u8FDB\u7A0B\u6B63\u5728\u5360\u7528\u7AEF\u53E3 ${port2} `)));
12797
+ process.exit(1);
12798
+ };
12799
+ }
12800
+ });
12801
+
12802
+ // src/service/process/exit.ts
12803
+ var exit_exports = {};
12804
+ __export(exit_exports, {
12805
+ processExit: () => processExit
12806
+ });
12807
+ var exitStatus, processExit;
12808
+ var init_exit = __esm({
12809
+ "src/service/process/exit.ts"() {
12810
+ init_check();
12811
+ init_exec();
12812
+ init_uptime();
12813
+ exitStatus = false;
12814
+ processExit = async (code) => {
12815
+ try {
12816
+ if (exitStatus) return;
12817
+ exitStatus = true;
12818
+ const { redis: redis3 } = await Promise.resolve().then(() => (init_index(), index_exports));
12819
+ await redis3.save();
12820
+ logger.mark(tips(`\u8FD0\u884C\u7ED3\u675F \u8FD0\u884C\u65F6\u95F4\uFF1A${uptime2()} \u9000\u51FA\u7801\uFF1A${code ?? "\u672A\u77E5"}`));
12821
+ if (process.env.pm_id) {
12822
+ await exec(`pm2 delete ${process.env.pm_id}`);
12823
+ }
12824
+ } finally {
12825
+ setTimeout(() => {
12826
+ exitStatus = true;
12827
+ }, 200);
12828
+ process.exit();
12829
+ }
12830
+ };
12831
+ }
12832
+ });
12833
+
12834
+ // src/service/process/signalCapture.ts
12835
+ var processHandler;
12836
+ var init_signalCapture = __esm({
12837
+ "src/service/process/signalCapture.ts"() {
12838
+ init_exit();
12839
+ init_listeners();
12840
+ processHandler = () => {
12841
+ process.once("SIGHUP", (code) => processExit(code));
12842
+ process.once("SIGINT", (code) => processExit(code));
12843
+ process.once("SIGTERM", (code) => processExit(code));
12844
+ process.once("SIGBREAK", (code) => processExit(code));
12845
+ process.once("SIGQUIT", (code) => processExit(code));
12846
+ process.on("warning", (warning) => listeners.emit("warn", warning));
12847
+ process.on("uncaughtException", (error, origin) => {
12848
+ listeners.emit("error", error, origin);
12849
+ });
12850
+ process.on("unhandledRejection", (error, promise) => {
12851
+ listeners.emit("error", error, promise);
12852
+ });
12853
+ process.on("rejectionHandled", (error) => {
12854
+ listeners.emit("error", error);
12855
+ });
12856
+ listeners.on("error", (...args) => {
12857
+ logger.error(...args);
12858
+ });
12859
+ if (process.env.pm_id) process.env.RUNTIME = "pm2";
12860
+ };
12861
+ }
12862
+ });
12863
+
12864
+ // src/service/process/index.ts
12865
+ var initProcess;
12866
+ var init_process = __esm({
12867
+ "src/service/process/index.ts"() {
12868
+ init_check();
12869
+ init_signalCapture();
12870
+ initProcess = async (port2) => {
12871
+ processHandler();
12872
+ await checkProcess(port2);
11659
12873
  };
11660
12874
  }
11661
12875
  });
@@ -11821,7 +13035,7 @@ body: ${JSON.stringify(req.body)}
11821
13035
  });
11822
13036
 
11823
13037
  // src/server/common/common.ts
11824
- var verifyToken, auth;
13038
+ var verifyToken, auth2;
11825
13039
  var init_common2 = __esm({
11826
13040
  "src/server/common/common.ts"() {
11827
13041
  init_config();
@@ -11855,7 +13069,7 @@ var init_common2 = __esm({
11855
13069
  return false;
11856
13070
  }
11857
13071
  };
11858
- auth = {
13072
+ auth2 = {
11859
13073
  /**
11860
13074
  * get请求鉴权
11861
13075
  * @description 支持请求头中携带`Authorization`字段
@@ -11911,10 +13125,10 @@ var init_middleware = __esm({
11911
13125
  return;
11912
13126
  }
11913
13127
  if (req.method === "POST") {
11914
- const verify = await auth.postAuth(req, res);
13128
+ const verify = await auth2.postAuth(req, res);
11915
13129
  if (!verify) return;
11916
13130
  } else if (req.method === "GET") {
11917
- const verify = await auth.getAuth(req, res);
13131
+ const verify = await auth2.getAuth(req, res);
11918
13132
  if (!verify) return;
11919
13133
  } else {
11920
13134
  createMethodNotAllowedResponse(res);
@@ -12169,7 +13383,7 @@ var init_source = __esm({
12169
13383
  const requests = PLUGIN_SOURCES.map(async (url) => {
12170
13384
  const time2 = Date.now();
12171
13385
  try {
12172
- const response = await axios8.get(url);
13386
+ const response = await axios10.get(url);
12173
13387
  logger.info(`[\u63D2\u4EF6\u5217\u8868] \u4ECE ${url} \u83B7\u53D6\u6210\u529F \u8017\u65F6${logger.yellow(Date.now() - time2 + "")}ms`);
12174
13388
  return response.data;
12175
13389
  } catch (error) {
@@ -12186,7 +13400,7 @@ var init_source = __esm({
12186
13400
  raceRequest = async (urls) => {
12187
13401
  const requests = urls.map(async (url) => {
12188
13402
  try {
12189
- const response = await axios8.get(url, { timeout: 1e4 });
13403
+ const response = await axios10.get(url, { timeout: 1e4 });
12190
13404
  return response.data;
12191
13405
  } catch {
12192
13406
  return null;
@@ -12821,7 +14035,7 @@ var init_getLog = __esm({
12821
14035
 
12822
14036
  // src/server/plugins/cache.ts
12823
14037
  var CACHE_KEY, CACHE_EXPIRE, getPluginListCache, setPluginListCache, deletePluginListCache, paginatePlugins;
12824
- var init_cache3 = __esm({
14038
+ var init_cache4 = __esm({
12825
14039
  "src/server/plugins/cache.ts"() {
12826
14040
  init_index();
12827
14041
  CACHE_KEY = "karin:web:plugin:list";
@@ -13013,7 +14227,7 @@ function cleanupTasks() {
13013
14227
  var taskQueue, pluginInstall, pluginUninstall, pluginGetTaskStatus, pluginGetTaskList, pluginUpdateTaskStatus;
13014
14228
  var init_install = __esm({
13015
14229
  "src/server/plugins/install.ts"() {
13016
- init_cache3();
14230
+ init_cache4();
13017
14231
  init_response();
13018
14232
  taskQueue = /* @__PURE__ */ new Map();
13019
14233
  pluginInstall = async (req, res) => {
@@ -13130,7 +14344,7 @@ var init_test_url = __esm({
13130
14344
  try {
13131
14345
  const startTime = Date.now();
13132
14346
  const url = host2 === github ? testUrl : `${host2}/${testUrl}`;
13133
- await axios8.get(url, { signal: controllers[index5].signal, timeout: 2 * 1e3 });
14347
+ await axios10.get(url, { signal: controllers[index5].signal, timeout: 2 * 1e3 });
13134
14348
  const endTime = Date.now();
13135
14349
  controllers.forEach((controller, i) => {
13136
14350
  if (i !== index5) controller.abort();
@@ -13183,9 +14397,9 @@ var init_info2 = __esm({
13183
14397
  ];
13184
14398
  const npmApiList = npmApi.map((item) => `${item}/${dateRange}/${name}`);
13185
14399
  const npmDownloads = await Promise.race(
13186
- npmApiList.map((item) => axios8.get(item, { timeout: 5e3 }))
14400
+ npmApiList.map((item) => axios10.get(item, { timeout: 5e3 }))
13187
14401
  ).then((result) => result.data.downloads).catch(() => 0);
13188
- const cnpmDownloads = await axios8.get(
14402
+ const cnpmDownloads = await axios10.get(
13189
14403
  `https://registry.npmmirror.com/downloads/range/${dateRange}/${name}`,
13190
14404
  { timeout: 5e3 }
13191
14405
  ).then((result) => {
@@ -13210,7 +14424,7 @@ var init_info2 = __esm({
13210
14424
  ];
13211
14425
  const registryList = registry.map((item) => `${item}/${name}`);
13212
14426
  try {
13213
- const registryResult = await Promise.race(registryList.map((item) => axios8.get(item, { timeout: 5e3 })));
14427
+ const registryResult = await Promise.race(registryList.map((item) => axios10.get(item, { timeout: 5e3 })));
13214
14428
  if (registryResult.status === 200) {
13215
14429
  const latest = registryResult.data["dist-tags"].latest;
13216
14430
  const size = registryResult.data.versions[latest].dist.unpackedSize;
@@ -13241,7 +14455,7 @@ var init_info2 = __esm({
13241
14455
  const [, owner, repo] = match;
13242
14456
  const cleanRepo = repo.replace(".git", "");
13243
14457
  const apiUrl = `https://api.github.com/repos/${owner}/${cleanRepo}`;
13244
- const response = await axios8.get(apiUrl, { timeout: 5e3 });
14458
+ const response = await axios10.get(apiUrl, { timeout: 5e3 });
13245
14459
  if (response.status === 200) {
13246
14460
  const {
13247
14461
  pushed_at: pushedAt,
@@ -13269,7 +14483,7 @@ var init_info2 = __esm({
13269
14483
  const [, owner, repo] = match;
13270
14484
  const cleanRepo = repo.replace(".git", "");
13271
14485
  const apiUrl = `https://gitee.com/api/v5/repos/${owner}/${cleanRepo}`;
13272
- const response = await axios8.get(apiUrl, { timeout: 5e3 });
14486
+ const response = await axios10.get(apiUrl, { timeout: 5e3 });
13273
14487
  if (response.status === 200) {
13274
14488
  const {
13275
14489
  pushed_at: pushedAt,
@@ -13315,7 +14529,7 @@ var init_plugins = __esm({
13315
14529
  init_response();
13316
14530
  init_update();
13317
14531
  init_info2();
13318
- init_cache3();
14532
+ init_cache4();
13319
14533
  getFullPluginList = async () => {
13320
14534
  const [list2, createUrl, localPlugins] = await Promise.all([
13321
14535
  fetchPluginList(),
@@ -13630,7 +14844,7 @@ var init_terminalManager = __esm({
13630
14844
  logger.info(`[terminal] \u975E\u6CD5\u8BF7\u6C42: ${request2.url}`);
13631
14845
  return;
13632
14846
  }
13633
- const verifyStatus = auth.terminalAuth(token, userId);
14847
+ const verifyStatus = auth2.terminalAuth(token, userId);
13634
14848
  if (!verifyStatus) {
13635
14849
  socket.close();
13636
14850
  logger.info(`[terminal] \u9274\u6743\u5931\u8D25: ${request2.url}`);
@@ -14107,15 +15321,15 @@ headers: ${JSON.stringify(request2.headers, null, 2)}`
14107
15321
  });
14108
15322
  return;
14109
15323
  }
14110
- if (request2.url === "/puppeteer") {
15324
+ if (request2.url === "/puppeteer" || request2.url === "/snapka") {
14111
15325
  const cfg = getRenderCfg();
14112
15326
  if (!cfg.ws_server.enable) {
14113
- logger.warn("[WebSocket] puppeteerServer \u672A\u542F\u7528");
15327
+ logger.warn("[WebSocket] snapkaServer \u672A\u542F\u7528");
14114
15328
  socket.close();
14115
15329
  return;
14116
15330
  }
14117
- if (request2.headers["x-client-name"] === "@karinjs/puppeteer-server") {
14118
- emitEvent(WS_CONNECTION_PUPPETEER_2, socket, request2);
15331
+ if (request2.headers["x-client-id"] === "snapka") {
15332
+ emitEvent(WS_SNAPKA, socket, request2);
14119
15333
  } else {
14120
15334
  emitEvent(WS_CONNECTION_PUPPETEER, socket, request2);
14121
15335
  }
@@ -14427,6 +15641,8 @@ var init_loader = __esm({
14427
15641
  if (pkg2.type !== "app" && ((_f = (_e = pkg2 == null ? void 0 : pkg2.pkgData) == null ? void 0 : _e.karin) == null ? void 0 : _f.static)) {
14428
15642
  const list3 = Array.isArray(pkg2.pkgData.karin.static) ? pkg2.pkgData.karin.static : [pkg2.pkgData.karin.static];
14429
15643
  cache3.static.push(...list3.map((file) => path4.resolve(pkg2.dir, file)));
15644
+ } else {
15645
+ cache3.static.push(path4.resolve(pkg2.dir, "resource"));
14430
15646
  }
14431
15647
  }));
14432
15648
  await Promise.all([...allPromises, ...entryPromises]);
@@ -14649,14 +15865,14 @@ var init_start = __esm({
14649
15865
  });
14650
15866
 
14651
15867
  // src/core/db/redis/mock/key/index.ts
14652
- var init_key2 = __esm({
15868
+ var init_key3 = __esm({
14653
15869
  "src/core/db/redis/mock/key/index.ts"() {
14654
15870
  }
14655
15871
  });
14656
15872
  var RedisClient;
14657
15873
  var init_mock = __esm({
14658
15874
  "src/core/db/redis/mock/index.ts"() {
14659
- init_key2();
15875
+ init_key3();
14660
15876
  init_common();
14661
15877
  RedisClient = class extends EventEmitter {
14662
15878
  /** 键、类型、过期时间映射 */
@@ -15459,766 +16675,527 @@ var init_mock = __esm({
15459
16675
  * @param key 哈希表的键
15460
16676
  * @returns 返回所有值数组
15461
16677
  */
15462
- async hVals(key) {
15463
- if (!this.#hash[key]) return [];
15464
- if (this.checkExpire(key)) return [];
15465
- return Object.values(this.#hash[key]).map((value) => value.toString());
15466
- }
15467
- /**
15468
- * 获取哈希表中字段数量
15469
- * @param key 哈希表的键
15470
- * @returns 返回字段数量
15471
- */
15472
- async hLen(key) {
15473
- if (!this.#hash[key]) return 0;
15474
- if (this.checkExpire(key)) return 0;
15475
- return Object.keys(this.#hash[key]).length;
15476
- }
15477
- /**
15478
- * 批量获取哈希表中字段的值
15479
- * @param key 哈希表的键
15480
- * @param fields 要获取的字段数组
15481
- * @returns 返回字段值数组,不存在的字段返回null
15482
- */
15483
- async hMGet(key, ...fields) {
15484
- if (!this.#hash[key]) return fields.map(() => null);
15485
- if (this.checkExpire(key)) return fields.map(() => null);
15486
- return fields.map((field) => {
15487
- const value = this.#hash[key][field];
15488
- return value !== void 0 ? value.toString() : null;
15489
- });
15490
- }
15491
- /**
15492
- * 批量设置哈希表中字段的值
15493
- * @param key 哈希表的键
15494
- * @param fieldValues 字段和值的数组,格式为[field1, value1, field2, value2, ...]
15495
- * @returns 返回"OK"
15496
- */
15497
- async hMSet(key, ...fieldValues) {
15498
- if (!this.#hash[key]) {
15499
- this.store[key] = { type: "hash" /* HASH */, expire: -1 };
15500
- this.#hash[key] = {};
15501
- } else if (this.checkExpire(key, false)) {
15502
- this.store[key].expire = -1;
15503
- this.#hash[key] = {};
15504
- }
15505
- for (let i = 0; i < fieldValues.length; i += 2) {
15506
- if (i + 1 < fieldValues.length) {
15507
- const field = fieldValues[i].toString();
15508
- const value = fieldValues[i + 1];
15509
- this.#hash[key][field] = value;
15510
- }
15511
- }
15512
- this.#sqlite.set(key, JSON.stringify(this.#hash[key]), "hash" /* HASH */, this.store[key].expire);
15513
- return "OK";
15514
- }
15515
- /**
15516
- * 获取列表长度
15517
- * @param key 列表的键
15518
- * @returns 返回列表长度
15519
- */
15520
- async lLen(key) {
15521
- if (!this.#list[key]) return 0;
15522
- if (this.checkExpire(key)) return 0;
15523
- return this.#list[key].length;
15524
- }
15525
- /**
15526
- * 获取列表指定索引的元素
15527
- * @param key 列表的键
15528
- * @param index 索引,0表示第一个元素,-1表示最后一个元素
15529
- * @returns 返回元素值,索引超出范围返回null
15530
- */
15531
- async lIndex(key, index5) {
15532
- if (!this.#list[key]) return null;
15533
- if (this.checkExpire(key)) return null;
15534
- const list2 = this.#list[key];
15535
- if (index5 < 0) {
15536
- index5 = list2.length + index5;
15537
- }
15538
- if (index5 < 0 || index5 >= list2.length) {
15539
- return null;
15540
- }
15541
- return list2[index5].toString();
15542
- }
15543
- /**
15544
- * 设置列表指定索引的元素值
15545
- * @param key 列表的键
15546
- * @param index 索引
15547
- * @param value 值
15548
- * @returns 成功返回"OK",失败返回错误
15549
- */
15550
- async lSet(key, index5, value) {
15551
- if (!this.#list[key]) return null;
15552
- if (this.checkExpire(key)) return null;
15553
- const list2 = this.#list[key];
15554
- if (index5 < 0) {
15555
- index5 = list2.length + index5;
15556
- }
15557
- if (index5 < 0 || index5 >= list2.length) {
15558
- return null;
15559
- }
15560
- list2[index5] = value;
15561
- this.#sqlite.set(key, JSON.stringify(list2), "list" /* LIST */, this.store[key].expire);
15562
- return "OK";
15563
- }
15564
- /**
15565
- * 移除列表中与指定值相等的元素
15566
- * @param key 列表的键
15567
- * @param count 移除的数量,0表示移除所有匹配的元素,正数表示从头部开始移除,负数表示从尾部开始移除
15568
- * @param value 要移除的值
15569
- * @returns 返回移除的元素数量
15570
- */
15571
- async lRem(key, count3, value) {
15572
- if (!this.#list[key]) return 0;
15573
- if (this.checkExpire(key)) return 0;
15574
- const list2 = this.#list[key];
15575
- const strValue = value.toString();
15576
- let removed = 0;
15577
- if (count3 === 0) {
15578
- const newList = list2.filter((item) => item.toString() !== strValue);
15579
- removed = list2.length - newList.length;
15580
- this.#list[key] = newList;
15581
- } else if (count3 > 0) {
15582
- for (let i = 0; i < list2.length && removed < count3; i++) {
15583
- if (list2[i].toString() === strValue) {
15584
- list2.splice(i, 1);
15585
- removed++;
15586
- i--;
15587
- }
15588
- }
15589
- } else {
15590
- count3 = Math.abs(count3);
15591
- for (let i = list2.length - 1; i >= 0 && removed < count3; i--) {
15592
- if (list2[i].toString() === strValue) {
15593
- list2.splice(i, 1);
15594
- removed++;
15595
- }
15596
- }
15597
- }
15598
- this.#sqlite.set(key, JSON.stringify(list2), "list" /* LIST */, this.store[key].expire);
15599
- return removed;
15600
- }
15601
- /**
15602
- * 获取集合中元素数量
15603
- * @param key 集合的键
15604
- * @returns 返回集合中元素数量
15605
- */
15606
- async sCard(key) {
15607
- if (!this.#set[key]) return 0;
15608
- if (this.checkExpire(key)) return 0;
15609
- return this.#set[key].size;
15610
- }
15611
- /**
15612
- * 计算集合的差集
15613
- * @param keys 集合的键数组
15614
- * @returns 返回差集数组
15615
- */
15616
- async sDiff(...keys) {
15617
- if (keys.length === 0) return [];
15618
- const firstKey = keys[0];
15619
- if (!this.#set[firstKey]) return [];
15620
- if (this.checkExpire(firstKey)) return [];
15621
- const result = /* @__PURE__ */ new Set();
15622
- for (const item of this.#set[firstKey]) {
15623
- result.add(item.toString());
15624
- }
15625
- for (let i = 1; i < keys.length; i++) {
15626
- const key = keys[i];
15627
- if (!this.#set[key] || this.checkExpire(key)) continue;
15628
- for (const item of this.#set[key]) {
15629
- result.delete(item.toString());
15630
- }
15631
- }
15632
- return Array.from(result);
15633
- }
15634
- /**
15635
- * 计算集合的交集
15636
- * @param keys 集合的键数组
15637
- * @returns 返回交集数组
15638
- */
15639
- async sInter(...keys) {
15640
- if (keys.length === 0) return [];
15641
- const validKeys = keys.filter((key) => this.#set[key] && !this.checkExpire(key));
15642
- if (validKeys.length === 0) return [];
15643
- const result = /* @__PURE__ */ new Set();
15644
- const firstKey = validKeys[0];
15645
- for (const item of this.#set[firstKey]) {
15646
- let inAllSets = true;
15647
- for (let i = 1; i < validKeys.length; i++) {
15648
- const key = validKeys[i];
15649
- if (!this.#set[key].has(item.toString())) {
15650
- inAllSets = false;
15651
- break;
15652
- }
15653
- }
15654
- if (inAllSets) {
15655
- result.add(item.toString());
15656
- }
15657
- }
15658
- return Array.from(result);
15659
- }
15660
- /**
15661
- * 计算集合的并集
15662
- * @param keys 集合的键数组
15663
- * @returns 返回并集数组
15664
- */
15665
- async sUnion(...keys) {
15666
- const result = /* @__PURE__ */ new Set();
15667
- for (const key of keys) {
15668
- if (!this.#set[key] || this.checkExpire(key)) continue;
15669
- for (const item of this.#set[key]) {
15670
- result.add(item.toString());
15671
- }
15672
- }
15673
- return Array.from(result);
15674
- }
15675
- /**
15676
- * 将多个键的值同时获取
15677
- * @param keys 要获取的键数组
15678
- * @returns 返回值数组,不存在的键返回null
15679
- */
15680
- async mGet(...keys) {
15681
- return Promise.all(keys.map((key) => this.get(key)));
15682
- }
15683
- /**
15684
- * 同时设置多个键值对
15685
- * @param keyValues 键值对数组,格式为[key1, value1, key2, value2, ...]
15686
- * @returns 返回"OK"
15687
- */
15688
- async mSet(...keyValues) {
15689
- for (let i = 0; i < keyValues.length; i += 2) {
15690
- if (i + 1 < keyValues.length) {
15691
- const key = keyValues[i].toString();
15692
- const value = keyValues[i + 1];
15693
- await this.set(key, value);
15694
- }
15695
- }
15696
- return "OK";
15697
- }
15698
- /**
15699
- * 设置键的新值并返回旧值
15700
- * @param key 键
15701
- * @param value 新值
15702
- * @returns 返回旧值,如果键不存在则返回null
15703
- */
15704
- async getSet(key, value) {
15705
- const oldValue = await this.get(key);
15706
- await this.set(key, value);
15707
- return oldValue;
15708
- }
15709
- /**
15710
- * 修复zRange方法,使用正确的zset数据结构
15711
- * 返回有序集合的成员数量
15712
- * @param key 有序集合的键
15713
- * @returns 返回有序集合的成员数量
15714
- */
15715
- async zRange(key, start3, stop) {
15716
- if (!this.#zset[key]) return [];
16678
+ async hVals(key) {
16679
+ if (!this.#hash[key]) return [];
15717
16680
  if (this.checkExpire(key)) return [];
15718
- const sortedEntries = [...this.#zset[key]].sort((a, b) => a.score - b.score);
15719
- return sortedEntries.slice(start3, stop + 1).map((entry) => entry.member.toString());
16681
+ return Object.values(this.#hash[key]).map((value) => value.toString());
15720
16682
  }
15721
16683
  /**
15722
- * 按分数范围返回有序集合的成员
15723
- * @param key 有序集合的键
15724
- * @param min 最小分数
15725
- * @param max 最大分数
15726
- * @returns 返回指定分数范围的成员数组
16684
+ * 获取哈希表中字段数量
16685
+ * @param key 哈希表的键
16686
+ * @returns 返回字段数量
15727
16687
  */
15728
- async zRangeByScore(key, min, max) {
15729
- if (!this.#zset[key]) return [];
15730
- if (this.checkExpire(key)) return [];
15731
- return this.#zset[key].filter((entry) => entry.score >= min && entry.score <= max).sort((a, b) => a.score - b.score).map((entry) => entry.member.toString());
16688
+ async hLen(key) {
16689
+ if (!this.#hash[key]) return 0;
16690
+ if (this.checkExpire(key)) return 0;
16691
+ return Object.keys(this.#hash[key]).length;
15732
16692
  }
15733
16693
  /**
15734
- * 按分数降序返回有序集合的成员
15735
- * @param key 有序集合的键
15736
- * @param start 起始索引
15737
- * @param stop 结束索引
15738
- * @returns 返回指定范围的成员数组(按分数降序)
16694
+ * 批量获取哈希表中字段的值
16695
+ * @param key 哈希表的键
16696
+ * @param fields 要获取的字段数组
16697
+ * @returns 返回字段值数组,不存在的字段返回null
15739
16698
  */
15740
- async zRevRange(key, start3, stop) {
15741
- if (!this.#zset[key]) return [];
15742
- if (this.checkExpire(key)) return [];
15743
- const sortedEntries = [...this.#zset[key]].sort((a, b) => b.score - a.score);
15744
- return sortedEntries.slice(start3, stop + 1).map((entry) => entry.member.toString());
16699
+ async hMGet(key, ...fields) {
16700
+ if (!this.#hash[key]) return fields.map(() => null);
16701
+ if (this.checkExpire(key)) return fields.map(() => null);
16702
+ return fields.map((field) => {
16703
+ const value = this.#hash[key][field];
16704
+ return value !== void 0 ? value.toString() : null;
16705
+ });
15745
16706
  }
15746
16707
  /**
15747
- * 获取有序集合中指定成员的排名(按分数降序)
15748
- * @param key 有序集合的键
15749
- * @param member 成员
15750
- * @returns 返回成员的排名,不存在返回null
16708
+ * 批量设置哈希表中字段的值
16709
+ * @param key 哈希表的键
16710
+ * @param fieldValues 字段和值的数组,格式为[field1, value1, field2, value2, ...]
16711
+ * @returns 返回"OK"
15751
16712
  */
15752
- async zRevRank(key, member) {
15753
- if (!this.#zset[key]) return null;
15754
- if (this.checkExpire(key)) return null;
15755
- const strMember = member.toString();
15756
- const sortedEntries = [...this.#zset[key]].sort((a, b) => b.score - a.score);
15757
- for (let i = 0; i < sortedEntries.length; i++) {
15758
- if (sortedEntries[i].member.toString() === strMember) {
15759
- return i;
16713
+ async hMSet(key, ...fieldValues) {
16714
+ if (!this.#hash[key]) {
16715
+ this.store[key] = { type: "hash" /* HASH */, expire: -1 };
16716
+ this.#hash[key] = {};
16717
+ } else if (this.checkExpire(key, false)) {
16718
+ this.store[key].expire = -1;
16719
+ this.#hash[key] = {};
16720
+ }
16721
+ for (let i = 0; i < fieldValues.length; i += 2) {
16722
+ if (i + 1 < fieldValues.length) {
16723
+ const field = fieldValues[i].toString();
16724
+ const value = fieldValues[i + 1];
16725
+ this.#hash[key][field] = value;
15760
16726
  }
15761
16727
  }
15762
- return null;
16728
+ this.#sqlite.set(key, JSON.stringify(this.#hash[key]), "hash" /* HASH */, this.store[key].expire);
16729
+ return "OK";
15763
16730
  }
15764
16731
  /**
15765
- * 从有序集合中移除一个或多个成员
15766
- * @param key 有序集合的键
15767
- * @param member 要移除的成员
15768
- * @returns 返回成功移除的成员数量
16732
+ * 获取列表长度
16733
+ * @param key 列表的键
16734
+ * @returns 返回列表长度
15769
16735
  */
15770
- async zRem(key, member) {
15771
- if (!this.#zset[key]) return 0;
16736
+ async lLen(key) {
16737
+ if (!this.#list[key]) return 0;
15772
16738
  if (this.checkExpire(key)) return 0;
15773
- const strMember = member.toString();
15774
- const index5 = this.#zset[key].findIndex((entry) => entry.member.toString() === strMember);
15775
- if (index5 !== -1) {
15776
- this.#zset[key].splice(index5, 1);
15777
- this.#sqlite.set(key, JSON.stringify(this.#zset[key]), "zset" /* ZSET */, this.store[key].expire);
15778
- return 1;
15779
- }
15780
- return 0;
16739
+ return this.#list[key].length;
15781
16740
  }
15782
16741
  /**
15783
- * 根据键类型获取值的字符串表示
15784
- * @param key 键名
15785
- * @returns 值的字符串表示
16742
+ * 获取列表指定索引的元素
16743
+ * @param key 列表的键
16744
+ * @param index 索引,0表示第一个元素,-1表示最后一个元素
16745
+ * @returns 返回元素值,索引超出范围返回null
15786
16746
  */
15787
- getValueStringByKey(key) {
15788
- const { type } = this.store[key];
15789
- switch (type) {
15790
- case "str" /* STR */:
15791
- return this.#str[key];
15792
- case "num" /* NUM */:
15793
- return String(this.#num[key]);
15794
- case "hash" /* HASH */:
15795
- return JSON.stringify(this.#hash[key]);
15796
- case "list" /* LIST */:
15797
- return JSON.stringify(this.#list[key]);
15798
- case "set" /* SET */:
15799
- return JSON.stringify(Array.from(this.#set[key]));
15800
- case "zset" /* ZSET */:
15801
- return JSON.stringify(this.#zset[key]);
15802
- case "pf" /* PF */:
15803
- return JSON.stringify(Array.from(this.#pf[key]));
15804
- case "bit" /* BIT */:
15805
- return this.#bit[key].toString("base64");
15806
- default:
15807
- return "";
16747
+ async lIndex(key, index5) {
16748
+ if (!this.#list[key]) return null;
16749
+ if (this.checkExpire(key)) return null;
16750
+ const list2 = this.#list[key];
16751
+ if (index5 < 0) {
16752
+ index5 = list2.length + index5;
15808
16753
  }
16754
+ if (index5 < 0 || index5 >= list2.length) {
16755
+ return null;
16756
+ }
16757
+ return list2[index5].toString();
15809
16758
  }
15810
- async save() {
15811
- const keys = await this.#sqlite.keys();
15812
- const { removed, added, common } = diffSimpleArray(keys, Object.keys(this.store));
15813
- removed.forEach((key) => {
15814
- this.#sqlite.del(key);
15815
- });
15816
- added.forEach((key) => {
15817
- const { type, expire } = this.store[key];
15818
- const value = this.getValueStringByKey(key);
15819
- this.#sqlite.set(key, value, type, expire);
15820
- });
15821
- await Promise.all(common.map(async (key) => {
15822
- const data = this.store[key];
15823
- if (!data) return;
15824
- const { type, expire } = data;
15825
- const currentValue = this.getValueStringByKey(key);
15826
- const sql = await this.#sqlite.get(key);
15827
- if ((sql == null ? void 0 : sql.expire) !== expire || (sql == null ? void 0 : sql.value) !== currentValue) {
15828
- this.#sqlite.set(key, currentValue, type, expire);
15829
- }
15830
- }));
16759
+ /**
16760
+ * 设置列表指定索引的元素值
16761
+ * @param key 列表的键
16762
+ * @param index 索引
16763
+ * @param value 值
16764
+ * @returns 成功返回"OK",失败返回错误
16765
+ */
16766
+ async lSet(key, index5, value) {
16767
+ if (!this.#list[key]) return null;
16768
+ if (this.checkExpire(key)) return null;
16769
+ const list2 = this.#list[key];
16770
+ if (index5 < 0) {
16771
+ index5 = list2.length + index5;
16772
+ }
16773
+ if (index5 < 0 || index5 >= list2.length) {
16774
+ return null;
16775
+ }
16776
+ list2[index5] = value;
16777
+ this.#sqlite.set(key, JSON.stringify(list2), "list" /* LIST */, this.store[key].expire);
15831
16778
  return "OK";
15832
16779
  }
15833
- };
15834
- }
15835
- });
15836
-
15837
- // src/core/db/redis/mock.ts
15838
- var init_mock2 = __esm({
15839
- "src/core/db/redis/mock.ts"() {
15840
- init_mock();
15841
- }
15842
- });
15843
- var create, start, createRedis, isArm64, mock;
15844
- var init_redis2 = __esm({
15845
- "src/core/db/redis/redis.ts"() {
15846
- init_env();
15847
- init_config();
15848
- init_root();
15849
- init_exec();
15850
- init_mock2();
15851
- init_sqlite();
15852
- create = async (options) => {
15853
- try {
15854
- const client = createClient(options);
15855
- await client.connect();
15856
- Object.defineProperty(client, "id", { value: "Redis" });
15857
- return client;
15858
- } catch (error) {
15859
- logger.debug(`${logger.red("[redis] \u542F\u52A8\u5931\u8D25:")} ${JSON.stringify(options)}`);
15860
- logger.debug(error);
15861
- }
15862
- };
15863
- start = async () => {
15864
- logger.debug("[redis] \u6B63\u5728\u5C1D\u8BD5\u542F\u52A8 Redis...");
15865
- if (isWin()) {
15866
- const result = await exec("redis-server.exe redis.conf", { booleanResult: true });
15867
- if (result) return result;
15868
- const service = "net start Redis";
15869
- return await exec(service, { booleanResult: true });
15870
- }
15871
- const cmd = "redis-server --save 300 10 --daemonize yes" + await isArm64();
15872
- return await exec(cmd, { booleanResult: true });
15873
- };
15874
- createRedis = async () => {
15875
- try {
15876
- const options = redis();
15877
- let client = await create(options);
15878
- if (client) {
15879
- logger.info(`[redis] ${logger.green("Redis \u8FDE\u63A5\u6210\u529F")}`);
15880
- return client;
15881
- }
15882
- const result = await start();
15883
- if (result) {
15884
- logger.debug(logger.green("[redis] \u4E3B\u52A8\u62C9\u8D77 Redis \u6210\u529F"));
15885
- client = await create(options);
16780
+ /**
16781
+ * 移除列表中与指定值相等的元素
16782
+ * @param key 列表的键
16783
+ * @param count 移除的数量,0表示移除所有匹配的元素,正数表示从头部开始移除,负数表示从尾部开始移除
16784
+ * @param value 要移除的值
16785
+ * @returns 返回移除的元素数量
16786
+ */
16787
+ async lRem(key, count3, value) {
16788
+ if (!this.#list[key]) return 0;
16789
+ if (this.checkExpire(key)) return 0;
16790
+ const list2 = this.#list[key];
16791
+ const strValue = value.toString();
16792
+ let removed = 0;
16793
+ if (count3 === 0) {
16794
+ const newList = list2.filter((item) => item.toString() !== strValue);
16795
+ removed = list2.length - newList.length;
16796
+ this.#list[key] = newList;
16797
+ } else if (count3 > 0) {
16798
+ for (let i = 0; i < list2.length && removed < count3; i++) {
16799
+ if (list2[i].toString() === strValue) {
16800
+ list2.splice(i, 1);
16801
+ removed++;
16802
+ i--;
16803
+ }
16804
+ }
15886
16805
  } else {
15887
- logger.debug(logger.red("[redis] \u4E3B\u52A8\u62C9\u8D77 Redis \u5931\u8D25"));
16806
+ count3 = Math.abs(count3);
16807
+ for (let i = list2.length - 1; i >= 0 && removed < count3; i--) {
16808
+ if (list2[i].toString() === strValue) {
16809
+ list2.splice(i, 1);
16810
+ removed++;
16811
+ }
16812
+ }
15888
16813
  }
15889
- if (client) return client;
15890
- throw new Error("Redis \u542F\u52A8\u5931\u8D25");
15891
- } catch (error) {
15892
- logger.debug(`[redis] ${logger.red("Redis \u8FDE\u63A5\u5931\u8D25")}`);
15893
- logger.debug(error);
15894
- logger.debug(logger.yellow("[redis] \u5C06\u964D\u7EA7\u4E3A redis-mock \u5B9E\u73B0"));
15895
- return mock();
16814
+ this.#sqlite.set(key, JSON.stringify(list2), "list" /* LIST */, this.store[key].expire);
16815
+ return removed;
15896
16816
  }
15897
- };
15898
- isArm64 = async () => {
15899
- if (os.arch() !== "arm64") return "";
15900
- const { stdout } = await exec("redis-server -v");
15901
- const version = stdout.toString();
15902
- if (!version) return "";
15903
- const RedisVersion = version.match(/v=(\d)./);
15904
- if (RedisVersion && Number(RedisVersion[1]) >= 6) return " --ignore-warnings ARM64-COW-BUG";
15905
- return "";
15906
- };
15907
- mock = async () => {
15908
- const sqlite = await new SQLiteWrapper(path4.join(redisSqlite3Path, "redis.db")).init();
15909
- const redis3 = await new RedisClient(sqlite).init();
15910
- Object.defineProperty(redis3, "id", { value: "mock" });
15911
- return redis3;
15912
- };
15913
- }
15914
- });
15915
-
15916
- // src/core/db/index.ts
15917
- var init_db = __esm({
15918
- "src/core/db/index.ts"() {
15919
- init_redis2();
15920
- init_mock2();
15921
- init_kv();
15922
- }
15923
- });
15924
-
15925
- // src/adapter/render/admin/cache.ts
15926
- var index2, cache11, registerRender, unregisterRender, getRender, callRender, getRenderCount, getRenderList, renderHtml, renderMultiHtml, RenderCache, render2, Renderer;
15927
- var init_cache4 = __esm({
15928
- "src/adapter/render/admin/cache.ts"() {
15929
- index2 = 0;
15930
- cache11 = [];
15931
- registerRender = (id, render4) => {
15932
- const i = ++index2;
15933
- cache11.push({ index: i, id, render: render4 });
15934
- logger.mark(`[render:${index2}] ${logger.green("\u6CE8\u518C\u6210\u529F")}: ${id}`);
15935
- return i;
15936
- };
15937
- unregisterRender = (index5) => {
15938
- const app2 = cache11.find((app3) => app3.index === index5);
15939
- if (!app2) {
15940
- logger.error(`[render] \u5378\u8F7D\u5931\u8D25: \u4E0D\u5B58\u5728\u7D22\u5F15 ${index5}`);
15941
- return false;
16817
+ /**
16818
+ * 获取集合中元素数量
16819
+ * @param key 集合的键
16820
+ * @returns 返回集合中元素数量
16821
+ */
16822
+ async sCard(key) {
16823
+ if (!this.#set[key]) return 0;
16824
+ if (this.checkExpire(key)) return 0;
16825
+ return this.#set[key].size;
15942
16826
  }
15943
- cache11.splice(cache11.findIndex((app3) => app3.index === index5), 1);
15944
- logger.mark(`[render] ${logger.yellow("\u5378\u8F7D\u6210\u529F")}: ${app2.id}`);
15945
- return true;
15946
- };
15947
- getRender = (id) => {
15948
- if (cache11.length === 0) throw new Error("[\u8C03\u7528\u6E32\u67D3\u5668\u5931\u8D25] \u6E32\u67D3\u5668\u5217\u8868\u4E3A\u7A7A");
15949
- if (!id) {
15950
- const app3 = cache11[Math.floor(Math.random() * cache11.length)];
15951
- return app3;
16827
+ /**
16828
+ * 计算集合的差集
16829
+ * @param keys 集合的键数组
16830
+ * @returns 返回差集数组
16831
+ */
16832
+ async sDiff(...keys) {
16833
+ if (keys.length === 0) return [];
16834
+ const firstKey = keys[0];
16835
+ if (!this.#set[firstKey]) return [];
16836
+ if (this.checkExpire(firstKey)) return [];
16837
+ const result = /* @__PURE__ */ new Set();
16838
+ for (const item of this.#set[firstKey]) {
16839
+ result.add(item.toString());
16840
+ }
16841
+ for (let i = 1; i < keys.length; i++) {
16842
+ const key = keys[i];
16843
+ if (!this.#set[key] || this.checkExpire(key)) continue;
16844
+ for (const item of this.#set[key]) {
16845
+ result.delete(item.toString());
16846
+ }
16847
+ }
16848
+ return Array.from(result);
15952
16849
  }
15953
- if (typeof id === "number") {
15954
- const app3 = cache11.find((app4) => app4.index === id);
15955
- if (!app3) throw new Error(`[\u8C03\u7528\u6E32\u67D3\u5668\u5931\u8D25] \u672A\u627E\u5230\u6E32\u67D3\u5668\uFF1A${id}`);
15956
- return app3;
16850
+ /**
16851
+ * 计算集合的交集
16852
+ * @param keys 集合的键数组
16853
+ * @returns 返回交集数组
16854
+ */
16855
+ async sInter(...keys) {
16856
+ if (keys.length === 0) return [];
16857
+ const validKeys = keys.filter((key) => this.#set[key] && !this.checkExpire(key));
16858
+ if (validKeys.length === 0) return [];
16859
+ const result = /* @__PURE__ */ new Set();
16860
+ const firstKey = validKeys[0];
16861
+ for (const item of this.#set[firstKey]) {
16862
+ let inAllSets = true;
16863
+ for (let i = 1; i < validKeys.length; i++) {
16864
+ const key = validKeys[i];
16865
+ if (!this.#set[key].has(item.toString())) {
16866
+ inAllSets = false;
16867
+ break;
16868
+ }
16869
+ }
16870
+ if (inAllSets) {
16871
+ result.add(item.toString());
16872
+ }
16873
+ }
16874
+ return Array.from(result);
15957
16875
  }
15958
- const app2 = cache11.find((app3) => app3.id === id);
15959
- if (!app2) throw new Error(`[\u8C03\u7528\u6E32\u67D3\u5668\u5931\u8D25] \u672A\u627E\u5230\u6E32\u67D3\u5668\uFF1A${id}`);
15960
- return app2;
15961
- };
15962
- callRender = async (options, id) => {
15963
- const res = getRender(id);
15964
- const result = await res.render(Object.assign(options, { encoding: "base64" }));
15965
- return result;
15966
- };
15967
- getRenderCount = () => cache11.length;
15968
- getRenderList = () => {
15969
- const list2 = cache11.map((app2) => app2);
15970
- return list2;
15971
- };
15972
- renderHtml = (data) => {
15973
- return callRender({
15974
- file: data,
15975
- name: "render",
15976
- encoding: "base64",
15977
- pageGotoParams: {
15978
- waitUntil: "networkidle2"
16876
+ /**
16877
+ * 计算集合的并集
16878
+ * @param keys 集合的键数组
16879
+ * @returns 返回并集数组
16880
+ */
16881
+ async sUnion(...keys) {
16882
+ const result = /* @__PURE__ */ new Set();
16883
+ for (const key of keys) {
16884
+ if (!this.#set[key] || this.checkExpire(key)) continue;
16885
+ for (const item of this.#set[key]) {
16886
+ result.add(item.toString());
16887
+ }
15979
16888
  }
15980
- });
15981
- };
15982
- renderMultiHtml = (file, multiPage) => {
15983
- if (!multiPage && multiPage !== 0) multiPage = true;
15984
- return callRender({
15985
- file,
15986
- name: "render",
15987
- encoding: "base64",
15988
- multiPage,
15989
- pageGotoParams: {
15990
- waitUntil: "networkidle2"
16889
+ return Array.from(result);
16890
+ }
16891
+ /**
16892
+ * 将多个键的值同时获取
16893
+ * @param keys 要获取的键数组
16894
+ * @returns 返回值数组,不存在的键返回null
16895
+ */
16896
+ async mGet(...keys) {
16897
+ return Promise.all(keys.map((key) => this.get(key)));
16898
+ }
16899
+ /**
16900
+ * 同时设置多个键值对
16901
+ * @param keyValues 键值对数组,格式为[key1, value1, key2, value2, ...]
16902
+ * @returns 返回"OK"
16903
+ */
16904
+ async mSet(...keyValues) {
16905
+ for (let i = 0; i < keyValues.length; i += 2) {
16906
+ if (i + 1 < keyValues.length) {
16907
+ const key = keyValues[i].toString();
16908
+ const value = keyValues[i + 1];
16909
+ await this.set(key, value);
16910
+ }
15991
16911
  }
15992
- });
15993
- };
15994
- RenderCache = class {
16912
+ return "OK";
16913
+ }
15995
16914
  /**
15996
- * 注册渲染器
15997
- * @param data 渲染器数据
15998
- * @param data.id 渲染器ID
15999
- * @param data.type 渲染器类型
16000
- * @param ata.render 渲染器标准方法
16001
- * @returns 渲染器索引
16915
+ * 设置键的新值并返回旧值
16916
+ * @param key
16917
+ * @param value 新值
16918
+ * @returns 返回旧值,如果键不存在则返回null
16002
16919
  */
16003
- app(data) {
16004
- return registerRender(data.id, data.render);
16920
+ async getSet(key, value) {
16921
+ const oldValue = await this.get(key);
16922
+ await this.set(key, value);
16923
+ return oldValue;
16005
16924
  }
16006
16925
  /**
16007
- * 卸载渲染器
16008
- * @param index 渲染器索引
16009
- * @returns 是否卸载成功
16010
- */
16011
- unapp(index5) {
16012
- return unregisterRender(index5);
16926
+ * 修复zRange方法,使用正确的zset数据结构
16927
+ * 返回有序集合的成员数量
16928
+ * @param key 有序集合的键
16929
+ * @returns 返回有序集合的成员数量
16930
+ */
16931
+ async zRange(key, start3, stop) {
16932
+ if (!this.#zset[key]) return [];
16933
+ if (this.checkExpire(key)) return [];
16934
+ const sortedEntries = [...this.#zset[key]].sort((a, b) => a.score - b.score);
16935
+ return sortedEntries.slice(start3, stop + 1).map((entry) => entry.member.toString());
16013
16936
  }
16014
16937
  /**
16015
- * 返回渲染器实例 未键入id返回第一个
16016
- * @param id 渲染器ID
16017
- * @returns 渲染器实例
16018
- */
16019
- App(id = "") {
16020
- return getRender(id);
16938
+ * 按分数范围返回有序集合的成员
16939
+ * @param key 有序集合的键
16940
+ * @param min 最小分数
16941
+ * @param max 最大分数
16942
+ * @returns 返回指定分数范围的成员数组
16943
+ */
16944
+ async zRangeByScore(key, min, max) {
16945
+ if (!this.#zset[key]) return [];
16946
+ if (this.checkExpire(key)) return [];
16947
+ return this.#zset[key].filter((entry) => entry.score >= min && entry.score <= max).sort((a, b) => a.score - b.score).map((entry) => entry.member.toString());
16021
16948
  }
16022
16949
  /**
16023
- * 调用标准渲染器
16024
- */
16025
- async render(options, id) {
16026
- return callRender(options, id);
16950
+ * 按分数降序返回有序集合的成员
16951
+ * @param key 有序集合的键
16952
+ * @param start 起始索引
16953
+ * @param stop 结束索引
16954
+ * @returns 返回指定范围的成员数组(按分数降序)
16955
+ */
16956
+ async zRevRange(key, start3, stop) {
16957
+ if (!this.#zset[key]) return [];
16958
+ if (this.checkExpire(key)) return [];
16959
+ const sortedEntries = [...this.#zset[key]].sort((a, b) => b.score - a.score);
16960
+ return sortedEntries.slice(start3, stop + 1).map((entry) => entry.member.toString());
16961
+ }
16962
+ /**
16963
+ * 获取有序集合中指定成员的排名(按分数降序)
16964
+ * @param key 有序集合的键
16965
+ * @param member 成员
16966
+ * @returns 返回成员的排名,不存在返回null
16967
+ */
16968
+ async zRevRank(key, member) {
16969
+ if (!this.#zset[key]) return null;
16970
+ if (this.checkExpire(key)) return null;
16971
+ const strMember = member.toString();
16972
+ const sortedEntries = [...this.#zset[key]].sort((a, b) => b.score - a.score);
16973
+ for (let i = 0; i < sortedEntries.length; i++) {
16974
+ if (sortedEntries[i].member.toString() === strMember) {
16975
+ return i;
16976
+ }
16977
+ }
16978
+ return null;
16027
16979
  }
16028
16980
  /**
16029
- * 快速渲染
16030
- * @param data html路径、http地址
16031
- * @returns 返回图片base64或数组
16032
- */
16033
- async renderHtml(data) {
16034
- return renderHtml(data);
16981
+ * 从有序集合中移除一个或多个成员
16982
+ * @param key 有序集合的键
16983
+ * @param member 要移除的成员
16984
+ * @returns 返回成功移除的成员数量
16985
+ */
16986
+ async zRem(key, member) {
16987
+ if (!this.#zset[key]) return 0;
16988
+ if (this.checkExpire(key)) return 0;
16989
+ const strMember = member.toString();
16990
+ const index5 = this.#zset[key].findIndex((entry) => entry.member.toString() === strMember);
16991
+ if (index5 !== -1) {
16992
+ this.#zset[key].splice(index5, 1);
16993
+ this.#sqlite.set(key, JSON.stringify(this.#zset[key]), "zset" /* ZSET */, this.store[key].expire);
16994
+ return 1;
16995
+ }
16996
+ return 0;
16035
16997
  }
16036
16998
  /**
16037
- * 快速分片渲染
16038
- * @param data html路径、http地址
16039
- * @param multiPage 分片高度 自动计算传true
16040
- */
16041
- async renderMultiHtml(data, multiPage) {
16042
- return renderMultiHtml(data, multiPage);
16043
- }
16044
- };
16045
- render2 = new RenderCache();
16046
- Renderer = render2;
16047
- }
16048
- });
16049
- var createHttpRenderClient;
16050
- var init_http2 = __esm({
16051
- "src/adapter/render/connect/http.ts"() {
16052
- init_cache4();
16053
- init_render();
16054
- createHttpRenderClient = () => {
16055
- const cfg = getRenderCfg();
16056
- if (!cfg.http_server || !Array.isArray(cfg.http_server) || cfg.http_server.length === 0) {
16057
- logger.trace("[render][http] \u672A\u914D\u7F6E\u4EFB\u4F55\u6B63\u5411HTTP \u5DF2\u8DF3\u8FC7\u521B\u5EFA");
16058
- return;
16059
- }
16060
- return Promise.allSettled(cfg.http_server.map(async (item) => {
16061
- let { url, token, enable } = item;
16062
- if (!enable) return;
16063
- url = url.replace("/puppeteer", "");
16064
- const headers = { authorization: crypto.createHash("md5").update(`Bearer ${token}`).digest("hex") };
16065
- try {
16066
- const result = await axios8.get(`${url}/ping`, { timeout: 5e3 });
16067
- if (result.status !== 200 || String(result.data.status) !== "200") {
16068
- logger.error(`[render][http] \u521B\u5EFA\u6E32\u67D3\u5668\u5931\u8D25: \u65E0\u6CD5\u8FDE\u63A5 ${url}`);
16069
- }
16070
- const auth3 = await axios8.get(`${url}/auth`, { headers, timeout: 5e3 });
16071
- if (auth3.status !== 200 || String(auth3.data.status) !== "200") {
16072
- logger.error(`[render][http] \u521B\u5EFA\u6E32\u67D3\u5668\u5931\u8D25: \u9274\u6743\u9519\u8BEF ${url}`);
16073
- return;
16074
- }
16075
- } catch (error) {
16076
- if (axios8.isAxiosError(error)) {
16077
- const { response } = error;
16078
- logger.error(`[render][http] \u521B\u5EFA\u6E32\u67D3\u5668\u5931\u8D25: ${response == null ? void 0 : response.status} ${response == null ? void 0 : response.statusText} - ${JSON.stringify((response == null ? void 0 : response.data) || "\u672A\u77E5\u9519\u8BEF")}`);
16079
- } else {
16080
- logger.error(`[render][http] \u521B\u5EFA\u6E32\u67D3\u5668\u5931\u8D25: ${error}`);
16081
- }
16082
- return;
16999
+ * 根据键类型获取值的字符串表示
17000
+ * @param key 键名
17001
+ * @returns 值的字符串表示
17002
+ */
17003
+ getValueStringByKey(key) {
17004
+ const { type } = this.store[key];
17005
+ switch (type) {
17006
+ case "str" /* STR */:
17007
+ return this.#str[key];
17008
+ case "num" /* NUM */:
17009
+ return String(this.#num[key]);
17010
+ case "hash" /* HASH */:
17011
+ return JSON.stringify(this.#hash[key]);
17012
+ case "list" /* LIST */:
17013
+ return JSON.stringify(this.#list[key]);
17014
+ case "set" /* SET */:
17015
+ return JSON.stringify(Array.from(this.#set[key]));
17016
+ case "zset" /* ZSET */:
17017
+ return JSON.stringify(this.#zset[key]);
17018
+ case "pf" /* PF */:
17019
+ return JSON.stringify(Array.from(this.#pf[key]));
17020
+ case "bit" /* BIT */:
17021
+ return this.#bit[key].toString("base64");
17022
+ default:
17023
+ return "";
16083
17024
  }
16084
- const index5 = registerRender("puppeteer", async (options) => {
16085
- var _a;
16086
- try {
16087
- const result = await axios8.post(`${url}/puppeteer`, options, { headers });
16088
- if (result.status !== 200) {
16089
- throw new Error(`[render][http] \u6E32\u67D3\u5931\u8D25: ${result.status} ${result.statusText} - ${((_a = result.data) == null ? void 0 : _a.message) || "\u672A\u77E5\u9519\u8BEF"}`);
16090
- }
16091
- return result.data;
16092
- } catch (error) {
16093
- if (axios8.isAxiosError(error)) {
16094
- if (!error.response) {
16095
- unregisterRender(index5);
16096
- throw new Error(`[render][http] \u7F51\u7EDC\u8FDE\u63A5\u5931\u8D25: ${error.message}`);
16097
- }
16098
- const { response } = error;
16099
- throw new Error(`[render][http] \u6E32\u67D3\u5931\u8D25: ${response == null ? void 0 : response.status} ${response == null ? void 0 : response.statusText} - ${JSON.stringify((response == null ? void 0 : response.data) || "\u672A\u77E5\u9519\u8BEF")}`);
16100
- }
16101
- if (error instanceof Error) {
16102
- throw error;
16103
- }
16104
- throw new Error(`[render][unknown] \u672A\u77E5\u9519\u8BEF: ${error}`);
16105
- }
17025
+ }
17026
+ async save() {
17027
+ const keys = await this.#sqlite.keys();
17028
+ const { removed, added, common } = diffSimpleArray(keys, Object.keys(this.store));
17029
+ removed.forEach((key) => {
17030
+ this.#sqlite.del(key);
16106
17031
  });
16107
- }));
17032
+ added.forEach((key) => {
17033
+ const { type, expire } = this.store[key];
17034
+ const value = this.getValueStringByKey(key);
17035
+ this.#sqlite.set(key, value, type, expire);
17036
+ });
17037
+ await Promise.all(common.map(async (key) => {
17038
+ const data = this.store[key];
17039
+ if (!data) return;
17040
+ const { type, expire } = data;
17041
+ const currentValue = this.getValueStringByKey(key);
17042
+ const sql = await this.#sqlite.get(key);
17043
+ if ((sql == null ? void 0 : sql.expire) !== expire || (sql == null ? void 0 : sql.value) !== currentValue) {
17044
+ this.#sqlite.set(key, currentValue, type, expire);
17045
+ }
17046
+ }));
17047
+ return "OK";
17048
+ }
16108
17049
  };
16109
17050
  }
16110
17051
  });
16111
17052
 
16112
- // src/adapter/render/admin/template.ts
16113
- var template_exports = {};
16114
- __export(template_exports, {
16115
- renderTemplate: () => renderTemplate,
16116
- renderTpl: () => renderTpl,
16117
- startCleanExpiredFiles: () => startCleanExpiredFiles
17053
+ // src/core/db/redis/mock.ts
17054
+ var init_mock2 = __esm({
17055
+ "src/core/db/redis/mock.ts"() {
17056
+ init_mock();
17057
+ }
16118
17058
  });
16119
- var renderTpl, renderTemplate, getOutputPath, cleanExpiredFiles, startCleanExpiredFiles;
16120
- var init_template = __esm({
16121
- "src/adapter/render/admin/template.ts"() {
17059
+ var create, start, createRedis, isArm64, mock;
17060
+ var init_redis2 = __esm({
17061
+ "src/core/db/redis/redis.ts"() {
17062
+ init_env();
17063
+ init_config();
16122
17064
  init_root();
16123
- init_fsSync();
16124
- init_file();
16125
- renderTpl = (options) => {
16126
- if (typeof options.file !== "string") {
16127
- throw TypeError("\u6A21\u677F\u6587\u4EF6\u8DEF\u5F84\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32");
16128
- }
16129
- if (!options.name) {
16130
- options.name = path4.basename(options.file) || "render";
16131
- }
16132
- if (options.data) {
16133
- if (options.file.startsWith("http")) {
16134
- throw TypeError("\u4ED6\u55B5\u7684 \u4E0D\u4F1A\u771F\u7684\u6709\u7B28\u6BD4\u4F20\u4E2Ahttp\u6765\u5F53\u505A\u6A21\u677F\u5427...");
16135
- }
16136
- const file = path4.resolve(options.file);
16137
- const tplData = fs5.readFileSync(file, "utf-8");
16138
- const renderData = template.render(tplData, options.data);
16139
- const outputPath = getOutputPath(options.file, renderData, options.name);
16140
- fs5.writeFileSync(outputPath, renderData);
16141
- delete options.data;
16142
- options.file = `file://${outputPath}`;
16143
- return options;
16144
- }
16145
- if (!options.file.startsWith("http") && !options.file.startsWith("file")) {
16146
- options.file = `file://${path4.resolve(options.file)}`;
17065
+ init_exec();
17066
+ init_mock2();
17067
+ init_sqlite();
17068
+ create = async (options) => {
17069
+ try {
17070
+ const client = createClient(options);
17071
+ await client.connect();
17072
+ Object.defineProperty(client, "id", { value: "Redis" });
17073
+ return client;
17074
+ } catch (error) {
17075
+ logger.debug(`${logger.red("[redis] \u542F\u52A8\u5931\u8D25:")} ${JSON.stringify(options)}`);
17076
+ logger.debug(error);
16147
17077
  }
16148
- delete options.data;
16149
- return options;
16150
17078
  };
16151
- renderTemplate = (options) => {
16152
- if (typeof options.file !== "string") {
16153
- throw TypeError("\u6A21\u677F\u6587\u4EF6\u8DEF\u5F84\u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32");
16154
- }
16155
- if ("name" in options) {
16156
- options.file_name = options.name;
16157
- delete options.name;
16158
- }
16159
- if (!options.file_name) {
16160
- options.file_name = path4.basename(options.file) || "render";
16161
- }
16162
- if (options.data) {
16163
- if (options.file.startsWith("http")) {
16164
- throw TypeError("\u4ED6\u55B5\u7684 \u4E0D\u4F1A\u771F\u7684\u6709\u7B28\u6BD4\u4F20\u4E2Ahttp\u6765\u5F53\u505A\u6A21\u677F\u5427...");
16165
- }
16166
- const file = path4.resolve(options.file);
16167
- const tplData = fs5.readFileSync(file, "utf-8");
16168
- const renderData = template.render(tplData, options.data);
16169
- const outputPath = getOutputPath(options.file, renderData, options.file_name);
16170
- fs5.writeFileSync(outputPath, renderData);
16171
- delete options.data;
16172
- options.file = `file://${outputPath}`;
16173
- return options;
16174
- }
16175
- if (!options.file.startsWith("http") && !options.file.startsWith("file")) {
16176
- options.file = `file://${path4.resolve(options.file)}`;
17079
+ start = async () => {
17080
+ logger.debug("[redis] \u6B63\u5728\u5C1D\u8BD5\u542F\u52A8 Redis...");
17081
+ if (isWin()) {
17082
+ const result = await exec("redis-server.exe redis.conf", { booleanResult: true });
17083
+ if (result) return result;
17084
+ const service = "net start Redis";
17085
+ return await exec(service, { booleanResult: true });
16177
17086
  }
16178
- delete options.data;
16179
- return options;
17087
+ const cmd = "redis-server --save 300 10 --daemonize yes" + await isArm64();
17088
+ return await exec(cmd, { booleanResult: true });
16180
17089
  };
16181
- getOutputPath = (file, data, name) => {
16182
- const extname = path4.extname(file);
16183
- const basename = path4.basename(file, extname);
16184
- const fileDir = path4.join(htmlPath, name || "render");
16185
- mkdirSync(fileDir);
16186
- const contentHash = __require("crypto").createHash("md5").update(data).digest("hex").substring(0, 8);
16187
- const filePath = path4.join(fileDir, `${basename}-${contentHash}${extname}`);
16188
- if (fs5.existsSync(filePath)) {
16189
- const now = /* @__PURE__ */ new Date();
16190
- try {
16191
- fs5.utimesSync(filePath, now, now);
16192
- } catch (err) {
16193
- logger.error(`[\u6587\u4EF6\u66F4\u65B0] \u66F4\u65B0\u6587\u4EF6\u65F6\u51FA\u9519: ${filePath}, ${err}`);
17090
+ createRedis = async () => {
17091
+ try {
17092
+ const options = redis();
17093
+ let client = await create(options);
17094
+ if (client) {
17095
+ logger.info(`[redis] ${logger.green("Redis \u8FDE\u63A5\u6210\u529F")}`);
17096
+ return client;
17097
+ }
17098
+ const result = await start();
17099
+ if (result) {
17100
+ logger.debug(logger.green("[redis] \u4E3B\u52A8\u62C9\u8D77 Redis \u6210\u529F"));
17101
+ client = await create(options);
17102
+ } else {
17103
+ logger.debug(logger.red("[redis] \u4E3B\u52A8\u62C9\u8D77 Redis \u5931\u8D25"));
16194
17104
  }
16195
- return filePath;
17105
+ if (client) return client;
17106
+ throw new Error("Redis \u542F\u52A8\u5931\u8D25");
17107
+ } catch (error) {
17108
+ logger.debug(`[redis] ${logger.red("Redis \u8FDE\u63A5\u5931\u8D25")}`);
17109
+ logger.debug(error);
17110
+ logger.debug(logger.yellow("[redis] \u5C06\u964D\u7EA7\u4E3A redis-mock \u5B9E\u73B0"));
17111
+ return mock();
16196
17112
  }
16197
- fs5.writeFileSync(filePath, data);
16198
- return filePath;
16199
17113
  };
16200
- cleanExpiredFiles = async () => {
16201
- let count3 = 0;
16202
- const now = Date.now();
16203
- const files = await getAllFiles(htmlPath, { suffixs: [".html"] });
16204
- if (!files.length) return;
16205
- const EXPIRE_TIME = 10 * 60 * 1e3;
16206
- for (const file of files) {
17114
+ isArm64 = async () => {
17115
+ if (os.arch() !== "arm64") return "";
17116
+ const { stdout } = await exec("redis-server -v");
17117
+ const version = stdout.toString();
17118
+ if (!version) return "";
17119
+ const RedisVersion = version.match(/v=(\d)./);
17120
+ if (RedisVersion && Number(RedisVersion[1]) >= 6) return " --ignore-warnings ARM64-COW-BUG";
17121
+ return "";
17122
+ };
17123
+ mock = async () => {
17124
+ const sqlite = await new SQLiteWrapper(path4.join(redisSqlite3Path, "redis.db")).init();
17125
+ const redis3 = await new RedisClient(sqlite).init();
17126
+ Object.defineProperty(redis3, "id", { value: "mock" });
17127
+ return redis3;
17128
+ };
17129
+ }
17130
+ });
17131
+
17132
+ // src/core/db/index.ts
17133
+ var init_db = __esm({
17134
+ "src/core/db/index.ts"() {
17135
+ init_redis2();
17136
+ init_mock2();
17137
+ init_kv();
17138
+ }
17139
+ });
17140
+ var createHttpRenderClient;
17141
+ var init_http3 = __esm({
17142
+ "src/adapter/render/connect/http.ts"() {
17143
+ init_cache3();
17144
+ init_render();
17145
+ createHttpRenderClient = () => {
17146
+ const cfg = getRenderCfg();
17147
+ if (!cfg.http_server || !Array.isArray(cfg.http_server) || cfg.http_server.length === 0) {
17148
+ logger.trace("[render][http] \u672A\u914D\u7F6E\u4EFB\u4F55\u6B63\u5411HTTP \u5DF2\u8DF3\u8FC7\u521B\u5EFA");
17149
+ return;
17150
+ }
17151
+ return Promise.allSettled(cfg.http_server.map(async (item) => {
17152
+ let { url, token, enable, isSnapka } = item;
17153
+ if (!enable || isSnapka) return;
17154
+ url = url.replace("/puppeteer", "");
17155
+ const headers = { authorization: crypto.createHash("md5").update(`Bearer ${token}`).digest("hex") };
16207
17156
  try {
16208
- const stats = await fs5.promises.stat(file);
16209
- const lastModified = stats.mtimeMs;
16210
- if (now - lastModified > EXPIRE_TIME) {
16211
- await fs5.promises.unlink(file);
16212
- count3++;
17157
+ const result = await axios10.get(`${url}/ping`, { timeout: 5e3 });
17158
+ if (result.status !== 200 || String(result.data.status) !== "200") {
17159
+ logger.error(`[render][http] \u521B\u5EFA\u6E32\u67D3\u5668\u5931\u8D25: \u65E0\u6CD5\u8FDE\u63A5 ${url}`);
16213
17160
  }
16214
- } catch (err) {
16215
- logger.error(`[\u6587\u4EF6\u6E05\u7406] \u5904\u7406\u6587\u4EF6\u65F6\u51FA\u9519: ${file}, ${err}`);
17161
+ const auth3 = await axios10.get(`${url}/auth`, { headers, timeout: 5e3 });
17162
+ if (auth3.status !== 200 || String(auth3.data.status) !== "200") {
17163
+ logger.error(`[render][http] \u521B\u5EFA\u6E32\u67D3\u5668\u5931\u8D25: \u9274\u6743\u9519\u8BEF ${url}`);
17164
+ return;
17165
+ }
17166
+ } catch (error) {
17167
+ if (axios10.isAxiosError(error)) {
17168
+ const { response } = error;
17169
+ logger.error(`[render][http] \u521B\u5EFA\u6E32\u67D3\u5668\u5931\u8D25: ${response == null ? void 0 : response.status} ${response == null ? void 0 : response.statusText} - ${JSON.stringify((response == null ? void 0 : response.data) || "\u672A\u77E5\u9519\u8BEF")}`);
17170
+ } else {
17171
+ logger.error(`[render][http] \u521B\u5EFA\u6E32\u67D3\u5668\u5931\u8D25: ${error}`);
17172
+ }
17173
+ return;
16216
17174
  }
16217
- }
16218
- logger.mark(`[\u6587\u4EF6\u6E05\u7406] \u6E05\u7406HTML\u5B8C\u6210: ${count3}/${files.length}`);
16219
- };
16220
- startCleanExpiredFiles = () => {
16221
- schedule.scheduleJob(process.env.CLEAN_HTML_CRON || "*/10 * * * *", cleanExpiredFiles);
17175
+ const index5 = registerRender("puppeteer", async (options) => {
17176
+ var _a;
17177
+ try {
17178
+ const result = await axios10.post(`${url}/puppeteer`, options, { headers });
17179
+ if (result.status !== 200) {
17180
+ throw new Error(`[render][http] \u6E32\u67D3\u5931\u8D25: ${result.status} ${result.statusText} - ${((_a = result.data) == null ? void 0 : _a.message) || "\u672A\u77E5\u9519\u8BEF"}`);
17181
+ }
17182
+ return result.data;
17183
+ } catch (error) {
17184
+ if (axios10.isAxiosError(error)) {
17185
+ if (!error.response) {
17186
+ unregisterRender(index5);
17187
+ throw new Error(`[render][http] \u7F51\u7EDC\u8FDE\u63A5\u5931\u8D25: ${error.message}`);
17188
+ }
17189
+ const { response } = error;
17190
+ throw new Error(`[render][http] \u6E32\u67D3\u5931\u8D25: ${response == null ? void 0 : response.status} ${response == null ? void 0 : response.statusText} - ${JSON.stringify((response == null ? void 0 : response.data) || "\u672A\u77E5\u9519\u8BEF")}`);
17191
+ }
17192
+ if (error instanceof Error) {
17193
+ throw error;
17194
+ }
17195
+ throw new Error(`[render][unknown] \u672A\u77E5\u9519\u8BEF: ${error}`);
17196
+ }
17197
+ });
17198
+ }));
16222
17199
  };
16223
17200
  }
16224
17201
  });
@@ -16226,7 +17203,7 @@ var WebSocketRender;
16226
17203
  var init_ws3 = __esm({
16227
17204
  "src/adapter/render/connect/ws.ts"() {
16228
17205
  init_template();
16229
- init_cache4();
17206
+ init_cache3();
16230
17207
  init_static();
16231
17208
  WebSocketRender = class {
16232
17209
  /** websocket实例 */
@@ -16289,7 +17266,7 @@ var init_ws3 = __esm({
16289
17266
  * @param data 数据
16290
17267
  */
16291
17268
  async static(echo, data) {
16292
- const result = isStatic(data.file);
17269
+ const result = isPublic(data.file);
16293
17270
  if (!result) {
16294
17271
  logger.warn(`[WebSocket] \u8BBF\u95EE\u7684\u8DEF\u5F84\u975E\u6CD5: echo: ${echo} data: ${JSON.stringify(data)}`);
16295
17272
  return this.socket.send(JSON.stringify({ echo, status: "error", data: "\u975E\u6CD5\u7684\u8BBF\u95EE\u8DEF\u5F84" }));
@@ -16328,7 +17305,7 @@ var init_ws3 = __esm({
16328
17305
  }
16329
17306
  });
16330
17307
  var WebSocketClientRenderer, createWebSocketRenderClient;
16331
- var init_client2 = __esm({
17308
+ var init_client3 = __esm({
16332
17309
  "src/adapter/render/connect/client.ts"() {
16333
17310
  init_ws3();
16334
17311
  init_render();
@@ -16396,8 +17373,8 @@ var init_client2 = __esm({
16396
17373
  return;
16397
17374
  }
16398
17375
  return Promise.allSettled(cfg.ws_client.map(async (item) => {
16399
- const { url, token, enable } = item;
16400
- if (!enable) return;
17376
+ const { url, token, enable, isSnapka } = item;
17377
+ if (!enable || isSnapka) return;
16401
17378
  const headers = { Authorization: crypto.createHash("md5").update(`Bearer ${token}`).digest("hex") };
16402
17379
  const socket = new WebSocket(url, { headers });
16403
17380
  const renderer = new WebSocketClientRenderer(socket, url, headers);
@@ -16423,7 +17400,7 @@ __export(server_exports, {
16423
17400
  WebSocketServerRenderer: () => WebSocketServerRenderer
16424
17401
  });
16425
17402
  var WebSocketServerRenderer;
16426
- var init_server2 = __esm({
17403
+ var init_server3 = __esm({
16427
17404
  "src/adapter/render/connect/server.ts"() {
16428
17405
  init_ws3();
16429
17406
  init_internal();
@@ -16462,12 +17439,12 @@ var init_server2 = __esm({
16462
17439
  var initRender2;
16463
17440
  var init_render2 = __esm({
16464
17441
  "src/adapter/render/index.ts"() {
16465
- init_http2();
16466
- init_client2();
17442
+ init_http3();
17443
+ init_client3();
16467
17444
  initRender2 = async () => {
16468
17445
  createHttpRenderClient();
16469
17446
  createWebSocketRenderClient();
16470
- await Promise.resolve().then(() => (init_server2(), server_exports));
17447
+ await Promise.resolve().then(() => (init_server3(), server_exports));
16471
17448
  };
16472
17449
  }
16473
17450
  });
@@ -16637,7 +17614,7 @@ var init_button2 = __esm({
16637
17614
  var render3;
16638
17615
  var init_render3 = __esm({
16639
17616
  "src/core/karin/render.ts"() {
16640
- init_cache4();
17617
+ init_cache3();
16641
17618
  render3 = (options, multiPageOrId, id) => {
16642
17619
  if (options === "opt") {
16643
17620
  return callRender(multiPageOrId, id);
@@ -16964,7 +17941,7 @@ var init_karin = __esm({
16964
17941
  });
16965
17942
 
16966
17943
  // src/server/index.ts
16967
- var init_server3 = __esm({
17944
+ var init_server4 = __esm({
16968
17945
  "src/server/index.ts"() {
16969
17946
  init_indx();
16970
17947
  init_router();
@@ -17659,16 +18636,19 @@ var init_components = __esm({
17659
18636
  var hooks;
17660
18637
  var init_hooks = __esm({
17661
18638
  "src/hooks/index.ts"() {
17662
- init_emptyMessage();
18639
+ init_empty();
17663
18640
  init_messaeg();
17664
18641
  init_sendMsg();
18642
+ init_eventCall();
17665
18643
  hooks = {
17666
18644
  /** 消息hook */
17667
18645
  message,
17668
18646
  /** 发送消息钩子 */
17669
18647
  sendMsg,
17670
- /** 未找到匹配插件消息钩子 */
17671
- emptyMessage
18648
+ /** 未找到匹配插件钩子 */
18649
+ empty,
18650
+ /** 事件调用插件钩子 */
18651
+ eventCall
17672
18652
  };
17673
18653
  }
17674
18654
  });
@@ -17717,7 +18697,7 @@ var init_class2 = __esm({
17717
18697
  };
17718
18698
  }
17719
18699
  });
17720
- var index3, botID, AdapterConsole, adapter2;
18700
+ var index4, botID, AdapterConsole, adapter2;
17721
18701
  var init_input2 = __esm({
17722
18702
  "src/adapter/input/index.ts"() {
17723
18703
  init_base();
@@ -17729,7 +18709,7 @@ var init_input2 = __esm({
17729
18709
  init_config();
17730
18710
  init_create();
17731
18711
  init_event2();
17732
- index3 = 0;
18712
+ index4 = 0;
17733
18713
  botID = "console";
17734
18714
  AdapterConsole = class extends AdapterBase {
17735
18715
  constructor() {
@@ -17802,7 +18782,7 @@ var init_input2 = __esm({
17802
18782
  }
17803
18783
  async sendMsg(contact3, elements, retryCount) {
17804
18784
  const time2 = Date.now();
17805
- const messageId = (++index3).toString();
18785
+ const messageId = (++index4).toString();
17806
18786
  const result = {
17807
18787
  message_id: messageId,
17808
18788
  messageId,
@@ -17838,7 +18818,7 @@ var init_input2 = __esm({
17838
18818
  }
17839
18819
  async getUrl(data, ext) {
17840
18820
  const cfg = adapter();
17841
- const name = (++index3).toString();
18821
+ const name = (++index4).toString();
17842
18822
  const file = path4.join(consolePath, `${name}${ext}`);
17843
18823
  await fs5.promises.writeFile(file, await buffer(data));
17844
18824
  if (cfg.console.isLocal) {
@@ -18123,165 +19103,6 @@ var init_adapter3 = __esm({
18123
19103
  init_render2();
18124
19104
  }
18125
19105
  });
18126
- var getMd5, auth2;
18127
- var init_auth = __esm({
18128
- "src/adapter/puppeteer/auth.ts"() {
18129
- getMd5 = (token) => {
18130
- return crypto.createHash("md5").update(token).digest("hex");
18131
- };
18132
- auth2 = (token) => {
18133
- if (!process.env.WS_SERVER_AUTH_KEY) return true;
18134
- if (!token) return false;
18135
- if (token === `Bearer ${process.env.WS_SERVER_AUTH_KEY}`) return true;
18136
- if (token === `Bearer ${getMd5(getMd5(process.env.WS_SERVER_AUTH_KEY))}`) return true;
18137
- return false;
18138
- };
18139
- }
18140
- });
18141
-
18142
- // src/adapter/puppeteer/key.ts
18143
- var createWsResponseKey;
18144
- var init_key3 = __esm({
18145
- "src/adapter/puppeteer/key.ts"() {
18146
- createWsResponseKey = (echo) => {
18147
- return `_response:${echo}`;
18148
- };
18149
- }
18150
- });
18151
-
18152
- // src/adapter/puppeteer/request.ts
18153
- var index4, createRequestError, sendWsRequest, sendWsScreenshotRequest;
18154
- var init_request4 = __esm({
18155
- "src/adapter/puppeteer/request.ts"() {
18156
- init_internal();
18157
- init_key3();
18158
- index4 = 0;
18159
- createRequestError = (options, errorType, cause) => {
18160
- return new Error(
18161
- `[sendRequest] \u8BF7\u6C42\u9519\u8BEF:
18162
- options: ${options}
18163
- error: ${errorType}`,
18164
- { cause }
18165
- );
18166
- };
18167
- sendWsRequest = (socket, data, options = { timeout: 60 * 1e3, onRequest: true }) => {
18168
- return new Promise((resolve, reject) => {
18169
- const timeout2 = (options == null ? void 0 : options.timeout) ?? 60 * 1e3;
18170
- if (socket.readyState !== socket.OPEN) {
18171
- return reject(createRequestError(
18172
- JSON.stringify(data),
18173
- `WebSocket\u672A\u8FDE\u63A5\uFF0C\u5F53\u524D\u72B6\u6001: ${socket.readyState}`
18174
- ));
18175
- }
18176
- if (options.onRequest) {
18177
- if (index4 >= Number.MAX_SAFE_INTEGER) {
18178
- index4 = 0;
18179
- }
18180
- const echo = (++index4).toString();
18181
- const key = createWsResponseKey(echo);
18182
- const str2 = JSON.stringify({ ...data, echo });
18183
- const result = (data2) => {
18184
- clearTimeout(timer);
18185
- if ((data2 == null ? void 0 : data2.status) === "ok") {
18186
- return resolve(data2.data);
18187
- }
18188
- reject(createRequestError(str2, "\u8BF7\u6C42\u5931\u8D25", data2));
18189
- };
18190
- const timer = setTimeout(() => {
18191
- listeners.off(key, result);
18192
- reject(createRequestError(str2, `\u8BF7\u6C42\u8D85\u65F6 ${timeout2}ms`));
18193
- }, timeout2);
18194
- listeners.once(key, result);
18195
- try {
18196
- socket.send(str2);
18197
- } catch (error) {
18198
- clearTimeout(timer);
18199
- listeners.off(key, result);
18200
- reject(createRequestError(str2, "\u53D1\u9001\u5931\u8D25", error));
18201
- }
18202
- return;
18203
- }
18204
- try {
18205
- socket.send(JSON.stringify(data));
18206
- resolve(void 0);
18207
- } catch (error) {
18208
- reject(createRequestError(JSON.stringify(data), "\u53D1\u9001\u5931\u8D25", error));
18209
- }
18210
- });
18211
- };
18212
- sendWsScreenshotRequest = (socket, params, timeout2 = 60 * 1e3) => {
18213
- return sendWsRequest(
18214
- socket,
18215
- {
18216
- params,
18217
- type: "request",
18218
- action: params.data ? "render" : "screenshot"
18219
- },
18220
- {
18221
- onRequest: true,
18222
- timeout: timeout2
18223
- }
18224
- );
18225
- };
18226
- }
18227
- });
18228
-
18229
- // src/adapter/puppeteer/server.ts
18230
- var server_exports2 = {};
18231
- __export(server_exports2, {
18232
- initWebSocketPuppeteerServer: () => initWebSocketPuppeteerServer
18233
- });
18234
- var WebSocketPuppeteerServer, initWebSocketPuppeteerServer;
18235
- var init_server4 = __esm({
18236
- "src/adapter/puppeteer/server.ts"() {
18237
- init_auth();
18238
- init_internal();
18239
- init_key3();
18240
- init_request4();
18241
- init_key();
18242
- init_template();
18243
- init_cache4();
18244
- WebSocketPuppeteerServer = async (socket, request2) => {
18245
- let index5 = -1;
18246
- const authorization = request2.headers["authorization"];
18247
- if (!auth2(authorization)) {
18248
- socket.close();
18249
- logger.error(`[WebSocket] \u9274\u6743\u5931\u8D25: authorization: ${authorization} url: ${request2.url}`);
18250
- return;
18251
- }
18252
- const render4 = (options) => {
18253
- if (options.data) {
18254
- options = renderTemplate(options);
18255
- }
18256
- return sendWsScreenshotRequest(socket, options);
18257
- };
18258
- socket.on("close", () => {
18259
- index5 > 0 && unregisterRender(index5);
18260
- socket.removeAllListeners();
18261
- socket.close();
18262
- });
18263
- socket.on("message", (event) => {
18264
- const raw2 = event.toString();
18265
- const { type, status, echo, data } = JSON.parse(raw2) || {};
18266
- logger.debug(`[WebSocket] ${echo} ${type} ${status}`);
18267
- logger.trace(`[WebSocket] ${echo} ${raw2}`);
18268
- if (type !== "response") {
18269
- logger.error(`[WebSocket] \u672A\u77E5\u7684\u8BF7\u6C42: ${raw2}`);
18270
- return;
18271
- }
18272
- const key = createWsResponseKey(echo);
18273
- listeners.emit(key, { status, data });
18274
- });
18275
- index5 = registerRender("@karinjs/puppeteer-server", render4);
18276
- };
18277
- initWebSocketPuppeteerServer = () => {
18278
- listeners.on(WS_CONNECTION_PUPPETEER_2, (socket, request2, call2) => {
18279
- call2();
18280
- WebSocketPuppeteerServer(socket, request2);
18281
- });
18282
- };
18283
- }
18284
- });
18285
19106
 
18286
19107
  // src/index.ts
18287
19108
  var index_exports = {};
@@ -18386,9 +19207,9 @@ __export(index_exports, {
18386
19207
  WS_CONNECTION: () => WS_CONNECTION,
18387
19208
  WS_CONNECTION_ONEBOT: () => WS_CONNECTION_ONEBOT,
18388
19209
  WS_CONNECTION_PUPPETEER: () => WS_CONNECTION_PUPPETEER,
18389
- WS_CONNECTION_PUPPETEER_2: () => WS_CONNECTION_PUPPETEER_2,
18390
19210
  WS_CONNECTION_SANDBOX: () => WS_CONNECTION_SANDBOX,
18391
19211
  WS_CONNECTION_TERMINAL: () => WS_CONNECTION_TERMINAL,
19212
+ WS_SNAPKA: () => WS_SNAPKA,
18392
19213
  Watch: () => Watch,
18393
19214
  Watcher: () => Watcher,
18394
19215
  YamlEditor: () => YamlEditor,
@@ -18522,16 +19343,37 @@ __export(index_exports, {
18522
19343
  isLocalRequest: () => isLocalRequest,
18523
19344
  isLoopback: () => isLoopback,
18524
19345
  isMac: () => isMac,
19346
+ isPackaged: () => isPackaged,
18525
19347
  isPkg: () => isPkg,
18526
19348
  isPlugin: () => isPlugin,
19349
+ isPublic: () => isPublic,
18527
19350
  isRoot: () => isRoot,
18528
- isStatic: () => isStatic,
18529
19351
  isSubPath: () => isSubPath,
18530
19352
  isWin: () => isWin2,
18531
19353
  json: () => json,
18532
19354
  karin: () => karin,
18533
19355
  karinDir: () => karinDir,
18534
19356
  karinMain: () => karinMain,
19357
+ karinPathBase: () => karinPathBase,
19358
+ karinPathComment: () => karinPathComment,
19359
+ karinPathConfig: () => karinPathConfig,
19360
+ karinPathConsole: () => karinPathConsole,
19361
+ karinPathData: () => karinPathData,
19362
+ karinPathDb: () => karinPathDb,
19363
+ karinPathDefaultConfig: () => karinPathDefaultConfig,
19364
+ karinPathDefaultView: () => karinPathDefaultView,
19365
+ karinPathHtml: () => karinPathHtml,
19366
+ karinPathKv: () => karinPathKv,
19367
+ karinPathLogs: () => karinPathLogs,
19368
+ karinPathMain: () => karinPathMain,
19369
+ karinPathPlugins: () => karinPathPlugins,
19370
+ karinPathPm2Config: () => karinPathPm2Config,
19371
+ karinPathRedisSqlite3: () => karinPathRedisSqlite3,
19372
+ karinPathResource: () => karinPathResource,
19373
+ karinPathRoot: () => karinPathRoot,
19374
+ karinPathSandboxData: () => karinPathSandboxData,
19375
+ karinPathSandboxTemp: () => karinPathSandboxTemp,
19376
+ karinPathTemp: () => karinPathTemp,
18535
19377
  karinToQQBot: () => karinToQQBot,
18536
19378
  key: () => key_exports,
18537
19379
  kvPath: () => kvPath,
@@ -18561,7 +19403,7 @@ __export(index_exports, {
18561
19403
  redisSqlite3Path: () => redisSqlite3Path,
18562
19404
  registerBot: () => registerBot,
18563
19405
  registerRender: () => registerRender,
18564
- render: () => render2,
19406
+ render: () => render,
18565
19407
  renderHtml: () => renderHtml,
18566
19408
  renderMultiHtml: () => renderMultiHtml,
18567
19409
  renderTpl: () => renderTpl,
@@ -18574,6 +19416,7 @@ __export(index_exports, {
18574
19416
  router: () => router,
18575
19417
  sandboxDataPath: () => sandboxDataPath,
18576
19418
  sandboxTempPath: () => sandboxTempPath,
19419
+ satisfies: () => satisfies,
18577
19420
  save: () => save,
18578
19421
  segment: () => segment_exports,
18579
19422
  sendMsg: () => sendMsg2,
@@ -18626,10 +19469,10 @@ var init_index = __esm({
18626
19469
  init_service();
18627
19470
  init_karin();
18628
19471
  init_utils();
18629
- init_server3();
19472
+ init_server4();
18630
19473
  init_onebot();
18631
19474
  init_event2();
18632
- init_cache4();
19475
+ init_cache3();
18633
19476
  init_types2();
18634
19477
  init_components();
18635
19478
  init_hooks();
@@ -18655,12 +19498,18 @@ var init_index = __esm({
18655
19498
  await initRender2();
18656
19499
  const { startCleanExpiredFiles: startCleanExpiredFiles2 } = await Promise.resolve().then(() => (init_template(), template_exports));
18657
19500
  startCleanExpiredFiles2();
18658
- const { initWebSocketPuppeteerServer: initWebSocketPuppeteerServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
19501
+ const {
19502
+ initWebSocketPuppeteerServer: initWebSocketPuppeteerServer2,
19503
+ initSnapkaClient: initSnapkaClient2,
19504
+ initSnapkaHttp: initSnapkaHttp2
19505
+ } = await Promise.resolve().then(() => (init_snapka(), snapka_exports));
18659
19506
  initWebSocketPuppeteerServer2();
19507
+ initSnapkaClient2();
19508
+ initSnapkaHttp2();
18660
19509
  };
18661
19510
  start2();
18662
19511
  }
18663
19512
  });
18664
19513
  init_index();
18665
19514
 
18666
- export { AdapterBase, BATCH_UPDATE_PLUGINS_ROUTER, BaseEvent, Bot, CHECK_PLUGIN_ROUTER, CLOSE_TERMINAL_ROUTER, CONSOLE_ROUTER, CREATE_TERMINAL_ROUTER, DirectMessage, EVENT_COUNT, EXIT_ROUTER, FILE_CHANGE, FriendDecreaseNotice, FriendIncreaseNotice, FriendMessage, GET_BOTS_ROUTER, GET_CONFIG_ROUTER, GET_LOCAL_PLUGIN_LIST_ROUTER, GET_LOG_FILE_LIST_ROUTER, GET_LOG_FILE_ROUTER, GET_LOG_ROUTER, GET_NETWORK_STATUS_ROUTER, GET_ONLINE_PLUGIN_LIST_ROUTER, GET_PLUGIN_APPS_ROUTER, GET_PLUGIN_CONFIG_ROUTER, GET_PLUGIN_FILE_ROUTER, GET_PLUGIN_LIST_ROUTER, GET_TASK_LIST_ROUTER, GET_TASK_STATUS_ROUTER, GET_TERMINAL_LIST_ROUTER, GET_UPDATABLE_PLUGINS_ROUTER, GET_WEBUI_PLUGIN_LIST_ROUTER, GET_WEBUI_PLUGIN_VERSIONS_ROUTER, GroupAdminChangedNotice, GroupApplyRequest, GroupCardChangedNotice, GroupFileUploadedNotice, GroupHlightsChangedNotice, GroupHonorChangedNotice, GroupInviteRequest, GroupLuckKingNotice, GroupMemberBanNotice, GroupMemberDecreaseNotice, GroupMemberIncreaseNotice, GroupMemberTitleUpdatedNotice, GroupMessage, GroupMessageReactionNotice, GroupNotice, GroupPokeNotice, GroupRecallNotice, GroupSignInNotice, GroupTempMessage, GroupWholeBanNotice, GuildMessage, INSTALL_PLUGIN_ROUTER, INSTALL_WEBUI_PLUGIN_ROUTER, IS_PLUGIN_CONFIG_EXIST_ROUTER, LOGIN_ROUTER, MessageBase, NoticeBase, OB11ApiAction, OB11Event, OB11MessageSubType, OB11MessageType, OB11NoticeType, OB11RequestType, OB11Sex, PING_ROUTER, Plugin, PrivateApplyRequest, PrivateFileUploadedNotice, PrivatePokeNotice, PrivateRecallNotice, RECV_MSG, REFRESH_ROUTER, RESTART_ROUTER, ReceiveLikeNotice, Renderer, RequestBase, SAVE_CONFIG_ROUTER, SAVE_PLUGIN_CONFIG_ROUTER, SEND_MSG, SET_LOG_LEVEL_ROUTER, SYSTEM_INFO_ROUTER, SYSTEM_STATUS_KARIN_ROUTER, SYSTEM_STATUS_ROUTER, SYSTEM_STATUS_WS_ROUTER, UNINSTALL_PLUGIN_ROUTER, UNINSTALL_WEBUI_PLUGIN_ROUTER, UPDATE_CORE_ROUTER, UPDATE_PLUGIN_ROUTER, UPDATE_TASK_STATUS_ROUTER, UPDATE_WEBUI_PLUGIN_VERSION_ROUTER, WS_CLOSE, WS_CLOSE_ONEBOT, WS_CLOSE_PUPPETEER, WS_CLOSE_SANDBOX, WS_CONNECTION, WS_CONNECTION_ONEBOT, WS_CONNECTION_PUPPETEER, WS_CONNECTION_PUPPETEER_2, WS_CONNECTION_SANDBOX, WS_CONNECTION_TERMINAL, Watch, Watcher, YamlEditor, absPath, accordion, accordionItem, accordionPro, app, applyComments, base64, basePath, buffer, buttonHandle, callRender, changelog_exports as changelog, checkGitPluginUpdate, checkPkgUpdate, clearRequire, clearRequireFile, comment, commentPath, common_exports as common, components, config_exports as config, configPath, consolePath, contact2 as contact, contactDirect, contactFriend, contactGroup, contactGroupTemp, contactGuild, copyConfig, copyConfigSync, copyFiles, copyFilesSync, createClient2 as createClient, createDirectMessage, createFriendDecreaseNotice, createFriendIncreaseNotice, createFriendMessage, createGroupAdminChangedNotice, createGroupApplyRequest, createGroupCardChangedNotice, createGroupFileUploadedNotice, createGroupHlightsChangedNotice, createGroupHonorChangedNotice, createGroupInviteRequest, createGroupLuckKingNotice, createGroupMemberAddNotice, createGroupMemberBanNotice, createGroupMemberDelNotice, createGroupMemberTitleUpdatedNotice, createGroupMessage, createGroupMessageReactionNotice, createGroupPokeNotice, createGroupRecallNotice, createGroupSignInNotice, createGroupTempMessage, createGroupWholeBanNotice, createGuildMessage, createHttp, createInnerLogger, createPluginDir, createPrivateApplyRequest, createPrivateFileUploadedNotice, createPrivatePokeNotice, createPrivateRecallNotice, createRawMessage, createReceiveLikeNotice, dataPath, db, dbPath, debug2 as debug, karin as default, defaultConfigPath, defaultViewPath, divider, downFile, errorToString, exec, existToMkdir, existToMkdirSync, exists, existsSync, ffmpeg, ffplay, ffprobe, fs_exports as file, fileToUrl, fileToUrlHandlerKey, filesByExt, formatTime, fs_exports2 as fs, getAllBot, getAllBotID, getAllBotList, getAllFiles, getAllFilesSync, getBot, getBotCount, getCommit, getFiles, getHash, getPid, getPkgVersion, getPluginInfo, getPlugins, getRelPath, getRemotePkgVersion, getRender, getRenderCount, getRenderList, getRequestIp, getTime, handler, hooks, htmlPath, importModule, initOneBot, input, isClass, isDir, isDirSync, isDocker, isFile, isFileSync, isIPv4Loop, isIPv6Loop, isLinux, isLocalRequest, isLoopback, isMac, isPkg, isPlugin, isRoot, isStatic, isSubPath, isWin2 as isWin, json, karin, karinDir, karinMain, karinToQQBot, key_exports as key, kvPath, lock, lockMethod, lockProp, log, logger2 as logger, logs, logsPath, makeForward, makeMessage, mkdir, mkdirSync, parseChangelog, pkgRoot, pluginDir, pm2Path, qqbotToKarin, randomStr, range, read, readFile, readJson, readJsonSync, redis2 as redis, redisSqlite3Path, registerBot, registerRender, render2 as render, renderHtml, renderMultiHtml, renderTpl, requireFile, requireFileSync, resourcePath, restart, restartDirect, rmSync, router, sandboxDataPath, sandboxTempPath, save, segment_exports as segment, sendMsg2 as sendMsg, sender, senderDirect, senderFriend, senderGroup, senderGroupTemp, senderGuild, sep, server, splitPath, start2 as start, stream, stringifyError, switchComponent, system_exports as system, tempPath, unregisterBot, unregisterRender, updateAllGitPlugin, updateAllPkg, updateGitPlugin, updatePkg, uptime, urlToPath, watch, watchAndMerge, write, writeJson, writeJsonSync, yaml2 as yaml };
19515
+ export { AdapterBase, BATCH_UPDATE_PLUGINS_ROUTER, BaseEvent, Bot, CHECK_PLUGIN_ROUTER, CLOSE_TERMINAL_ROUTER, CONSOLE_ROUTER, CREATE_TERMINAL_ROUTER, DirectMessage, EVENT_COUNT, EXIT_ROUTER, FILE_CHANGE, FriendDecreaseNotice, FriendIncreaseNotice, FriendMessage, GET_BOTS_ROUTER, GET_CONFIG_ROUTER, GET_LOCAL_PLUGIN_LIST_ROUTER, GET_LOG_FILE_LIST_ROUTER, GET_LOG_FILE_ROUTER, GET_LOG_ROUTER, GET_NETWORK_STATUS_ROUTER, GET_ONLINE_PLUGIN_LIST_ROUTER, GET_PLUGIN_APPS_ROUTER, GET_PLUGIN_CONFIG_ROUTER, GET_PLUGIN_FILE_ROUTER, GET_PLUGIN_LIST_ROUTER, GET_TASK_LIST_ROUTER, GET_TASK_STATUS_ROUTER, GET_TERMINAL_LIST_ROUTER, GET_UPDATABLE_PLUGINS_ROUTER, GET_WEBUI_PLUGIN_LIST_ROUTER, GET_WEBUI_PLUGIN_VERSIONS_ROUTER, GroupAdminChangedNotice, GroupApplyRequest, GroupCardChangedNotice, GroupFileUploadedNotice, GroupHlightsChangedNotice, GroupHonorChangedNotice, GroupInviteRequest, GroupLuckKingNotice, GroupMemberBanNotice, GroupMemberDecreaseNotice, GroupMemberIncreaseNotice, GroupMemberTitleUpdatedNotice, GroupMessage, GroupMessageReactionNotice, GroupNotice, GroupPokeNotice, GroupRecallNotice, GroupSignInNotice, GroupTempMessage, GroupWholeBanNotice, GuildMessage, INSTALL_PLUGIN_ROUTER, INSTALL_WEBUI_PLUGIN_ROUTER, IS_PLUGIN_CONFIG_EXIST_ROUTER, LOGIN_ROUTER, MessageBase, NoticeBase, OB11ApiAction, OB11Event, OB11MessageSubType, OB11MessageType, OB11NoticeType, OB11RequestType, OB11Sex, PING_ROUTER, Plugin, PrivateApplyRequest, PrivateFileUploadedNotice, PrivatePokeNotice, PrivateRecallNotice, RECV_MSG, REFRESH_ROUTER, RESTART_ROUTER, ReceiveLikeNotice, Renderer, RequestBase, SAVE_CONFIG_ROUTER, SAVE_PLUGIN_CONFIG_ROUTER, SEND_MSG, SET_LOG_LEVEL_ROUTER, SYSTEM_INFO_ROUTER, SYSTEM_STATUS_KARIN_ROUTER, SYSTEM_STATUS_ROUTER, SYSTEM_STATUS_WS_ROUTER, UNINSTALL_PLUGIN_ROUTER, UNINSTALL_WEBUI_PLUGIN_ROUTER, UPDATE_CORE_ROUTER, UPDATE_PLUGIN_ROUTER, UPDATE_TASK_STATUS_ROUTER, UPDATE_WEBUI_PLUGIN_VERSION_ROUTER, WS_CLOSE, WS_CLOSE_ONEBOT, WS_CLOSE_PUPPETEER, WS_CLOSE_SANDBOX, WS_CONNECTION, WS_CONNECTION_ONEBOT, WS_CONNECTION_PUPPETEER, WS_CONNECTION_SANDBOX, WS_CONNECTION_TERMINAL, WS_SNAPKA, Watch, Watcher, YamlEditor, absPath, accordion, accordionItem, accordionPro, app, applyComments, base64, basePath, buffer, buttonHandle, callRender, changelog_exports as changelog, checkGitPluginUpdate, checkPkgUpdate, clearRequire, clearRequireFile, comment, commentPath, common_exports as common, components, config_exports as config, configPath, consolePath, contact2 as contact, contactDirect, contactFriend, contactGroup, contactGroupTemp, contactGuild, copyConfig, copyConfigSync, copyFiles, copyFilesSync, createClient2 as createClient, createDirectMessage, createFriendDecreaseNotice, createFriendIncreaseNotice, createFriendMessage, createGroupAdminChangedNotice, createGroupApplyRequest, createGroupCardChangedNotice, createGroupFileUploadedNotice, createGroupHlightsChangedNotice, createGroupHonorChangedNotice, createGroupInviteRequest, createGroupLuckKingNotice, createGroupMemberAddNotice, createGroupMemberBanNotice, createGroupMemberDelNotice, createGroupMemberTitleUpdatedNotice, createGroupMessage, createGroupMessageReactionNotice, createGroupPokeNotice, createGroupRecallNotice, createGroupSignInNotice, createGroupTempMessage, createGroupWholeBanNotice, createGuildMessage, createHttp, createInnerLogger, createPluginDir, createPrivateApplyRequest, createPrivateFileUploadedNotice, createPrivatePokeNotice, createPrivateRecallNotice, createRawMessage, createReceiveLikeNotice, dataPath, db, dbPath, debug2 as debug, karin as default, defaultConfigPath, defaultViewPath, divider, downFile, errorToString, exec, existToMkdir, existToMkdirSync, exists, existsSync, ffmpeg, ffplay, ffprobe, fs_exports as file, fileToUrl, fileToUrlHandlerKey, filesByExt, formatTime, fs_exports2 as fs, getAllBot, getAllBotID, getAllBotList, getAllFiles, getAllFilesSync, getBot, getBotCount, getCommit, getFiles, getHash, getPid, getPkgVersion, getPluginInfo, getPlugins, getRelPath, getRemotePkgVersion, getRender, getRenderCount, getRenderList, getRequestIp, getTime, handler, hooks, htmlPath, importModule, initOneBot, input, isClass, isDir, isDirSync, isDocker, isFile, isFileSync, isIPv4Loop, isIPv6Loop, isLinux, isLocalRequest, isLoopback, isMac, isPackaged, isPkg, isPlugin, isPublic, isRoot, isSubPath, isWin2 as isWin, json, karin, karinDir, karinMain, karinPathBase, karinPathComment, karinPathConfig, karinPathConsole, karinPathData, karinPathDb, karinPathDefaultConfig, karinPathDefaultView, karinPathHtml, karinPathKv, karinPathLogs, karinPathMain, karinPathPlugins, karinPathPm2Config, karinPathRedisSqlite3, karinPathResource, karinPathRoot, karinPathSandboxData, karinPathSandboxTemp, karinPathTemp, karinToQQBot, key_exports as key, kvPath, lock, lockMethod, lockProp, log, logger2 as logger, logs, logsPath, makeForward, makeMessage, mkdir, mkdirSync, parseChangelog, pkgRoot, pluginDir, pm2Path, qqbotToKarin, randomStr, range, read, readFile, readJson, readJsonSync, redis2 as redis, redisSqlite3Path, registerBot, registerRender, render, renderHtml, renderMultiHtml, renderTpl, requireFile, requireFileSync, resourcePath, restart, restartDirect, rmSync, router, sandboxDataPath, sandboxTempPath, satisfies, save, segment_exports as segment, sendMsg2 as sendMsg, sender, senderDirect, senderFriend, senderGroup, senderGroupTemp, senderGuild, sep, server, splitPath, start2 as start, stream, stringifyError, switchComponent, system_exports as system, tempPath, unregisterBot, unregisterRender, updateAllGitPlugin, updateAllPkg, updateGitPlugin, updatePkg, uptime, urlToPath, watch, watchAndMerge, write, writeJson, writeJsonSync, yaml2 as yaml };