most-box 0.1.0 → 0.1.2

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 (390) hide show
  1. package/README.md +24 -16
  2. package/electron/main.js +72 -8
  3. package/electron/preload.js +6 -0
  4. package/out/404/index.html +2 -2
  5. package/out/404.html +2 -2
  6. package/out/__next.__PAGE__.txt +6 -6
  7. package/out/__next._full.txt +23 -20
  8. package/out/__next._head.txt +3 -3
  9. package/out/__next._index.txt +8 -6
  10. package/out/__next._tree.txt +6 -4
  11. package/out/_next/static/chunks/0-n3pg7th.zza.js +1 -0
  12. package/out/_next/static/chunks/0.4j.0k5a64vg.js +1 -0
  13. package/out/_next/static/chunks/0.e2avjgna_b2.js +1 -0
  14. package/out/_next/static/chunks/0.ozi1_x2.m.~.js +1 -0
  15. package/out/_next/static/chunks/0.t5wlt51zou5.js +1 -0
  16. package/out/_next/static/chunks/0.w4hkvap~bva.js +1 -0
  17. package/out/_next/static/chunks/00d9h1tddnnnd.js +1 -0
  18. package/out/_next/static/chunks/00tkdqwxch-3s.js +1 -0
  19. package/out/_next/static/chunks/01l3o90g~1z42.js +1 -0
  20. package/out/_next/static/chunks/01mfky9camw6i.js +1 -0
  21. package/out/_next/static/chunks/01r.v-pqs1vrm.js +1 -0
  22. package/out/_next/static/chunks/03edqrb4zdj~g.js +31 -0
  23. package/out/_next/static/chunks/03h_6oo-gqkhz.js +1 -0
  24. package/out/_next/static/chunks/{0ho~log~~-jwp.css → 03h~nhgj0hv3p.css} +1 -1
  25. package/out/_next/static/chunks/04hcgsanv1hhu.js +1 -0
  26. package/out/_next/static/chunks/05g2q0w5b34.g.js +1 -0
  27. package/out/_next/static/chunks/05of77xycbt8~.js +1 -0
  28. package/out/_next/static/chunks/05zwemzfjx3sh.js +1 -0
  29. package/out/_next/static/chunks/06dpc5df94.v1.js +1 -0
  30. package/out/_next/static/chunks/06e1~1-z_ic9a.js +1 -0
  31. package/out/_next/static/chunks/075s7sn.ns~u5.js +1 -0
  32. package/out/_next/static/chunks/07dynrbvd3.f4.js +1 -0
  33. package/out/_next/static/chunks/07p~uva5pwgwe.js +1 -0
  34. package/out/_next/static/chunks/07r9nn-pzlgg1.js +1 -0
  35. package/out/_next/static/chunks/07td.jq7xff84.css +1 -0
  36. package/out/_next/static/chunks/08.72abkgwy9g.js +1 -0
  37. package/out/_next/static/chunks/08576xhv~~jck.js +1 -0
  38. package/out/_next/static/chunks/08u211~k~qu52.js +1 -0
  39. package/out/_next/static/chunks/098.p.2-zm4p7.js +1 -0
  40. package/out/_next/static/chunks/09ngvtajm7e5y.js +1 -0
  41. package/out/_next/static/chunks/09ps~-43n5qyo.js +1 -0
  42. package/out/_next/static/chunks/09v7_0gclxr46.js +1 -0
  43. package/out/_next/static/chunks/09yql86dir9c4.js +1 -0
  44. package/out/_next/static/chunks/09zmlfljowj1~.js +1 -0
  45. package/out/_next/static/chunks/0_s~ebb-7b2hr.js +1 -0
  46. package/out/_next/static/chunks/0_w-0-2z5oqd_.js +1 -0
  47. package/out/_next/static/chunks/0adx~d-j05c9d.css +24 -0
  48. package/out/_next/static/chunks/0ao1lbi4b.sfa.js +1 -0
  49. package/out/_next/static/chunks/0aq.rc9woa2nz.js +1 -0
  50. package/out/_next/static/chunks/0bld2u_ld~va2.js +1 -0
  51. package/out/_next/static/chunks/0bliugh5lxw55.js +1 -0
  52. package/out/_next/static/chunks/0cn9a7aimbdzq.js +1 -0
  53. package/out/_next/static/chunks/0d3f-nk3c.2re.js +1 -0
  54. package/out/_next/static/chunks/0dtohpf7~3d12.js +1 -0
  55. package/out/_next/static/chunks/0e-3e8h7g99yf.js +1 -0
  56. package/out/_next/static/chunks/0e531nije_ln2.js +1 -0
  57. package/out/_next/static/chunks/0e5zvj_rh0z3m.js +1 -0
  58. package/out/_next/static/chunks/0etes81d_cihn.js +1 -0
  59. package/out/_next/static/chunks/0f4y~rkk-n81e.js +1 -0
  60. package/out/_next/static/chunks/0fk~0~p7ivfn1.js +1 -0
  61. package/out/_next/static/chunks/0fw6juc~lsj3z.js +1 -0
  62. package/out/_next/static/chunks/0g0u7785a73vo.js +1 -0
  63. package/out/_next/static/chunks/0g_a~e050bgzg.css +1 -0
  64. package/out/_next/static/chunks/0g_fpgh7drfda.js +1 -0
  65. package/out/_next/static/chunks/{0n~dq4kpx9xxx.js → 0gcsdf57gcm6h.js} +1 -1
  66. package/out/_next/static/chunks/0gwian.hp3-92.js +1 -0
  67. package/out/_next/static/chunks/0gze5uso1mbe9.js +1 -0
  68. package/out/_next/static/chunks/0h4r.qtmpa6eh.js +1 -0
  69. package/out/_next/static/chunks/0hf.aosc-7172.js +1 -0
  70. package/out/_next/static/chunks/0hgz35c1ejbs9.js +1 -0
  71. package/out/_next/static/chunks/0hpev4am9jpmu.css +1 -0
  72. package/out/_next/static/chunks/0hrw-r.xmvmsq.js +1 -0
  73. package/out/_next/static/chunks/0hzg4al.v~8~m.js +1 -0
  74. package/out/_next/static/chunks/0ip9xrols_83o.js +1 -0
  75. package/out/_next/static/chunks/0j4-d0qf.v~kn.js +1 -0
  76. package/out/_next/static/chunks/0jhdeq.j9_02m.js +1 -0
  77. package/out/_next/static/chunks/0jy63h3i-y69i.js +1 -0
  78. package/out/_next/static/chunks/0kdnx_u-60k9s.js +1 -0
  79. package/out/_next/static/chunks/0kq~edq42o1-c.js +1 -0
  80. package/out/_next/static/chunks/0l5_.uqb-uqb8.js +1 -0
  81. package/out/_next/static/chunks/0l682p362d-5w.js +1 -0
  82. package/out/_next/static/chunks/0m68p9txef5rs.js +1 -0
  83. package/out/_next/static/chunks/0mex8svsiv-2l.js +1 -0
  84. package/out/_next/static/chunks/0mme-fm5d2oz2.js +1 -0
  85. package/out/_next/static/chunks/0myp4sjagr~h0.js +1 -0
  86. package/out/_next/static/chunks/0myq9gs8szydh.js +1 -0
  87. package/out/_next/static/chunks/0n.qlfk~z7o.6.js +1 -0
  88. package/out/_next/static/chunks/0n4t80gjc3q5h.js +1 -0
  89. package/out/_next/static/chunks/0o9ce4cyf76by.js +736 -0
  90. package/out/_next/static/chunks/0oz3yl6_-716p.js +1 -0
  91. package/out/_next/static/chunks/0p0sv~fuddvgr.js +1 -0
  92. package/out/_next/static/chunks/0pt.5cg1t09qs.js +1 -0
  93. package/out/_next/static/chunks/0q0ksgxg98xgd.js +1 -0
  94. package/out/_next/static/chunks/0qgx9t4jx16ua.css +1 -0
  95. package/out/_next/static/chunks/0qqupeexg83u7.js +1 -0
  96. package/out/_next/static/chunks/0rb-ri481.kc9.js +1 -0
  97. package/out/_next/static/chunks/0rsnmahfd.59p.js +1 -0
  98. package/out/_next/static/chunks/0rt6rgnvr-s_p.js +1 -0
  99. package/out/_next/static/chunks/0runh28p_gg6..js +1 -0
  100. package/out/_next/static/chunks/0shy.t1fwqcev.js +1 -0
  101. package/out/_next/static/chunks/{0d3shmwh5_nmn.js → 0t2xr05rlu96l.js} +1 -1
  102. package/out/_next/static/chunks/0t6h56rhg1y5i.js +1 -0
  103. package/out/_next/static/chunks/0tdqd1zunusgk.js +1 -0
  104. package/out/_next/static/chunks/0ujbnp38x63ek.js +1 -0
  105. package/out/_next/static/chunks/0ukyg~tkm~h2m.css +1 -0
  106. package/out/_next/static/chunks/0v68pdrp54lb-.js +1 -0
  107. package/out/_next/static/chunks/0vsm0m5sxrb.3.js +1 -0
  108. package/out/_next/static/chunks/0vzlz.iboqo3c.js +1 -0
  109. package/out/_next/static/chunks/0w87vbpkf-ogd.js +1 -0
  110. package/out/_next/static/chunks/0wtf0xsiicxx6.js +1 -0
  111. package/out/_next/static/chunks/0xdwau5k2augv.css +4 -0
  112. package/out/_next/static/chunks/0xgg0~kmf3gd-.js +1 -0
  113. package/out/_next/static/chunks/0xj24-70ptdzp.js +1 -0
  114. package/out/_next/static/chunks/0xxlx772fr3x4.js +1 -0
  115. package/out/_next/static/chunks/0y.li-~3oybew.js +1 -0
  116. package/out/_next/static/chunks/0yl2t7cs-n_ng.js +1 -0
  117. package/out/_next/static/chunks/0yq3kh.hchtm_.js +1 -0
  118. package/out/_next/static/chunks/0ys0l5au.9c2c.js +1 -0
  119. package/out/_next/static/chunks/0z48pmi6buytt.js +1 -0
  120. package/out/_next/static/chunks/0zapnvgy89mg..js +1 -0
  121. package/out/_next/static/chunks/0~.-vxi5oc.r0.js +1 -0
  122. package/out/_next/static/chunks/0~3ik-hfp9s-7.js +1 -0
  123. package/out/_next/static/chunks/0~4f5p6tvn1lq.js +1 -0
  124. package/out/_next/static/chunks/0~_0ys.2whxbw.js +1 -0
  125. package/out/_next/static/chunks/0~_ui9l7.2sxf.js +1 -0
  126. package/out/_next/static/chunks/1037jlyw5~7ht.js +1 -0
  127. package/out/_next/static/chunks/1045hfzu533z0.js +1 -0
  128. package/out/_next/static/chunks/104e5nmc.c-pl.js +1 -0
  129. package/out/_next/static/chunks/109taw1pbh-0b.js +1 -0
  130. package/out/_next/static/chunks/10x7~onqwp338.js +1 -0
  131. package/out/_next/static/chunks/10ynz1dy483wf.js +1 -0
  132. package/out/_next/static/chunks/11hds.mg~4_r-.js +1 -0
  133. package/out/_next/static/chunks/11ibzaklcauw~.js +1 -0
  134. package/out/_next/static/chunks/11z.0s6.42b.p.js +1 -0
  135. package/out/_next/static/chunks/12-9n56l0y3yr.js +1 -0
  136. package/out/_next/static/chunks/126enaq~f7scl.js +1 -0
  137. package/out/_next/static/chunks/12nr19.nnn6s3.js +5 -0
  138. package/out/_next/static/chunks/{0qub_r0x_r-e9.css → 12pep-2t-qg4n.css} +1 -1
  139. package/out/_next/static/chunks/1380op_pfk.qo.js +1 -0
  140. package/out/_next/static/chunks/146oiw1bggtn4.js +1 -0
  141. package/out/_next/static/chunks/14_inksek_rth.js +2 -0
  142. package/out/_next/static/chunks/14_po2rb_arn4.js +1 -0
  143. package/out/_next/static/chunks/14a4fwbiq.l3z.js +1 -0
  144. package/out/_next/static/chunks/14cowsqn95m1k.js +1 -0
  145. package/out/_next/static/chunks/14dtd3l03v.kx.js +1 -0
  146. package/out/_next/static/chunks/14tm3qa-v9o-4.js +1 -0
  147. package/out/_next/static/chunks/15-o4kb-evqd7.js +1 -0
  148. package/out/_next/static/chunks/153-sz7s.qml2.js +1 -0
  149. package/out/_next/static/chunks/157z7bowux3xj.js +1 -0
  150. package/out/_next/static/chunks/15m1_677az2cm.js +1 -0
  151. package/out/_next/static/chunks/15v.~.ne6ogkk.js +1 -0
  152. package/out/_next/static/chunks/16i.qbk8t8gf_.js +1 -0
  153. package/out/_next/static/chunks/16u9f35gylw8l.js +1 -0
  154. package/out/_next/static/chunks/16xls5tt_68lx.js +1 -0
  155. package/out/_next/static/chunks/17ajyb5ogk5yj.js +1 -0
  156. package/out/_next/static/chunks/17dyfxbq8yz8n.js +1 -0
  157. package/out/_next/static/chunks/180zln9pcq9ih.js +1 -0
  158. package/out/_next/static/chunks/1814izi5gh.kp.js +1 -0
  159. package/out/_next/static/chunks/turbopack-0xta0kqwzkf28.js +1 -0
  160. package/out/_next/static/media/KaTeX_AMS-Regular.0b~8ki5y928w2.woff +0 -0
  161. package/out/_next/static/media/KaTeX_AMS-Regular.0p1vbqd84i2~o.woff2 +0 -0
  162. package/out/_next/static/media/KaTeX_AMS-Regular.173t6ktr7uf-w.ttf +0 -0
  163. package/out/_next/static/media/KaTeX_Caligraphic-Bold.01-pzluls4zgb.woff2 +0 -0
  164. package/out/_next/static/media/KaTeX_Caligraphic-Bold.0x2v1lwn~880f.woff +0 -0
  165. package/out/_next/static/media/KaTeX_Caligraphic-Bold.16zv5fax0h0ka.ttf +0 -0
  166. package/out/_next/static/media/KaTeX_Caligraphic-Regular.02i3z7wig438t.ttf +0 -0
  167. package/out/_next/static/media/KaTeX_Caligraphic-Regular.0rysu1t-ncjq8.woff2 +0 -0
  168. package/out/_next/static/media/KaTeX_Caligraphic-Regular.10927swgekwun.woff +0 -0
  169. package/out/_next/static/media/KaTeX_Fraktur-Bold.0e-16u10iuyyf.woff +0 -0
  170. package/out/_next/static/media/KaTeX_Fraktur-Bold.0et27v~3~4uhe.ttf +0 -0
  171. package/out/_next/static/media/KaTeX_Fraktur-Bold.0w23i72~hprpq.woff2 +0 -0
  172. package/out/_next/static/media/KaTeX_Fraktur-Regular.0b.riegzdfue2.woff +0 -0
  173. package/out/_next/static/media/KaTeX_Fraktur-Regular.0rekyoa-52fj_.woff2 +0 -0
  174. package/out/_next/static/media/KaTeX_Fraktur-Regular.0vjwa15znhk~4.ttf +0 -0
  175. package/out/_next/static/media/KaTeX_Main-Bold.09i7~607shf-h.ttf +0 -0
  176. package/out/_next/static/media/KaTeX_Main-Bold.09lmynrorhcbw.woff +0 -0
  177. package/out/_next/static/media/KaTeX_Main-Bold.16pfc63_du6mx.woff2 +0 -0
  178. package/out/_next/static/media/KaTeX_Main-BoldItalic.0cp37g7x1q8h6.woff +0 -0
  179. package/out/_next/static/media/KaTeX_Main-BoldItalic.0d54rk08rx11s.woff2 +0 -0
  180. package/out/_next/static/media/KaTeX_Main-BoldItalic.15j6k~hix2t_0.ttf +0 -0
  181. package/out/_next/static/media/KaTeX_Main-Italic.0382gqciexmbu.woff +0 -0
  182. package/out/_next/static/media/KaTeX_Main-Italic.06o5nq0_91v60.woff2 +0 -0
  183. package/out/_next/static/media/KaTeX_Main-Italic.0su4i6mm18-wo.ttf +0 -0
  184. package/out/_next/static/media/KaTeX_Main-Regular.08zh8z.7shijf.ttf +0 -0
  185. package/out/_next/static/media/KaTeX_Main-Regular.0diheg01zyoph.woff +0 -0
  186. package/out/_next/static/media/KaTeX_Main-Regular.0kaf-ag2_wkm-.woff2 +0 -0
  187. package/out/_next/static/media/KaTeX_Math-BoldItalic.0ajzxypnbx1h1.ttf +0 -0
  188. package/out/_next/static/media/KaTeX_Math-BoldItalic.0ck1myuerwyqw.woff +0 -0
  189. package/out/_next/static/media/KaTeX_Math-BoldItalic.0ja97dn.cpc87.woff2 +0 -0
  190. package/out/_next/static/media/KaTeX_Math-Italic.09xkhecjcn5r9.woff +0 -0
  191. package/out/_next/static/media/KaTeX_Math-Italic.0x23a-bmp-5tg.ttf +0 -0
  192. package/out/_next/static/media/KaTeX_Math-Italic.0zrha2c4sl2je.woff2 +0 -0
  193. package/out/_next/static/media/KaTeX_SansSerif-Bold.05a9.pc1j_zx9.woff2 +0 -0
  194. package/out/_next/static/media/KaTeX_SansSerif-Bold.0jcl-ayi1uun0.woff +0 -0
  195. package/out/_next/static/media/KaTeX_SansSerif-Bold.0re8y.dm7.mt5.ttf +0 -0
  196. package/out/_next/static/media/KaTeX_SansSerif-Italic.0a0234dc3s62j.woff2 +0 -0
  197. package/out/_next/static/media/KaTeX_SansSerif-Italic.0judofdln9731.woff +0 -0
  198. package/out/_next/static/media/KaTeX_SansSerif-Italic.10z1iap9pfus8.ttf +0 -0
  199. package/out/_next/static/media/KaTeX_SansSerif-Regular.0h9yjlugq4q_e.woff +0 -0
  200. package/out/_next/static/media/KaTeX_SansSerif-Regular.0v6gcj32-czft.woff2 +0 -0
  201. package/out/_next/static/media/KaTeX_SansSerif-Regular.0zm18kga42ebc.ttf +0 -0
  202. package/out/_next/static/media/KaTeX_Script-Regular.0c4.h-mer83d_.woff2 +0 -0
  203. package/out/_next/static/media/KaTeX_Script-Regular.0q14y6zkzlpob.ttf +0 -0
  204. package/out/_next/static/media/KaTeX_Script-Regular.0ze6v4r_-99oy.woff +0 -0
  205. package/out/_next/static/media/KaTeX_Size1-Regular.013x6a4ierotp.woff2 +0 -0
  206. package/out/_next/static/media/KaTeX_Size1-Regular.0kidw0oi.m68o.woff +0 -0
  207. package/out/_next/static/media/KaTeX_Size1-Regular.0m6y-i6wfokni.ttf +0 -0
  208. package/out/_next/static/media/KaTeX_Size2-Regular.0blpmluwilgbg.woff +0 -0
  209. package/out/_next/static/media/KaTeX_Size2-Regular.0d5inmyp-tyv3.woff2 +0 -0
  210. package/out/_next/static/media/KaTeX_Size2-Regular.0wnhnvj-.k9d5.ttf +0 -0
  211. package/out/_next/static/media/KaTeX_Size3-Regular.01h0xm_sfctj3.woff +0 -0
  212. package/out/_next/static/media/KaTeX_Size3-Regular.0iukctyhw5j56.woff2 +0 -0
  213. package/out/_next/static/media/KaTeX_Size3-Regular.0jl8mqyf4gzpn.ttf +0 -0
  214. package/out/_next/static/media/KaTeX_Size4-Regular.0w3.rb_c4stzk.woff2 +0 -0
  215. package/out/_next/static/media/KaTeX_Size4-Regular.0wr_9l81-mu06.ttf +0 -0
  216. package/out/_next/static/media/KaTeX_Size4-Regular.12tvaesf3.zl3.woff +0 -0
  217. package/out/_next/static/media/KaTeX_Typewriter-Regular.0c4zdxz~8frhm.woff2 +0 -0
  218. package/out/_next/static/media/KaTeX_Typewriter-Regular.0cgrzn5l3kao5.woff +0 -0
  219. package/out/_next/static/media/KaTeX_Typewriter-Regular.128~qc3858otl.ttf +0 -0
  220. package/out/_not-found/__next._full.txt +21 -19
  221. package/out/_not-found/__next._head.txt +3 -3
  222. package/out/_not-found/__next._index.txt +8 -6
  223. package/out/_not-found/__next._not-found.__PAGE__.txt +4 -4
  224. package/out/_not-found/__next._not-found.txt +3 -3
  225. package/out/_not-found/__next._tree.txt +3 -2
  226. package/out/_not-found/index.html +2 -2
  227. package/out/_not-found/index.txt +21 -19
  228. package/out/admin/__next._full.txt +23 -0
  229. package/out/admin/__next._head.txt +5 -0
  230. package/out/admin/__next._index.txt +9 -0
  231. package/out/admin/__next._tree.txt +5 -0
  232. package/out/admin/__next.admin.__PAGE__.txt +9 -0
  233. package/out/admin/__next.admin.txt +5 -0
  234. package/out/admin/index.html +15 -0
  235. package/out/admin/index.txt +23 -0
  236. package/out/app/__next._full.txt +15 -13
  237. package/out/app/__next._head.txt +3 -3
  238. package/out/app/__next._index.txt +8 -6
  239. package/out/app/__next._tree.txt +4 -2
  240. package/out/app/__next.app.__PAGE__.txt +4 -4
  241. package/out/app/__next.app.txt +3 -4
  242. package/out/app/index.html +2 -2
  243. package/out/app/index.txt +15 -13
  244. package/out/chat/__next._full.txt +16 -14
  245. package/out/chat/__next._head.txt +3 -3
  246. package/out/chat/__next._index.txt +8 -6
  247. package/out/chat/__next._tree.txt +5 -3
  248. package/out/chat/__next.chat.__PAGE__.txt +4 -4
  249. package/out/chat/__next.chat.txt +4 -5
  250. package/out/chat/index.html +2 -2
  251. package/out/chat/index.txt +16 -14
  252. package/out/chat/join/__next._full.txt +25 -0
  253. package/out/chat/join/__next._head.txt +5 -0
  254. package/out/chat/join/__next._index.txt +9 -0
  255. package/out/chat/join/__next._tree.txt +5 -0
  256. package/out/chat/join/__next.chat.join.__PAGE__.txt +9 -0
  257. package/out/chat/join/__next.chat.join.txt +5 -0
  258. package/out/chat/join/__next.chat.txt +5 -0
  259. package/out/chat/join/index.html +15 -0
  260. package/out/chat/join/index.txt +25 -0
  261. package/out/download/__next._full.txt +34 -33
  262. package/out/download/__next._head.txt +3 -3
  263. package/out/download/__next._index.txt +8 -6
  264. package/out/download/__next._tree.txt +6 -4
  265. package/out/download/__next.download.__PAGE__.txt +13 -14
  266. package/out/download/__next.download.txt +3 -3
  267. package/out/download/index.html +2 -2
  268. package/out/download/index.txt +34 -33
  269. package/out/index.html +2 -2
  270. package/out/index.txt +23 -20
  271. package/out/note/__next._full.txt +24 -0
  272. package/out/{changelog → note}/__next._head.txt +3 -3
  273. package/out/note/__next._index.txt +9 -0
  274. package/out/note/__next._tree.txt +4 -0
  275. package/out/note/__next.note.__PAGE__.txt +9 -0
  276. package/out/note/__next.note.txt +5 -0
  277. package/out/note/index.html +15 -0
  278. package/out/note/index.txt +24 -0
  279. package/out/ping/__next._full.txt +23 -20
  280. package/out/ping/__next._head.txt +3 -3
  281. package/out/ping/__next._index.txt +8 -6
  282. package/out/ping/__next._tree.txt +6 -4
  283. package/out/ping/__next.ping.__PAGE__.txt +5 -5
  284. package/out/ping/__next.ping.txt +4 -4
  285. package/out/ping/index.html +2 -2
  286. package/out/ping/index.txt +23 -20
  287. package/out/web3/__next._full.txt +16 -14
  288. package/out/web3/__next._head.txt +3 -3
  289. package/out/web3/__next._index.txt +8 -6
  290. package/out/web3/__next._tree.txt +5 -3
  291. package/out/web3/__next.web3.__PAGE__.txt +4 -4
  292. package/out/web3/__next.web3.txt +4 -5
  293. package/out/web3/ed25519/__next._full.txt +14 -12
  294. package/out/web3/ed25519/__next._head.txt +3 -3
  295. package/out/web3/ed25519/__next._index.txt +8 -6
  296. package/out/web3/ed25519/__next._tree.txt +5 -3
  297. package/out/web3/ed25519/__next.web3.ed25519.__PAGE__.txt +2 -2
  298. package/out/web3/ed25519/__next.web3.ed25519.txt +3 -3
  299. package/out/web3/ed25519/__next.web3.txt +4 -5
  300. package/out/web3/ed25519/index.html +1 -1
  301. package/out/web3/ed25519/index.txt +14 -12
  302. package/out/web3/index.html +2 -2
  303. package/out/web3/index.txt +16 -14
  304. package/out/web3/tools/__next._full.txt +14 -12
  305. package/out/web3/tools/__next._head.txt +3 -3
  306. package/out/web3/tools/__next._index.txt +8 -6
  307. package/out/web3/tools/__next._tree.txt +5 -3
  308. package/out/web3/tools/__next.web3.tools.__PAGE__.txt +2 -2
  309. package/out/web3/tools/__next.web3.tools.txt +3 -3
  310. package/out/web3/tools/__next.web3.txt +4 -5
  311. package/out/web3/tools/index.html +1 -1
  312. package/out/web3/tools/index.txt +14 -12
  313. package/package.json +30 -13
  314. package/server/index.js +188 -901
  315. package/server/src/config.js +5 -1
  316. package/server/src/core/channelAttachment.js +68 -0
  317. package/server/src/core/cid.js +6 -71
  318. package/server/src/core/cidTopic.js +29 -0
  319. package/server/src/core/mostLink.js +88 -0
  320. package/server/src/http/access.js +123 -0
  321. package/server/src/http/app.js +1095 -0
  322. package/server/src/http/errors.js +35 -0
  323. package/server/src/http/nodeLogs.js +53 -0
  324. package/server/src/http/nodeStatus.js +146 -0
  325. package/server/src/http/staticFiles.js +84 -0
  326. package/server/src/http/uploads.js +114 -0
  327. package/server/src/index.js +1539 -301
  328. package/server/src/node/config.js +191 -0
  329. package/server/src/node/logs.js +94 -0
  330. package/server/src/utils/api.js +359 -8
  331. package/server/src/utils/auth.js +63 -0
  332. package/server/src/utils/dateTime.js +30 -0
  333. package/server/src/utils/downloadMessages.js +89 -0
  334. package/server/src/utils/errors.js +14 -0
  335. package/server/src/utils/mostWallet.js +185 -1
  336. package/server/src/utils/mp.js +2 -26
  337. package/server/src/utils/noteBackup.js +116 -0
  338. package/server/src/utils/noteUtils.js +128 -0
  339. package/server/src/utils/userIdentity.js +8 -61
  340. package/out/_next/static/chunks/003jnm.v5tzw5.js +0 -1
  341. package/out/_next/static/chunks/00re8v.gbcywn.js +0 -1
  342. package/out/_next/static/chunks/00s106sbq8t9v.js +0 -1
  343. package/out/_next/static/chunks/012hi627qrdnn.js +0 -1
  344. package/out/_next/static/chunks/0174xh3wfsjm1.js +0 -2
  345. package/out/_next/static/chunks/02~o2nmo5pmy1.js +0 -1
  346. package/out/_next/static/chunks/07t.dhhokszz5.css +0 -1
  347. package/out/_next/static/chunks/0_wia9ofmsi1c.css +0 -2
  348. package/out/_next/static/chunks/0ah8fihozo2_u.js +0 -5
  349. package/out/_next/static/chunks/0bzupvr5gt3k9.js +0 -31
  350. package/out/_next/static/chunks/0e_h0d3ekzks8.css +0 -1
  351. package/out/_next/static/chunks/0gdluj423gso1.js +0 -1
  352. package/out/_next/static/chunks/0gmoiq06srjay.css +0 -1
  353. package/out/_next/static/chunks/0imkasy7kb67u.js +0 -1
  354. package/out/_next/static/chunks/0jjc_b9q_ldi2.js +0 -1
  355. package/out/_next/static/chunks/0jl~j62iz2uvr.js +0 -1
  356. package/out/_next/static/chunks/0lqslm813wk_h.js +0 -1
  357. package/out/_next/static/chunks/0q782fxxd0lx~.js +0 -1
  358. package/out/_next/static/chunks/0slwj0c46k5cu.js +0 -1
  359. package/out/_next/static/chunks/0sorqk.oc6b7j.css +0 -1
  360. package/out/_next/static/chunks/0tapzqc6hgvx-.js +0 -1
  361. package/out/_next/static/chunks/0xsc7z5x8n7wg.js +0 -1
  362. package/out/_next/static/chunks/0zm~gys2jwl0g.js +0 -1
  363. package/out/_next/static/chunks/turbopack-0a_g3u0ud~jb8.js +0 -1
  364. package/out/changelog/__next._full.txt +0 -22
  365. package/out/changelog/__next._index.txt +0 -7
  366. package/out/changelog/__next._tree.txt +0 -3
  367. package/out/changelog/__next.changelog.__PAGE__.txt +0 -10
  368. package/out/changelog/__next.changelog.txt +0 -5
  369. package/out/changelog/index.html +0 -15
  370. package/out/changelog/index.txt +0 -22
  371. package/out/docs/__next._full.txt +0 -22
  372. package/out/docs/__next._head.txt +0 -5
  373. package/out/docs/__next._index.txt +0 -7
  374. package/out/docs/__next._tree.txt +0 -3
  375. package/out/docs/__next.docs.__PAGE__.txt +0 -10
  376. package/out/docs/__next.docs.txt +0 -5
  377. package/out/docs/getting-started/__next._full.txt +0 -22
  378. package/out/docs/getting-started/__next._head.txt +0 -5
  379. package/out/docs/getting-started/__next._index.txt +0 -7
  380. package/out/docs/getting-started/__next._tree.txt +0 -3
  381. package/out/docs/getting-started/__next.docs.getting-started.__PAGE__.txt +0 -10
  382. package/out/docs/getting-started/__next.docs.getting-started.txt +0 -5
  383. package/out/docs/getting-started/__next.docs.txt +0 -5
  384. package/out/docs/getting-started/index.html +0 -15
  385. package/out/docs/getting-started/index.txt +0 -22
  386. package/out/docs/index.html +0 -15
  387. package/out/docs/index.txt +0 -22
  388. /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → t7ZIeQpVvjz4a7-5Tt-VK}/_buildManifest.js +0 -0
  389. /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → t7ZIeQpVvjz4a7-5Tt-VK}/_clientMiddlewareManifest.js +0 -0
  390. /package/out/_next/static/{iOB2EBwOGZ0iYW7Lbg9u_ → t7ZIeQpVvjz4a7-5Tt-VK}/_ssgManifest.js +0 -0
