most-box 0.1.4 → 0.1.6
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.
- package/README.md +22 -12
- package/electron/main.js +31 -10
- package/out/404/index.html +3 -3
- package/out/404.html +3 -3
- package/out/__next.__PAGE__.txt +6 -6
- package/out/__next._full.txt +16 -16
- package/out/__next._head.txt +3 -3
- package/out/__next._index.txt +8 -8
- package/out/__next._tree.txt +5 -5
- package/out/_next/static/chunks/{06lttvu7563zo.css → 0-ryc9icn6dql.css} +1 -1
- package/out/_next/static/chunks/088-v8tzobg5g.js +1 -0
- package/out/_next/static/chunks/0g9303i8psy6z.js +1 -0
- package/out/_next/static/chunks/0nwdp-n94owg0.css +1 -0
- package/out/_next/static/chunks/{0pt.5cg1t09qs.js → 0s7i7nfr9j3b1.js} +1 -1
- package/out/_next/static/chunks/0vmjat-s4a3yj.css +1 -0
- package/out/_next/static/chunks/10p6-qnuk3p9x.js +1 -0
- package/out/_next/static/chunks/1ei8b9nw-ea8p.css +1 -0
- package/out/_next/static/chunks/1lxjpnw925-0p.css +1 -0
- package/out/_next/static/chunks/1v-molv0hbcjl.js +1 -0
- package/out/_next/static/chunks/23kls47vn_rpg.css +23 -0
- package/out/_next/static/chunks/2524ggtr3e4fp.js +1 -0
- package/out/_next/static/chunks/2fmkcw8ui5xp3.js +5 -0
- package/out/_next/static/chunks/2mcmt4yla_xle.js +1 -0
- package/out/_next/static/chunks/2uget3ephe4e3.js +736 -0
- package/out/_next/static/chunks/2v7_4ps1l4a8o.css +1 -0
- package/out/_next/static/chunks/2va-v1iiap4zv.js +1 -0
- package/out/_next/static/chunks/2vk2ln79gpvm4.js +1 -0
- package/out/_next/static/chunks/2vm9uslik2wfi.css +5 -0
- package/out/_next/static/chunks/37msy2-4ucgts.js +1 -0
- package/out/_next/static/chunks/384w3w4qvhw61.js +1 -0
- package/out/_next/static/chunks/3aa-weedhv4e0.js +1 -0
- package/out/_next/static/chunks/3erbaukgkw8f2.js +1 -0
- package/out/_next/static/chunks/3fea100s764m-.js +1 -0
- package/out/_next/static/chunks/3g0c367tk4esf.js +1 -0
- package/out/_next/static/chunks/{0gcsdf57gcm6h.js → 3oe03qxgd_rid.js} +1 -1
- package/out/_next/static/chunks/3qj5xz_d4cbk6.js +1 -0
- package/out/_next/static/chunks/3r5wf57k0gys9.js +1 -0
- package/out/_next/static/chunks/3yc_zd5vxq0j7.css +1 -0
- package/out/_next/static/chunks/{turbopack-0xta0kqwzkf28.js → turbopack-026p0g9v9_pva.js} +1 -1
- package/out/_not-found/__next._full.txt +13 -13
- package/out/_not-found/__next._head.txt +3 -3
- package/out/_not-found/__next._index.txt +8 -8
- package/out/_not-found/__next._not-found.__PAGE__.txt +4 -4
- package/out/_not-found/__next._not-found.txt +3 -3
- package/out/_not-found/__next._tree.txt +3 -3
- package/out/_not-found/index.html +3 -3
- package/out/_not-found/index.txt +13 -13
- package/out/admin/__next._full.txt +15 -15
- package/out/admin/__next._head.txt +3 -3
- package/out/admin/__next._index.txt +8 -8
- package/out/admin/__next._tree.txt +4 -4
- package/out/admin/__next.admin.__PAGE__.txt +4 -4
- package/out/admin/__next.admin.txt +4 -4
- package/out/admin/index.html +3 -3
- package/out/admin/index.txt +15 -15
- package/out/app/__next._full.txt +14 -14
- package/out/app/__next._head.txt +3 -3
- package/out/app/__next._index.txt +8 -8
- package/out/app/__next._tree.txt +3 -3
- package/out/app/__next.app.__PAGE__.txt +4 -4
- package/out/app/__next.app.txt +3 -3
- package/out/app/index.html +3 -3
- package/out/app/index.txt +14 -14
- package/out/chat/__next._full.txt +15 -15
- package/out/chat/__next._head.txt +3 -3
- package/out/chat/__next._index.txt +8 -8
- package/out/chat/__next._tree.txt +4 -4
- package/out/chat/__next.chat.__PAGE__.txt +4 -4
- package/out/chat/__next.chat.txt +4 -4
- package/out/chat/index.html +3 -3
- package/out/chat/index.txt +15 -15
- package/out/chat/join/__next._full.txt +15 -15
- package/out/chat/join/__next._head.txt +3 -3
- package/out/chat/join/__next._index.txt +8 -8
- package/out/chat/join/__next._tree.txt +4 -4
- package/out/chat/join/__next.chat.join.__PAGE__.txt +4 -4
- package/out/chat/join/__next.chat.join.txt +3 -3
- package/out/chat/join/__next.chat.txt +4 -4
- package/out/chat/join/index.html +3 -3
- package/out/chat/join/index.txt +15 -15
- package/out/demo/__next._full.txt +27 -0
- package/out/demo/__next._head.txt +5 -0
- package/out/demo/__next._index.txt +9 -0
- package/out/demo/__next._tree.txt +7 -0
- package/out/demo/__next.demo.__PAGE__.txt +12 -0
- package/out/demo/__next.demo.txt +5 -0
- package/out/demo/index.html +17 -0
- package/out/demo/index.txt +27 -0
- package/out/download/__next._full.txt +35 -37
- package/out/download/__next._head.txt +3 -3
- package/out/download/__next._index.txt +8 -8
- package/out/download/__next._tree.txt +5 -5
- package/out/download/__next.download.__PAGE__.txt +7 -7
- package/out/download/__next.download.txt +3 -3
- package/out/download/index.html +3 -3
- package/out/download/index.txt +35 -37
- package/out/favicon.ico +0 -0
- package/out/game/__next._full.txt +13 -13
- package/out/game/__next._head.txt +3 -3
- package/out/game/__next._index.txt +8 -8
- package/out/game/__next._tree.txt +4 -4
- package/out/game/__next.game.__PAGE__.txt +2 -2
- package/out/game/__next.game.txt +4 -4
- package/out/game/gandengyan/__next._full.txt +16 -16
- package/out/game/gandengyan/__next._head.txt +3 -3
- package/out/game/gandengyan/__next._index.txt +8 -8
- package/out/game/gandengyan/__next._tree.txt +5 -5
- package/out/game/gandengyan/__next.game.gandengyan.__PAGE__.txt +5 -5
- package/out/game/gandengyan/__next.game.gandengyan.txt +3 -3
- package/out/game/gandengyan/__next.game.txt +4 -4
- package/out/game/gandengyan/index.html +3 -3
- package/out/game/gandengyan/index.txt +16 -16
- package/out/game/index.html +1 -1
- package/out/game/index.txt +13 -13
- package/out/game/zhajinhua/__next._full.txt +15 -15
- package/out/game/zhajinhua/__next._head.txt +3 -3
- package/out/game/zhajinhua/__next._index.txt +8 -8
- package/out/game/zhajinhua/__next._tree.txt +4 -4
- package/out/game/zhajinhua/__next.game.txt +4 -4
- package/out/game/zhajinhua/__next.game.zhajinhua.__PAGE__.txt +4 -4
- package/out/game/zhajinhua/__next.game.zhajinhua.txt +3 -3
- package/out/game/zhajinhua/index.html +3 -3
- package/out/game/zhajinhua/index.txt +15 -15
- package/out/index.html +3 -3
- package/out/index.txt +16 -16
- package/out/logo-512.png +0 -0
- package/out/logo.ico +0 -0
- package/out/logo.svg +12 -0
- package/out/note/__next._full.txt +14 -14
- package/out/note/__next._head.txt +3 -3
- package/out/note/__next._index.txt +8 -8
- package/out/note/__next._tree.txt +3 -3
- package/out/note/__next.note.__PAGE__.txt +4 -4
- package/out/note/__next.note.txt +3 -3
- package/out/note/index.html +3 -3
- package/out/note/index.txt +14 -14
- package/out/ping/__next._full.txt +16 -16
- package/out/ping/__next._head.txt +3 -3
- package/out/ping/__next._index.txt +8 -8
- package/out/ping/__next._tree.txt +5 -5
- package/out/ping/__next.ping.__PAGE__.txt +5 -5
- package/out/ping/__next.ping.txt +4 -4
- package/out/ping/index.html +3 -3
- package/out/ping/index.txt +16 -16
- package/out/web3/__next._full.txt +15 -15
- package/out/web3/__next._head.txt +3 -3
- package/out/web3/__next._index.txt +8 -8
- package/out/web3/__next._tree.txt +4 -4
- package/out/web3/__next.web3.__PAGE__.txt +4 -4
- package/out/web3/__next.web3.txt +4 -4
- package/out/web3/ed25519/__next._full.txt +13 -13
- package/out/web3/ed25519/__next._head.txt +3 -3
- package/out/web3/ed25519/__next._index.txt +8 -8
- package/out/web3/ed25519/__next._tree.txt +4 -4
- package/out/web3/ed25519/__next.web3.ed25519.__PAGE__.txt +2 -2
- package/out/web3/ed25519/__next.web3.ed25519.txt +3 -3
- package/out/web3/ed25519/__next.web3.txt +4 -4
- package/out/web3/ed25519/index.html +1 -1
- package/out/web3/ed25519/index.txt +13 -13
- package/out/web3/index.html +3 -3
- package/out/web3/index.txt +15 -15
- package/out/web3/tools/__next._full.txt +13 -13
- package/out/web3/tools/__next._head.txt +3 -3
- package/out/web3/tools/__next._index.txt +8 -8
- package/out/web3/tools/__next._tree.txt +4 -4
- package/out/web3/tools/__next.web3.tools.__PAGE__.txt +2 -2
- package/out/web3/tools/__next.web3.tools.txt +3 -3
- package/out/web3/tools/__next.web3.txt +4 -4
- package/out/web3/tools/index.html +1 -1
- package/out/web3/tools/index.txt +13 -13
- package/package.json +27 -27
- package/public/favicon.ico +0 -0
- package/public/logo-512.png +0 -0
- package/public/logo.ico +0 -0
- package/public/logo.svg +12 -0
- package/server/src/core/mostLink.js +1 -1
- package/server/src/games/gandengyan.js +49 -19
- package/server/src/http/app.js +40 -15
- package/server/src/http/nodeStatus.js +37 -0
- package/server/src/http/uploads.js +1 -0
- package/server/src/index.js +417 -112
- package/server/src/utils/avatar.js +3 -2
- package/out/_next/static/chunks/03gsbg0fr00ey.js +0 -1
- package/out/_next/static/chunks/0adx~d-j05c9d.css +0 -24
- package/out/_next/static/chunks/0ao1lbi4b.sfa.js +0 -1
- package/out/_next/static/chunks/0fo9-h4knidcz.js +0 -1
- package/out/_next/static/chunks/0g_a~e050bgzg.css +0 -1
- package/out/_next/static/chunks/0h4r.qtmpa6eh.js +0 -1
- package/out/_next/static/chunks/0hpev4am9jpmu.css +0 -1
- package/out/_next/static/chunks/0hyds~bp.auvh.js +0 -1
- package/out/_next/static/chunks/0i9sfdypwuw8~.js +0 -1
- package/out/_next/static/chunks/0o9ce4cyf76by.js +0 -736
- package/out/_next/static/chunks/0olqjomda37-e.js +0 -1
- package/out/_next/static/chunks/0puk.7e.tr2zy.js +0 -1
- package/out/_next/static/chunks/0qgx9t4jx16ua.css +0 -1
- package/out/_next/static/chunks/0s1k6rlwy02c2.js +0 -1
- package/out/_next/static/chunks/0sgltmtk_9s8p.css +0 -1
- package/out/_next/static/chunks/0snehvtvu1n4q.js +0 -1
- package/out/_next/static/chunks/0s~g.l~x049o2.js +0 -1
- package/out/_next/static/chunks/0t_3xxx4zkerp.js +0 -5
- package/out/_next/static/chunks/0u38kke9vhobe.js +0 -1
- package/out/_next/static/chunks/0vd4_a5x-wpdh.js +0 -1
- package/out/_next/static/chunks/0xdwau5k2augv.css +0 -4
- package/out/_next/static/chunks/0xx_10jns1.s7.css +0 -1
- package/out/_next/static/chunks/10f-t2n4y1zx8.js +0 -1
- package/out/_next/static/chunks/13jdyag9a-~kk.js +0 -1
- package/out/_next/static/chunks/153-sz7s.qml2.js +0 -1
- package/out/_next/static/chunks/17cwkb2yn_akx.js +0 -1
- /package/out/_next/static/{sSvbBrwXZY-4lBmcHshga → NPIlpdzQWkiVZpgfhlypH}/_buildManifest.js +0 -0
- /package/out/_next/static/{sSvbBrwXZY-4lBmcHshga → NPIlpdzQWkiVZpgfhlypH}/_clientMiddlewareManifest.js +0 -0
- /package/out/_next/static/{sSvbBrwXZY-4lBmcHshga → NPIlpdzQWkiVZpgfhlypH}/_ssgManifest.js +0 -0
- /package/out/_next/static/chunks/{0bld2u_ld~va2.js → 0-jy8rfo075fy.js} +0 -0
- /package/out/_next/static/chunks/{0bliugh5lxw55.js → 0-kczrcxjk7lc.js} +0 -0
- /package/out/_next/static/chunks/{00d9h1tddnnnd.js → 012yllpioyi-k.js} +0 -0
- /package/out/_next/static/chunks/{00tkdqwxch-3s.js → 02f7w-ybfnvpd.js} +0 -0
- /package/out/_next/static/chunks/{01l3o90g~1z42.js → 04_v8i3c2y4ni.js} +0 -0
- /package/out/_next/static/chunks/{01xlw8hd842-c.js → 05-c3ty_6dwfk.js} +0 -0
- /package/out/_next/static/chunks/{01mfky9camw6i.js → 052vp9tk7oqx6.js} +0 -0
- /package/out/_next/static/chunks/{01r.v-pqs1vrm.js → 05k6874y7n0cw.js} +0 -0
- /package/out/_next/static/chunks/{02zzxfop_k6tl.css → 09g8c9-u_uh1z.css} +0 -0
- /package/out/_next/static/chunks/{03edqrb4zdj~g.js → 0az8vxg2gfuhm.js} +0 -0
- /package/out/_next/static/chunks/{03h_6oo-gqkhz.js → 0b899y85ei3i_.js} +0 -0
- /package/out/_next/static/chunks/{03~yq9q893hmn.js → 0cz1d0mv5g_q7.js} +0 -0
- /package/out/_next/static/chunks/{04hcgsanv1hhu.js → 0eg1osglq6nq7.js} +0 -0
- /package/out/_next/static/chunks/{05g2q0w5b34.g.js → 0hlvocunlbrjs.js} +0 -0
- /package/out/_next/static/chunks/{05of77xycbt8~.js → 0i9k23rx749fx.js} +0 -0
- /package/out/_next/static/chunks/{05zwemzfjx3sh.js → 0j6wiyqf1637r.js} +0 -0
- /package/out/_next/static/chunks/{06dpc5df94.v1.js → 0knzyzd1jvley.js} +0 -0
- /package/out/_next/static/chunks/{06e1~1-z_ic9a.js → 0kp8ujaqwut11.js} +0 -0
- /package/out/_next/static/chunks/{075s7sn.ns~u5.js → 0n92y9hb-ta0u.js} +0 -0
- /package/out/_next/static/chunks/{07dynrbvd3.f4.js → 0nybb-z3ufrbx.js} +0 -0
- /package/out/_next/static/chunks/{07r9nn-pzlgg1.js → 0o-o9af-grvj8.js} +0 -0
- /package/out/_next/static/chunks/{07p~uva5pwgwe.js → 0oxr0r0aewn99.js} +0 -0
- /package/out/_next/static/chunks/{08576xhv~~jck.js → 0qh3b90ouc9bd.js} +0 -0
- /package/out/_next/static/chunks/{08u211~k~qu52.js → 0sh_jm8siqvek.js} +0 -0
- /package/out/_next/static/chunks/{08.72abkgwy9g.js → 0t86ducxkqweb.js} +0 -0
- /package/out/_next/static/chunks/{098.p.2-zm4p7.js → 0u0j5i6-n4oqd.js} +0 -0
- /package/out/_next/static/chunks/{09ngvtajm7e5y.js → 0v73vfxjds7sj.js} +0 -0
- /package/out/_next/static/chunks/{09ps~-43n5qyo.js → 0ve8ixremhwy0.js} +0 -0
- /package/out/_next/static/chunks/{09v7_0gclxr46.js → 0vv5cwj6kr506.js} +0 -0
- /package/out/_next/static/chunks/{09yql86dir9c4.js → 0w3wf8o-ewec9.js} +0 -0
- /package/out/_next/static/chunks/{09zmlfljowj1~.js → 0w6o4o76scrb2.js} +0 -0
- /package/out/_next/static/chunks/{0n4t80gjc3q5h.js → 1-88dio6azz54.js} +0 -0
- /package/out/_next/static/chunks/{0cn9a7aimbdzq.js → 12zg24u7mbv4z.js} +0 -0
- /package/out/_next/static/chunks/{0d3f-nk3c.2re.js → 14lsse587-ccf.js} +0 -0
- /package/out/_next/static/chunks/{0dtohpf7~3d12.js → 16qtikqm_sate.js} +0 -0
- /package/out/_next/static/chunks/{0e531nije_ln2.js → 17_ly1mk2z3q8.js} +0 -0
- /package/out/_next/static/chunks/{0e5zvj_rh0z3m.js → 181421-y2xzj7.js} +0 -0
- /package/out/_next/static/chunks/{0myp4sjagr~h0.js → 1_e-vuvfsntao.js} +0 -0
- /package/out/_next/static/chunks/{0e-3e8h7g99yf.js → 1aljc62wfhqhr.js} +0 -0
- /package/out/_next/static/chunks/{0f4y~rkk-n81e.js → 1b7mbzsylsn-m.js} +0 -0
- /package/out/_next/static/chunks/{0fk~0~p7ivfn1.js → 1cjakikh0o1tm.js} +0 -0
- /package/out/_next/static/chunks/{0fw6juc~lsj3z.js → 1dfzez629llzh.js} +0 -0
- /package/out/_next/static/chunks/{0g0u7785a73vo.js → 1e4ilit3ave6c.js} +0 -0
- /package/out/_next/static/chunks/{0gze5uso1mbe9.js → 1gzgcv355ziff.js} +0 -0
- /package/out/_next/static/chunks/{0g_fpgh7drfda.js → 1h0o6fj73le9_.js} +0 -0
- /package/out/_next/static/chunks/{0hf.aosc-7172.js → 1in766ibz5l-p.js} +0 -0
- /package/out/_next/static/chunks/{0hgz35c1ejbs9.js → 1ip_c70si4tj2.js} +0 -0
- /package/out/_next/static/chunks/{0hrw-r.xmvmsq.js → 1jlu197-yog_n.js} +0 -0
- /package/out/_next/static/chunks/{0hzg4al.v~8~m.js → 1k788fny29y_j.js} +0 -0
- /package/out/_next/static/chunks/{0ip9xrols_83o.js → 1mnhfyfn52md5.js} +0 -0
- /package/out/_next/static/chunks/{0j4-d0qf.v~kn.js → 1o8brm8yipzn4.js} +0 -0
- /package/out/_next/static/chunks/{0jhdeq.j9_02m.js → 1p8oa39bqu6ed.js} +0 -0
- /package/out/_next/static/chunks/{0jy63h3i-y69i.js → 1qmnmb_dutuw8.js} +0 -0
- /package/out/_next/static/chunks/{0kdnx_u-60k9s.js → 1s6rdcw0q185p.js} +0 -0
- /package/out/_next/static/chunks/{0kq~edq42o1-c.js → 1ta0w8zc7tae7.js} +0 -0
- /package/out/_next/static/chunks/{0l682p362d-5w.js → 1uvi_hie0s3z5.js} +0 -0
- /package/out/_next/static/chunks/{0m68p9txef5rs.js → 1y36s6sv2z7r4.js} +0 -0
- /package/out/_next/static/chunks/{0mme-fm5d2oz2.js → 1zf4i-oj7n-ll.js} +0 -0
- /package/out/_next/static/chunks/{0y.li-~3oybew.js → 2-vtwv8h_uokj.js} +0 -0
- /package/out/_next/static/chunks/{0n.qlfk~z7o.6.js → 2227enga_0c-6.js} +0 -0
- /package/out/_next/static/chunks/{0oz3yl6_-716p.js → 24zr4q96g-eii.js} +0 -0
- /package/out/_next/static/chunks/{0pqt~8bl3ukh4.js → 27jktro2p5rq9.js} +0 -0
- /package/out/_next/static/chunks/{0yl2t7cs-n_ng.js → 2_cqphhur0a6t.js} +0 -0
- /package/out/_next/static/chunks/{0yq3kh.hchtm_.js → 2_s88st3j0tql.js} +0 -0
- /package/out/_next/static/chunks/{0ys0l5au.9c2c.js → 2_y6edbaubqrt.js} +0 -0
- /package/out/_next/static/chunks/{0qqupeexg83u7.js → 2at8y3pbt5cue.js} +0 -0
- /package/out/_next/static/chunks/{0rb-ri481.kc9.js → 2cv1zex4has67.js} +0 -0
- /package/out/_next/static/chunks/{0rsnmahfd.59p.js → 2e6j5h4ftd4jd.js} +0 -0
- /package/out/_next/static/chunks/{0rt6rgnvr-s_p.js → 2e8b26r0td7ou.js} +0 -0
- /package/out/_next/static/chunks/{0runh28p_gg6..js → 2ecppdrjm9cs4.js} +0 -0
- /package/out/_next/static/chunks/{0shy.t1fwqcev.js → 2gl0wusc9zf3d.js} +0 -0
- /package/out/_next/static/chunks/{0t2xr05rlu96l.js → 2im7c515bo69p.js} +0 -0
- /package/out/_next/static/chunks/{0t6h56rhg1y5i.js → 2ixaku9ie8hym.js} +0 -0
- /package/out/_next/static/chunks/{0tdqd1zunusgk.js → 2jhnrjgj_k2-z.js} +0 -0
- /package/out/_next/static/chunks/{0ujbnp38x63ek.js → 2n6pb94vmohgf.js} +0 -0
- /package/out/_next/static/chunks/{0ukyg~tkm~h2m.css → 2nbju8t9-ux58.css} +0 -0
- /package/out/_next/static/chunks/{0v68pdrp54lb-.js → 2pdxw43rsbho0.js} +0 -0
- /package/out/_next/static/chunks/{0vsm0m5sxrb.3.js → 2r6z3vlfw0ppd.js} +0 -0
- /package/out/_next/static/chunks/{0vzlz.iboqo3c.js → 2rskzmv3skmq3.js} +0 -0
- /package/out/_next/static/chunks/{0w87vbpkf-ogd.js → 2stoe6xiau1b3.js} +0 -0
- /package/out/_next/static/chunks/{0xgg0~kmf3gd-.js → 2wqoc60afpg_5.js} +0 -0
- /package/out/_next/static/chunks/{0xj24-70ptdzp.js → 2wyvwsayrr98o.js} +0 -0
- /package/out/_next/static/chunks/{0xxlx772fr3x4.js → 2y3o2mnyfnx68.js} +0 -0
- /package/out/_next/static/chunks/{16i.qbk8t8gf_.js → 3-7y7sjol3yto.js} +0 -0
- /package/out/_next/static/chunks/{0z48pmi6buytt.js → 3089gugfv3ov9.js} +0 -0
- /package/out/_next/static/chunks/{0zapnvgy89mg..js → 30s3_0brd77ky.js} +0 -0
- /package/out/_next/static/chunks/{0_s~ebb-7b2hr.js → 35idql3ziq0wz.js} +0 -0
- /package/out/_next/static/chunks/{0_w-0-2z5oqd_.js → 35unmm4isvqg5.js} +0 -0
- /package/out/_next/static/chunks/{0-n3pg7th.zza.js → 389wmv2b6x2nn.js} +0 -0
- /package/out/_next/static/chunks/{0~4f5p6tvn1lq.js → 39-oy5n969lo6.js} +0 -0
- /package/out/_next/static/chunks/{0~3ik-hfp9s-7.js → 39yvee40syj70.js} +0 -0
- /package/out/_next/static/chunks/{0~_0ys.2whxbw.js → 3clhij8e1eul0.js} +0 -0
- /package/out/_next/static/chunks/{0~_ui9l7.2sxf.js → 3cnsdzbvm3q7p.js} +0 -0
- /package/out/_next/static/chunks/{0~.-vxi5oc.r0.js → 3cxmalqqghdac.js} +0 -0
- /package/out/_next/static/chunks/{0.4j.0k5a64vg.js → 3d9p88evh2scq.js} +0 -0
- /package/out/_next/static/chunks/{0.ozi1_x2.m.~.js → 3eyprczj7yrg6.js} +0 -0
- /package/out/_next/static/chunks/{0.t5wlt51zou5.js → 3f9v_gtppe4hs.js} +0 -0
- /package/out/_next/static/chunks/{0.w4hkvap~bva.js → 3fj0amtzqae6f.js} +0 -0
- /package/out/_next/static/chunks/{1037jlyw5~7ht.js → 3gf98e08a-l_e.js} +0 -0
- /package/out/_next/static/chunks/{1045hfzu533z0.js → 3gi6og9m_yaak.js} +0 -0
- /package/out/_next/static/chunks/{104e5nmc.c-pl.js → 3giw7r1lii84y.js} +0 -0
- /package/out/_next/static/chunks/{109taw1pbh-0b.js → 3gzhy1cs_f2oi.js} +0 -0
- /package/out/_next/static/chunks/{10ynz1dy483wf.js → 3i_ceknny1oqt.js} +0 -0
- /package/out/_next/static/chunks/{10x7~onqwp338.js → 3iw0815ssih3b.js} +0 -0
- /package/out/_next/static/chunks/{11hds.mg~4_r-.js → 3kun-vwr7nzd4.js} +0 -0
- /package/out/_next/static/chunks/{11ibzaklcauw~.js → 3kxm1e-b1er3_.js} +0 -0
- /package/out/_next/static/chunks/{11z.0s6.42b.p.js → 3mc8fynmv71yg.js} +0 -0
- /package/out/_next/static/chunks/{126enaq~f7scl.js → 3n6cor2n9zyn7.js} +0 -0
- /package/out/_next/static/chunks/{12pep-2t-qg4n.css → 3or2h8swxfxyj.css} +0 -0
- /package/out/_next/static/chunks/{12-9n56l0y3yr.js → 3ppt04b6xqz29.js} +0 -0
- /package/out/_next/static/chunks/{1380op_pfk.qo.js → 3ql2pi_m5_5p_.js} +0 -0
- /package/out/_next/static/chunks/{14a4fwbiq.l3z.js → 3t-6u8caafiu9.js} +0 -0
- /package/out/_next/static/chunks/{146oiw1bggtn4.js → 3tqdzb_n12tdm.js} +0 -0
- /package/out/_next/static/chunks/{14cowsqn95m1k.js → 3u6zpg943kpst.js} +0 -0
- /package/out/_next/static/chunks/{14dtd3l03v.kx.js → 3uaedu2hf291z.js} +0 -0
- /package/out/_next/static/chunks/{14tm3qa-v9o-4.js → 3vladx3wh0d4k.js} +0 -0
- /package/out/_next/static/chunks/{14_inksek_rth.js → 3w4o9hklow6fg.js} +0 -0
- /package/out/_next/static/chunks/{14_po2rb_arn4.js → 3w56w25z6u89b.js} +0 -0
- /package/out/_next/static/chunks/{157z7bowux3xj.js → 3x1y_gkazt6kx.js} +0 -0
- /package/out/_next/static/chunks/{15m1_677az2cm.js → 3y7r1h96dtcov.js} +0 -0
- /package/out/_next/static/chunks/{15v.~.ne6ogkk.js → 3z0hydntmwg19.js} +0 -0
- /package/out/_next/static/chunks/{15-o4kb-evqd7.js → 3zhu1svjr0bc5.js} +0 -0
- /package/out/_next/static/chunks/{16u9f35gylw8l.js → 404orp1erq__7.js} +0 -0
- /package/out/_next/static/chunks/{17ajyb5ogk5yj.js → 41talcs-dc2tc.js} +0 -0
- /package/out/_next/static/chunks/{17dyfxbq8yz8n.js → 421pn8weymo-b.js} +0 -0
- /package/out/_next/static/chunks/{180zln9pcq9ih.js → 44987pmr20now.js} +0 -0
- /package/out/_next/static/chunks/{1814izi5gh.kp.js → 449ygeh62gitc.js} +0 -0
- /package/out/_next/static/media/{KaTeX_AMS-Regular.0b~8ki5y928w2.woff → KaTeX_AMS-Regular.10y3kupq4t663.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_AMS-Regular.0p1vbqd84i2~o.woff2 → KaTeX_AMS-Regular.25ieegmnh38ts.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_AMS-Regular.173t6ktr7uf-w.ttf → KaTeX_AMS-Regular.418dr7cz3fo2x.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Caligraphic-Bold.01-pzluls4zgb.woff2 → KaTeX_Caligraphic-Bold.06b-ya9t43ioz.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Caligraphic-Bold.0x2v1lwn~880f.woff → KaTeX_Caligraphic-Bold.2vmk2hva4ctha.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Caligraphic-Bold.16zv5fax0h0ka.ttf → KaTeX_Caligraphic-Bold.40ltxhe834pns.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Caligraphic-Regular.02i3z7wig438t.ttf → KaTeX_Caligraphic-Regular.07-7u27-nhn_r.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Caligraphic-Regular.0rysu1t-ncjq8.woff2 → KaTeX_Caligraphic-Regular.2eph4dlhid_m9.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Caligraphic-Regular.10927swgekwun.woff → KaTeX_Caligraphic-Regular.3gxeetazf831f.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Fraktur-Bold.0et27v~3~4uhe.ttf → KaTeX_Fraktur-Bold.19yqa_tc9d_gx.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Fraktur-Bold.0e-16u10iuyyf.woff → KaTeX_Fraktur-Bold.1alcy76__wdj2.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Fraktur-Bold.0w23i72~hprpq.woff2 → KaTeX_Fraktur-Bold.2sasz-d-jtw8y.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Fraktur-Regular.0b.riegzdfue2.woff → KaTeX_Fraktur-Regular.110oo81prr9n5.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Fraktur-Regular.0rekyoa-52fj_.woff2 → KaTeX_Fraktur-Regular.2d10y4xmjvzlf.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Fraktur-Regular.0vjwa15znhk~4.ttf → KaTeX_Fraktur-Regular.2qhy34r6a05dn.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Bold.09i7~607shf-h.ttf → KaTeX_Main-Bold.0us_n0tnxlxu7.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Bold.09lmynrorhcbw.woff → KaTeX_Main-Bold.0v1esh257kqpe.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Bold.16pfc63_du6mx.woff2 → KaTeX_Main-Bold.3-rowy8o6_4ky.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-BoldItalic.0cp37g7x1q8h6.woff → KaTeX_Main-BoldItalic.13355ck5zr48q.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-BoldItalic.0d54rk08rx11s.woff2 → KaTeX_Main-BoldItalic.14r2naom8mrec.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-BoldItalic.15j6k~hix2t_0.ttf → KaTeX_Main-BoldItalic.3x_u9cepaced0.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Italic.0382gqciexmbu.woff → KaTeX_Main-Italic.0afv392dj4w59.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Italic.06o5nq0_91v60.woff2 → KaTeX_Main-Italic.0lig0v9j0700p.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Italic.0su4i6mm18-wo.ttf → KaTeX_Main-Italic.2hkw3230mfwcv.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Regular.08zh8z.7shijf.ttf → KaTeX_Main-Regular.0symfa7dqj6jd.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Regular.0diheg01zyoph.woff → KaTeX_Main-Regular.15u8r3b2y7fv4.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Main-Regular.0kaf-ag2_wkm-.woff2 → KaTeX_Main-Regular.1ryvsdzh2w1_e.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Math-BoldItalic.0ajzxypnbx1h1.ttf → KaTeX_Math-BoldItalic.0y5w36a5aq__2.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Math-BoldItalic.0ck1myuerwyqw.woff → KaTeX_Math-BoldItalic.12pl58orkw9rg.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Math-BoldItalic.0ja97dn.cpc87.woff2 → KaTeX_Math-BoldItalic.1oopuu636h4il.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Math-Italic.09xkhecjcn5r9.woff → KaTeX_Math-Italic.0w0b1ugh62cfr.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Math-Italic.0x23a-bmp-5tg.ttf → KaTeX_Math-Italic.2vkekfblmz5nb.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Math-Italic.0zrha2c4sl2je.woff2 → KaTeX_Math-Italic.32405s1aq8vas.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Bold.05a9.pc1j_zx9.woff2 → KaTeX_SansSerif-Bold.0h3wi2z_eouyg.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Bold.0jcl-ayi1uun0.woff → KaTeX_SansSerif-Bold.1ovw5p-yjp56g.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Bold.0re8y.dm7.mt5.ttf → KaTeX_SansSerif-Bold.2d03q85pwxpti.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Italic.0a0234dc3s62j.woff2 → KaTeX_SansSerif-Italic.0wkjc4dm2kcit.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Italic.0judofdln9731.woff → KaTeX_SansSerif-Italic.1qavw__2zz8gk.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Italic.10z1iap9pfus8.ttf → KaTeX_SansSerif-Italic.3i-q087b23-m8.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Regular.0h9yjlugq4q_e.woff → KaTeX_SansSerif-Regular.1i4afx8nk8n4r.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Regular.0v6gcj32-czft.woff2 → KaTeX_SansSerif-Regular.2peiewu59z3d-.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_SansSerif-Regular.0zm18kga42ebc.ttf → KaTeX_SansSerif-Regular.31pbu25feko_c.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Script-Regular.0c4.h-mer83d_.woff2 → KaTeX_Script-Regular.11h14300o9pd0.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Script-Regular.0q14y6zkzlpob.ttf → KaTeX_Script-Regular.28p_x7iz71ofe.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Script-Regular.0ze6v4r_-99oy.woff → KaTeX_Script-Regular.3110jb9c-bxna.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Size1-Regular.013x6a4ierotp.woff2 → KaTeX_Size1-Regular.03lhvx36ekcou.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Size1-Regular.0kidw0oi.m68o.woff → KaTeX_Size1-Regular.1slf4bh0hc6vm.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Size1-Regular.0m6y-i6wfokni.ttf → KaTeX_Size1-Regular.1y57-ck23ey8c.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Size2-Regular.0blpmluwilgbg.woff → KaTeX_Size2-Regular.0-kwyvx03omo8.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Size2-Regular.0d5inmyp-tyv3.woff2 → KaTeX_Size2-Regular.14s5gg-puz6h-.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Size2-Regular.0wnhnvj-.k9d5.ttf → KaTeX_Size2-Regular.2u0s-b07k2o9m.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Size3-Regular.01h0xm_sfctj3.woff → KaTeX_Size3-Regular.04o9a_02gu_e8.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Size3-Regular.0iukctyhw5j56.woff2 → KaTeX_Size3-Regular.1n1rgzz84z8r9.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Size3-Regular.0jl8mqyf4gzpn.ttf → KaTeX_Size3-Regular.1pkn-dge4q0fv.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Size4-Regular.0w3.rb_c4stzk.woff2 → KaTeX_Size4-Regular.2sgotkdv3dcyv.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Size4-Regular.0wr_9l81-mu06.ttf → KaTeX_Size4-Regular.2uelkfk2yna5e.ttf} +0 -0
- /package/out/_next/static/media/{KaTeX_Size4-Regular.12tvaesf3.zl3.woff → KaTeX_Size4-Regular.3p2r1l7xmebxv.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Typewriter-Regular.0c4zdxz~8frhm.woff2 → KaTeX_Typewriter-Regular.11gr2d2wuwz77.woff2} +0 -0
- /package/out/_next/static/media/{KaTeX_Typewriter-Regular.0cgrzn5l3kao5.woff → KaTeX_Typewriter-Regular.12f8myjij3617.woff} +0 -0
- /package/out/_next/static/media/{KaTeX_Typewriter-Regular.128~qc3858otl.ttf → KaTeX_Typewriter-Regular.3nee9kjfy6nm8.ttf} +0 -0
- /package/out/{pwa-512x512.png → avatar.png} +0 -0
- /package/public/{pwa-512x512.png → avatar.png} +0 -0
package/server/src/index.js
CHANGED
|
@@ -48,7 +48,6 @@ import {
|
|
|
48
48
|
SWARM_KEEP_ALIVE_INTERVAL,
|
|
49
49
|
SWARM_RANDOM_PUNCH_INTERVAL,
|
|
50
50
|
DRIVE_ENTRY_TIMEOUT,
|
|
51
|
-
DRIVE_SYNC_TIMEOUT,
|
|
52
51
|
STREAM_READ_TIMEOUT,
|
|
53
52
|
FILE_WRITE_CHUNK_SIZE,
|
|
54
53
|
DOWNLOAD_POLL_INTERVAL_MIN,
|
|
@@ -67,12 +66,39 @@ import {
|
|
|
67
66
|
} from './config.js'
|
|
68
67
|
|
|
69
68
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
69
|
+
const CHAT_FILE_ROOT = 'chat-file'
|
|
70
70
|
|
|
71
71
|
function normalizeOwnerAddress(address) {
|
|
72
72
|
const value = String(address || '').trim()
|
|
73
73
|
return /^0x[a-fA-F0-9]{40}$/.test(value) ? value.toLowerCase() : ''
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
function getPathBaseName(fileName) {
|
|
77
|
+
const parts = String(fileName || '').split('/').filter(Boolean)
|
|
78
|
+
return parts[parts.length - 1] || 'unnamed_file'
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getDisplayPathFolder(fileName) {
|
|
82
|
+
const parts = String(fileName || '').split('/').filter(Boolean)
|
|
83
|
+
parts.pop()
|
|
84
|
+
return parts.join('/')
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function buildMostLink(cid, fileName) {
|
|
88
|
+
return `most://${cid}?filename=${encodeURIComponent(fileName)}`
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function normalizeChannelDisplayName(input, fallbackAddress = '') {
|
|
92
|
+
const value = String(input || '').trim()
|
|
93
|
+
if (value) return value.slice(0, 50)
|
|
94
|
+
return fallbackAddress ? fallbackAddress.slice(0, 10) : ''
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function normalizeChannelAvatar(input) {
|
|
98
|
+
const value = String(input || '').trim()
|
|
99
|
+
return value ? value.slice(0, 4096) : ''
|
|
100
|
+
}
|
|
101
|
+
|
|
76
102
|
function createOfflineSwarm() {
|
|
77
103
|
return {
|
|
78
104
|
connections: new Set(),
|
|
@@ -528,6 +554,10 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
528
554
|
}
|
|
529
555
|
}
|
|
530
556
|
|
|
557
|
+
this.#assertDisplayNameAvailable(safeFileName, {
|
|
558
|
+
ownerAddress,
|
|
559
|
+
})
|
|
560
|
+
|
|
531
561
|
// 获取或创建该 CID 对应的 drive
|
|
532
562
|
let drive = this.#drives.get(name)
|
|
533
563
|
|
|
@@ -644,39 +674,48 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
644
674
|
const cidString = parsed.cid
|
|
645
675
|
console.log(`[MostBox] Parsed CID: ${cidString}`)
|
|
646
676
|
const { driveName: name } = this.#getCidInfo(cidString)
|
|
677
|
+
const linkFileName = sanitizeFilename(parsed.fileName)
|
|
647
678
|
|
|
648
|
-
const
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
679
|
+
const localContent = await this.#getLocalCidContent(cidString, {
|
|
680
|
+
ownerAddress,
|
|
681
|
+
public: true,
|
|
682
|
+
allowHoldingFallback: true,
|
|
683
|
+
})
|
|
684
|
+
if (localContent) {
|
|
685
|
+
const existingFile = localContent.fileRecord
|
|
686
|
+
console.log(
|
|
687
|
+
`[MostBox] CID content already exists locally: ${cidString}`
|
|
688
|
+
)
|
|
653
689
|
const existingHolding = this.#holdings.find(
|
|
654
690
|
item => item.cid === cidString
|
|
655
691
|
)
|
|
656
|
-
const existingSize = Number(existingFile.size)
|
|
657
692
|
await this.#joinCidTopicInternal(cidString, {
|
|
658
693
|
server: true,
|
|
659
694
|
client: false,
|
|
660
695
|
})
|
|
661
696
|
this.#upsertHolding({
|
|
662
697
|
cid: cidString,
|
|
663
|
-
fileName:
|
|
698
|
+
fileName:
|
|
699
|
+
existingHolding?.fileName || existingFile?.fileName || linkFileName,
|
|
664
700
|
size:
|
|
665
701
|
existingHolding?.size ??
|
|
666
|
-
(Number.isFinite(
|
|
702
|
+
(Number.isFinite(localContent.size) ? localContent.size : 0),
|
|
667
703
|
localPath:
|
|
668
|
-
existingHolding?.localPath || existingFile
|
|
669
|
-
driveName: existingFile
|
|
704
|
+
existingHolding?.localPath || existingFile?.localPath || null,
|
|
705
|
+
driveName: existingFile?.driveName || name,
|
|
670
706
|
source: existingHolding?.source || 'published',
|
|
671
707
|
})
|
|
672
708
|
return {
|
|
673
709
|
taskId,
|
|
674
|
-
fileName:
|
|
710
|
+
fileName: linkFileName,
|
|
675
711
|
alreadyExists: true,
|
|
676
712
|
}
|
|
677
713
|
}
|
|
678
714
|
|
|
679
|
-
|
|
715
|
+
this.#assertDisplayNameAvailable(linkFileName, {
|
|
716
|
+
ownerAddress,
|
|
717
|
+
excludeCid: cidString,
|
|
718
|
+
})
|
|
680
719
|
|
|
681
720
|
if (taskState.aborted) throw new Error('Download cancelled')
|
|
682
721
|
|
|
@@ -924,11 +963,14 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
924
963
|
const existingIndex = this.#publishedFiles.findIndex(
|
|
925
964
|
f => f.cid === cidString && this.#recordMatchesOwner(f, ownerAddress)
|
|
926
965
|
)
|
|
966
|
+
this.#assertDisplayNameAvailable(sanitizedFileName, {
|
|
967
|
+
ownerAddress,
|
|
968
|
+
excludeCid: cidString,
|
|
969
|
+
})
|
|
927
970
|
if (existingIndex !== -1) {
|
|
928
971
|
const existing = this.#publishedFiles[existingIndex]
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
}
|
|
972
|
+
existing.fileName = sanitizedFileName
|
|
973
|
+
existing.driveName = name
|
|
932
974
|
existing.publishedAt = new Date().toISOString()
|
|
933
975
|
} else {
|
|
934
976
|
this.#publishedFiles.push({
|
|
@@ -959,6 +1001,35 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
959
1001
|
}
|
|
960
1002
|
}
|
|
961
1003
|
|
|
1004
|
+
/**
|
|
1005
|
+
* 快速检查 most:// 链接对应的 CID 内容是否已在本机可读。
|
|
1006
|
+
*/
|
|
1007
|
+
async getLocalCidAvailability(link, options = {}) {
|
|
1008
|
+
this.#ensureInitialized()
|
|
1009
|
+
const ownerAddress = normalizeOwnerAddress(options.ownerAddress)
|
|
1010
|
+
const parsed = parseMostLink(link)
|
|
1011
|
+
if (parsed.error) {
|
|
1012
|
+
throw new ValidationError(parsed.error)
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
const localContent = await this.#getLocalCidContent(parsed.cid, {
|
|
1016
|
+
ownerAddress,
|
|
1017
|
+
public: true,
|
|
1018
|
+
allowHoldingFallback: true,
|
|
1019
|
+
})
|
|
1020
|
+
if (!localContent) {
|
|
1021
|
+
return null
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
return {
|
|
1025
|
+
available: true,
|
|
1026
|
+
cid: parsed.cid,
|
|
1027
|
+
fileName: sanitizeFilename(parsed.fileName),
|
|
1028
|
+
size: localContent.size,
|
|
1029
|
+
alreadyExists: true,
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
962
1033
|
/**
|
|
963
1034
|
* 检测 most:// 链接当前是否能找到可下载内容,但不读取文件内容。
|
|
964
1035
|
* @param {string} link - most:// 链接
|
|
@@ -978,15 +1049,17 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
978
1049
|
|
|
979
1050
|
const cidString = parsed.cid
|
|
980
1051
|
const { driveName: name } = this.#getCidInfo(cidString)
|
|
981
|
-
const
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1052
|
+
const localContent = await this.#getLocalCidContent(cidString, {
|
|
1053
|
+
ownerAddress,
|
|
1054
|
+
public: true,
|
|
1055
|
+
allowHoldingFallback: true,
|
|
1056
|
+
})
|
|
1057
|
+
if (localContent) {
|
|
985
1058
|
return {
|
|
986
1059
|
available: true,
|
|
987
1060
|
cid: cidString,
|
|
988
|
-
fileName:
|
|
989
|
-
size:
|
|
1061
|
+
fileName: sanitizeFilename(parsed.fileName),
|
|
1062
|
+
size: localContent.size,
|
|
990
1063
|
alreadyExists: true,
|
|
991
1064
|
}
|
|
992
1065
|
}
|
|
@@ -1172,6 +1245,20 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1172
1245
|
|
|
1173
1246
|
const { driveName } = this.#getCidInfo(fileRecord.cid)
|
|
1174
1247
|
|
|
1248
|
+
const existingIndex = this.#publishedFiles.findIndex(
|
|
1249
|
+
f => f.cid === fileRecord.cid && this.#recordMatchesOwner(f, ownerAddress)
|
|
1250
|
+
)
|
|
1251
|
+
if (existingIndex !== -1) {
|
|
1252
|
+
this.#trashFiles.splice(index, 1)
|
|
1253
|
+
this.#saveTrashMetadata()
|
|
1254
|
+
return this.listPublishedFiles({ ownerAddress })
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
this.#assertDisplayNameAvailable(fileRecord.fileName, {
|
|
1258
|
+
ownerAddress,
|
|
1259
|
+
excludeCid: fileRecord.cid,
|
|
1260
|
+
})
|
|
1261
|
+
|
|
1175
1262
|
this.#publishedFiles.push({
|
|
1176
1263
|
fileName: fileRecord.fileName,
|
|
1177
1264
|
cid: fileRecord.cid,
|
|
@@ -1361,6 +1448,10 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1361
1448
|
throw new Error('File not found')
|
|
1362
1449
|
}
|
|
1363
1450
|
const safeFileName = sanitizeFilename(newFileName)
|
|
1451
|
+
this.#assertDisplayNameAvailable(safeFileName, {
|
|
1452
|
+
ownerAddress,
|
|
1453
|
+
excludeCid: cid,
|
|
1454
|
+
})
|
|
1364
1455
|
this.#publishedFiles[index].fileName = safeFileName
|
|
1365
1456
|
this.#publishedFiles[index].publishedAt = new Date().toISOString()
|
|
1366
1457
|
this.#savePublishedMetadata()
|
|
@@ -1382,7 +1473,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1382
1473
|
this.#ensureInitialized()
|
|
1383
1474
|
const ownerAddress = normalizeOwnerAddress(options.ownerAddress)
|
|
1384
1475
|
const prefix = oldPath + '/'
|
|
1385
|
-
const
|
|
1476
|
+
const updates = []
|
|
1386
1477
|
|
|
1387
1478
|
for (const file of this.#publishedFiles) {
|
|
1388
1479
|
if (
|
|
@@ -1393,16 +1484,27 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1393
1484
|
const newFileName = sanitizeFilename(
|
|
1394
1485
|
remainder ? newPath + '/' + remainder : newPath
|
|
1395
1486
|
)
|
|
1396
|
-
|
|
1397
|
-
file.publishedAt = new Date().toISOString()
|
|
1398
|
-
updatedFiles.push({
|
|
1399
|
-
cid: file.cid,
|
|
1400
|
-
fileName: file.fileName,
|
|
1401
|
-
link: `most://${file.cid}?filename=${encodeURIComponent(file.fileName)}`,
|
|
1402
|
-
})
|
|
1487
|
+
updates.push({ file, newFileName })
|
|
1403
1488
|
}
|
|
1404
1489
|
}
|
|
1405
1490
|
|
|
1491
|
+
for (const { file, newFileName } of updates) {
|
|
1492
|
+
this.#assertDisplayNameAvailable(newFileName, {
|
|
1493
|
+
ownerAddress,
|
|
1494
|
+
excludeCid: file.cid,
|
|
1495
|
+
})
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
const updatedFiles = updates.map(({ file, newFileName }) => {
|
|
1499
|
+
file.fileName = newFileName
|
|
1500
|
+
file.publishedAt = new Date().toISOString()
|
|
1501
|
+
return {
|
|
1502
|
+
cid: file.cid,
|
|
1503
|
+
fileName: file.fileName,
|
|
1504
|
+
link: `most://${file.cid}?filename=${encodeURIComponent(file.fileName)}`,
|
|
1505
|
+
}
|
|
1506
|
+
})
|
|
1507
|
+
|
|
1406
1508
|
if (updatedFiles.length > 0) {
|
|
1407
1509
|
this.#savePublishedMetadata()
|
|
1408
1510
|
}
|
|
@@ -1517,7 +1619,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1517
1619
|
...channel,
|
|
1518
1620
|
members: Array.isArray(channel.members)
|
|
1519
1621
|
? channel.members.filter(
|
|
1520
|
-
member => normalizeOwnerAddress(member) !== ownerAddress
|
|
1622
|
+
member => normalizeOwnerAddress(member?.address) !== ownerAddress
|
|
1521
1623
|
)
|
|
1522
1624
|
: [],
|
|
1523
1625
|
}))
|
|
@@ -1678,28 +1780,23 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1678
1780
|
options = {}
|
|
1679
1781
|
) {
|
|
1680
1782
|
this.#ensureInitialized()
|
|
1783
|
+
if (typeof offset === 'object' && offset !== null) {
|
|
1784
|
+
options = offset
|
|
1785
|
+
offset = 0
|
|
1786
|
+
limit = DEFAULT_READ_LIMIT
|
|
1787
|
+
}
|
|
1681
1788
|
const ownerAddress = normalizeOwnerAddress(options.ownerAddress)
|
|
1682
1789
|
|
|
1683
|
-
const
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
)
|
|
1688
|
-
if (!fileRecord) {
|
|
1790
|
+
const localContent = await this.#getLocalCidContent(cid, {
|
|
1791
|
+
ownerAddress,
|
|
1792
|
+
public: options.public,
|
|
1793
|
+
})
|
|
1794
|
+
if (!localContent) {
|
|
1689
1795
|
throw new Error('File not found')
|
|
1690
1796
|
}
|
|
1691
1797
|
|
|
1692
|
-
const drive = await this.#getDriveForFile(fileRecord)
|
|
1693
|
-
|
|
1694
|
-
// Hyperdrive 中 key 为 '/' + cid
|
|
1695
1798
|
const driveKey = '/' + cid
|
|
1696
|
-
const
|
|
1697
|
-
wait: true,
|
|
1698
|
-
timeout: DRIVE_ENTRY_TIMEOUT,
|
|
1699
|
-
})
|
|
1700
|
-
if (!entry || !entry.value) {
|
|
1701
|
-
throw new Error('File content not available')
|
|
1702
|
-
}
|
|
1799
|
+
const { drive } = localContent
|
|
1703
1800
|
|
|
1704
1801
|
const chunks = []
|
|
1705
1802
|
const stream = drive.createReadStream(driveKey, {
|
|
@@ -1743,25 +1840,16 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1743
1840
|
this.#ensureInitialized()
|
|
1744
1841
|
const ownerAddress = normalizeOwnerAddress(options.ownerAddress)
|
|
1745
1842
|
|
|
1746
|
-
const
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
)
|
|
1751
|
-
if (!fileRecord) {
|
|
1843
|
+
const localContent = await this.#getLocalCidContent(cid, {
|
|
1844
|
+
ownerAddress,
|
|
1845
|
+
public: options.public,
|
|
1846
|
+
})
|
|
1847
|
+
if (!localContent) {
|
|
1752
1848
|
throw new Error('File not found')
|
|
1753
1849
|
}
|
|
1754
1850
|
|
|
1755
|
-
const drive = await this.#getDriveForFile(fileRecord)
|
|
1756
|
-
|
|
1757
1851
|
const driveKey = '/' + cid
|
|
1758
|
-
const
|
|
1759
|
-
wait: true,
|
|
1760
|
-
timeout: DRIVE_ENTRY_TIMEOUT,
|
|
1761
|
-
})
|
|
1762
|
-
if (!entry || !entry.value || !entry.value.blob) {
|
|
1763
|
-
throw new Error('File content not available')
|
|
1764
|
-
}
|
|
1852
|
+
const { drive, entry, fileRecord } = localContent
|
|
1765
1853
|
|
|
1766
1854
|
const totalSize = entry.value.blob.byteLength || 0
|
|
1767
1855
|
|
|
@@ -1808,19 +1896,63 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1808
1896
|
return { buffer, fileName: fileRecord.fileName, totalSize }
|
|
1809
1897
|
}
|
|
1810
1898
|
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1899
|
+
async #hasLocalDriveContent(drive, key) {
|
|
1900
|
+
try {
|
|
1901
|
+
return await drive.has(key)
|
|
1902
|
+
} catch {
|
|
1903
|
+
return false
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
async #getLocalCidContent(cid, options = {}) {
|
|
1908
|
+
const ownerAddress = normalizeOwnerAddress(options.ownerAddress)
|
|
1909
|
+
const fileRecord = this.#publishedFiles.find(
|
|
1910
|
+
f =>
|
|
1911
|
+
f.cid === cid &&
|
|
1912
|
+
(options.public || this.#recordMatchesOwner(f, ownerAddress))
|
|
1913
|
+
)
|
|
1914
|
+
if (!options.allowHoldingFallback && !fileRecord) {
|
|
1915
|
+
return null
|
|
1916
|
+
}
|
|
1917
|
+
const holding = this.#holdings.find(item => item.cid === cid)
|
|
1918
|
+
const { driveName } = this.#getCidInfo(cid)
|
|
1919
|
+
const drive = await this.#getOrCreateDrive(
|
|
1920
|
+
fileRecord?.driveName || holding?.driveName || driveName,
|
|
1921
|
+
{ server: true, client: false }
|
|
1922
|
+
)
|
|
1923
|
+
const driveKey = '/' + cid
|
|
1924
|
+
|
|
1925
|
+
try {
|
|
1926
|
+
const entry = await drive.entry(driveKey, { wait: false })
|
|
1927
|
+
if (!entry?.value?.blob) {
|
|
1928
|
+
return null
|
|
1929
|
+
}
|
|
1930
|
+
const hasContent = await this.#hasLocalDriveContent(drive, driveKey)
|
|
1931
|
+
if (!hasContent) {
|
|
1932
|
+
return null
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
const size =
|
|
1936
|
+
Number(entry.value.blob.byteLength) ||
|
|
1937
|
+
Number(fileRecord?.size) ||
|
|
1938
|
+
Number(holding?.size) ||
|
|
1939
|
+
0
|
|
1940
|
+
return {
|
|
1941
|
+
drive,
|
|
1942
|
+
entry,
|
|
1943
|
+
size,
|
|
1944
|
+
fileRecord: fileRecord || {
|
|
1945
|
+
cid,
|
|
1946
|
+
fileName: holding?.fileName || cid,
|
|
1947
|
+
driveName: holding?.driveName || driveName,
|
|
1948
|
+
localPath: holding?.localPath || null,
|
|
1949
|
+
size,
|
|
1950
|
+
ownerAddress,
|
|
1951
|
+
},
|
|
1952
|
+
}
|
|
1953
|
+
} catch {
|
|
1954
|
+
return null
|
|
1821
1955
|
}
|
|
1822
|
-
await this.#syncDrive(drive)
|
|
1823
|
-
return drive
|
|
1824
1956
|
}
|
|
1825
1957
|
|
|
1826
1958
|
// --- 频道管理 ---
|
|
@@ -1848,14 +1980,16 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1848
1980
|
|
|
1849
1981
|
const existing = this.#channels.find(c => c.name === name)
|
|
1850
1982
|
if (existing) {
|
|
1851
|
-
if (
|
|
1852
|
-
existing.members = []
|
|
1853
|
-
}
|
|
1854
|
-
if (ownerAddress && !existing.members.includes(ownerAddress)) {
|
|
1855
|
-
existing.members.push(ownerAddress)
|
|
1983
|
+
if (this.#upsertChannelMember(existing, options)) {
|
|
1856
1984
|
this.#saveChannelsMetadata()
|
|
1857
1985
|
}
|
|
1858
|
-
return {
|
|
1986
|
+
return {
|
|
1987
|
+
name: existing.name,
|
|
1988
|
+
key: existing.coreKey,
|
|
1989
|
+
coreKey: existing.coreKey,
|
|
1990
|
+
createdAt: existing.createdAt,
|
|
1991
|
+
type: existing.type,
|
|
1992
|
+
}
|
|
1859
1993
|
}
|
|
1860
1994
|
|
|
1861
1995
|
const ns = this.#store.namespace(`channel-${name}`)
|
|
@@ -1882,9 +2016,10 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1882
2016
|
createdAt: new Date().toISOString(),
|
|
1883
2017
|
type: channelType,
|
|
1884
2018
|
ownerAddress,
|
|
1885
|
-
members:
|
|
2019
|
+
members: [],
|
|
1886
2020
|
remoteCoreKeys: [],
|
|
1887
2021
|
}
|
|
2022
|
+
this.#upsertChannelMember(channelInfo, options)
|
|
1888
2023
|
|
|
1889
2024
|
this.#channels.push(channelInfo)
|
|
1890
2025
|
const coreKeyHex = b4a.toString(core.key, 'hex')
|
|
@@ -1901,7 +2036,13 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1901
2036
|
console.log(`[MostBox] Channel created: ${name}`)
|
|
1902
2037
|
this.emit('channel:joined', { name, key: channelInfo.coreKey })
|
|
1903
2038
|
|
|
1904
|
-
return {
|
|
2039
|
+
return {
|
|
2040
|
+
name,
|
|
2041
|
+
key: channelInfo.coreKey,
|
|
2042
|
+
coreKey: channelInfo.coreKey,
|
|
2043
|
+
createdAt: channelInfo.createdAt,
|
|
2044
|
+
type: channelInfo.type,
|
|
2045
|
+
}
|
|
1905
2046
|
}
|
|
1906
2047
|
|
|
1907
2048
|
/**
|
|
@@ -1916,11 +2057,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1916
2057
|
|
|
1917
2058
|
const existing = this.#channels.find(c => c.name === name)
|
|
1918
2059
|
if (existing) {
|
|
1919
|
-
if (
|
|
1920
|
-
existing.members = []
|
|
1921
|
-
}
|
|
1922
|
-
if (ownerAddress && !existing.members.includes(ownerAddress)) {
|
|
1923
|
-
existing.members.push(ownerAddress)
|
|
2060
|
+
if (this.#upsertChannelMember(existing, options)) {
|
|
1924
2061
|
this.#saveChannelsMetadata()
|
|
1925
2062
|
}
|
|
1926
2063
|
if (coreKey && coreKey !== existing.coreKey) {
|
|
@@ -1933,7 +2070,13 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1933
2070
|
}
|
|
1934
2071
|
await this.#openRemoteChannelCore(name, coreKey)
|
|
1935
2072
|
}
|
|
1936
|
-
return {
|
|
2073
|
+
return {
|
|
2074
|
+
name: existing.name,
|
|
2075
|
+
key: existing.coreKey,
|
|
2076
|
+
coreKey: existing.coreKey,
|
|
2077
|
+
createdAt: existing.createdAt,
|
|
2078
|
+
type: existing.type,
|
|
2079
|
+
}
|
|
1937
2080
|
}
|
|
1938
2081
|
|
|
1939
2082
|
if (!coreKey) {
|
|
@@ -1969,10 +2112,11 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1969
2112
|
createdAt: new Date().toISOString(),
|
|
1970
2113
|
type: 'group',
|
|
1971
2114
|
ownerAddress,
|
|
1972
|
-
members:
|
|
2115
|
+
members: [],
|
|
1973
2116
|
remoteCoreKeys:
|
|
1974
2117
|
remoteCoreKeyHex === localCoreKeyHex ? [] : [remoteCoreKeyHex],
|
|
1975
2118
|
}
|
|
2119
|
+
this.#upsertChannelMember(channelInfo, options)
|
|
1976
2120
|
|
|
1977
2121
|
this.#channels.push(channelInfo)
|
|
1978
2122
|
if (!this.#channelCores.has(name)) {
|
|
@@ -1991,7 +2135,13 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1991
2135
|
console.log(`[MostBox] Joined channel: ${name}`)
|
|
1992
2136
|
this.emit('channel:joined', { name, key: localCoreKeyHex })
|
|
1993
2137
|
|
|
1994
|
-
return {
|
|
2138
|
+
return {
|
|
2139
|
+
name,
|
|
2140
|
+
key: localCoreKeyHex,
|
|
2141
|
+
coreKey: localCoreKeyHex,
|
|
2142
|
+
createdAt: channelInfo.createdAt,
|
|
2143
|
+
type: channelInfo.type,
|
|
2144
|
+
}
|
|
1995
2145
|
}
|
|
1996
2146
|
|
|
1997
2147
|
/**
|
|
@@ -2011,7 +2161,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2011
2161
|
const channel = this.#channels[index]
|
|
2012
2162
|
if (ownerAddress && Array.isArray(channel.members)) {
|
|
2013
2163
|
channel.members = channel.members.filter(
|
|
2014
|
-
member => normalizeOwnerAddress(member) !== ownerAddress
|
|
2164
|
+
member => normalizeOwnerAddress(member?.address) !== ownerAddress
|
|
2015
2165
|
)
|
|
2016
2166
|
if (channel.members.length > 0) {
|
|
2017
2167
|
this.#saveChannelsMetadata()
|
|
@@ -2112,7 +2262,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2112
2262
|
return this.#channels
|
|
2113
2263
|
.filter(c => {
|
|
2114
2264
|
if (!ownerAddress) return true
|
|
2115
|
-
return
|
|
2265
|
+
return this.#channelHasMember(c, ownerAddress)
|
|
2116
2266
|
})
|
|
2117
2267
|
.filter(c => {
|
|
2118
2268
|
if (type) return c.type === type
|
|
@@ -2129,6 +2279,18 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2129
2279
|
}))
|
|
2130
2280
|
}
|
|
2131
2281
|
|
|
2282
|
+
getChannelMembers(name, options = {}) {
|
|
2283
|
+
this.#ensureInitialized()
|
|
2284
|
+
this.#assertChannelMember(name, options.ownerAddress)
|
|
2285
|
+
|
|
2286
|
+
const channel = this.#channels.find(c => c.name === name)
|
|
2287
|
+
if (!channel) {
|
|
2288
|
+
throw new Error('频道不存在')
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
return this.#getChannelMembers(channel)
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2132
2294
|
/**
|
|
2133
2295
|
* 获取频道消息
|
|
2134
2296
|
* @param {string} name - 频道名
|
|
@@ -2180,7 +2342,11 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2180
2342
|
const start = Math.max(0, total - offset - limit)
|
|
2181
2343
|
const end = total - offset
|
|
2182
2344
|
|
|
2183
|
-
return unique
|
|
2345
|
+
return unique
|
|
2346
|
+
.slice(start, end)
|
|
2347
|
+
.map(({ _coreKey, _index, ...msg }) =>
|
|
2348
|
+
this.#normalizeChannelMessageForResponse(name, msg)
|
|
2349
|
+
)
|
|
2184
2350
|
}
|
|
2185
2351
|
|
|
2186
2352
|
/**
|
|
@@ -2195,6 +2361,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2195
2361
|
async sendMessage(name, content, author, authorName, options = {}) {
|
|
2196
2362
|
this.#ensureInitialized()
|
|
2197
2363
|
this.#assertChannelMember(name, options.ownerAddress)
|
|
2364
|
+
const channel = this.#channels.find(c => c.name === name)
|
|
2198
2365
|
|
|
2199
2366
|
const localKeyHex = this.#channelLocalCoreKey.get(name)
|
|
2200
2367
|
const coresMap = this.#channelCores.get(name)
|
|
@@ -2215,6 +2382,16 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2215
2382
|
if (attachment && trimmed !== attachment.link) {
|
|
2216
2383
|
throw new ValidationError('attachment content must match link')
|
|
2217
2384
|
}
|
|
2385
|
+
if (
|
|
2386
|
+
channel &&
|
|
2387
|
+
this.#upsertChannelMember(channel, {
|
|
2388
|
+
ownerAddress: options.ownerAddress,
|
|
2389
|
+
displayName: authorName,
|
|
2390
|
+
avatar: options.avatar,
|
|
2391
|
+
})
|
|
2392
|
+
) {
|
|
2393
|
+
this.#saveChannelsMetadata()
|
|
2394
|
+
}
|
|
2218
2395
|
|
|
2219
2396
|
const message = {
|
|
2220
2397
|
type: 'message',
|
|
@@ -2304,11 +2481,125 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2304
2481
|
if (!channel) {
|
|
2305
2482
|
throw new Error('频道不存在')
|
|
2306
2483
|
}
|
|
2484
|
+
if (!this.#channelHasMember(channel, normalizedOwner)) {
|
|
2485
|
+
throw new PermissionError('未加入该频道')
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
#channelHasMember(channel, ownerAddress) {
|
|
2490
|
+
const normalizedOwner = normalizeOwnerAddress(ownerAddress)
|
|
2491
|
+
if (!normalizedOwner || !Array.isArray(channel?.members)) return false
|
|
2492
|
+
return channel.members.some(
|
|
2493
|
+
member => normalizeOwnerAddress(member?.address) === normalizedOwner
|
|
2494
|
+
)
|
|
2495
|
+
}
|
|
2496
|
+
|
|
2497
|
+
#upsertChannelMember(channel, options = {}) {
|
|
2498
|
+
const address = normalizeOwnerAddress(options.ownerAddress)
|
|
2499
|
+
if (!address) return false
|
|
2500
|
+
|
|
2501
|
+
if (!Array.isArray(channel.members)) {
|
|
2502
|
+
channel.members = []
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
const displayName = normalizeChannelDisplayName(options.displayName, address)
|
|
2506
|
+
const avatar = normalizeChannelAvatar(options.avatar)
|
|
2507
|
+
const existing = channel.members.find(
|
|
2508
|
+
member => normalizeOwnerAddress(member?.address) === address
|
|
2509
|
+
)
|
|
2510
|
+
|
|
2511
|
+
if (existing) {
|
|
2512
|
+
let changed = false
|
|
2513
|
+
if (existing.address !== address) {
|
|
2514
|
+
existing.address = address
|
|
2515
|
+
changed = true
|
|
2516
|
+
}
|
|
2517
|
+
if (displayName && existing.displayName !== displayName) {
|
|
2518
|
+
existing.displayName = displayName
|
|
2519
|
+
changed = true
|
|
2520
|
+
}
|
|
2521
|
+
if (avatar && existing.avatar !== avatar) {
|
|
2522
|
+
existing.avatar = avatar
|
|
2523
|
+
changed = true
|
|
2524
|
+
}
|
|
2525
|
+
if (!existing.joinedAt) {
|
|
2526
|
+
existing.joinedAt = new Date().toISOString()
|
|
2527
|
+
changed = true
|
|
2528
|
+
}
|
|
2529
|
+
return changed
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
const member = {
|
|
2533
|
+
address,
|
|
2534
|
+
displayName,
|
|
2535
|
+
joinedAt: new Date().toISOString(),
|
|
2536
|
+
}
|
|
2537
|
+
if (avatar) {
|
|
2538
|
+
member.avatar = avatar
|
|
2539
|
+
}
|
|
2540
|
+
channel.members.push(member)
|
|
2541
|
+
return true
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
#getChannelMembers(channel) {
|
|
2545
|
+
const members = Array.isArray(channel?.members) ? channel.members : []
|
|
2546
|
+
return members
|
|
2547
|
+
.map((member, index) => ({
|
|
2548
|
+
address: normalizeOwnerAddress(member?.address),
|
|
2549
|
+
displayName: normalizeChannelDisplayName(
|
|
2550
|
+
member?.displayName,
|
|
2551
|
+
normalizeOwnerAddress(member?.address)
|
|
2552
|
+
),
|
|
2553
|
+
avatar: normalizeChannelAvatar(member?.avatar),
|
|
2554
|
+
joinedAt: String(member?.joinedAt || ''),
|
|
2555
|
+
_index: index,
|
|
2556
|
+
}))
|
|
2557
|
+
.filter(member => member.address && member.joinedAt)
|
|
2558
|
+
.sort((a, b) => {
|
|
2559
|
+
const timeDiff =
|
|
2560
|
+
new Date(a.joinedAt).getTime() - new Date(b.joinedAt).getTime()
|
|
2561
|
+
return timeDiff || a._index - b._index
|
|
2562
|
+
})
|
|
2563
|
+
.map(({ _index, ...member }) =>
|
|
2564
|
+
member.avatar ? member : { ...member, avatar: undefined }
|
|
2565
|
+
)
|
|
2566
|
+
}
|
|
2567
|
+
|
|
2568
|
+
#normalizeChannelMessageForResponse(channelName, message) {
|
|
2569
|
+
const attachment = message?.attachment
|
|
2570
|
+
if (!attachment?.cid || !attachment.fileName) {
|
|
2571
|
+
return message
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
const oldFileName = sanitizeFilename(String(attachment.fileName))
|
|
2575
|
+
const channelPrefix = `${CHAT_FILE_ROOT}/${channelName}/`
|
|
2576
|
+
const fileName = oldFileName.startsWith(channelPrefix)
|
|
2577
|
+
? oldFileName
|
|
2578
|
+
: `${channelPrefix}${getPathBaseName(oldFileName)}`
|
|
2579
|
+
const link = buildMostLink(attachment.cid, fileName)
|
|
2580
|
+
const content =
|
|
2581
|
+
typeof message.content === 'string' &&
|
|
2582
|
+
(message.content === attachment.link ||
|
|
2583
|
+
parseMostLink(message.content).cid === attachment.cid)
|
|
2584
|
+
? link
|
|
2585
|
+
: message.content
|
|
2586
|
+
|
|
2307
2587
|
if (
|
|
2308
|
-
|
|
2309
|
-
|
|
2588
|
+
fileName === attachment.fileName &&
|
|
2589
|
+
link === attachment.link &&
|
|
2590
|
+
content === message.content
|
|
2310
2591
|
) {
|
|
2311
|
-
|
|
2592
|
+
return message
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
return {
|
|
2596
|
+
...message,
|
|
2597
|
+
content,
|
|
2598
|
+
attachment: {
|
|
2599
|
+
...attachment,
|
|
2600
|
+
fileName,
|
|
2601
|
+
link,
|
|
2602
|
+
},
|
|
2312
2603
|
}
|
|
2313
2604
|
}
|
|
2314
2605
|
|
|
@@ -2504,7 +2795,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2504
2795
|
size,
|
|
2505
2796
|
localPath: record.localPath || null,
|
|
2506
2797
|
topic: topicHex,
|
|
2507
|
-
driveName
|
|
2798
|
+
driveName,
|
|
2508
2799
|
source: record.source || 'manual',
|
|
2509
2800
|
}
|
|
2510
2801
|
}
|
|
@@ -2692,6 +2983,31 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2692
2983
|
return normalizeOwnerAddress(record.ownerAddress) === normalizedOwner
|
|
2693
2984
|
}
|
|
2694
2985
|
|
|
2986
|
+
#assertDisplayNameAvailable(fileName, options = {}) {
|
|
2987
|
+
const ownerAddress = normalizeOwnerAddress(options.ownerAddress)
|
|
2988
|
+
const safeFileName = sanitizeFilename(fileName)
|
|
2989
|
+
const folder = getDisplayPathFolder(safeFileName)
|
|
2990
|
+
const baseName = getPathBaseName(safeFileName)
|
|
2991
|
+
const conflict = this.#publishedFiles.find(file => {
|
|
2992
|
+
if (
|
|
2993
|
+
options.excludeCid &&
|
|
2994
|
+
file.cid === options.excludeCid &&
|
|
2995
|
+
this.#recordMatchesOwner(file, ownerAddress)
|
|
2996
|
+
) {
|
|
2997
|
+
return false
|
|
2998
|
+
}
|
|
2999
|
+
if (!this.#recordMatchesOwner(file, ownerAddress)) return false
|
|
3000
|
+
const existingFileName = sanitizeFilename(file.fileName)
|
|
3001
|
+
return (
|
|
3002
|
+
getDisplayPathFolder(existingFileName) === folder &&
|
|
3003
|
+
getPathBaseName(existingFileName) === baseName
|
|
3004
|
+
)
|
|
3005
|
+
})
|
|
3006
|
+
if (conflict) {
|
|
3007
|
+
throw new ConflictError(`已有同名文件: ${safeFileName}`)
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
|
|
2695
3011
|
#hasPublishedReference(cid) {
|
|
2696
3012
|
return this.#publishedFiles.some(file => file.cid === cid)
|
|
2697
3013
|
}
|
|
@@ -2740,20 +3056,6 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2740
3056
|
}
|
|
2741
3057
|
}
|
|
2742
3058
|
|
|
2743
|
-
async #syncDrive(drive, timeout = DRIVE_SYNC_TIMEOUT) {
|
|
2744
|
-
try {
|
|
2745
|
-
const updated = await Promise.race([
|
|
2746
|
-
drive.update(),
|
|
2747
|
-
new Promise((_, reject) =>
|
|
2748
|
-
setTimeout(() => reject(new Error('Sync timeout')), timeout)
|
|
2749
|
-
),
|
|
2750
|
-
])
|
|
2751
|
-
return updated
|
|
2752
|
-
} catch {
|
|
2753
|
-
return false
|
|
2754
|
-
}
|
|
2755
|
-
}
|
|
2756
|
-
|
|
2757
3059
|
#getMetadataPath() {
|
|
2758
3060
|
return path.join(this.#options.dataPath, 'published-files.json')
|
|
2759
3061
|
}
|
|
@@ -2911,7 +3213,10 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2911
3213
|
if (entry && entry.type === 'message') {
|
|
2912
3214
|
this.emit('channel:message', {
|
|
2913
3215
|
channel: channelName,
|
|
2914
|
-
message:
|
|
3216
|
+
message: this.#normalizeChannelMessageForResponse(
|
|
3217
|
+
channelName,
|
|
3218
|
+
entry
|
|
3219
|
+
),
|
|
2915
3220
|
})
|
|
2916
3221
|
}
|
|
2917
3222
|
} catch (err) {
|