@@ -0,0 +1,63 @@
1
+ import { verifyMessage } from 'ethers'
2
+ import { mostSignMessage } from './mostWallet.js'
3
+
4
+ export const AUTH_MAX_AGE_MS = 5 * 60 * 1000
5
+
6
+ export function normalizeAddress(address) {
7
+ const value = String(address || '').trim()
8
+ return /^0x[a-fA-F0-9]{40}$/.test(value) ? value.toLowerCase() : ''
9
+ }
10
+
11
+ export function buildAuthMessage(timestamp, method, path) {
12
+ return `${timestamp}:${String(method || 'GET').toUpperCase()}:${normalizeAuthPath(path)}`
13
+ }
14
+
15
+ export function normalizeAuthPath(path) {
16
+ try {
17
+ return new URL(path, 'http://most.box').pathname
18
+ } catch {
19
+ return String(path || '').split('?')[0] || '/'
20
+ }
21
+ }
22
+
23
+ export async function buildAuthHeaders(identity, method, path) {
24
+ if (!identity?.danger) return {}
25
+ const timestamp = Date.now().toString()
26
+ const message = buildAuthMessage(timestamp, method, path)
27
+ const { address, signature } = await mostSignMessage(identity.danger, message)
28
+ return {
29
+ Authorization: `${address},${timestamp},${signature}`,
30
+ }
31
+ }
32
+
33
+ export function verifyAuthHeader(header, method, path, options = {}) {
34
+ const [addressRaw, timestampRaw, signature] = String(header || '').split(',')
35
+ const address = normalizeAddress(addressRaw)
36
+ const timestamp = Number(timestampRaw)
37
+ const now = options.now || Date.now()
38
+
39
+ if (!address || !Number.isFinite(timestamp) || !signature) {
40
+ return { ok: false, error: 'Missing or invalid authorization' }
41
+ }
42
+ if (Math.abs(now - timestamp) > (options.maxAgeMs || AUTH_MAX_AGE_MS)) {
43
+ return { ok: false, error: 'Authorization expired' }
44
+ }
45
+
46
+ try {
47
+ const message = buildAuthMessage(timestampRaw, method, path)
48
+ const recovered = normalizeAddress(verifyMessage(message, signature))
49
+ if (recovered !== address) {
50
+ return { ok: false, error: 'Authorization address mismatch' }
51
+ }
52
+ return { ok: true, address }
53
+ } catch {
54
+ return { ok: false, error: 'Invalid authorization signature' }
55
+ }
56
+ }
57
+
58
+ export function parseInviteList(value = '') {
59
+ return String(value || '')
60
+ .split(',')
61
+ .map(item => item.trim())
62
+ .filter(Boolean)
63
+ }
@@ -0,0 +1,30 @@
1
+ import dayjs from 'dayjs'
2
+
3
+ export function formatDate(time) {
4
+ if (!time) return ''
5
+ const date = dayjs(Number(time))
6
+ const hour = date.hour()
7
+ let timeOfDay
8
+
9
+ if (hour >= 0 && hour < 3) {
10
+ timeOfDay = '凌晨'
11
+ } else if (hour >= 3 && hour < 6) {
12
+ timeOfDay = '拂晓'
13
+ } else if (hour >= 6 && hour < 9) {
14
+ timeOfDay = '早晨'
15
+ } else if (hour >= 9 && hour < 12) {
16
+ timeOfDay = '上午'
17
+ } else if (hour >= 12 && hour < 15) {
18
+ timeOfDay = '下午'
19
+ } else if (hour >= 15 && hour < 18) {
20
+ timeOfDay = '傍晚'
21
+ } else if (hour >= 18 && hour < 21) {
22
+ timeOfDay = '晚上'
23
+ } else {
24
+ timeOfDay = '深夜'
25
+ }
26
+
27
+ return date.format(`YYYY年M月D日 ${timeOfDay}h:m`)
28
+ }
29
+
30
+ export const formatTime = formatDate
@@ -0,0 +1,89 @@
1
+ import { parseMostLink } from '../core/mostLink.js'
2
+
3
+ const DOWNLOAD_CHECK_MESSAGES = {
4
+ timeout:
5
+ '检测等待超时,暂时没有等到在线种子响应。请确认分享者或其他下载者仍在线做种,稍后再检测。',
6
+ offline: '无法连接本地节点,请确认 MostBox 后端正在运行后再检测。',
7
+ missingApi: '当前后端还没有检测接口,请重启 MostBox 后端后再试。',
8
+ validation:
9
+ '链接格式不正确,请粘贴完整的 most://<cid>?filename=... 分享链接。',
10
+ nameConflict: '下载目录已有同名文件,请先重命名或移走后再检测。',
11
+ noPeer:
12
+ '暂时没有发现在线种子。请确认分享者或其他下载者仍在线做种,稍后再检测。',
13
+ permission: '下载目录不可写,请检查目录权限后再检测。',
14
+ starting: '本地节点还没有启动完成,请稍等几秒后重新检测。',
15
+ server: '本地节点检测时出错,请稍后重试或查看节点日志。',
16
+ fallback: '检测未通过,请确认链接完整、发布者在线且本机网络正常。',
17
+ }
18
+
19
+ const LINK_VALIDATION_MESSAGES = {
20
+ 'Link must be a valid most:// URL':
21
+ '链接无法解析,请粘贴完整的 most://<cid>?filename=... 分享链接。',
22
+ 'Link must use most:// protocol': '链接协议不正确,应以 most:// 开头。',
23
+ 'Link path is not supported':
24
+ '链接里不应包含路径,请使用 most://<cid>?filename=... 格式。',
25
+ 'Invalid CID format': 'CID 无效,请确认 most:// 后面的内容没有缺失或被截断。',
26
+ 'Invalid CID format: CID v1 required':
27
+ 'CID 格式不符合 MostBox 要求,请确认分享链接完整。',
28
+ 'CID digest must be 32 bytes':
29
+ 'CID 格式不符合 MostBox 要求,请确认分享链接完整。',
30
+ 'filename is required':
31
+ '链接缺少 filename 参数,请复制完整分享链接后再检测。',
32
+ }
33
+
34
+ export function getDownloadCheckErrorMessageFromPayload(
35
+ data = {},
36
+ errorName = ''
37
+ ) {
38
+ if (errorName === 'TimeoutError') return DOWNLOAD_CHECK_MESSAGES.timeout
39
+ if (!data.status) return DOWNLOAD_CHECK_MESSAGES.offline
40
+ if (data.status === 404) return DOWNLOAD_CHECK_MESSAGES.missingApi
41
+
42
+ switch (data.code) {
43
+ case 'VALIDATION_ERROR':
44
+ return DOWNLOAD_CHECK_MESSAGES.validation
45
+ case 'CONFLICT':
46
+ return data.error
47
+ ? `${data.error},请先处理同名文件后再下载。`
48
+ : DOWNLOAD_CHECK_MESSAGES.nameConflict
49
+ case 'PEER_NOT_FOUND':
50
+ return DOWNLOAD_CHECK_MESSAGES.noPeer
51
+ case 'PERMISSION_ERROR':
52
+ return data.error
53
+ ? `下载目录不可写:${data.error}`
54
+ : DOWNLOAD_CHECK_MESSAGES.permission
55
+ case 'ENGINE_NOT_INITIALIZED':
56
+ return DOWNLOAD_CHECK_MESSAGES.starting
57
+ default:
58
+ break
59
+ }
60
+
61
+ if (data.status === 503) return DOWNLOAD_CHECK_MESSAGES.noPeer
62
+ if (data.status >= 500) return DOWNLOAD_CHECK_MESSAGES.server
63
+ return data.error
64
+ ? `检测未通过:${data.error}`
65
+ : DOWNLOAD_CHECK_MESSAGES.fallback
66
+ }
67
+
68
+ export function getDownloadLinkValidationMessage(link = '') {
69
+ const value = String(link || '').trim()
70
+ if (!value) return '请先粘贴 most:// 分享链接。'
71
+
72
+ const result = parseMostLink(value)
73
+ if (!result.error) {
74
+ return result.fileName?.trim()
75
+ ? null
76
+ : LINK_VALIDATION_MESSAGES['filename is required']
77
+ }
78
+
79
+ if (result.error.startsWith('Unsupported query parameter: ')) {
80
+ const unsupportedParam = result.error.slice(
81
+ 'Unsupported query parameter: '.length
82
+ )
83
+ return `链接包含暂不支持的参数 ${unsupportedParam},请只保留 filename。`
84
+ }
85
+
86
+ return (
87
+ LINK_VALIDATION_MESSAGES[result.error] || DOWNLOAD_CHECK_MESSAGES.validation
88
+ )
89
+ }
@@ -58,6 +58,20 @@ export class PermissionError extends AppError {
58
58
  }
59
59
  }
60
60
 
61
+ export class ConflictError extends AppError {
62
+ constructor(message = 'Resource conflict') {
63
+ super(message, 'CONFLICT')
64
+ this.name = 'ConflictError'
65
+ }
66
+ }
67
+
68
+ export class StorageCapacityError extends AppError {
69
+ constructor(message = 'Storage capacity exceeded') {
70
+ super(message, 'STORAGE_CAPACITY_ERROR')
71
+ this.name = 'StorageCapacityError'
72
+ }
73
+ }
74
+
61
75
  export class EngineNotInitializedError extends AppError {
62
76
  constructor(message = 'Engine not initialized. Call start() first.') {
63
77
  super(message, 'ENGINE_NOT_INITIALIZED')
@@ -1,4 +1,6 @@
1
1
  import {
2
+ decodeBase64,
3
+ encodeBase64,
2
4
  pbkdf2,
3
5
  sha256,
4
6
  getBytes,
@@ -10,8 +12,15 @@ import {
10
12
  import nacl from 'tweetnacl'
11
13
 
12
14
  const SALT_PREFIX = '/most.box/'
13
- const PBKDF2_ITERATIONS = 3
15
+ const PBKDF2_ITERATIONS = 50_000
14
16
  const PBKDF2_KEY_LENGTH = 32
17
+ const BOX_TOKEN_VERSION = 1
18
+ const BOX_TIMESTAMP_BYTES = 8
19
+ const BOX_TOKEN_HEADER_BYTES =
20
+ 1 + BOX_TIMESTAMP_BYTES + nacl.secretbox.nonceLength
21
+ const BOX_TOKEN_MIN_BYTES =
22
+ BOX_TOKEN_HEADER_BYTES + nacl.secretbox.overheadLength
23
+ const BOX_LABEL = new TextEncoder().encode('MP-AE')
15
24
 
16
25
  export function mostWallet(username, password) {
17
26
  const salt = toUtf8Bytes(SALT_PREFIX + username)
@@ -40,3 +49,178 @@ export function most25519(danger) {
40
49
  ed_public_key: hexlify(ed25519KeyPair.publicKey),
41
50
  }
42
51
  }
52
+
53
+ export async function mostSignMessage(danger, message) {
54
+ const account = HDNodeWallet.fromPhrase(mostMnemonic(danger))
55
+ return {
56
+ address: account.address,
57
+ signature: await account.signMessage(message),
58
+ }
59
+ }
60
+
61
+ export function mostEncode(text, danger) {
62
+ const bytes = new TextEncoder().encode(text)
63
+ const nonce = nacl.randomBytes(nacl.secretbox.nonceLength)
64
+ const key = getBytes(danger).slice(0, nacl.secretbox.keyLength)
65
+ const encrypted = nacl.secretbox(bytes, nonce, key)
66
+
67
+ return ['mp://1', encodeBase64(nonce), encodeBase64(encrypted)].join('.')
68
+ }
69
+
70
+ export function mostDecode(data, danger) {
71
+ const [prefix, nonce64, encrypted64] = String(data || '').split('.')
72
+ if (prefix !== 'mp://1' || !nonce64 || !encrypted64) return ''
73
+
74
+ const key = getBytes(danger).slice(0, nacl.secretbox.keyLength)
75
+ const decrypted = nacl.secretbox.open(
76
+ decodeBase64(encrypted64),
77
+ decodeBase64(nonce64),
78
+ key
79
+ )
80
+
81
+ return decrypted ? new TextDecoder().decode(decrypted) : ''
82
+ }
83
+
84
+ function concatBytes(parts) {
85
+ const total = parts.reduce((sum, part) => sum + part.length, 0)
86
+ const output = new Uint8Array(total)
87
+ let offset = 0
88
+ for (const part of parts) {
89
+ output.set(part, offset)
90
+ offset += part.length
91
+ }
92
+ return output
93
+ }
94
+
95
+ function encodeBase64Url(bytes) {
96
+ return encodeBase64(bytes)
97
+ .replaceAll('+', '-')
98
+ .replaceAll('/', '_')
99
+ .replaceAll('=', '')
100
+ }
101
+
102
+ function decodeBase64Url(value) {
103
+ const token = String(value || '').trim()
104
+ if (!token || !/^[A-Za-z0-9_-]+$/.test(token)) return null
105
+
106
+ try {
107
+ const standard = token
108
+ .replaceAll('-', '+')
109
+ .replaceAll('_', '/')
110
+ .padEnd(Math.ceil(token.length / 4) * 4, '=')
111
+ return decodeBase64(standard)
112
+ } catch {
113
+ return null
114
+ }
115
+ }
116
+
117
+ function encodeTimestampMs(value) {
118
+ const output = new Uint8Array(BOX_TIMESTAMP_BYTES)
119
+ const view = new DataView(output.buffer)
120
+ view.setBigUint64(0, BigInt(value), false)
121
+ return output
122
+ }
123
+
124
+ function decodeTimestampMs(bytes) {
125
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
126
+ return Number(view.getBigUint64(0, false))
127
+ }
128
+
129
+ function readBoxTokenPayload(data) {
130
+ const payload = decodeBase64Url(data)
131
+ if (
132
+ !payload ||
133
+ payload.length < BOX_TOKEN_MIN_BYTES ||
134
+ payload[0] !== BOX_TOKEN_VERSION
135
+ ) {
136
+ return null
137
+ }
138
+
139
+ const timestampBytes = payload.slice(1, 1 + BOX_TIMESTAMP_BYTES)
140
+ const nonce = payload.slice(1 + BOX_TIMESTAMP_BYTES, BOX_TOKEN_HEADER_BYTES)
141
+ const encrypted = payload.slice(BOX_TOKEN_HEADER_BYTES)
142
+
143
+ return {
144
+ version: payload[0],
145
+ timestampMs: decodeTimestampMs(timestampBytes),
146
+ nonce,
147
+ encrypted,
148
+ }
149
+ }
150
+
151
+ function deriveDirectionalBoxKey(
152
+ senderPublicKey,
153
+ recipientPublicKey,
154
+ sharedKey
155
+ ) {
156
+ return nacl
157
+ .hash(
158
+ concatBytes([BOX_LABEL, senderPublicKey, recipientPublicKey, sharedKey])
159
+ )
160
+ .slice(0, nacl.secretbox.keyLength)
161
+ }
162
+
163
+ export function mostBoxEncrypt(text, { senderPrivateKey, recipientPublicKey }) {
164
+ const senderSecretKey = getBytes(senderPrivateKey)
165
+ const senderPublicKey =
166
+ nacl.box.keyPair.fromSecretKey(senderSecretKey).publicKey
167
+ const recipientPublicKeyBytes = getBytes(recipientPublicKey)
168
+ const sharedKey = nacl.box.before(recipientPublicKeyBytes, senderSecretKey)
169
+ const boxKey = deriveDirectionalBoxKey(
170
+ senderPublicKey,
171
+ recipientPublicKeyBytes,
172
+ sharedKey
173
+ )
174
+ const nonce = nacl.randomBytes(nacl.secretbox.nonceLength)
175
+ const encrypted = nacl.secretbox(
176
+ new TextEncoder().encode(text),
177
+ nonce,
178
+ boxKey
179
+ )
180
+ const payload = concatBytes([
181
+ new Uint8Array([BOX_TOKEN_VERSION]),
182
+ encodeTimestampMs(Date.now()),
183
+ nonce,
184
+ encrypted,
185
+ ])
186
+
187
+ return encodeBase64Url(payload)
188
+ }
189
+
190
+ export function parseMostBoxToken(data) {
191
+ const payload = readBoxTokenPayload(data)
192
+ if (!payload) return null
193
+
194
+ return {
195
+ version: payload.version,
196
+ timestampMs: payload.timestampMs,
197
+ nonce: encodeBase64Url(payload.nonce),
198
+ }
199
+ }
200
+
201
+ export function mostBoxDecrypt(data, { senderPublicKey, recipientPrivateKey }) {
202
+ const payload = readBoxTokenPayload(data)
203
+ if (!payload) return ''
204
+
205
+ try {
206
+ const recipientSecretKey = getBytes(recipientPrivateKey)
207
+ const recipientPublicKey =
208
+ nacl.box.keyPair.fromSecretKey(recipientSecretKey).publicKey
209
+ const senderPublicKeyBytes = getBytes(senderPublicKey)
210
+ const sharedKey = nacl.box.before(senderPublicKeyBytes, recipientSecretKey)
211
+ const boxKey = deriveDirectionalBoxKey(
212
+ senderPublicKeyBytes,
213
+ recipientPublicKey,
214
+ sharedKey
215
+ )
216
+ const decrypted = nacl.secretbox.open(
217
+ payload.encrypted,
218
+ payload.nonce,
219
+ boxKey
220
+ )
221
+
222
+ return decrypted ? new TextDecoder().decode(decrypted) : ''
223
+ } catch {
224
+ return ''
225
+ }
226
+ }
@@ -1,7 +1,7 @@
1
1
  import { getBytes } from 'ethers'
2
- import dayjs from 'dayjs'
3
2
  import nacl from 'tweetnacl'
4
3
  import { generateAvatar } from './avatar.js'
4
+ import { formatTime } from './dateTime.js'
5
5
 
6
6
  const BASE36_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz'
7
7
 
@@ -77,29 +77,5 @@ export const getIPNS = (private_key, ed_public_key) => {
77
77
  return 'k' + baseXEncode(cidBytes, BASE36_ALPHABET)
78
78
  }
79
79
 
80
- export const formatTime = time => {
81
- if (!time) return ''
82
- const date = dayjs(Number(time))
83
- const hour = date.hour()
84
- let timeOfDay
85
- if (hour >= 0 && hour < 3) {
86
- timeOfDay = '凌晨'
87
- } else if (hour >= 3 && hour < 6) {
88
- timeOfDay = '拂晓'
89
- } else if (hour >= 6 && hour < 9) {
90
- timeOfDay = '早晨'
91
- } else if (hour >= 9 && hour < 12) {
92
- timeOfDay = '上午'
93
- } else if (hour >= 12 && hour < 15) {
94
- timeOfDay = '下午'
95
- } else if (hour >= 15 && hour < 18) {
96
- timeOfDay = '傍晚'
97
- } else if (hour >= 18 && hour < 21) {
98
- timeOfDay = '薄暮'
99
- } else {
100
- timeOfDay = '深夜'
101
- }
102
- return date.format(`YYYY年M月D日 ${timeOfDay}h点`)
103
- }
104
-
105
80
  export const avatar = generateAvatar
81
+ export { formatTime }
@@ -0,0 +1,116 @@
1
+ import { mostDecode, mostEncode, mostSignMessage } from './mostWallet.js'
2
+ import { calculateNoteCid } from './noteUtils.js'
3
+
4
+ export const NOTE_BACKUP_API_URL = 'https://api.most.box/auth/backup'
5
+
6
+ async function readBackupApiError(response, fallback) {
7
+ const data = await response
8
+ .clone()
9
+ .json()
10
+ .catch(() => null)
11
+ return data?.error || fallback
12
+ }
13
+
14
+ export function encryptNotesBackup(notes, danger) {
15
+ return mostEncode(JSON.stringify({ notes: notes || [] }), danger)
16
+ }
17
+
18
+ export function decryptNotesBackup(content, danger) {
19
+ if (!String(content || '').startsWith('mp://1')) {
20
+ throw new Error('无效的备份数据格式')
21
+ }
22
+
23
+ const decrypted = mostDecode(content, danger)
24
+ if (!decrypted) {
25
+ throw new Error('解密失败,请确认当前 Web3 登录账号正确')
26
+ }
27
+
28
+ const data = JSON.parse(decrypted)
29
+ if (!Array.isArray(data.notes)) {
30
+ throw new Error('备份数据缺少 notes')
31
+ }
32
+ return data
33
+ }
34
+
35
+ export async function calculateNotesBackupCid(notes) {
36
+ return calculateNoteCid(JSON.stringify({ notes: notes || [] }))
37
+ }
38
+
39
+ export async function getBackupAuthHeaders(
40
+ wallet,
41
+ method,
42
+ url = NOTE_BACKUP_API_URL
43
+ ) {
44
+ const timestamp = Date.now().toString()
45
+ const path = new URL(url).pathname
46
+ const message = `${timestamp}:${String(method).toUpperCase()}:${path}`
47
+ const { address, signature } = await mostSignMessage(wallet.danger, message)
48
+ return {
49
+ Authorization: `${address},${timestamp},${signature}`,
50
+ }
51
+ }
52
+
53
+ export async function buildNotesBackupUpload(wallet, notes) {
54
+ const payload = JSON.stringify({ notes: notes || [] })
55
+ const cid = await calculateNoteCid(payload)
56
+ const encrypted = encryptNotesBackup(notes, wallet.danger)
57
+ return {
58
+ cid,
59
+ body: encrypted,
60
+ headers: {
61
+ 'Content-Type': 'text/plain',
62
+ 'x-backup-cid': cid,
63
+ ...(await getBackupAuthHeaders(wallet, 'PUT', NOTE_BACKUP_API_URL)),
64
+ },
65
+ }
66
+ }
67
+
68
+ export async function uploadNotesBackup(
69
+ wallet,
70
+ notes,
71
+ url = NOTE_BACKUP_API_URL
72
+ ) {
73
+ const upload = await buildNotesBackupUpload(wallet, notes)
74
+ const response = await fetch(url, {
75
+ method: 'PUT',
76
+ headers: upload.headers,
77
+ body: upload.body,
78
+ })
79
+ if (!response.ok) {
80
+ throw new Error(await readBackupApiError(response, '云备份失败'))
81
+ }
82
+ return {
83
+ cid: upload.cid,
84
+ }
85
+ }
86
+
87
+ export async function downloadNotesBackup(wallet, url = NOTE_BACKUP_API_URL) {
88
+ const response = await fetch(url, {
89
+ method: 'GET',
90
+ headers: await getBackupAuthHeaders(wallet, 'GET', url),
91
+ })
92
+ if (response.status === 404) {
93
+ return {
94
+ found: false,
95
+ cid: '',
96
+ time: 0,
97
+ notes: [],
98
+ }
99
+ }
100
+ if (!response.ok) {
101
+ throw new Error(await readBackupApiError(response, '云端恢复失败'))
102
+ }
103
+
104
+ const encrypted = await response.text()
105
+ if (!encrypted) {
106
+ throw new Error('云端无备份数据')
107
+ }
108
+
109
+ const data = decryptNotesBackup(encrypted, wallet.danger)
110
+ return {
111
+ found: true,
112
+ cid: response.headers.get('x-backup-cid') || '',
113
+ time: Number(response.headers.get('x-backup-time') || 0),
114
+ notes: data.notes,
115
+ }
116
+ }
@@ -0,0 +1,128 @@
1
+ import { CID } from 'multiformats/cid'
2
+ import * as raw from 'multiformats/codecs/raw'
3
+ import { sha256 } from 'multiformats/hashes/sha2'
4
+
5
+ export function normalizeNotePath(input = '') {
6
+ return String(input)
7
+ .replace(/\\/g, '/')
8
+ .split('/')
9
+ .map(part => part.trim())
10
+ .filter(part => part && part !== '.')
11
+ .filter(part => part !== '..')
12
+ .join('/')
13
+ }
14
+
15
+ export function getNoteFullPath(note) {
16
+ const path = normalizeNotePath(note?.path || '')
17
+ const name = String(note?.name || '').trim()
18
+ return path ? `${path}/${name}` : name
19
+ }
20
+
21
+ export function validateNoteName(name) {
22
+ const value = String(name || '').trim()
23
+ if (!value) return { valid: false, error: '请输入名称' }
24
+ if (value.includes('/')) return { valid: false, error: '名称不能包含 /' }
25
+ if (value.includes('\\')) return { valid: false, error: '名称不能包含 \\' }
26
+ return { valid: true, name: value }
27
+ }
28
+
29
+ export async function calculateNoteCid(content = '') {
30
+ const bytes = new TextEncoder().encode(String(content))
31
+ const hash = await sha256.digest(bytes)
32
+ return CID.create(1, raw.code, hash).toString()
33
+ }
34
+
35
+ export function filterNotesByPath(notes, currentPath = '', query = '') {
36
+ const normalizedCurrentPath = normalizeNotePath(currentPath)
37
+ const normalizedQuery = query.trim().toLowerCase()
38
+ const files = Array.isArray(notes) ? notes : []
39
+
40
+ if (normalizedQuery) {
41
+ return files
42
+ .filter(note =>
43
+ String(note.name || '')
44
+ .toLowerCase()
45
+ .includes(normalizedQuery)
46
+ )
47
+ .sort(sortNotesForExplorer)
48
+ }
49
+
50
+ const directItems = []
51
+ const inferredDirs = new Map()
52
+
53
+ for (const note of files) {
54
+ const notePath = normalizeNotePath(note.path || '')
55
+
56
+ if (notePath === normalizedCurrentPath) {
57
+ directItems.push(note)
58
+ continue
59
+ }
60
+
61
+ if (
62
+ normalizedCurrentPath === '' ||
63
+ notePath.startsWith(`${normalizedCurrentPath}/`)
64
+ ) {
65
+ const relativePath =
66
+ normalizedCurrentPath === ''
67
+ ? notePath
68
+ : notePath.slice(normalizedCurrentPath.length + 1)
69
+ const firstSegment = relativePath.split('/').filter(Boolean)[0]
70
+
71
+ if (firstSegment && !inferredDirs.has(firstSegment)) {
72
+ inferredDirs.set(firstSegment, {
73
+ name: firstSegment,
74
+ type: 'directory',
75
+ path: normalizedCurrentPath,
76
+ size: 0,
77
+ cid: `__dir__${normalizedCurrentPath}/${firstSegment}`,
78
+ created_at: note.created_at || Date.now(),
79
+ updated_at: note.updated_at || note.created_at || Date.now(),
80
+ })
81
+ }
82
+ }
83
+ }
84
+
85
+ return [...inferredDirs.values(), ...directItems].sort(sortNotesForExplorer)
86
+ }
87
+
88
+ export function renameNotesByPath(notes, oldFullPath, targetPath, targetName) {
89
+ const oldPath = normalizeNotePath(oldFullPath)
90
+ const newPath = normalizeNotePath(targetPath)
91
+ const cleanName = String(targetName || '').trim()
92
+ const targetFullPath = normalizeNotePath(
93
+ newPath ? `${newPath}/${cleanName}` : cleanName
94
+ )
95
+ const now = Date.now()
96
+
97
+ return notes.map(note => {
98
+ const fullPath = getNoteFullPath(note)
99
+
100
+ if (fullPath === oldPath) {
101
+ return { ...note, path: newPath, name: cleanName, updated_at: now }
102
+ }
103
+
104
+ if (fullPath.startsWith(`${oldPath}/`)) {
105
+ const relativePath = fullPath.slice(oldPath.length + 1)
106
+ const nextFullPath = normalizeNotePath(
107
+ `${targetFullPath}/${relativePath}`
108
+ )
109
+ const lastSlash = nextFullPath.lastIndexOf('/')
110
+ return {
111
+ ...note,
112
+ path: lastSlash === -1 ? '' : nextFullPath.slice(0, lastSlash),
113
+ name: nextFullPath.slice(lastSlash + 1),
114
+ updated_at: now,
115
+ }
116
+ }
117
+
118
+ return note
119
+ })
120
+ }
121
+
122
+ function sortNotesForExplorer(a, b) {
123
+ if (a.type === 'directory' && b.type !== 'directory') return -1
124
+ if (a.type !== 'directory' && b.type === 'directory') return 1
125
+ return (
126
+ (b.updated_at || b.created_at || 0) - (a.updated_at || a.created_at || 0)
127
+ )
128
+ }