mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
713 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f1e8ef1cf6 | ||
![]() |
5e5ac0162e | ||
![]() |
0c013820f0 | ||
![]() |
4b3a9e5847 | ||
![]() |
e4982256a4 | ||
![]() |
babc4927a8 | ||
![]() |
6dd84cf469 | ||
![]() |
a8800e3899 | ||
![]() |
5f03496046 | ||
![]() |
41500c17a2 | ||
![]() |
2dcfde8b9a | ||
![]() |
5c3305d8fa | ||
![]() |
0d1fe99f53 | ||
![]() |
4c03ffeec7 | ||
![]() |
8101d17482 | ||
![]() |
bc7b4dcc2a | ||
![]() |
3db8b9078d | ||
![]() |
943dbbefd3 | ||
![]() |
480abcb853 | ||
![]() |
60aaaff58e | ||
![]() |
e3b889bbe8 | ||
![]() |
ac5506a43b | ||
![]() |
b29f533a3b | ||
![]() |
a8ee86b09e | ||
![]() |
0238c53302 | ||
![]() |
665e3c806f | ||
![]() |
8c96838441 | ||
![]() |
4a722daec6 | ||
![]() |
4e0cdbcb91 | ||
![]() |
08976624cd | ||
![]() |
fdeba94653 | ||
![]() |
d3b100b7e5 | ||
![]() |
1de3e18b08 | ||
![]() |
d5c3c95682 | ||
![]() |
dabe1e29ed | ||
![]() |
203d1c0cfc | ||
![]() |
7edd8601be | ||
![]() |
a4423247f4 | ||
![]() |
4834b203a0 | ||
![]() |
bbabb32d13 | ||
![]() |
95112d6bdf | ||
![]() |
36cdca5a3e | ||
![]() |
6980a9f3fc | ||
![]() |
7b09479cd2 | ||
![]() |
5825fd6f36 | ||
![]() |
2d5b45dd82 | ||
![]() |
52dda1d1fe | ||
![]() |
420624bee4 | ||
![]() |
8abde7b7d0 | ||
![]() |
9e5b1ba28e | ||
![]() |
b9c7d3c18e | ||
![]() |
10aeccbbe5 | ||
![]() |
15d351ebc2 | ||
![]() |
7194f31cb6 | ||
![]() |
84b7e82446 | ||
![]() |
8264423b1a | ||
![]() |
37f897f3bf | ||
![]() |
fe3efac145 | ||
![]() |
9773aebefc | ||
![]() |
06f2b8c371 | ||
![]() |
e8f0bb8350 | ||
![]() |
9bfa6b827b | ||
![]() |
b21bc17a58 | ||
![]() |
f4d5d417d0 | ||
![]() |
91fc83621e | ||
![]() |
461feca0ca | ||
![]() |
5e9afab3f7 | ||
![]() |
2599ca6450 | ||
![]() |
fc99ad3a39 | ||
![]() |
10e1c3e72c | ||
![]() |
af5dedd4d4 | ||
![]() |
3b986c1076 | ||
![]() |
72f77e8b7c | ||
![]() |
e893bf676f | ||
![]() |
80eb34f611 | ||
![]() |
5d01947552 | ||
![]() |
d3a025ef7b | ||
![]() |
c466df841e | ||
![]() |
b3c6e2a0f3 | ||
![]() |
076c9cfed7 | ||
![]() |
c3f3d12f83 | ||
![]() |
44974034ec | ||
![]() |
d6175acd38 | ||
![]() |
62eee5f05c | ||
![]() |
d4e5201913 | ||
![]() |
f4d584765a | ||
![]() |
26e224f852 | ||
![]() |
252358ed66 | ||
![]() |
475afeb7c8 | ||
![]() |
7cbbb846eb | ||
![]() |
25f947968c | ||
![]() |
cad824dcbc | ||
![]() |
e506f50b00 | ||
![]() |
96ec149a98 | ||
![]() |
8c913512f6 | ||
![]() |
4cc307299d | ||
![]() |
407c6b4c5f | ||
![]() |
8f87070434 | ||
![]() |
4a63996ee2 | ||
![]() |
0358fe7620 | ||
![]() |
55e64395ed | ||
![]() |
ff5fb18e14 | ||
![]() |
52dd960857 | ||
![]() |
430221c2de | ||
![]() |
217bdf8f92 | ||
![]() |
38c6c869bf | ||
![]() |
84d46da67e | ||
![]() |
eb9d6240d7 | ||
![]() |
2d44a871b0 | ||
![]() |
3f89f350ff | ||
![]() |
1a8407a782 | ||
![]() |
cf288a3f73 | ||
![]() |
f1f37fb180 | ||
![]() |
fb0dd079fd | ||
![]() |
a6c584c85c | ||
![]() |
77adf35a30 | ||
![]() |
dc6951c2a9 | ||
![]() |
d14ba3f0f7 | ||
![]() |
78ddf36e35 | ||
![]() |
d42734624d | ||
![]() |
b5dbd9d59b | ||
![]() |
bed3e1289b | ||
![]() |
b11ca4e60e | ||
![]() |
4fcf3aa2bd | ||
![]() |
dc39da8ca5 | ||
![]() |
c10c87d28e | ||
![]() |
c6fe6f1cc5 | ||
![]() |
1c2bbeb26d | ||
![]() |
17ed3692d0 | ||
![]() |
966a00f41e | ||
![]() |
fd8d8f89aa | ||
![]() |
305bb74072 | ||
![]() |
7f4dcdd134 | ||
![]() |
aac37dcce1 | ||
![]() |
f539c662a5 | ||
![]() |
c82f346dd0 | ||
![]() |
21b4a87837 | ||
![]() |
ae73bcf24b | ||
![]() |
2a3b56bde1 | ||
![]() |
b8ebededd8 | ||
![]() |
227c4c422c | ||
![]() |
652bfb93cc | ||
![]() |
c2278e3536 | ||
![]() |
caa2fca4e8 | ||
![]() |
745cb0175c | ||
![]() |
e5165a780f | ||
![]() |
b4b91af02b | ||
![]() |
5649ff9c2e | ||
![]() |
5b4bf6c62a | ||
![]() |
93cb662282 | ||
![]() |
00a8715e58 | ||
![]() |
7ecd479b3e | ||
![]() |
8fe7d3aaec | ||
![]() |
f32a693393 | ||
![]() |
17ebc01597 | ||
![]() |
827fb698e1 | ||
![]() |
32bdf10fd2 | ||
![]() |
b795e6c3d2 | ||
![]() |
42ba524e4e | ||
![]() |
317c6d96e3 | ||
![]() |
3692d1499f | ||
![]() |
b21fbad8a3 | ||
![]() |
743334a68a | ||
![]() |
951413eb38 | ||
![]() |
32dcdef853 | ||
![]() |
34c9254d4a | ||
![]() |
14012a4668 | ||
![]() |
575debca63 | ||
![]() |
763cac8532 | ||
![]() |
43faacd7a7 | ||
![]() |
1d4e307e96 | ||
![]() |
7f8933b0de | ||
![]() |
81608ff025 | ||
![]() |
db63675b8e | ||
![]() |
f74a83bc46 | ||
![]() |
bc1deba3e4 | ||
![]() |
d6113a8f0a | ||
![]() |
2062cd48ea | ||
![]() |
1c965ef515 | ||
![]() |
58291b7156 | ||
![]() |
afd1648d80 | ||
![]() |
21814ffa9a | ||
![]() |
9d3522da54 | ||
![]() |
e07a76755e | ||
![]() |
ba46bcdeae | ||
![]() |
8d7e44314c | ||
![]() |
35a67498c7 | ||
![]() |
90dd934f95 | ||
![]() |
4087045542 | ||
![]() |
d11cef5907 | ||
![]() |
76c91d226c | ||
![]() |
c2b4dd2afd | ||
![]() |
25b39cb39a | ||
![]() |
35dcb7b88b | ||
![]() |
e5f7e7c26e | ||
![]() |
c5c11fd6a6 | ||
![]() |
8134083419 | ||
![]() |
a87e624198 | ||
![]() |
e4c62d20b4 | ||
![]() |
fa195d9e55 | ||
![]() |
5ef5773d23 | ||
![]() |
6eea52afdf | ||
![]() |
80e64af30f | ||
![]() |
563b6ddc36 | ||
![]() |
c051ab9dc4 | ||
![]() |
87737a8bdb | ||
![]() |
94273d80b0 | ||
![]() |
a08ec2a4bd | ||
![]() |
d246c556f4 | ||
![]() |
65aa365e38 | ||
![]() |
eeeae449b4 | ||
![]() |
17c10a7ba2 | ||
![]() |
69f4383678 | ||
![]() |
07852a7295 | ||
![]() |
20b7e9b6b5 | ||
![]() |
75f43ccea4 | ||
![]() |
59e5785e93 | ||
![]() |
b38f52dba9 | ||
![]() |
2a6b17a48e | ||
![]() |
a6c056a894 | ||
![]() |
5c3442a71f | ||
![]() |
390253242f | ||
![]() |
9ab80fe1ac | ||
![]() |
91fdd09e7a | ||
![]() |
db5bd5c8a4 | ||
![]() |
ef94c2fe7c | ||
![]() |
72a25ed8e1 | ||
![]() |
eb065e218f | ||
![]() |
33426736fc | ||
![]() |
896658d5ce | ||
![]() |
b14135ed72 | ||
![]() |
a1baf2e32d | ||
![]() |
f9aa2d3bce | ||
![]() |
c95d0e0696 | ||
![]() |
ad4b84d446 | ||
![]() |
3e27d5fcb0 | ||
![]() |
48a100f49a | ||
![]() |
698649f981 | ||
![]() |
780078c3aa | ||
![]() |
4c25e4ddee | ||
![]() |
c0a5ac2ac5 | ||
![]() |
0435409870 | ||
![]() |
c521269409 | ||
![]() |
1e252b7e4c | ||
![]() |
d72b1edc48 | ||
![]() |
f7307e8e01 | ||
![]() |
127905f04b | ||
![]() |
261c6dabd5 | ||
![]() |
cae84bbf02 | ||
![]() |
cdb2bc52fa | ||
![]() |
cd2972eee0 | ||
![]() |
4036aa8d0e | ||
![]() |
52c6927c44 | ||
![]() |
a16e0a21a2 | ||
![]() |
e796b21157 | ||
![]() |
1c6bc478b4 | ||
![]() |
98f39c6388 | ||
![]() |
570c83571b | ||
![]() |
c0c38d89e0 | ||
![]() |
b866cfc03c | ||
![]() |
28c2755b37 | ||
![]() |
57bfc5c73a | ||
![]() |
0f3f7d53a3 | ||
![]() |
529e50fd7f | ||
![]() |
2fa283f91d | ||
![]() |
029a9ade93 | ||
![]() |
f1ca8b15c8 | ||
![]() |
4d8edd5da9 | ||
![]() |
6c63990653 | ||
![]() |
5b521409c6 | ||
![]() |
3268fc1014 | ||
![]() |
19afb4941b | ||
![]() |
40e5111d41 | ||
![]() |
a3a40e1e74 | ||
![]() |
101caa6826 | ||
![]() |
875fed8d77 | ||
![]() |
69e28eb000 | ||
![]() |
e5d3a8360c | ||
![]() |
4545d9285b | ||
![]() |
6702024805 | ||
![]() |
78bad4842b | ||
![]() |
b9a913cfed | ||
![]() |
6f5a6f353f | ||
![]() |
790c4f589d | ||
![]() |
cd1bd3461f | ||
![]() |
0280dcd6a8 | ||
![]() |
fc337292bc | ||
![]() |
fb1daa0e21 | ||
![]() |
579b9dc0c2 | ||
![]() |
dedd0be352 | ||
![]() |
1c7d9c3513 | ||
![]() |
0c7dfe2af4 | ||
![]() |
8d1351a8a3 | ||
![]() |
e6e68a6036 | ||
![]() |
24658edc45 | ||
![]() |
09eaa3116a | ||
![]() |
e9bff466b5 | ||
![]() |
5d77f50160 | ||
![]() |
2ab91e363f | ||
![]() |
34d881426f | ||
![]() |
13ecaa0ad4 | ||
![]() |
ce6185b1f7 | ||
![]() |
2cfde6b75a | ||
![]() |
37d0354751 | ||
![]() |
0a0edcf203 | ||
![]() |
d6aad2ea28 | ||
![]() |
63084506ee | ||
![]() |
c5d313574f | ||
![]() |
caab998212 | ||
![]() |
aa037cc3d9 | ||
![]() |
642bffe374 | ||
![]() |
d682b154fc | ||
![]() |
d4a06d98cf | ||
![]() |
856b5e16b1 | ||
![]() |
a0aa208860 | ||
![]() |
037a11e04f | ||
![]() |
bd8a1d715f | ||
![]() |
54ab1dc091 | ||
![]() |
9471e63857 | ||
![]() |
fa4a403f38 | ||
![]() |
d608d65bf4 | ||
![]() |
c0f2df172a | ||
![]() |
788ef5d81c | ||
![]() |
1c6b5cffe1 | ||
![]() |
c04382b623 | ||
![]() |
0bbe51f8fd | ||
![]() |
ff7d7d15a0 | ||
![]() |
4b3d083d3a | ||
![]() |
a566dd390b | ||
![]() |
7d1442da04 | ||
![]() |
17fc982f55 | ||
![]() |
ba417e2274 | ||
![]() |
d345094b75 | ||
![]() |
6da477480d | ||
![]() |
e274088c06 | ||
![]() |
1bcaa73c5c | ||
![]() |
ca94e8f621 | ||
![]() |
1c4e198f59 | ||
![]() |
fdd13f9c66 | ||
![]() |
4333ab624e | ||
![]() |
9fe1eb3a42 | ||
![]() |
ad251a7682 | ||
![]() |
1fa740de2d | ||
![]() |
466b89064a | ||
![]() |
2748cb0ba3 | ||
![]() |
aef0d5bdde | ||
![]() |
c71e8f024a | ||
![]() |
9411f07321 | ||
![]() |
9b2a5c9bbf | ||
![]() |
2b275523a0 | ||
![]() |
31fe2f6da4 | ||
![]() |
f95db623a5 | ||
![]() |
a46313e483 | ||
![]() |
31c330826e | ||
![]() |
c4cf800142 | ||
![]() |
b64a2b0006 | ||
![]() |
a3702f2270 | ||
![]() |
d221b1d470 | ||
![]() |
0b22a6bc1d | ||
![]() |
07e8acd003 | ||
![]() |
9fce617c57 | ||
![]() |
8d5c736975 | ||
![]() |
4ccec05186 | ||
![]() |
a4f456f002 | ||
![]() |
fbdb941c27 | ||
![]() |
a41cd42e8d | ||
![]() |
77521e4627 | ||
![]() |
b6a1242bac | ||
![]() |
2f325cfe26 | ||
![]() |
193b0ad0f0 | ||
![]() |
ed476b7793 | ||
![]() |
720fd94b7f | ||
![]() |
ff87da105c | ||
![]() |
a875e65536 | ||
![]() |
0b2c6bb662 | ||
![]() |
e44e2fbbb7 | ||
![]() |
b3c93644fd | ||
![]() |
a56b7ff636 | ||
![]() |
c724236930 | ||
![]() |
4853320b2b | ||
![]() |
ba1acb6ac1 | ||
![]() |
f32a6320fc | ||
![]() |
9f914ce36a | ||
![]() |
b037644e5a | ||
![]() |
afd8c59f83 | ||
![]() |
8aa4af3e91 | ||
![]() |
630a8a2b97 | ||
![]() |
dc34c4d00c | ||
![]() |
fb42729dec | ||
![]() |
b06989216a | ||
![]() |
e5144f08cd | ||
![]() |
c4a60190e8 | ||
![]() |
efe9e4fa4c | ||
![]() |
45800b1559 | ||
![]() |
b0b2b8104f | ||
![]() |
8dbc012825 | ||
![]() |
a434176063 | ||
![]() |
a013f750c7 | ||
![]() |
aa1f49d02f | ||
![]() |
7125a26309 | ||
![]() |
329a35ebf0 | ||
![]() |
d30043f595 | ||
![]() |
745dfa1911 | ||
![]() |
76203f49a7 | ||
![]() |
870a915377 | ||
![]() |
c174fce227 | ||
![]() |
2b6e42e919 | ||
![]() |
df73e1e5a3 | ||
![]() |
3e902311d4 | ||
![]() |
64a0037265 | ||
![]() |
bcd4e38093 | ||
![]() |
181a77d627 | ||
![]() |
b353595ba9 | ||
![]() |
75e3bb4f17 | ||
![]() |
d2fa9192d4 | ||
![]() |
4bcadc2de4 | ||
![]() |
8ddff74260 | ||
![]() |
95940fdb64 | ||
![]() |
9cd5708948 | ||
![]() |
d361683d79 | ||
![]() |
9ad17a01f7 | ||
![]() |
22ca1d443c | ||
![]() |
2662e875ca | ||
![]() |
8ae0d07ec1 | ||
![]() |
76a9edb7f5 | ||
![]() |
0ccb464e5b | ||
![]() |
bef600efa2 | ||
![]() |
58a182cd33 | ||
![]() |
aa43334f41 | ||
![]() |
a2a4c97f6c | ||
![]() |
4217ba99fd | ||
![]() |
589725f5cc | ||
![]() |
3fea4602f8 | ||
![]() |
8ea6aae875 | ||
![]() |
2c70b2af68 | ||
![]() |
54a2cbcb42 | ||
![]() |
fdef821c60 | ||
![]() |
dfa798a35d | ||
![]() |
39b8eb6ff1 | ||
![]() |
6cf71f67a9 | ||
![]() |
f2e919725e | ||
![]() |
869599126e | ||
![]() |
3b1b200f6f | ||
![]() |
93c646e3e4 | ||
![]() |
3552f80a21 | ||
![]() |
66d3a63998 | ||
![]() |
6447825978 | ||
![]() |
18b7df9fca | ||
![]() |
c3781cab96 | ||
![]() |
776098dba6 | ||
![]() |
8d1b4f61e7 | ||
![]() |
c13e2bdb96 | ||
![]() |
4682254157 | ||
![]() |
d7ca6b9213 | ||
![]() |
4a76afbde8 | ||
![]() |
a68349c23a | ||
![]() |
920e005366 | ||
![]() |
659f339020 | ||
![]() |
3ee2d463af | ||
![]() |
686ddb5460 | ||
![]() |
e5d62488b7 | ||
![]() |
eb93dd5005 | ||
![]() |
6999d02d2d | ||
![]() |
790e2b1427 | ||
![]() |
a29c7cdfe4 | ||
![]() |
6b7cd692a6 | ||
![]() |
4d3925872a | ||
![]() |
2bd0f6934a | ||
![]() |
51783f17ed | ||
![]() |
ce3aef3526 | ||
![]() |
ee70afdfbb | ||
![]() |
d96c4a56a2 | ||
![]() |
9a39513dea | ||
![]() |
8f22d63315 | ||
![]() |
7f2a5bb95e | ||
![]() |
0118dbd5fb | ||
![]() |
09405de26c | ||
![]() |
efa5ee0e57 | ||
![]() |
80d558f37a | ||
![]() |
901adc3fc7 | ||
![]() |
01417be954 | ||
![]() |
43b780cbe6 | ||
![]() |
e83f36a12f | ||
![]() |
77e3fc4ab0 | ||
![]() |
eafd1adaba | ||
![]() |
6b53abb7c9 | ||
![]() |
f994c5d284 | ||
![]() |
6fda220107 | ||
![]() |
da290ed1c3 | ||
![]() |
7e9cd80a1c | ||
![]() |
379b7413d8 | ||
![]() |
9181a4df16 | ||
![]() |
df982afd51 | ||
![]() |
5c2c3b4317 | ||
![]() |
92d1309103 | ||
![]() |
c43ee3c1d6 | ||
![]() |
e0726e5283 | ||
![]() |
5f3775584b | ||
![]() |
77873d63c5 | ||
![]() |
9e6b09765e | ||
![]() |
1ad6ea4049 | ||
![]() |
7c41da1cb9 | ||
![]() |
adcf4bfc53 | ||
![]() |
7a6321a9c1 | ||
![]() |
d56b27a7b0 | ||
![]() |
ed7657ab5f | ||
![]() |
a414838416 | ||
![]() |
93646577dc | ||
![]() |
46db66038e | ||
![]() |
efc4e9ce56 | ||
![]() |
8d5eac7f80 | ||
![]() |
7b94e49b81 | ||
![]() |
c35fd4bdc8 | ||
![]() |
98590e2d90 | ||
![]() |
e6da0e5dd5 | ||
![]() |
cb2baf747d | ||
![]() |
a2f2eb03ce | ||
![]() |
5c6acbb780 | ||
![]() |
1be7031199 | ||
![]() |
ed6399bde9 | ||
![]() |
6709893781 | ||
![]() |
686a426cda | ||
![]() |
4f90bc7813 | ||
![]() |
e307b289ae | ||
![]() |
3baeff61a7 | ||
![]() |
93ab9d12ee | ||
![]() |
36e1317792 | ||
![]() |
fa3e90a021 | ||
![]() |
782a69cf13 | ||
![]() |
d495f351c0 | ||
![]() |
30bd3d2d52 | ||
![]() |
ff5a21cca5 | ||
![]() |
f8abb73c92 | ||
![]() |
e97f323d9a | ||
![]() |
3d27a4c05d | ||
![]() |
9dbc13dbe4 | ||
![]() |
c46a4c75b1 | ||
![]() |
0bded73f16 | ||
![]() |
1333733684 | ||
![]() |
003be934de | ||
![]() |
93ef20d358 | ||
![]() |
94e1a6f0ba | ||
![]() |
8661d09d57 | ||
![]() |
0e5e21dc4e | ||
![]() |
3b25c4987c | ||
![]() |
2212eb17aa | ||
![]() |
768bac1db8 | ||
![]() |
3aef75085f | ||
![]() |
ce8bef638a | ||
![]() |
f0a0c90304 | ||
![]() |
cd6c32b21d | ||
![]() |
b31876d2d1 | ||
![]() |
ebab8a190e | ||
![]() |
1b7ce8e7a5 | ||
![]() |
646bb6bd79 | ||
![]() |
5a84b97ca9 | ||
![]() |
6d41b5a4a1 | ||
![]() |
a8bce36f3b | ||
![]() |
ac2132f8ba | ||
![]() |
cab4b57abe | ||
![]() |
938fb30359 | ||
![]() |
62346d7d9d | ||
![]() |
cf1e5ca64b | ||
![]() |
7d2d683d96 | ||
![]() |
fe5042f1c3 | ||
![]() |
a1dd76aee0 | ||
![]() |
d1c91be167 | ||
![]() |
9748d99f34 | ||
![]() |
c90ffbeb62 | ||
![]() |
eb7fafeabf | ||
![]() |
3e50629462 | ||
![]() |
65281a4554 | ||
![]() |
454ec09d6a | ||
![]() |
60e3c6858d | ||
![]() |
f911f5b4fc | ||
![]() |
ad1694d291 | ||
![]() |
1130965f26 | ||
![]() |
fe1f28998b | ||
![]() |
45727fce05 | ||
![]() |
d5c23e5add | ||
![]() |
e3a8285f6c | ||
![]() |
a791221cf6 | ||
![]() |
b954d9b403 | ||
![]() |
5e7e24a271 | ||
![]() |
ffb1e598f6 | ||
![]() |
bc2da8a645 | ||
![]() |
6f2be3ed30 | ||
![]() |
033a7bffb3 | ||
![]() |
f2b2ea61a1 | ||
![]() |
6f0783acc4 | ||
![]() |
ce60aa3823 | ||
![]() |
8075e70606 | ||
![]() |
4402fc2d0a | ||
![]() |
3e3ecda551 | ||
![]() |
50beb8f346 | ||
![]() |
8e033e3e06 | ||
![]() |
dc029a318b | ||
![]() |
8e91bc2c8e | ||
![]() |
0ff5b4e90b | ||
![]() |
20dec19bfe | ||
![]() |
d261fbff26 | ||
![]() |
6594b33bcc | ||
![]() |
a1bb6cc1b1 | ||
![]() |
7ce195b68e | ||
![]() |
16d8d04aaa | ||
![]() |
59565f7d90 | ||
![]() |
43784a2495 | ||
![]() |
3811d7469e | ||
![]() |
c72b40a1e1 | ||
![]() |
f00933969d | ||
![]() |
759adc45e3 | ||
![]() |
27ecf78372 | ||
![]() |
c91b83a7ba | ||
![]() |
39373ee63a | ||
![]() |
2db64c69ae | ||
![]() |
a699b71c02 | ||
![]() |
6c07d22cda | ||
![]() |
a2ee900ed5 | ||
![]() |
e709f31b99 | ||
![]() |
35afb12756 | ||
![]() |
9bed9fe162 | ||
![]() |
4ff5553804 | ||
![]() |
32213be7a7 | ||
![]() |
84894a73e1 | ||
![]() |
b6ea185ce7 | ||
![]() |
814ac0f731 | ||
![]() |
a40bb29da3 | ||
![]() |
e9b90079c0 | ||
![]() |
dba383c27e | ||
![]() |
42059b5817 | ||
![]() |
f92a17c01b | ||
![]() |
d6552ce333 | ||
![]() |
0db89bde5a | ||
![]() |
56a12185d4 | ||
![]() |
c40170db5d | ||
![]() |
1df3e9c414 | ||
![]() |
b1570df8b9 | ||
![]() |
023fd1ce36 | ||
![]() |
a7fe74bc0c | ||
![]() |
26c9abd9da | ||
![]() |
a5e34645c5 | ||
![]() |
b2831c0a19 | ||
![]() |
648c1ea0f9 | ||
![]() |
9cd927e06a | ||
![]() |
4272413f55 | ||
![]() |
e1711b7af6 | ||
![]() |
f7d3f27d45 | ||
![]() |
3a7a47f82d | ||
![]() |
cc211706d5 | ||
![]() |
22f74be4cd | ||
![]() |
5a00d14f94 | ||
![]() |
ecb4e7bf9f | ||
![]() |
56e5b546e1 | ||
![]() |
272f5a2f4f | ||
![]() |
ddcbe78a01 | ||
![]() |
00b6c964e2 | ||
![]() |
d7d2b06ecc | ||
![]() |
fafc59360d | ||
![]() |
19e105785e | ||
![]() |
b87ac09e43 | ||
![]() |
af9092d7c7 | ||
![]() |
24a1ffd652 | ||
![]() |
662813cc58 | ||
![]() |
d890b78290 | ||
![]() |
58747d7d4a | ||
![]() |
0773a4f39c | ||
![]() |
66cc7f8a1f | ||
![]() |
01ab40bf4a | ||
![]() |
4c09147fd1 | ||
![]() |
f9f426d788 | ||
![]() |
ff8fa1bf31 | ||
![]() |
59f99e4f6a | ||
![]() |
7449ce9c3b | ||
![]() |
f6bc8f0a1f | ||
![]() |
4d10b8cdee | ||
![]() |
5a61c5de09 | ||
![]() |
f84d0db811 | ||
![]() |
36ce3b08fe | ||
![]() |
da8ea5b545 | ||
![]() |
fad3dbf4cd | ||
![]() |
034d12c347 | ||
![]() |
c94dbf1d9a | ||
![]() |
e516687a9e | ||
![]() |
4a2f77b0a6 | ||
![]() |
7b29ecba71 | ||
![]() |
11241b8e07 | ||
![]() |
52bbd1f20b | ||
![]() |
4044750515 | ||
![]() |
b670c546b9 | ||
![]() |
f37bbf93cb | ||
![]() |
87311ab41a | ||
![]() |
ecb4d1845c | ||
![]() |
35c232ab25 | ||
![]() |
df0be2e251 | ||
![]() |
871b3a102b | ||
![]() |
02299e3892 | ||
![]() |
6af4d6f5b8 | ||
![]() |
4fb5700367 | ||
![]() |
8579276381 | ||
![]() |
7ba60b22c5 | ||
![]() |
031932f41c | ||
![]() |
079d0a89b1 | ||
![]() |
c4fdce6d64 | ||
![]() |
5604c2b29f | ||
![]() |
74b5ab2b47 | ||
![]() |
c29cbfe123 | ||
![]() |
6fe5cb1ffd | ||
![]() |
7edd5a7a8e | ||
![]() |
c1edc1b99b | ||
![]() |
4d1d890f72 | ||
![]() |
fe0f82fa2b | ||
![]() |
84083a65a8 | ||
![]() |
fc91c6bc08 |
@@ -5,7 +5,7 @@ root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
end_of_line = lf|crlf
|
||||
insert_final_newline = true
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
@@ -18,4 +18,4 @@ indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Unfortunately, EditorConfig doesn't support space configuration inside import braces directly.
|
||||
# You'll need to rely on your linter/formatter like ESLint or Prettier for that.
|
||||
# You'll need to rely on your linter/formatter like ESLint or Prettier for that.
|
@@ -1 +1 @@
|
||||
VITE_BUILD_TYPE = Production
|
||||
VITE_BUILD_TYPE = Production
|
||||
|
@@ -1,9 +1,10 @@
|
||||
module.exports = {
|
||||
'env': {
|
||||
'browser': true,
|
||||
'es2021': true,
|
||||
'node': true
|
||||
},
|
||||
'ignorePatterns': ['src/core/', 'src/core.lib/'],
|
||||
'ignorePatterns': ['src/core/', 'src/core.lib/','src/proto/'],
|
||||
'extends': [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended'
|
||||
|
11
.github/workflows/build.yml
vendored
11
.github/workflows/build.yml
vendored
@@ -1,6 +1,11 @@
|
||||
name: "Build"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions: write-all
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
@@ -9,7 +14,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target_platform: [linux,darwin]
|
||||
target_platform: [linux]
|
||||
target_arch: [x64, arm64]
|
||||
steps:
|
||||
- name: Clone Main Repository
|
||||
@@ -17,6 +22,7 @@ jobs:
|
||||
with:
|
||||
repository: 'NapNeko/NapCatQQ'
|
||||
submodules: true
|
||||
ref: main
|
||||
token: ${{ secrets.NAPCAT_BUILD }}
|
||||
- name: Use Node.js 20.X
|
||||
uses: actions/setup-node@v4
|
||||
@@ -48,6 +54,7 @@ jobs:
|
||||
with:
|
||||
repository: 'NapNeko/NapCatQQ'
|
||||
submodules: true
|
||||
ref: main
|
||||
token: ${{ secrets.NAPCAT_BUILD }}
|
||||
- name: Use Node.js 20.X
|
||||
uses: actions/setup-node@v4
|
||||
@@ -64,4 +71,4 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: NapCat.${{ matrix.target_platform }}.${{ matrix.target_arch }}
|
||||
path: dist
|
||||
path: dist
|
||||
|
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
@@ -14,6 +14,7 @@ jobs:
|
||||
- name: Clone Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract version from tag
|
||||
@@ -27,14 +28,15 @@ jobs:
|
||||
- name: Check Version
|
||||
run: |
|
||||
ls
|
||||
node ./script/checkVersion.js
|
||||
node ./script/checkVersion.cjs
|
||||
sh ./checkVersion.sh
|
||||
build-linux:
|
||||
needs: [check-version]
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target_platform: [linux,darwin]
|
||||
target_platform: [linux]
|
||||
target_arch: [x64, arm64]
|
||||
steps:
|
||||
- name: Clone Main Repository
|
||||
@@ -42,6 +44,7 @@ jobs:
|
||||
with:
|
||||
repository: 'NapNeko/NapCatQQ'
|
||||
submodules: true
|
||||
ref: main
|
||||
token: ${{ secrets.NAPCAT_BUILD }}
|
||||
- name: Use Node.js 20.X
|
||||
uses: actions/setup-node@v4
|
||||
@@ -50,6 +53,8 @@ jobs:
|
||||
|
||||
- name: Build NuCat Linux
|
||||
run: |
|
||||
export NAPCAT_BUILDSYS=${{ matrix.target_platform }}
|
||||
export NAPCAT_BUILDARCH=${{ matrix.target_arch }}
|
||||
npm i --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
|
||||
npm run build:prod
|
||||
cd dist
|
||||
@@ -62,6 +67,7 @@ jobs:
|
||||
path: dist
|
||||
build-win32:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-version]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -73,6 +79,7 @@ jobs:
|
||||
with:
|
||||
repository: 'NapNeko/NapCatQQ'
|
||||
submodules: true
|
||||
ref: main
|
||||
token: ${{ secrets.NAPCAT_BUILD }}
|
||||
|
||||
- name: Use Node.js 20.X
|
||||
@@ -82,6 +89,8 @@ jobs:
|
||||
|
||||
- name: Build NuCat Linux
|
||||
run: |
|
||||
export NAPCAT_BUILDSYS=${{ matrix.target_platform }}
|
||||
export NAPCAT_BUILDARCH=${{ matrix.target_arch }}
|
||||
npm i --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
|
||||
npm run build:prod
|
||||
cd dist
|
||||
@@ -107,16 +116,23 @@ jobs:
|
||||
base=$(basename "$dir")
|
||||
zip -r "${base}.zip" "$dir"
|
||||
done
|
||||
|
||||
- name: Extract version from tag
|
||||
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Clone Changes Log
|
||||
run: curl -o CHANGELOG.md https://fastly.jsdelivr.net/gh/NapNeko/NapCatQQ@main/docs/changelogs/CHANGELOG.v${{ env.VERSION }}.md
|
||||
|
||||
- name: Create Release Draft and Upload Artifacts
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: NapCat V0.0.0
|
||||
token: ${{ secrets.NAPCAT_BUILD }}
|
||||
name: NapCat V${{ env.VERSION }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body_path: CHANGELOG.md
|
||||
files: |
|
||||
NapCat.win32.x64.zip
|
||||
NapCat.linux.x64.zip
|
||||
NapCat.linux.arm64.zip
|
||||
NapCat.darwin.x64.zip
|
||||
NapCat.darwin.arm64.zip
|
||||
# NapCat.darwin.x64.zip
|
||||
# NapCat.darwin.arm64.zip
|
||||
draft: true
|
||||
|
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,11 +1,11 @@
|
||||
# Logs
|
||||
|
||||
# Develop
|
||||
node_modules/
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
out/
|
||||
dist/
|
||||
src/core.lib/common/
|
||||
/src/core.lib/common/
|
||||
/localdebug/
|
||||
|
||||
# Editor
|
||||
.vscode/*
|
||||
@@ -14,3 +14,4 @@ src/core.lib/common/
|
||||
|
||||
# Build
|
||||
*.db
|
||||
checkVersion.sh
|
||||
|
156
README.md
156
README.md
@@ -4,162 +4,30 @@
|
||||
|
||||
## 项目介绍
|
||||
|
||||
NapCatQQ(瞌睡猫QQ,不准叫我NCQQ!),像睡着了一样在后台低占用运行的无头(没有界面)的NTQQ
|
||||
NapCatQQ 是基于 PC NTQQ 本体实现一套无头 Bot 框架。
|
||||
|
||||
目前测试在 Windows 上表现优秀,最低可达只占用内存 **20M**左右
|
||||
名字寓意 瞌睡猫QQ,像睡着了一样在后台低占用运行的无需GUI界面的NTQQ。
|
||||
|
||||
由于 Linux 上的 QQ 图形依赖较多,会导致内存占用小高,大约 **100+M**,目前正在研究如何优化
|
||||
## 如何使用
|
||||
|
||||
具体占用会因人而异,QQ 群、好友越多占用越高
|
||||
可前往 [Release](https://github.com/NapNeko/NapCatQQ/releases/) 页面下载最新版本
|
||||
|
||||
## 下载
|
||||
**首次使用** 请务必前往 [官方文档](https://napneko.github.io/) 查看使用文档与教程
|
||||
|
||||
前往 Release 页面下载最新版本
|
||||
|
||||
## 启动
|
||||
|
||||
NapCat 是基于 官方NTQQ 实现的Bot框架,因此先需要安装官方QQ,**注意同个账号不能同时登录原版 QQ 和 NapCatQQ**
|
||||
|
||||
*如果没有安装 QQ 请往后翻查看安装方法*
|
||||
|
||||
修改 `config/onebot11.json`内容,并重名为 `onebot11_<你的QQ号>.json`,如`onebot11_1234567.json`
|
||||
|
||||
json 配置内容参数解释:
|
||||
|
||||
```json5
|
||||
{
|
||||
// 是否启用http服务,如果启用,可以通过http接口发送消息
|
||||
"enableHttp": false,
|
||||
// http服务端口
|
||||
"httpPort": 3000,
|
||||
// 是否启用正向websocket服务
|
||||
"enableWs": false,
|
||||
// 正向websocket服务端口
|
||||
"wsPort": 3001,
|
||||
// 是否启用反向websocket服务
|
||||
"enableWsReverse": false,
|
||||
// 反向websocket对接的地址, 如["ws://127.0.0.1:8080/onebot/v11/ws"]
|
||||
"wsReverseUrls": [],
|
||||
// 是否启用http上报服务
|
||||
"enableHttpPost": false,
|
||||
// http上报地址, 如["http://127.0.0.1:8080/onebot/v11/http"]
|
||||
"httpPostUrls": [],
|
||||
// http上报密钥,可为空
|
||||
"httpSecret": "",
|
||||
// 消息上报格式,array为消息组,string为cq码字符串
|
||||
"messagePostFormat": "array",
|
||||
// 是否上报自己发送的消息
|
||||
"reportSelfMessage": false,
|
||||
// 是否开启调试模式,开启后上报消息会携带一个raw字段,为原始消息内容
|
||||
"debug": false,
|
||||
// 调用get_file接口时如果获取不到url则使用base64字段返回文件内容
|
||||
"enableLocalFile2Url": true,
|
||||
// ws心跳间隔,单位毫秒
|
||||
"heartInterval": 30000,
|
||||
// access_token,可以为空
|
||||
"token": ""
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Windows 启动
|
||||
|
||||
运行`powershell ./napcat.ps1`, 或者 `napcat.bat`,如果出现乱码,可以尝试运行`napcat-utf8.ps1` 或 `napcat-utf8.bat`
|
||||
|
||||
*如果出现 powershell 运行不了,以管理员身份打开 powershell,输入 `Set-ExecutionPolicy RemoteSigned`*
|
||||
|
||||
### Linux 启动
|
||||
|
||||
运行`napcat.sh`
|
||||
|
||||
## 使用无需扫码快速登录
|
||||
|
||||
前提是你已经成功登录过QQ,可以加参数` -q <你的QQ>` 进行登录,如`napcat.sh -q 1234567`
|
||||
|
||||
## 安装
|
||||
|
||||
### Linux安装
|
||||
|
||||
#### 安装 Linux QQ(22741),已经安装了的可以跳过
|
||||
|
||||
目前还在研究怎么精简安装,暂时只能安装官方QQ整体依赖
|
||||
|
||||
下载QQ
|
||||
|
||||
[deb x86版本](https://dldir1.qq.com/qqfile/qq/QQNT/Linux/QQ_3.2.7_240403_amd64_01.deb)
|
||||
[deb arm版本](https://dldir1.qq.com/qqfile/qq/QQNT/Linux/QQ_3.2.7_240403_arm64_01.deb)
|
||||
|
||||
[rpm x86版本](https://dldir1.qq.com/qqfile/qq/QQNT/Linux/QQ_3.2.7_240403_x86_64_01.rpm)
|
||||
[rpm arm版本](https://dldir1.qq.com/qqfile/qq/QQNT/Linux/QQ_3.2.7_240403_aarch64_01.rpm)
|
||||
|
||||
```bash
|
||||
sudo apt install ./qq.deb
|
||||
```
|
||||
|
||||
```bash
|
||||
安装QQ的依赖
|
||||
sudo apt install libgbm1 libasound2
|
||||
```
|
||||
|
||||
### Windows 安装
|
||||
|
||||
#### 安装Windows QQ(22741),已经安装了的可以跳过
|
||||
|
||||
[Windows版本QQ下载](https://dldir1.qq.com/qqfile/qq/QQNT/Windows/QQ_9.9.9_240403_x64_01.exe)
|
||||
|
||||
### 编译安装 NapCat
|
||||
|
||||
**如果你是直接下载编译好的版本,可以跳过这一步**
|
||||
|
||||
准备环境 [node18.18](https://nodejs.org/download/release/v18.18.2/)
|
||||
|
||||
```
|
||||
export NODE_ENV=production
|
||||
npm install
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 二维码无法扫描
|
||||
|
||||
NapCat 会自动保存二维码到目录,可以手动打开图片扫描
|
||||
|
||||
如果没有条件访问本地目录,可以将二维码解析的 url 复制到二维码生成网站上生成二维码,然后手机QQ扫描
|
||||
|
||||
### 语音、视频发送失败
|
||||
|
||||
需要配置 ffmpeg,将 ffmpeg 目录加入环境变量,如果仍未生效,可以修改 napcat 启动脚本加入 FFMPEG_PATH 变量指定到 ffmpeg
|
||||
程序的完整路径
|
||||
|
||||
如 Windows 上修改 napcat.ps1,在第一行加入
|
||||
|
||||
```powershell
|
||||
$env:FFMPEG_PATH="d:\ffmpeg\bin\ffmpeg.exe"
|
||||
```
|
||||
|
||||
### 出现 error code v2:-1 之类的提示
|
||||
|
||||
不用管,这是正常现象,是因为 QQ 本身的问题,不影响使用
|
||||
|
||||
## API 文档
|
||||
|
||||
参考 [LLOneBot](https://llonebot.github.io/zh-CN/develop/api) 的文档
|
||||
|
||||
<!--
|
||||
QQ群:545402644
|
||||
-->
|
||||
|
||||
## 声明
|
||||
## 项目声明
|
||||
|
||||
* 请不要在无关地方宣传NapCatQQ,本项目只是用于学习 node 相关知识,切勿用于违法用途
|
||||
|
||||
* NapCat 不会收集用户隐私信息,但是未来可能会为了更好的利于 NapCat 的优化会收集一些设备信息,如 cpu 架构,系统版本等
|
||||
|
||||
## 相关链接
|
||||
|
||||
[TG群](https://t.me/+nLZEnpne-pQ1OWFl)
|
||||
[Telegram Link](https://t.me/+nLZEnpne-pQ1OWFl)
|
||||
|
||||
## 鸣谢名单
|
||||
[OpenShamrock]()
|
||||
|
||||
[Lagrange]()
|
||||
[Lagrange](https://github.com/LagrangeDev/Lagrange.Core)
|
||||
|
||||
<!--
|
||||
QQ群:545402644
|
||||
-->
|
||||
|
17
docs/changelogs/CHANGELOG.v1.3.3.md
Normal file
17
docs/changelogs/CHANGELOG.v1.3.3.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# v1.3.3
|
||||
|
||||
QQ Version: Windows 9.9.9-23424 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 尝试修复多开崩溃问题
|
||||
* 修复群列表更新问题
|
||||
* 修复兼容性问题支持Win7
|
||||
* 修复下载 http 资源缺少UA
|
||||
* 优化少量消息合并转发速度
|
||||
* 修复加载群通知时出现 getUserDetailInfo timeout 导致程序崩溃
|
||||
|
||||
## 新增与调整
|
||||
* 新增设置群公告 Api: /_send_group_notice
|
||||
* 新增重启实现 包括重启快速登录/普通重启 副作用: 原进程 无法清理
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
18
docs/changelogs/CHANGELOG.v1.3.5.md
Normal file
18
docs/changelogs/CHANGELOG.v1.3.5.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# v1.3.5
|
||||
|
||||
QQ Version: Windows 9.9.9-23424 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 优化启动脚本
|
||||
* 修复非管理时群成员减少事件上报 **无法获取操作者与操作类型**
|
||||
* 修复快速重启进程清理问题
|
||||
* 优化配置文件格式 支持自动更新配置 但仍然建议 **备份配置**
|
||||
* 修复正向反向ws多个客户端周期多次心跳问题
|
||||
|
||||
## 新增与调整
|
||||
* 支持WebUi热重载
|
||||
* 新增启动输出WEBUI秘钥
|
||||
* 新增群荣誉信息 /get_group_honor_info
|
||||
* 支持获取群系统消息 /get_group_system_msg
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/CHANGELOG.v1.3.6.md
Normal file
11
docs/changelogs/CHANGELOG.v1.3.6.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.3.6
|
||||
|
||||
QQ Version: Windows 9.9.9-23424 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 修复戳一戳多次上报问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
15
docs/changelogs/CHANGELOG.v1.3.8.md
Normal file
15
docs/changelogs/CHANGELOG.v1.3.8.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# v1.3.8
|
||||
|
||||
QQ Version: Windows 9.9.9-23873 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 优化打包后体积问题
|
||||
* 修复QQ等级获取
|
||||
* 兼容 9.7.x 版本换行符 统一为 \n
|
||||
* 修复处理加群请求 字段异常情况
|
||||
* 修复退群通知问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/CHANGELOG.v1.3.9.md
Normal file
11
docs/changelogs/CHANGELOG.v1.3.9.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.3.9
|
||||
|
||||
QQ Version: Windows 9.9.9-23873 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 修复QQ等级获取与兼容性问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
19
package.json
19
package.json
@@ -2,14 +2,15 @@
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "1.0.2",
|
||||
"version": "1.3.9",
|
||||
"scripts": {
|
||||
"watch:dev": "vite --mode development",
|
||||
"watch:prod": "vite --mode production",
|
||||
"build:dev": "vite build --mode development",
|
||||
"build:prod": "vite build --mode production",
|
||||
"build": "npm run build:dev",
|
||||
"build:core": "cd ./src/core && vite build --mode production",
|
||||
"build:core": "cd ./src/core && npm run build && cd ../.. && node ./script/copy-core.cjs",
|
||||
"build:webui": "cd ./src/webui && vite build",
|
||||
"watch": "npm run watch:dev",
|
||||
"debug-win": "powershell dist/napcat.ps1",
|
||||
"lint": "eslint --fix src/**/*.{js,ts}",
|
||||
@@ -18,9 +19,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@log4js-node/log4js-api": "^1.0.2",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-typescript": "^11.1.6",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/figlet": "^1.5.8",
|
||||
"@types/fluent-ffmpeg": "^2.1.24",
|
||||
@@ -35,7 +36,6 @@
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"i": "^0.3.7",
|
||||
"javascript-obfuscator": "^4.1.0",
|
||||
"protobufjs-cli": "^1.1.2",
|
||||
"rollup": "^4.13.2",
|
||||
"rollup-plugin-dts": "^6.1.0",
|
||||
"rollup-plugin-obfuscator": "^1.1.0",
|
||||
@@ -43,21 +43,24 @@
|
||||
"vite": "^5.2.6",
|
||||
"vite-plugin-cp": "^4.0.8",
|
||||
"vite-plugin-dts": "^3.8.2",
|
||||
"vite-tsconfig-paths": "^4.3.2"
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"@protobuf-ts/plugin": "^2.9.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": "^8.13.0",
|
||||
"commander": "^12.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^5.0.0-beta.2",
|
||||
"fast-xml-parser": "^4.3.6",
|
||||
"file-type": "^19.0.0",
|
||||
"fluent-ffmpeg": "^2.1.2",
|
||||
"image-size": "^1.1.1",
|
||||
"json-schema-to-ts": "^3.1.0",
|
||||
"log4js": "^6.9.1",
|
||||
"protobufjs": "^7.2.6",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"silk-wasm": "^3.3.4",
|
||||
"sqlite3": "^5.1.7",
|
||||
"uuid": "^9.0.1",
|
||||
"ws": "^8.16.0",
|
||||
"yaml": "^2.4.1"
|
||||
"ws": "^8.16.0"
|
||||
}
|
||||
}
|
||||
|
42
script/checkVersion.cjs
Normal file
42
script/checkVersion.cjs
Normal file
@@ -0,0 +1,42 @@
|
||||
const fs = require("fs");
|
||||
const process = require("process");
|
||||
|
||||
console.log("[NapCat] [CheckVersion] 开始检测当前仓库版本...");
|
||||
try {
|
||||
const packageJson = require("../package.json");
|
||||
const currentVersion = packageJson.version;
|
||||
const targetVersion = process.env.VERSION;
|
||||
|
||||
console.log("[NapCat] [CheckVersion] currentVersion:", currentVersion, "targetVersion:", targetVersion);
|
||||
|
||||
// 验证 targetVersion 格式
|
||||
if (!targetVersion || typeof targetVersion !== 'string') {
|
||||
console.error("[NapCat] [CheckVersion] 目标版本格式不正确或未设置!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 写入脚本文件的统一函数
|
||||
const writeScriptToFile = (content) => {
|
||||
fs.writeFileSync("./checkVersion.sh", content, { flag: 'w' });
|
||||
console.log("[NapCat] [CheckVersion] checkVersion.sh 文件已更新。");
|
||||
};
|
||||
|
||||
if (currentVersion === targetVersion) {
|
||||
// 不需要更新版本,写入一个简单的脚本
|
||||
const simpleScript = "#!/bin/bash\necho \"CheckVersion Is Done\"";
|
||||
writeScriptToFile(simpleScript);
|
||||
} else {
|
||||
// 更新版本,构建安全的sed命令
|
||||
const safeScriptContent = `
|
||||
#!/bin/bash
|
||||
git config --global user.email "bot@test.wumiao.wang"
|
||||
git config --global user.name "Version"
|
||||
sed -i "s/\\\"version\\\": \\\"${currentVersion}\\\"/\\\"version\\\": \\\"${targetVersion}\\\"/g" package.json
|
||||
git add .
|
||||
git commit -m "chore:version change"
|
||||
git push -u origin main`;
|
||||
writeScriptToFile(safeScriptContent);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[NapCat] [CheckVersion] 检测过程中发生错误:", error);
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
let fs = require("fs");
|
||||
let process = require("process")
|
||||
console.log("[NapCat] [CheckVersion] 开始检测当前仓库版本...");
|
||||
let currentVersion = require("./package.json").version;
|
||||
let targetVersion = process.env.VERSION;
|
||||
console.log("[NapCat] [CheckVersion] currentVersion:", currentVersion, " targetVersion:", targetVersion);
|
||||
// 借用dist目录输出脚本
|
||||
fs.mkdir("./dist");
|
||||
if (currentVersion === targetVersion) {
|
||||
fs.appendFileSync("./checkVersion.sh", "#!/bin/bashe\necho \"CheckVersion Is Done\"")
|
||||
} else {
|
||||
let packageJson = JSON.parse(fs.readFileSync("./package.json"));
|
||||
packageJson.version = targetVersion;
|
||||
fs.writeFileSync("./package.json", JSON.stringify(packageJson));
|
||||
fs.appendFileSync("./checkVersion.sh", "#!/bin/bashe\ngit add .\n git commit -m \"chore:version change\"\n git push")
|
||||
}
|
32
script/copy-core.cjs
Normal file
32
script/copy-core.cjs
Normal file
@@ -0,0 +1,32 @@
|
||||
let fs = require('fs');
|
||||
let path = require('path');
|
||||
|
||||
const coreDistDir = path.join(path.resolve(__dirname, '../'), 'src/core/dist/core/src');
|
||||
const coreLibDir = path.join(path.resolve(__dirname, '../'), 'src/core.lib/src');
|
||||
|
||||
function copyDir(currentPath, outputDir) {
|
||||
fs.readdir(currentPath, { withFileTypes: true }, (err, entries) => {
|
||||
if (err?.errno === -4058) return;
|
||||
|
||||
entries.forEach(entry => {
|
||||
const localBasePath = path.join(currentPath, entry.name);
|
||||
const outputLocalBasePath = path.join(outputDir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// 如果是目录,递归调用
|
||||
if (!fs.existsSync(outputLocalBasePath)) {
|
||||
fs.mkdirSync(outputLocalBasePath, { recursive: true });
|
||||
}
|
||||
copyDir(localBasePath, outputLocalBasePath);
|
||||
}
|
||||
else{
|
||||
// 如果是文件,直接复制
|
||||
fs.copyFile(localBasePath, outputLocalBasePath, (err) => {
|
||||
if (err) throw err;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
copyDir(coreDistDir, coreLibDir);
|
@@ -15,4 +15,4 @@ for %%a in ("!RetString!") do (
|
||||
set "QQPath=!pathWithoutUninstall!QQ.exe"
|
||||
set ELECTRON_RUN_AS_NODE=1
|
||||
echo !QQPath!
|
||||
"!QQPath!" ./napcat.cjs %*
|
||||
"!QQPath!" ./napcat.mjs %*
|
||||
|
@@ -5,11 +5,39 @@ function Get-QQpath {
|
||||
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe"
|
||||
}
|
||||
catch {
|
||||
return "D:\QQ.exe"
|
||||
throw "get QQ path error: $_"
|
||||
}
|
||||
}
|
||||
function Select-QQPath {
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
||||
|
||||
$dialogTitle = "Select QQ.exe"
|
||||
|
||||
$filePicker = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$filePicker.Title = $dialogTitle
|
||||
$filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*"
|
||||
$filePicker.FilterIndex = 1
|
||||
$null = $filePicker.ShowDialog()
|
||||
if (-not ($filePicker.FileName)) {
|
||||
throw "User did not select an .exe file."
|
||||
}
|
||||
return $filePicker.FileName
|
||||
}
|
||||
|
||||
$params = $args -join " "
|
||||
$QQpath = Get-QQpath
|
||||
$Bootfile = Join-Path $PSScriptRoot "napcat.cjs"
|
||||
Try {
|
||||
$QQpath = Get-QQpath
|
||||
}
|
||||
Catch {
|
||||
$QQpath = Select-QQPath
|
||||
}
|
||||
|
||||
if (!(Test-Path $QQpath)) {
|
||||
throw "provided QQ path is invalid: $QQpath"
|
||||
}
|
||||
|
||||
$Bootfile = Join-Path $PSScriptRoot "napcat.mjs"
|
||||
$env:ELECTRON_RUN_AS_NODE = 1
|
||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& '$QQpath' $Bootfile $params}"
|
||||
$commandInfo = Get-Command $QQpath -ErrorAction Stop
|
||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& '$($commandInfo.Path)' $Bootfile $params}"
|
@@ -14,4 +14,4 @@ for %%a in ("!RetString!") do (
|
||||
set "QQPath=!pathWithoutUninstall!QQ.exe"
|
||||
set ELECTRON_RUN_AS_NODE=1
|
||||
echo !QQPath!
|
||||
"!QQPath!" ./napcat.cjs %*
|
||||
"!QQPath!" ./napcat.mjs %*
|
||||
|
@@ -5,11 +5,39 @@ function Get-QQpath {
|
||||
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe"
|
||||
}
|
||||
catch {
|
||||
return "D:\QQ.exe"
|
||||
throw "get QQ path error: $_"
|
||||
}
|
||||
}
|
||||
function Select-QQPath {
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
||||
|
||||
$dialogTitle = "Select QQ.exe"
|
||||
|
||||
$filePicker = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$filePicker.Title = $dialogTitle
|
||||
$filePicker.Filter = "Executable Files (*.exe)|*.exe|All Files (*.*)|*.*"
|
||||
$filePicker.FilterIndex = 1
|
||||
$null = $filePicker.ShowDialog()
|
||||
if (-not ($filePicker.FileName)) {
|
||||
throw "User did not select an .exe file."
|
||||
}
|
||||
return $filePicker.FileName
|
||||
}
|
||||
|
||||
$params = $args -join " "
|
||||
$QQpath = Get-QQpath
|
||||
$Bootfile = Join-Path $PSScriptRoot "napcat.cjs"
|
||||
Try {
|
||||
$QQpath = Get-QQpath
|
||||
}
|
||||
Catch {
|
||||
$QQpath = Select-QQPath
|
||||
}
|
||||
|
||||
if (!(Test-Path $QQpath)) {
|
||||
throw "provided QQ path is invalid: $QQpath"
|
||||
}
|
||||
|
||||
$Bootfile = Join-Path $PSScriptRoot "napcat.mjs"
|
||||
$env:ELECTRON_RUN_AS_NODE = 1
|
||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& '$QQpath' $Bootfile $params}"
|
||||
$commandInfo = Get-Command $QQpath -ErrorAction Stop
|
||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& '$($commandInfo.Path)' $Bootfile $params}"
|
@@ -1,4 +1,21 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR=$(realpath $(dirname "${BASH_SOURCE[0]}"))
|
||||
|
||||
get_script_dir() {
|
||||
local script_path="${1:-$0}"
|
||||
local script_dir
|
||||
script_path=$(readlink -f "$script_path")
|
||||
script_dir=$(dirname "$script_path")
|
||||
|
||||
echo "$script_dir"
|
||||
}
|
||||
|
||||
SCRIPT_DIR=$(get_script_dir)
|
||||
|
||||
export ELECTRON_RUN_AS_NODE=1
|
||||
/opt/QQ/qq ${SCRIPT_DIR}/napcat.cjs $@
|
||||
|
||||
if ! [ -x /opt/QQ/qq ]; then
|
||||
echo "Error: /opt/QQ/qq is not executable or does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
/opt/QQ/qq "${SCRIPT_DIR}/napcat.mjs" "$@"
|
||||
|
@@ -1,85 +0,0 @@
|
||||
import {
|
||||
type Friend,
|
||||
type FriendRequest,
|
||||
type Group,
|
||||
type GroupMember, GroupNotify,
|
||||
type SelfInfo
|
||||
} from '@/core/qqnt/entities';
|
||||
import { isNumeric } from './utils/helper';
|
||||
import { log } from '@/common/utils/log';
|
||||
|
||||
export const selfInfo: SelfInfo = {
|
||||
uid: '',
|
||||
uin: '',
|
||||
nick: '',
|
||||
online: true
|
||||
};
|
||||
|
||||
// groupCode -> Group
|
||||
export const groups: Map<string, Group> = new Map<string, Group>();
|
||||
|
||||
// 群号 -> 群成员map(uid=>GroupMember)
|
||||
export const groupMembers: Map<string, Map<string, GroupMember>> = new Map<string, Map<string, GroupMember>>();
|
||||
|
||||
// uid -> Friend
|
||||
export const friends: Map<string, Friend> = new Map<string, Friend>();
|
||||
|
||||
export const friendRequests: Record<string, FriendRequest> = {}; // flag->FriendRequest
|
||||
export const groupNotifies: Record<string, GroupNotify> = {}; // flag->GroupNotify
|
||||
|
||||
export const napCatError = {
|
||||
ffmpegError: '',
|
||||
httpServerError: '',
|
||||
wsServerError: '',
|
||||
otherError: 'NapCat未能正常启动,请检查日志查看错误'
|
||||
};
|
||||
|
||||
export async function getFriend(uinOrUid: string): Promise<Friend | undefined> {
|
||||
uinOrUid = uinOrUid.toString();
|
||||
if (isNumeric(uinOrUid)) {
|
||||
const friendList = Array.from(friends.values());
|
||||
return friendList.find(friend => friend.uin === uinOrUid);
|
||||
} else {
|
||||
return friends.get(uinOrUid);
|
||||
}
|
||||
}
|
||||
|
||||
export async function getGroup(qq: string): Promise<Group | undefined> {
|
||||
const group = groups.get(qq.toString());
|
||||
return group;
|
||||
}
|
||||
|
||||
export async function getGroupMember(groupQQ: string | number, memberUinOrUid: string | number) {
|
||||
groupQQ = groupQQ.toString();
|
||||
memberUinOrUid = memberUinOrUid.toString();
|
||||
const members = groupMembers.get(groupQQ);
|
||||
if (!members) {
|
||||
return null;
|
||||
}
|
||||
// log('getGroupMember', members);
|
||||
if (isNumeric(memberUinOrUid)) {
|
||||
return Array.from(members.values()).find(member => member.uin === memberUinOrUid);
|
||||
} else {
|
||||
return members.get(memberUinOrUid);
|
||||
}
|
||||
}
|
||||
|
||||
export async function refreshGroupMembers(groupQQ: string) {
|
||||
// const group = groups.find(group => group.groupCode === groupQQ)
|
||||
// if (group) {
|
||||
// group.members = await NTQQGroupApi.getGroupMembers(groupQQ)
|
||||
// }
|
||||
}
|
||||
|
||||
export const uid2UinMap: Record<string, string> = {}; // 一串加密的字符串(uid) -> qq号
|
||||
|
||||
export function getUidByUin(uin: string) {
|
||||
for (const uid in uid2UinMap) {
|
||||
if (uid2UinMap[uid] === uin) {
|
||||
return uid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const tempGroupCodeMap: Record<string, string> = {}; // peerUid => 群号
|
||||
|
@@ -1,17 +1,19 @@
|
||||
import express, { Express, Request, Response } from 'express';
|
||||
import cors from 'cors';
|
||||
import http from 'http';
|
||||
import { log } from '../utils/log';
|
||||
import { log, logDebug, logError } from '../utils/log';
|
||||
import { ob11Config } from '@/onebot11/config';
|
||||
|
||||
type RegisterHandler = (res: Response, payload: any) => Promise<any>
|
||||
|
||||
export abstract class HttpServerBase {
|
||||
name: string = 'LLOneBot';
|
||||
name: string = 'NapCatQQ';
|
||||
private readonly expressAPP: Express;
|
||||
private server: http.Server | null = null;
|
||||
|
||||
constructor() {
|
||||
this.expressAPP = express();
|
||||
this.expressAPP.use(cors());
|
||||
this.expressAPP.use(express.urlencoded({ extended: true, limit: '5000mb' }));
|
||||
this.expressAPP.use((req, res, next) => {
|
||||
// 兼容处理没有带content-type的请求
|
||||
@@ -21,7 +23,7 @@ export abstract class HttpServerBase {
|
||||
// 调用原始的express.json()处理器
|
||||
originalJson(req, res, (err) => {
|
||||
if (err) {
|
||||
log('Error parsing JSON:', err);
|
||||
logError('Error parsing JSON:', err);
|
||||
return res.status(400).send('Invalid JSON');
|
||||
}
|
||||
next();
|
||||
@@ -35,14 +37,14 @@ export abstract class HttpServerBase {
|
||||
const authHeader = req.get('authorization');
|
||||
if (authHeader) {
|
||||
clientToken = authHeader.split('Bearer ').pop() || '';
|
||||
log('receive http header token', clientToken);
|
||||
logDebug('receive http header token', clientToken);
|
||||
} else if (req.query.access_token) {
|
||||
if (Array.isArray(req.query.access_token)) {
|
||||
clientToken = req.query.access_token[0].toString();
|
||||
} else {
|
||||
clientToken = req.query.access_token.toString();
|
||||
}
|
||||
log('receive http url token', clientToken);
|
||||
logDebug('receive http url token', clientToken);
|
||||
}
|
||||
|
||||
if (serverToken && clientToken != serverToken) {
|
||||
@@ -51,29 +53,29 @@ export abstract class HttpServerBase {
|
||||
next();
|
||||
}
|
||||
|
||||
start(port: number) {
|
||||
start(port: number, host: string) {
|
||||
try {
|
||||
this.expressAPP.get('/', (req: Request, res: Response) => {
|
||||
res.send(`${this.name}已启动`);
|
||||
});
|
||||
this.listen(port);
|
||||
this.listen(port, host);
|
||||
} catch (e: any) {
|
||||
log('HTTP服务启动失败', e.toString());
|
||||
// llonebotError.httpServerError = "HTTP服务启动失败, " + e.toString()
|
||||
logError('HTTP服务启动失败', e.toString());
|
||||
// httpServerError = "HTTP服务启动失败, " + e.toString()
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
// llonebotError.httpServerError = ""
|
||||
// httpServerError = ""
|
||||
if (this.server) {
|
||||
this.server.close();
|
||||
this.server = null;
|
||||
}
|
||||
}
|
||||
|
||||
restart(port: number) {
|
||||
restart(port: number, host: string) {
|
||||
this.stop();
|
||||
this.start(port);
|
||||
this.start(port, host);
|
||||
}
|
||||
|
||||
abstract handleFailed(res: Response, payload: any, err: any): void
|
||||
@@ -86,7 +88,7 @@ export abstract class HttpServerBase {
|
||||
// @ts-expect-error wait fix
|
||||
if (!this.expressAPP[method]) {
|
||||
const err = `${this.name} register router failed,${method} not exist`;
|
||||
log(err);
|
||||
logError(err);
|
||||
throw err;
|
||||
}
|
||||
// @ts-expect-error wait fix
|
||||
@@ -94,8 +96,10 @@ export abstract class HttpServerBase {
|
||||
let payload = req.body;
|
||||
if (method == 'get') {
|
||||
payload = req.query;
|
||||
} else if (req.query) {
|
||||
payload = { ...req.query, ...req.body };
|
||||
}
|
||||
log('收到http请求', url, payload);
|
||||
logDebug('收到http请求', url, payload);
|
||||
try {
|
||||
res.send(await handler(res, payload));
|
||||
} catch (e: any) {
|
||||
@@ -104,10 +108,17 @@ export abstract class HttpServerBase {
|
||||
});
|
||||
}
|
||||
|
||||
protected listen(port: number) {
|
||||
this.server = this.expressAPP.listen(port, '0.0.0.0', () => {
|
||||
const info = `${this.name} started 0.0.0.0:${port}`;
|
||||
log(info);
|
||||
});
|
||||
protected listen(port: number, host: string = '0.0.0.0') {
|
||||
host = host || '0.0.0.0';
|
||||
try {
|
||||
this.server = this.expressAPP.listen(port, host, () => {
|
||||
const info = `${this.name} started ${host}:${port}`;
|
||||
log(info);
|
||||
}).on('error', (err) => {
|
||||
logError('HTTP服务启动失败', err.toString());
|
||||
});
|
||||
} catch (e: any) {
|
||||
logError('HTTP服务启动失败, 请检查监听的ip地址和端口', e.stack.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -27,11 +27,17 @@ export class WebsocketServerBase {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
start(port: number) {
|
||||
start(port: number, host: string = '') {
|
||||
try {
|
||||
this.ws = new WebSocketServer({ port });
|
||||
this.ws = new WebSocketServer({
|
||||
port,
|
||||
host: '',
|
||||
maxPayload: 1024 * 1024 * 1024
|
||||
}).on('error', () => {
|
||||
});
|
||||
log(`ws服务启动成功, ${host}:${port}`);
|
||||
} catch (e: any) {
|
||||
throw Error('ws服务启动失败, ' + e.toString());
|
||||
throw Error('ws服务启动失败, 请检查监听的ip和端口' + e.toString());
|
||||
}
|
||||
this.ws.on('connection', (wsClient, req) => {
|
||||
const url: string = req.url!.split('?').shift() || '/';
|
||||
|
35
src/common/utils/AsyncQueue.ts
Normal file
35
src/common/utils/AsyncQueue.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { sleep } from '@/common/utils/helper';
|
||||
|
||||
type AsyncQueueTask = (() => void) | (()=>Promise<void>);
|
||||
|
||||
|
||||
export class AsyncQueue {
|
||||
private tasks: (AsyncQueueTask)[] = [];
|
||||
|
||||
public addTask(task: AsyncQueueTask) {
|
||||
this.tasks.push(task);
|
||||
// console.log('addTask', this.tasks.length);
|
||||
if (this.tasks.length === 1) {
|
||||
this.runQueue().then().catch(()=>{});
|
||||
}
|
||||
}
|
||||
|
||||
private async runQueue() {
|
||||
// console.log('runQueue', this.tasks.length);
|
||||
while (this.tasks.length > 0) {
|
||||
const task = this.tasks[0];
|
||||
// console.log('typeof task', typeof task);
|
||||
try {
|
||||
const taskRet = task();
|
||||
// console.log('type of taskRet', typeof taskRet, taskRet);
|
||||
if (taskRet instanceof Promise) {
|
||||
await taskRet;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
this.tasks.shift();
|
||||
await sleep(100);
|
||||
}
|
||||
}
|
||||
}
|
73
src/common/utils/ConfigBase.ts
Normal file
73
src/common/utils/ConfigBase.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import { log, logDebug, logError } from '@/common/utils/log';
|
||||
import { dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
const configDir = path.resolve(__dirname, 'config');
|
||||
fs.mkdirSync(configDir, { recursive: true });
|
||||
|
||||
|
||||
export class ConfigBase<T>{
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
protected getKeys(): string[] | null {
|
||||
// 决定 key 在json配置文件中的顺序
|
||||
return null;
|
||||
}
|
||||
|
||||
getConfigDir(){
|
||||
const configDir = path.resolve(__dirname, 'config');
|
||||
fs.mkdirSync(configDir, { recursive: true });
|
||||
return configDir;
|
||||
}
|
||||
getConfigPath(): string {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
read() {
|
||||
const configPath = this.getConfigPath();
|
||||
if (!fs.existsSync(configPath)) {
|
||||
try{
|
||||
fs.writeFileSync(configPath, JSON.stringify(this, this.getKeys(), 2));
|
||||
log(`配置文件${configPath}已创建\n如果修改此文件后需要重启 NapCat 生效`);
|
||||
}
|
||||
catch (e: any) {
|
||||
logError(`创建配置文件 ${configPath} 时发生错误:`, e.message);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
||||
logDebug(`配置文件${configPath}已加载`, data);
|
||||
Object.assign(this, data);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
this.save(this); // 保存一次,让新版本的字段写入
|
||||
return this;
|
||||
} catch (e: any) {
|
||||
if (e instanceof SyntaxError) {
|
||||
logError(`配置文件 ${configPath} 格式错误,请检查配置文件:`, e.message);
|
||||
} else {
|
||||
logError(`读取配置文件 ${configPath} 时发生错误:`, e.message);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
save(config: T) {
|
||||
Object.assign(this, config);
|
||||
const configPath = this.getConfigPath();
|
||||
try {
|
||||
fs.writeFileSync(configPath, JSON.stringify(this, this.getKeys(), 2));
|
||||
} catch (e: any) {
|
||||
logError(`保存配置文件 ${configPath} 时发生错误:`, e.message);
|
||||
}
|
||||
}
|
||||
}
|
@@ -37,24 +37,36 @@ type QQVersionConfigInfo = {
|
||||
}
|
||||
|
||||
let _qqVersionConfigInfo: QQVersionConfigInfo = {
|
||||
'baseVersion': '9.9.9-22578',
|
||||
'curVersion': '9.9.9-22578',
|
||||
'baseVersion': '9.9.9-23361',
|
||||
'curVersion': '9.9.9-23361',
|
||||
'prevVersion': '',
|
||||
'onErrorVersions': [],
|
||||
'buildId': '22578'
|
||||
'buildId': '23361'
|
||||
};
|
||||
|
||||
if (fs.existsSync(configVersionInfoPath)) {
|
||||
_qqVersionConfigInfo = JSON.parse(fs.readFileSync(configVersionInfoPath).toString());
|
||||
try {
|
||||
const _ =JSON.parse(fs.readFileSync(configVersionInfoPath).toString());
|
||||
_qqVersionConfigInfo = Object.assign(_qqVersionConfigInfo, _);
|
||||
} catch (e) {
|
||||
console.error('Load QQ version config info failed, Use default version', e);
|
||||
}
|
||||
}
|
||||
|
||||
export const qqVersionConfigInfo: QQVersionConfigInfo = _qqVersionConfigInfo;
|
||||
|
||||
export const qqPkgInfo: QQPkgInfo = require(pkgInfoPath);
|
||||
export const qqPkgInfo: QQPkgInfo = JSON.parse(fs.readFileSync(pkgInfoPath).toString());
|
||||
// platform_type: 3,
|
||||
// app_type: 4,
|
||||
// app_version: '9.9.9-23159',
|
||||
// qua: 'V1_WIN_NQ_9.9.9_23159_GW_B',
|
||||
// appid: '537213764',
|
||||
// platVer: '10.0.26100',
|
||||
// clientVer: '9.9.9-23159',
|
||||
|
||||
let _appid: string = '537213335'; // 默认为 Windows 平台的 appid
|
||||
let _appid: string = '537213803'; // 默认为 Windows 平台的 appid
|
||||
if (systemPlatform === 'linux') {
|
||||
_appid = '537213710';
|
||||
_appid = '537213827';
|
||||
}
|
||||
// todo: mac 平台的 appid
|
||||
export const appid = _appid;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import { encode, getDuration, getWavFileInfo, isWav } from 'silk-wasm';
|
||||
import fsPromise from 'fs/promises';
|
||||
import { log } from './log';
|
||||
import { log, logError } from './log';
|
||||
import path from 'node:path';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { spawn } from 'node:child_process';
|
||||
@@ -129,7 +129,7 @@ export async function encodeSilk(filePath: string) {
|
||||
};
|
||||
}
|
||||
} catch (error: any) {
|
||||
log('convert silk failed', error.stack);
|
||||
logError('convert silk failed', error.stack);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
24
src/common/utils/cpmodule.ts
Normal file
24
src/common/utils/cpmodule.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import * as os from 'os';
|
||||
import path from 'node:path';
|
||||
import fs from 'fs';
|
||||
import { dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
export function getModuleWithArchName(moduleName: string) {
|
||||
const systemPlatform = os.platform();
|
||||
const cpuArch = os.arch();
|
||||
return `${moduleName}-${systemPlatform}-${cpuArch}.node`;
|
||||
}
|
||||
|
||||
export function cpModule(moduleName: string) {
|
||||
const currentDir = path.resolve(__dirname);
|
||||
const fileName = `./${getModuleWithArchName(moduleName)}`;
|
||||
try {
|
||||
fs.copyFileSync(path.join(currentDir, fileName), path.join(currentDir, `${moduleName}.node`));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
@@ -1,323 +0,0 @@
|
||||
import { ElementType, FileElement, PicElement, PttElement, RawMessage, VideoElement } from '@/core/qqnt/entities';
|
||||
|
||||
import sqlite3 from 'sqlite3';
|
||||
import { log } from '@/common/utils/log';
|
||||
|
||||
type DBMsg = {
|
||||
id: number,
|
||||
longId: string,
|
||||
seq: number,
|
||||
peerUid: string,
|
||||
msg: string
|
||||
}
|
||||
|
||||
type DBFile = {
|
||||
name: string; // 文件名
|
||||
path: string;
|
||||
url: string;
|
||||
size: number;
|
||||
uuid: string;
|
||||
msgId: string;
|
||||
elementId: string;
|
||||
element: PicElement | VideoElement | FileElement | PttElement;
|
||||
elementType: ElementType.PIC | ElementType.VIDEO | ElementType.FILE | ElementType.PTT;
|
||||
}
|
||||
|
||||
|
||||
class DBUtilBase {
|
||||
protected db: sqlite3.Database | undefined;
|
||||
|
||||
createConnection(dbPath: string) {
|
||||
if (this.db) {
|
||||
return;
|
||||
}
|
||||
this.db = new sqlite3.Database(dbPath, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
|
||||
if (err) {
|
||||
log('Could not connect to database', err);
|
||||
return;
|
||||
}
|
||||
this.createTable();
|
||||
});
|
||||
}
|
||||
|
||||
protected createTable() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
close() {
|
||||
this.db?.close();
|
||||
}
|
||||
}
|
||||
|
||||
class DBUtil extends DBUtilBase {
|
||||
private msgCache: Map<string, RawMessage> = new Map<string, RawMessage>();
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const interval = 1000 * 60 * 10; // 10分钟清理一次缓存
|
||||
setInterval(() => {
|
||||
log('清理消息缓存');
|
||||
this.msgCache.forEach((msg, key) => {
|
||||
if ((Date.now() - parseInt(msg.msgTime) * 1000) > interval) {
|
||||
this.msgCache.delete(key);
|
||||
}
|
||||
});
|
||||
}, interval);
|
||||
}
|
||||
|
||||
|
||||
protected createTable() {
|
||||
// 消息记录
|
||||
const createTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS msgs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
long_id TEXT NOT NULL UNIQUE,
|
||||
seq INTEGER NOT NULL,
|
||||
peer_uid TEXT NOT NULL,
|
||||
msg TEXT NOT NULL
|
||||
)`;
|
||||
this.db!.run(createTableSQL, function (err) {
|
||||
if (err) {
|
||||
log('Could not create table', err);
|
||||
}
|
||||
});
|
||||
|
||||
// 文件缓存
|
||||
const createFileTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS files (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
url TEXT,
|
||||
size INTEGER NOT NULL,
|
||||
uuid TEXT,
|
||||
elementType INTEGER,
|
||||
element TEXT NOT NULL,
|
||||
elementId TEXT NOT NULL,
|
||||
msgId TEXT NOT NULL
|
||||
)`;
|
||||
this.db!.run(createFileTableSQL, function (err) {
|
||||
if (err) {
|
||||
log('Could not create table files', err);
|
||||
}
|
||||
});
|
||||
|
||||
// 接收到的临时会话消息uid
|
||||
const createTempUinTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS temp_uins (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
uid TEXT,
|
||||
uin TEXT
|
||||
)`;
|
||||
this.db!.run(createTempUinTableSQL, function (err) {
|
||||
if (err) {
|
||||
log('Could not create table temp_uins', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async getMsg(query: string, params: any[]) {
|
||||
const stmt = this.db!.prepare(query);
|
||||
return new Promise<RawMessage | null>((resolve, reject) => {
|
||||
stmt.get(...params, (err: any, row: DBMsg) => {
|
||||
// log("getMsg", row, err);
|
||||
if (err) {
|
||||
log('Could not get msg by short id', err);
|
||||
resolve(null);
|
||||
}
|
||||
try {
|
||||
const msg = JSON.parse(row.msg);
|
||||
msg.id = row.id;
|
||||
return resolve(msg);
|
||||
} catch (e) {
|
||||
return resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async getMsgByShortId(shortId: number): Promise<RawMessage | null> {
|
||||
const getStmt = 'SELECT * FROM msgs WHERE id = ?';
|
||||
return this.getMsg(getStmt, [shortId]);
|
||||
}
|
||||
|
||||
async getMsgByLongId(longId: string): Promise<RawMessage | null> {
|
||||
if (this.msgCache.has(longId)) {
|
||||
return this.msgCache.get(longId)!;
|
||||
}
|
||||
return this.getMsg('SELECT * FROM msgs WHERE long_id = ?', [longId]);
|
||||
}
|
||||
|
||||
async getMsgBySeq(peerUid: string, seq: string): Promise<RawMessage | null> {
|
||||
const stmt = 'SELECT * FROM msgs WHERE peer_uid = ? AND seq = ?';
|
||||
return this.getMsg(stmt, [peerUid, seq]);
|
||||
}
|
||||
|
||||
async addMsg(msg: RawMessage, update = true): Promise<number> {
|
||||
log('正在记录消息到数据库', msg.msgId);
|
||||
const existMsg = await this.getMsgByLongId(msg.msgId);
|
||||
if (existMsg) {
|
||||
// log('消息已存在,更新数据库', msg.msgId);
|
||||
if (update) this.updateMsg(msg).then();
|
||||
return existMsg.id!;
|
||||
}
|
||||
const stmt = this.db!.prepare('INSERT INTO msgs (long_id, seq, peer_uid, msg) VALUES (?, ?, ?, ?)');
|
||||
|
||||
// const runAsync = promisify(stmt.run.bind(stmt));
|
||||
return new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const dbInstance = this;
|
||||
stmt.run(msg.msgId, msg.msgSeq, msg.peerUid, JSON.stringify(msg), function (err: any) {
|
||||
if (err) {
|
||||
if (err.errno === 19) {
|
||||
// log('消息已存在,更新数据库', msg.msgId);
|
||||
dbInstance.getMsgByLongId(msg.msgId).then((msg: RawMessage | null) => {
|
||||
if (msg) {
|
||||
dbInstance.msgCache.set(msg.msgId, msg);
|
||||
// log('获取消息短id成功', msg.id);
|
||||
resolve(msg.id!);
|
||||
} else {
|
||||
log('db could not get msg by long id', err);
|
||||
resolve(-1);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log('db could not add msg', err);
|
||||
resolve(-1);
|
||||
}
|
||||
} else {
|
||||
// log("addMsg", this);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
msg.id = this.lastID;
|
||||
dbInstance.msgCache.set(msg.msgId, msg);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// log('获取消息短id成功', this.lastID);
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
resolve(this.lastID);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async updateMsg(msg: RawMessage) {
|
||||
const existMsg = this.msgCache.get(msg.msgId);
|
||||
if (existMsg) {
|
||||
Object.assign(existMsg, msg);
|
||||
}
|
||||
const stmt = this.db!.prepare('UPDATE msgs SET msg = ?, seq = ? WHERE long_id = ?');
|
||||
try {
|
||||
stmt.run(JSON.stringify(msg), msg.msgSeq, msg.msgId);
|
||||
} catch (e) {
|
||||
log('updateMsg db error', e);
|
||||
}
|
||||
}
|
||||
|
||||
async addFileCache(file: DBFile) {
|
||||
const stmt = this.db!.prepare('INSERT INTO files (name, path, url, size, uuid, elementType ,element, elementId, msgId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
||||
return new Promise((resolve, reject) => {
|
||||
stmt.run(file.name, file.path, file.url, file.size, file.uuid,
|
||||
file.elementType,
|
||||
JSON.stringify(file.element),
|
||||
file.elementId,
|
||||
file.msgId,
|
||||
function (err: any) {
|
||||
if (err) {
|
||||
log('db could not add file', err);
|
||||
reject(err);
|
||||
}
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async getFileCache(query: string, params: any[]) {
|
||||
const stmt = this.db!.prepare(query);
|
||||
return new Promise<DBFile | null>((resolve, reject) => {
|
||||
stmt.get(...params, (err: any, row: DBFile & { element: string }) => {
|
||||
if (err) {
|
||||
log('db could not get file cache', err);
|
||||
reject(err);
|
||||
}
|
||||
if (row) {
|
||||
row.element = JSON.parse(row.element);
|
||||
}
|
||||
resolve(row);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async getFileCacheByName(name: string): Promise<DBFile | null> {
|
||||
return this.getFileCache('SELECT * FROM files WHERE name = ?', [name]);
|
||||
}
|
||||
|
||||
async getFileCacheByUuid(uuid: string): Promise<DBFile | null> {
|
||||
return this.getFileCache('SELECT * FROM files WHERE uuid = ?', [uuid]);
|
||||
}
|
||||
|
||||
// todo: 是否所有的文件都有uuid?语音消息有没有uuid?
|
||||
async updateFileCache(file: DBFile) {
|
||||
const stmt = this.db!.prepare('UPDATE files SET path = ?, url = ? WHERE uuid = ?');
|
||||
return new Promise((resolve, reject) => {
|
||||
stmt.run(file.path, file.url, function (err: any) {
|
||||
if (err) {
|
||||
log('db could not update file cache', err);
|
||||
reject(err);
|
||||
}
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 被动收到的临时会话消息uin->uid
|
||||
async getReceivedTempUinMap() {
|
||||
const stmt = 'SELECT * FROM temp_uins';
|
||||
return new Promise<Record<string, string>>((resolve, reject) => {
|
||||
this.db!.all(stmt, (err, rows: { uin: string, uid: string }[]) => {
|
||||
if (err) {
|
||||
log('db could not get temp uin map', err);
|
||||
reject(err);
|
||||
}
|
||||
const map: Record<string, string> = {};
|
||||
rows.forEach(row => {
|
||||
map[row.uin] = row.uid;
|
||||
});
|
||||
resolve(map);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 通过uin获取临时会话消息uid
|
||||
async getUidByTempUin(uid: string) {
|
||||
const stmt = 'SELECT * FROM temp_uins WHERE uin = ?';
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
this.db!.get(stmt, [uid], (err, row: { uin: string, uid: string }) => {
|
||||
if (err) {
|
||||
log('db could not get temp uin map', err);
|
||||
reject(err);
|
||||
}
|
||||
resolve(row?.uid);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async addTempUin(uin: string, uid: string) {
|
||||
const existUid = await this.getUidByTempUin(uin);
|
||||
if (!existUid) {
|
||||
const stmt = this.db!.prepare('INSERT INTO temp_uins (uin, uid) VALUES (?, ?)');
|
||||
return new Promise((resolve, reject) => {
|
||||
stmt.run(uin, uid, function (err: any) {
|
||||
if (err) {
|
||||
log('db could not add temp uin', err);
|
||||
reject(err);
|
||||
}
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const dbUtil = new DBUtil();
|
@@ -4,13 +4,13 @@ import crypto from 'crypto';
|
||||
import util from 'util';
|
||||
import path from 'node:path';
|
||||
import { log } from './log';
|
||||
import { dbUtil } from './db';
|
||||
import { dbUtil } from '@/core/utils/db';
|
||||
import * as fileType from 'file-type';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { napCatCore } from '@/core';
|
||||
|
||||
export const getNapCatDir = () => {
|
||||
const p = path.join(napCatCore.wrapper.dataPath, 'NapCat');
|
||||
const p = path.join(napCatCore.dataPath, 'NapCat');
|
||||
fs.mkdirSync(p, { recursive: true });
|
||||
return p;
|
||||
};
|
||||
@@ -125,7 +125,7 @@ export async function httpDownload(options: string | HttpDownloadOptions): Promi
|
||||
}
|
||||
}
|
||||
}
|
||||
const fetchRes = await fetch(url, headers);
|
||||
const fetchRes = await fetch(url, { headers });
|
||||
if (!fetchRes.ok) throw new Error(`下载文件失败: ${fetchRes.statusText}`);
|
||||
|
||||
const blob = await fetchRes.blob();
|
||||
@@ -193,6 +193,7 @@ export async function uri2local(uri: string, fileName: string | null = null): Pr
|
||||
// res.ext = pathInfo.ext
|
||||
}
|
||||
}
|
||||
fileName = fileName.replace(/[/\\:*?"<>|]/g, '_');
|
||||
res.fileName = fileName;
|
||||
filePath = path.join(getTempDir(), uuidv4() + fileName);
|
||||
fs.writeFileSync(filePath, buffer);
|
||||
|
@@ -1,5 +1,13 @@
|
||||
import crypto from 'node:crypto';
|
||||
import path from 'node:path';
|
||||
import fs from 'fs/promises';
|
||||
import { log, logDebug } from './log';
|
||||
import { dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
export function sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
@@ -18,3 +26,154 @@ export function isNull(value: any) {
|
||||
export function isNumeric(str: string) {
|
||||
return /^\d+$/.test(str);
|
||||
}
|
||||
|
||||
export function truncateString(obj: any, maxLength = 500) {
|
||||
if (obj !== null && typeof obj === 'object') {
|
||||
Object.keys(obj).forEach(key => {
|
||||
if (typeof obj[key] === 'string') {
|
||||
// 如果是字符串且超过指定长度,则截断
|
||||
if (obj[key].length > maxLength) {
|
||||
obj[key] = obj[key].substring(0, maxLength) + '...';
|
||||
}
|
||||
} else if (typeof obj[key] === 'object') {
|
||||
// 如果是对象或数组,则递归调用
|
||||
truncateString(obj[key], maxLength);
|
||||
}
|
||||
});
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 函数缓存装饰器,根据方法名、参数、自定义key生成缓存键,在一定时间内返回缓存结果
|
||||
* @param ttl 超时时间,单位毫秒
|
||||
* @param customKey 自定义缓存键前缀,可为空,防止方法名参数名一致时导致缓存键冲突
|
||||
* @returns 处理后缓存或调用原方法的结果
|
||||
*/
|
||||
export function cacheFunc(ttl: number, customKey: string = '') {
|
||||
const cache = new Map<string, { expiry: number; value: any }>();
|
||||
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor {
|
||||
const originalMethod = descriptor.value;
|
||||
const className = target.constructor.name; // 获取类名
|
||||
const methodName = propertyKey; // 获取方法名
|
||||
descriptor.value = async function (...args: any[]) {
|
||||
const cacheKey = `${customKey}${className}.${methodName}:${JSON.stringify(args)}`;
|
||||
const cached = cache.get(cacheKey);
|
||||
if (cached && cached.expiry > Date.now()) {
|
||||
return cached.value;
|
||||
} else {
|
||||
const result = await originalMethod.apply(this, args);
|
||||
cache.set(cacheKey, { value: result, expiry: Date.now() + ttl });
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
return descriptor;
|
||||
};
|
||||
}
|
||||
export function isValidOldConfig(config: any) {
|
||||
if (typeof config !== 'object') {
|
||||
return false;
|
||||
}
|
||||
const requiredKeys = [
|
||||
'httpHost', 'httpPort', 'httpPostUrls', 'httpSecret',
|
||||
'wsHost', 'wsPort', 'wsReverseUrls', 'enableHttp',
|
||||
'enableHttpHeart', 'enableHttpPost', 'enableWs', 'enableWsReverse',
|
||||
'messagePostFormat', 'reportSelfMessage', 'enableLocalFile2Url',
|
||||
'debug', 'heartInterval', 'token', 'musicSignUrl'
|
||||
];
|
||||
for (const key of requiredKeys) {
|
||||
if (!(key in config)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!Array.isArray(config.httpPostUrls) || !Array.isArray(config.wsReverseUrls)) {
|
||||
return false;
|
||||
}
|
||||
if (config.httpPostUrls.some((url: any) => typeof url !== 'string')) {
|
||||
return false;
|
||||
}
|
||||
if (config.wsReverseUrls.some((url: any) => typeof url !== 'string')) {
|
||||
return false;
|
||||
}
|
||||
if (typeof config.httpPort !== 'number' || typeof config.wsPort !== 'number' || typeof config.heartInterval !== 'number') {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
typeof config.enableHttp !== 'boolean' ||
|
||||
typeof config.enableHttpHeart !== 'boolean' ||
|
||||
typeof config.enableHttpPost !== 'boolean' ||
|
||||
typeof config.enableWs !== 'boolean' ||
|
||||
typeof config.enableWsReverse !== 'boolean' ||
|
||||
typeof config.enableLocalFile2Url !== 'boolean' ||
|
||||
typeof config.reportSelfMessage !== 'boolean'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (config.messagePostFormat !== 'array' && config.messagePostFormat !== 'string') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
export function migrateConfig(oldConfig: any) {
|
||||
const newConfig = {
|
||||
http: {
|
||||
enable: oldConfig.enableHttp,
|
||||
host: oldConfig.httpHost,
|
||||
port: oldConfig.httpPort,
|
||||
secret: oldConfig.httpSecret,
|
||||
enableHeart: oldConfig.enableHttpHeart,
|
||||
enablePost: oldConfig.enableHttpPost,
|
||||
postUrls: oldConfig.httpPostUrls,
|
||||
},
|
||||
ws: {
|
||||
enable: oldConfig.enableWs,
|
||||
host: oldConfig.wsHost,
|
||||
port: oldConfig.wsPort,
|
||||
},
|
||||
reverseWs: {
|
||||
enable: oldConfig.enableWsReverse,
|
||||
urls: oldConfig.wsReverseUrls,
|
||||
},
|
||||
debug: oldConfig.debug,
|
||||
heartInterval: oldConfig.heartInterval,
|
||||
messagePostFormat: oldConfig.messagePostFormat,
|
||||
enableLocalFile2Url: oldConfig.enableLocalFile2Url,
|
||||
musicSignUrl: oldConfig.musicSignUrl,
|
||||
reportSelfMessage: oldConfig.reportSelfMessage,
|
||||
token: oldConfig.token,
|
||||
};
|
||||
return newConfig;
|
||||
}
|
||||
// 升级旧的配置到新的
|
||||
export async function UpdateConfig() {
|
||||
const configFiles = await fs.readdir(path.join(__dirname, 'config'));
|
||||
for (const file of configFiles) {
|
||||
if (file.match(/^onebot11_\d+.json$/)) {
|
||||
const CurrentConfig = JSON.parse(await fs.readFile(path.join(__dirname, 'config', file), 'utf8'));
|
||||
if (isValidOldConfig(CurrentConfig)) {
|
||||
log('正在迁移旧配置到新配置 File:', file);
|
||||
const NewConfig = migrateConfig(CurrentConfig);
|
||||
await fs.writeFile(path.join(__dirname, 'config', file), JSON.stringify(NewConfig, null, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export function isEqual(obj1: any, obj2: any) {
|
||||
if (obj1 === obj2) return true;
|
||||
if (obj1 == null || obj2 == null) return false;
|
||||
if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return obj1 === obj2;
|
||||
|
||||
const keys1 = Object.keys(obj1);
|
||||
const keys2 = Object.keys(obj2);
|
||||
|
||||
if (keys1.length !== keys2.length) return false;
|
||||
|
||||
for (const key of keys1) {
|
||||
if (!isEqual(obj1[key], obj2[key])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@@ -1,4 +1,123 @@
|
||||
import log4js, { Configuration } from 'log4js';
|
||||
import { truncateString } from '@/common/utils/helper';
|
||||
import path from 'node:path';
|
||||
import { SelfInfo } from '@/core';
|
||||
import { dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
export enum LogLevel {
|
||||
DEBUG = 'debug',
|
||||
INFO = 'info',
|
||||
WARN = 'warn',
|
||||
ERROR = 'error',
|
||||
FATAL = 'fatal',
|
||||
}
|
||||
|
||||
const logDir = path.join(path.resolve(__dirname), 'logs');
|
||||
|
||||
function getFormattedTimestamp() {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = (now.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = now.getDate().toString().padStart(2, '0');
|
||||
const hours = now.getHours().toString().padStart(2, '0');
|
||||
const minutes = now.getMinutes().toString().padStart(2, '0');
|
||||
const seconds = now.getSeconds().toString().padStart(2, '0');
|
||||
const milliseconds = now.getMilliseconds().toString().padStart(3, '0');
|
||||
return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}.${milliseconds}`;
|
||||
}
|
||||
|
||||
const filename = `${getFormattedTimestamp()}.log`;
|
||||
const logPath = path.join(logDir, filename);
|
||||
|
||||
const logConfig: Configuration = {
|
||||
appenders: {
|
||||
FileAppender: { // 输出到文件的appender
|
||||
type: 'file',
|
||||
filename: logPath, // 指定日志文件的位置和文件名
|
||||
maxLoogSize: 10485760, // 日志文件的最大大小(单位:字节),这里设置为10MB
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '%d{yyyy-MM-dd hh:mm:ss} [%p] - %m'
|
||||
}
|
||||
},
|
||||
ConsoleAppender: { // 输出到控制台的appender
|
||||
type: 'console',
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '%d{yyyy-MM-dd hh:mm:ss} [%p] - %m'
|
||||
}
|
||||
}
|
||||
},
|
||||
categories: {
|
||||
default: { appenders: ['FileAppender', 'ConsoleAppender'], level: 'debug' }, // 默认情况下同时输出到文件和控制台
|
||||
file: { appenders: ['FileAppender'], level: 'debug' },
|
||||
console: { appenders: ['ConsoleAppender'], level: 'debug' }
|
||||
}
|
||||
};
|
||||
|
||||
log4js.configure(logConfig);
|
||||
|
||||
|
||||
export function setLogLevel(fileLogLevel: LogLevel, consoleLogLevel: LogLevel) {
|
||||
logConfig.categories.file.level = fileLogLevel;
|
||||
logConfig.categories.console.level = consoleLogLevel;
|
||||
log4js.configure(logConfig);
|
||||
}
|
||||
|
||||
export function setLogSelfInfo(selfInfo: SelfInfo) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
logConfig.appenders.FileAppender.layout.pattern = logConfig.appenders.ConsoleAppender.layout.pattern =
|
||||
`%d{yyyy-MM-dd hh:mm:ss} [%p] ${selfInfo.nick}(${selfInfo.uin}) %m`;
|
||||
log4js.configure(logConfig);
|
||||
}
|
||||
|
||||
let fileLogEnabled = true;
|
||||
let consoleLogEnabled = true;
|
||||
export function enableFileLog(enable: boolean) {
|
||||
fileLogEnabled = enable;
|
||||
}
|
||||
export function enableConsoleLog(enable: boolean) {
|
||||
consoleLogEnabled = enable;
|
||||
}
|
||||
|
||||
function formatMsg(msg: any[]){
|
||||
let logMsg = '';
|
||||
for (const msgItem of msg) {
|
||||
// 判断是否是对象
|
||||
if (typeof msgItem === 'object') {
|
||||
const obj = JSON.parse(JSON.stringify(msgItem, null, 2));
|
||||
logMsg += JSON.stringify(truncateString(obj)) + ' ';
|
||||
continue;
|
||||
}
|
||||
logMsg += msgItem + ' ';
|
||||
}
|
||||
return '\n' + logMsg + '\n';
|
||||
}
|
||||
|
||||
function _log(level: LogLevel, ...args: any[]){
|
||||
if (consoleLogEnabled){
|
||||
log4js.getLogger('console')[level](formatMsg(args));
|
||||
}
|
||||
if (fileLogEnabled){
|
||||
log4js.getLogger('file')[level](formatMsg(args));
|
||||
}
|
||||
}
|
||||
|
||||
export function log(...args: any[]) {
|
||||
console.log(...args);
|
||||
}
|
||||
// info 等级
|
||||
_log(LogLevel.INFO, ...args);
|
||||
}
|
||||
|
||||
export function logDebug(...args: any[]) {
|
||||
_log(LogLevel.DEBUG, ...args);
|
||||
}
|
||||
|
||||
export function logError(...args: any[]) {
|
||||
_log(LogLevel.ERROR, ...args);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// QQ等级换算
|
||||
import { QQLevel } from '@/core/qqnt/entities';
|
||||
import { QQLevel } from '@/core/entities';
|
||||
|
||||
export function calcQQLevel(level: QQLevel) {
|
||||
const { crownNum, sunNum, moonNum, starNum } = level;
|
||||
|
44
src/common/utils/reboot.ts
Normal file
44
src/common/utils/reboot.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { resolve } from 'node:path';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { pid, ppid, exit } from 'node:process';
|
||||
import { dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
export async function rebootWithQuickLogin(uin: string) {
|
||||
const batScript = resolve(__dirname, './napcat.bat');
|
||||
const batUtf8Script = resolve(__dirname, './napcat-utf8.bat');
|
||||
const bashScript = resolve(__dirname, './napcat.sh');
|
||||
if (process.platform === 'win32') {
|
||||
const subProcess = spawn(`start ${batUtf8Script} -q ${uin}`, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' });
|
||||
subProcess.unref();
|
||||
// 子父进程一起送走 有点效果
|
||||
spawn('cmd /c taskkill /t /f /pid ' + pid.toString(), { detached: true, shell: true, stdio: 'ignore' });
|
||||
spawn('cmd /c taskkill /t /f /pid ' + ppid.toString(), { detached: true, shell: true, stdio: 'ignore' });
|
||||
} else if (process.platform === 'linux') {
|
||||
const subProcess = spawn(`${bashScript} -q ${uin}`, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' });
|
||||
//还没兼容
|
||||
subProcess.unref();
|
||||
exit(0);
|
||||
}
|
||||
//exit(0);
|
||||
}
|
||||
export async function rebootWithNormolLogin() {
|
||||
const batScript = resolve(__dirname, './napcat.bat');
|
||||
const batUtf8Script = resolve(__dirname, './napcat-utf8.bat');
|
||||
const bashScript = resolve(__dirname, './napcat.sh');
|
||||
if (process.platform === 'win32') {
|
||||
const subProcess = spawn(`start ${batUtf8Script} `, { detached: true, windowsHide: false, env: process.env, shell: true, stdio: 'ignore' });
|
||||
subProcess.unref();
|
||||
// 子父进程一起送走 有点效果
|
||||
spawn('cmd /c taskkill /t /f /pid ' + pid.toString(), { detached: true, shell: true, stdio: 'ignore' });
|
||||
spawn('cmd /c taskkill /t /f /pid ' + ppid.toString(), { detached: true, shell: true, stdio: 'ignore' });
|
||||
} else if (process.platform === 'linux') {
|
||||
const subProcess = spawn(`${bashScript}`, { detached: true, windowsHide: false, env: process.env, shell: true });
|
||||
subProcess.unref();
|
||||
exit(0);
|
||||
}
|
||||
}
|
87
src/common/utils/request.ts
Normal file
87
src/common/utils/request.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import https from 'node:https';
|
||||
import http from 'node:http';
|
||||
|
||||
export class RequestUtil {
|
||||
// 适用于获取服务器下发cookies时获取,仅GET
|
||||
static async HttpsGetCookies(url: string): Promise<Map<string, string>> {
|
||||
return new Promise<Map<string, string>>((resolve, reject) => {
|
||||
const protocol = url.startsWith('https://') ? https : http;
|
||||
protocol.get(url, (res) => {
|
||||
const cookiesHeader = res.headers['set-cookie'];
|
||||
if (!cookiesHeader) {
|
||||
resolve(new Map<string, string>());
|
||||
} else {
|
||||
const cookiesMap = new Map<string, string>();
|
||||
cookiesHeader.forEach((cookieStr) => {
|
||||
cookieStr.split(';').forEach((cookiePart) => {
|
||||
const trimmedPart = cookiePart.trim();
|
||||
if (trimmedPart.includes('=')) {
|
||||
const [key, value] = trimmedPart.split('=').map(part => part.trim());
|
||||
cookiesMap.set(key, decodeURIComponent(value)); // 解码cookie值
|
||||
}
|
||||
});
|
||||
});
|
||||
resolve(cookiesMap);
|
||||
}
|
||||
}).on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 请求和回复都是JSON data传原始内容 自动编码json
|
||||
static async HttpGetJson<T>(url: string, method: string = 'GET', data?: any, headers: Record<string, string> = {}, isJsonRet: boolean = true, isArgJson: boolean = true): Promise<T> {
|
||||
const option = new URL(url);
|
||||
const protocol = url.startsWith('https://') ? https : http;
|
||||
const options = {
|
||||
hostname: option.hostname,
|
||||
port: option.port,
|
||||
path: option.href,
|
||||
method: method,
|
||||
headers: headers
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = protocol.request(options, (res: any) => {
|
||||
let responseBody = '';
|
||||
res.on('data', (chunk: string | Buffer) => {
|
||||
responseBody += chunk.toString();
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
try {
|
||||
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
||||
if (isJsonRet) {
|
||||
const responseJson = JSON.parse(responseBody);
|
||||
resolve(responseJson as T);
|
||||
} else {
|
||||
resolve(responseBody as T);
|
||||
}
|
||||
} else {
|
||||
reject(new Error(`Unexpected status code: ${res.statusCode}`));
|
||||
}
|
||||
} catch (parseError) {
|
||||
reject(parseError);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (error: any) => {
|
||||
reject(error);
|
||||
});
|
||||
if (method === 'POST' || method === 'PUT' || method === 'PATCH') {
|
||||
if (isArgJson) {
|
||||
req.write(JSON.stringify(data));
|
||||
} else {
|
||||
req.write(data);
|
||||
}
|
||||
|
||||
}
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
// 请求返回都是原始内容
|
||||
static async HttpGetText(url: string, method: string = 'GET', data?: any, headers: Record<string, string> = {}) {
|
||||
return this.HttpGetJson<string>(url, method, data, headers, false, false);
|
||||
}
|
||||
}
|
@@ -1,9 +1,17 @@
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
// 缓解Win7设备兼容性问题
|
||||
let osName: string;
|
||||
try {
|
||||
osName = os.hostname();
|
||||
} catch (e) {
|
||||
osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4);
|
||||
}
|
||||
export const systemPlatform = os.platform();
|
||||
export const cpuArch = os.arch();
|
||||
export const systemVersion = os.release();
|
||||
export const hostname = os.hostname();
|
||||
export const hostname = osName;
|
||||
const homeDir = os.homedir();
|
||||
export const downloadsPath = path.join(homeDir, 'Downloads');
|
||||
export const systemName = os.type();
|
||||
export const systemName = os.type();
|
||||
|
31
src/common/utils/type.ts
Normal file
31
src/common/utils/type.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 运行时类型转换与检查类
|
||||
*/
|
||||
export class TypeCheck {
|
||||
static isEmpty(value: any): boolean {
|
||||
return value === null || value === undefined || value === '' ||
|
||||
(Array.isArray(value) && value.length === 0) || (typeof value === 'object' && Object.keys(value).length === 0);
|
||||
}
|
||||
}
|
||||
|
||||
export class TypeConvert {
|
||||
static toNumber(value: any): number {
|
||||
const num = Number(value);
|
||||
if (isNaN(num)) {
|
||||
throw new Error(`无法将输入转换为数字: ${value}`);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
static toString(value: any): string {
|
||||
return String(value);
|
||||
}
|
||||
|
||||
static toBoolean(value: any): boolean {
|
||||
return Boolean(value);
|
||||
}
|
||||
|
||||
static toArray(value: any): any[] {
|
||||
return Array.isArray(value) ? value : [value];
|
||||
}
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
import { request } from 'https';
|
||||
export function noifyLoginStatus() {
|
||||
const req = request(
|
||||
{
|
||||
hostname: 'napcat.wumiao.wang',
|
||||
path: '/api/send',
|
||||
port: 443,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0'
|
||||
}
|
||||
},
|
||||
(res) => {
|
||||
//let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
//data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
//console.log('Response:', data);
|
||||
});
|
||||
}
|
||||
);
|
||||
const StatesData = {
|
||||
type: 'event',
|
||||
payload: {
|
||||
'website': '952bf82f-8f49-4456-aec5-e17db5f27f7e',
|
||||
'hostname': 'napcat.demo.cn',
|
||||
'screen': '1920x1080',
|
||||
'language': 'zh-CN',
|
||||
'title': 'OneBot.Login',
|
||||
'url': '/login/onebot11',
|
||||
'referrer': 'https://napcat.demo.cn/login?type=onebot11'
|
||||
}
|
||||
};
|
||||
req.write(JSON.stringify(StatesData));
|
||||
req.end();
|
||||
}
|
@@ -1,44 +1,25 @@
|
||||
import { get as httpsGet } from 'node:https';
|
||||
function requestMirror(url: string): Promise<string | undefined> {
|
||||
return new Promise((resolve, reject) => {
|
||||
httpsGet(url, (response) => {
|
||||
let data = '';
|
||||
response.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
|
||||
response.on('end', () => {
|
||||
try {
|
||||
const parsedData = JSON.parse(data);
|
||||
const version = parsedData.version;
|
||||
resolve(version);
|
||||
} catch (error) {
|
||||
// 解析失败或无法访问域名,跳过
|
||||
resolve(undefined);
|
||||
}
|
||||
});
|
||||
}).on('error', (error) => {
|
||||
// 请求失败,跳过
|
||||
resolve(undefined);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
import { logDebug } from './log';
|
||||
import { RequestUtil } from './request';
|
||||
export async function checkVersion(): Promise<string> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const MirrorList =
|
||||
[
|
||||
'https://fastly.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json',
|
||||
'https://gcore.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json',
|
||||
'https://cdn.jsdelivr.us/gh/NapNeko/NapCatQQ@main/package.json',
|
||||
'https://jsd.cdn.zzko.cn/gh/NapNeko/NapCatQQ@main/package.json'
|
||||
];
|
||||
[
|
||||
'https://fastly.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json',
|
||||
'https://gcore.jsdelivr.net/gh/NapNeko/NapCatQQ@main/package.json',
|
||||
'https://cdn.jsdelivr.us/gh/NapNeko/NapCatQQ@main/package.json',
|
||||
'https://jsd.cdn.zzko.cn/gh/NapNeko/NapCatQQ@main/package.json'
|
||||
];
|
||||
let version = undefined;
|
||||
for (const url of MirrorList) {
|
||||
const version = await requestMirror(url);
|
||||
try {
|
||||
version = (await RequestUtil.HttpGetJson<{ version: string }>(url)).version;
|
||||
} catch (e) {
|
||||
logDebug(e);
|
||||
}
|
||||
if (version) {
|
||||
resolve(version);
|
||||
}
|
||||
}
|
||||
reject('get verison error!');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -16,8 +16,7 @@ export async function getVideoInfo(filePath: string) {
|
||||
size: number,
|
||||
filePath: string
|
||||
}>((resolve, reject) => {
|
||||
// todo: 从配置文件中读取ffmpeg路径
|
||||
const ffmpegPath = './ffmpeg';
|
||||
const ffmpegPath = process.env.FFMPEG_PATH;
|
||||
ffmpegPath && ffmpeg.setFfmpegPath(ffmpegPath);
|
||||
ffmpeg(filePath).ffprobe((err: any, metadata: any) => {
|
||||
if (err) {
|
||||
@@ -27,7 +26,7 @@ export async function getVideoInfo(filePath: string) {
|
||||
if (videoStream) {
|
||||
console.log(`视频尺寸: ${videoStream.width}x${videoStream.height}`);
|
||||
} else {
|
||||
console.log('未找到视频流信息。');
|
||||
return reject('未找到视频流信息。');
|
||||
}
|
||||
resolve({
|
||||
width: videoStream.width, height: videoStream.height,
|
||||
@@ -85,4 +84,4 @@ export function checkFfmpeg(newPath: string | null = null): Promise<boolean> {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
1
src/core
Submodule
1
src/core
Submodule
Submodule src/core added at 5572791869
@@ -1,5 +1,5 @@
|
||||
interface IDependsAdapter {
|
||||
onMSFStatusChange(args: unknown): void;
|
||||
onMSFStatusChange(arg1: number, arg2: number): void;
|
||||
onMSFSsoError(args: unknown): void;
|
||||
getGroupCode(args: unknown): void;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ export interface NodeIDependsAdapter extends IDependsAdapter {
|
||||
new (adapter: IDependsAdapter): NodeIDependsAdapter;
|
||||
}
|
||||
export declare class DependsAdapter implements IDependsAdapter {
|
||||
onMSFStatusChange(args: unknown): void;
|
||||
onMSFStatusChange(arg1: number, arg2: number): void;
|
||||
onMSFSsoError(args: unknown): void;
|
||||
getGroupCode(args: unknown): void;
|
||||
}
|
1
src/core.lib/src/adapters/NodeIDependsAdapter.js
Normal file
1
src/core.lib/src/adapters/NodeIDependsAdapter.js
Normal file
@@ -0,0 +1 @@
|
||||
function _0x3ffb(_0x1c9d40,_0x5c0f27){var _0x3f6fc1=_0x3f6f();return _0x3ffb=function(_0x3ffb38,_0x271006){_0x3ffb38=_0x3ffb38-0x106;var _0x4276a5=_0x3f6fc1[_0x3ffb38];return _0x4276a5;},_0x3ffb(_0x1c9d40,_0x5c0f27);}function _0x3f6f(){var _0x424618=['getGroupCode','1741044ILxECp','9UQYNaS','onMSFStatusChange','2991672SkTikU','1460KsUXQA','4776496veTTGZ','12661LifKnO','onMSFSsoError','129RqxIOj','5YyHkMs','445732NKyeiU','17092eYzbuN','2609103PKGyhk'];_0x3f6f=function(){return _0x424618;};return _0x3f6f();}var _0x4b3ca7=_0x3ffb;(function(_0x33ead7,_0x3bd86f){var _0x32553b=_0x3ffb,_0x4adca9=_0x33ead7();while(!![]){try{var _0x3ec3d5=parseInt(_0x32553b(0x108))/0x1+parseInt(_0x32553b(0x10c))/0x2+parseInt(_0x32553b(0x106))/0x3*(-parseInt(_0x32553b(0x109))/0x4)+parseInt(_0x32553b(0x107))/0x5*(parseInt(_0x32553b(0x10f))/0x6)+-parseInt(_0x32553b(0x10a))/0x7+-parseInt(_0x32553b(0x111))/0x8*(parseInt(_0x32553b(0x10d))/0x9)+parseInt(_0x32553b(0x110))/0xa*(-parseInt(_0x32553b(0x112))/0xb);if(_0x3ec3d5===_0x3bd86f)break;else _0x4adca9['push'](_0x4adca9['shift']());}catch(_0x38a67f){_0x4adca9['push'](_0x4adca9['shift']());}}}(_0x3f6f,0x786ea));export class DependsAdapter{[_0x4b3ca7(0x10e)](_0x3c085d,_0x69bfec){}[_0x4b3ca7(0x113)](_0x37eb86){}[_0x4b3ca7(0x10b)](_0x115358){}}
|
1
src/core.lib/src/adapters/NodeIDispatcherAdapter.js
Normal file
1
src/core.lib/src/adapters/NodeIDispatcherAdapter.js
Normal file
@@ -0,0 +1 @@
|
||||
var _0x52b112=_0xd933;(function(_0x4a6d40,_0x4c13c7){var _0xf87581=_0xd933,_0x29b633=_0x4a6d40();while(!![]){try{var _0x30e6af=parseInt(_0xf87581(0xa7))/0x1*(parseInt(_0xf87581(0xa4))/0x2)+-parseInt(_0xf87581(0xa6))/0x3*(parseInt(_0xf87581(0xab))/0x4)+-parseInt(_0xf87581(0xa8))/0x5+-parseInt(_0xf87581(0xaa))/0x6*(parseInt(_0xf87581(0xa1))/0x7)+parseInt(_0xf87581(0xa9))/0x8+-parseInt(_0xf87581(0xa5))/0x9+parseInt(_0xf87581(0xa2))/0xa;if(_0x30e6af===_0x4c13c7)break;else _0x29b633['push'](_0x29b633['shift']());}catch(_0xa6e89a){_0x29b633['push'](_0x29b633['shift']());}}}(_0x24bd,0x4f6e6));function _0xd933(_0x2d09b4,_0x3dd1dd){var _0x24bd66=_0x24bd();return _0xd933=function(_0xd93315,_0x493521){_0xd93315=_0xd93315-0xa0;var _0x158785=_0x24bd66[_0xd93315];return _0x158785;},_0xd933(_0x2d09b4,_0x3dd1dd);}export class DispatcherAdapter{['dispatchRequest'](_0x30d484){}[_0x52b112(0xa0)](_0x5ba9d6){}[_0x52b112(0xa3)](_0x625e47){}}function _0x24bd(){var _0x7d7cd8=['2uOYoUv','4014072veOxGh','19569xyvpdc','381509XEoltP','1035340ogRufz','4053608idUyPQ','6dctSqr','68iHMTrv','dispatchCall','3611804pSiiVh','7170790rxsDql','dispatchCallWithJson'];_0x24bd=function(){return _0x7d7cd8;};return _0x24bd();}
|
1
src/core.lib/src/adapters/NodeIGlobalAdapter.js
Normal file
1
src/core.lib/src/adapters/NodeIGlobalAdapter.js
Normal file
@@ -0,0 +1 @@
|
||||
function _0x50c4(){var _0x3eea2a=['getAppSetting','163730UvfChN','onGetSrvCalTime','onInstallFinished','104088erCANA','fixPicImgType','54toVfOL','1260681vpHdod','onGetOfflineMsg','268416SvTneZ','onLog','onUpdateGeneralFlag','onShowErrUITips','141243xTPnPi','6PeSSJq','170opSVVT','636996Rslxgl','1229680hZXLtw'];_0x50c4=function(){return _0x3eea2a;};return _0x50c4();}function _0x55b6(_0x70c27b,_0x3f3da4){var _0x50c4e0=_0x50c4();return _0x55b6=function(_0x55b601,_0x4f0278){_0x55b601=_0x55b601-0x175;var _0x39478e=_0x50c4e0[_0x55b601];return _0x39478e;},_0x55b6(_0x70c27b,_0x3f3da4);}var _0x33bddf=_0x55b6;(function(_0xba609f,_0x936df){var _0x5e1af5=_0x55b6,_0x41ca77=_0xba609f();while(!![]){try{var _0x47d9b9=parseInt(_0x5e1af5(0x17c))/0x1*(parseInt(_0x5e1af5(0x17d))/0x2)+parseInt(_0x5e1af5(0x176))/0x3+parseInt(_0x5e1af5(0x17f))/0x4+-parseInt(_0x5e1af5(0x17e))/0x5*(parseInt(_0x5e1af5(0x185))/0x6)+-parseInt(_0x5e1af5(0x182))/0x7+-parseInt(_0x5e1af5(0x178))/0x8*(parseInt(_0x5e1af5(0x175))/0x9)+parseInt(_0x5e1af5(0x180))/0xa;if(_0x47d9b9===_0x936df)break;else _0x41ca77['push'](_0x41ca77['shift']());}catch(_0xed31c1){_0x41ca77['push'](_0x41ca77['shift']());}}}(_0x50c4,0x4c157));export class GlobalAdapter{[_0x33bddf(0x179)](..._0x264d21){}[_0x33bddf(0x183)](..._0x2a10a7){}[_0x33bddf(0x17b)](..._0x507c11){}[_0x33bddf(0x186)](..._0x4f66c7){}[_0x33bddf(0x181)](..._0x11b2e5){}[_0x33bddf(0x184)](..._0x29bc58){}[_0x33bddf(0x17a)](..._0x51d8ee){}[_0x33bddf(0x177)](..._0x437666){}}
|
1
src/core.lib/src/adapters/index.js
Normal file
1
src/core.lib/src/adapters/index.js
Normal file
@@ -0,0 +1 @@
|
||||
function _0x2cc7(_0x2520ab,_0x5ce3c1){var _0x18ac5f=_0x18ac();return _0x2cc7=function(_0x2cc70c,_0x30e5af){_0x2cc70c=_0x2cc70c-0x105;var _0x4f53d0=_0x18ac5f[_0x2cc70c];return _0x4f53d0;},_0x2cc7(_0x2520ab,_0x5ce3c1);}function _0x18ac(){var _0x10a0e0=['2959586cxfKRA','806004JWBpxd','1467524jEbBvR','50250WfmcKe','1550916wbwZqP','5Shnsog','104106dckgZn','2170856AktLrt'];_0x18ac=function(){return _0x10a0e0;};return _0x18ac();}(function(_0x141983,_0x304f22){var _0xab2e7c=_0x2cc7,_0x5b6cf6=_0x141983();while(!![]){try{var _0x1e9083=-parseInt(_0xab2e7c(0x10b))/0x1+-parseInt(_0xab2e7c(0x109))/0x2+parseInt(_0xab2e7c(0x10c))/0x3+-parseInt(_0xab2e7c(0x10a))/0x4*(-parseInt(_0xab2e7c(0x105))/0x5)+-parseInt(_0xab2e7c(0x106))/0x6+-parseInt(_0xab2e7c(0x108))/0x7+parseInt(_0xab2e7c(0x107))/0x8;if(_0x1e9083===_0x304f22)break;else _0x5b6cf6['push'](_0x5b6cf6['shift']());}catch(_0x812e8b){_0x5b6cf6['push'](_0x5b6cf6['shift']());}}}(_0x18ac,0x3feb1));export*from'./NodeIDependsAdapter';export*from'./NodeIDispatcherAdapter';export*from'./NodeIGlobalAdapter';
|
37
src/core.lib/src/apis/file.d.ts
vendored
Normal file
37
src/core.lib/src/apis/file.d.ts
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import { CacheFileListItem, CacheFileType, ChatCacheListItemBasic, ChatType, ElementType } from '@/core/entities';
|
||||
import { GeneralCallResult } from '@/core';
|
||||
import * as fileType from 'file-type';
|
||||
import { ISizeCalculationResult } from 'image-size/dist/types/interface';
|
||||
export declare class NTQQFileApi {
|
||||
static getFileType(filePath: string): Promise<fileType.FileTypeResult | undefined>;
|
||||
static copyFile(filePath: string, destPath: string): Promise<void>;
|
||||
static getFileSize(filePath: string): Promise<number>;
|
||||
static uploadFile(filePath: string, elementType?: ElementType, elementSubType?: number): Promise<{
|
||||
md5: string;
|
||||
fileName: string;
|
||||
path: string;
|
||||
fileSize: number;
|
||||
ext: string;
|
||||
}>;
|
||||
static downloadMedia(msgId: string, chatType: ChatType, peerUid: string, elementId: string, thumbPath: string, sourcePath: string, timeout?: number, force?: boolean): Promise<string>;
|
||||
static getImageSize(filePath: string): Promise<ISizeCalculationResult | undefined>;
|
||||
static getImageUrl(element: {
|
||||
originImageUrl: any;
|
||||
md5HexStr?: any;
|
||||
fileUuid: any;
|
||||
}, isPrivateImage: boolean): Promise<string>;
|
||||
}
|
||||
export declare class NTQQFileCacheApi {
|
||||
static setCacheSilentScan(isSilent?: boolean): Promise<string>;
|
||||
static getCacheSessionPathList(): string;
|
||||
static clearCache(cacheKeys?: Array<string>): unknown;
|
||||
static addCacheScannedPaths(pathMap?: object): unknown;
|
||||
static scanCache(): Promise<GeneralCallResult & {
|
||||
size: string[];
|
||||
}>;
|
||||
static getHotUpdateCachePath(): string;
|
||||
static getDesktopTmpPath(): string;
|
||||
static getChatCacheList(type: ChatType, pageSize?: number, pageIndex?: number): unknown;
|
||||
static getFileCacheInfo(fileType: CacheFileType, pageSize?: number, lastRecord?: CacheFileListItem): void;
|
||||
static clearChatCache(chats?: ChatCacheListItemBasic[], fileKeys?: string[]): Promise<unknown>;
|
||||
}
|
1
src/core.lib/src/apis/file.js
Normal file
1
src/core.lib/src/apis/file.js
Normal file
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
import { FriendRequest } from '@/core/qqnt/entities';
|
||||
import { FriendRequest, User } from '@/core/entities';
|
||||
export declare class NTQQFriendApi {
|
||||
static getFriends(forced?: boolean): Promise<void>;
|
||||
static getFriends(forced?: boolean): Promise<User[]>;
|
||||
static handleFriendRequest(request: FriendRequest, accept: boolean): Promise<void>;
|
||||
}
|
1
src/core.lib/src/apis/friend.js
Normal file
1
src/core.lib/src/apis/friend.js
Normal file
@@ -0,0 +1 @@
|
||||
const _0x1797a0=_0x7579;(function(_0x4a00c9,_0x1a1bcf){const _0x4f7461=_0x7579,_0x3ab7bf=_0x4a00c9();while(!![]){try{const _0x5127a1=-parseInt(_0x4f7461(0xc0))/0x1+-parseInt(_0x4f7461(0xce))/0x2+-parseInt(_0x4f7461(0xca))/0x3+-parseInt(_0x4f7461(0xd5))/0x4+-parseInt(_0x4f7461(0xdc))/0x5+-parseInt(_0x4f7461(0xd7))/0x6+parseInt(_0x4f7461(0xc1))/0x7;if(_0x5127a1===_0x1a1bcf)break;else _0x3ab7bf['push'](_0x3ab7bf['shift']());}catch(_0x3b477f){_0x3ab7bf['push'](_0x3ab7bf['shift']());}}}(_0x38c8,0x1a6d1));import{BuddyListener,napCatCore}from'@/core';function _0x38c8(){const _0x10c91e=['getFriends','获取好友列表完成','ctBpC','onLoginSuccess','friendUid','set','713392fKCymF','uid','607770AgbOMf','开始获取好友列表','push','onBuddyListChange','SBtQW','340480axdnze','reqTime','getBuddyList','buddyList','94497USEBdn','5330262pmqsLp','Lbdfb','BMXGx','uin','then','获取好友列表超时','MherE','QOggR','session','260637funfGr','getBuddyService','MJWcD','handleFriendRequest','248220ncLXgZ'];_0x38c8=function(){return _0x10c91e;};return _0x38c8();}import{logDebug}from'@/common/utils/log';import{uid2UinMap}from'@/core/data';import{randomUUID}from'crypto';function _0x7579(_0x595e4d,_0x2b9809){const _0x38c8d8=_0x38c8();return _0x7579=function(_0x75790d,_0x26832b){_0x75790d=_0x75790d-0xc0;let _0x1d57ed=_0x38c8d8[_0x75790d];return _0x1d57ed;},_0x7579(_0x595e4d,_0x2b9809);}const buddyChangeTasks=new Map(),buddyListener=new BuddyListener();buddyListener[_0x1797a0(0xda)]=_0x397554=>{const _0x3a1160=_0x1797a0,_0x483bd1={'BMXGx':function(_0x7f1a28,_0xf6c771){return _0x7f1a28(_0xf6c771);}};for(const [_0x3011d4,_0x109955]of buddyChangeTasks){_0x483bd1[_0x3a1160(0xc3)](_0x109955,_0x397554),buddyChangeTasks['delete'](_0x3011d4);}},setTimeout(()=>{const _0xdbd5b2=_0x1797a0;napCatCore[_0xdbd5b2(0xd2)](()=>{napCatCore['addListener'](buddyListener);});},0x64);export class NTQQFriendApi{static async[_0x1797a0(0xcf)](_0x3e89fb=![]){const _0x5d7f15=_0x1797a0,_0x3241ae={'Lbdfb':function(_0x1cd2be,_0x3fd31a,_0x34022c){return _0x1cd2be(_0x3fd31a,_0x34022c);},'MherE':_0x5d7f15(0xd0),'SBtQW':function(_0x34b8dd,_0x2c8fc0,_0x22c34c){return _0x34b8dd(_0x2c8fc0,_0x22c34c);},'Kjaux':function(_0x2b59ba,_0x1dc4eb){return _0x2b59ba(_0x1dc4eb);},'ctBpC':_0x5d7f15(0xc6),'ygIll':function(_0xb4e617){return _0xb4e617();}};return new Promise((_0x435b37,_0x2f980c)=>{const _0x39913b=_0x5d7f15,_0x39f420={'MJWcD':function(_0x56d04d,_0x2d94f5){return _0x3241ae['Kjaux'](_0x56d04d,_0x2d94f5);},'QOggR':_0x3241ae[_0x39913b(0xd1)]};let _0x376d2e=![];setTimeout(()=>{const _0xe1411b=_0x39913b;!_0x376d2e&&(logDebug(_0xe1411b(0xc6)),_0x39f420[_0xe1411b(0xcc)](_0x2f980c,_0x39f420[_0xe1411b(0xc8)]));},0x1388);const _0x8c6619=[],_0x43bf21=_0x59f7b3=>{const _0x2ceb9a=_0x39913b;for(const _0x4375a9 of _0x59f7b3){for(const _0x137b40 of _0x4375a9[_0x2ceb9a(0xdf)]){_0x8c6619[_0x2ceb9a(0xd9)](_0x137b40),uid2UinMap[_0x137b40[_0x2ceb9a(0xd6)]]=_0x137b40[_0x2ceb9a(0xc4)];}}_0x376d2e=!![],_0x3241ae[_0x2ceb9a(0xc2)](logDebug,_0x3241ae[_0x2ceb9a(0xc7)],_0x8c6619),_0x435b37(_0x8c6619);};buddyChangeTasks[_0x39913b(0xd4)](_0x3241ae['ygIll'](randomUUID),_0x43bf21),napCatCore[_0x39913b(0xc9)][_0x39913b(0xcb)]()[_0x39913b(0xde)](_0x3e89fb)[_0x39913b(0xc5)](_0x472491=>{const _0x2905b9=_0x39913b;_0x3241ae[_0x2905b9(0xdb)](logDebug,_0x2905b9(0xd8),_0x472491);});});}static async[_0x1797a0(0xcd)](_0x39ccf9,_0xd0ee6f){const _0x96ed9a=_0x1797a0;napCatCore['session'][_0x96ed9a(0xcb)]()?.['approvalFriendRequest']({'friendUid':_0x39ccf9[_0x96ed9a(0xd3)],'reqTime':_0x39ccf9[_0x96ed9a(0xdd)],'accept':_0xd0ee6f});}}
|
33
src/core.lib/src/apis/group.d.ts
vendored
Normal file
33
src/core.lib/src/apis/group.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { GroupMember, GroupRequestOperateTypes, GroupMemberRole, GroupNotify, Group } from '../entities';
|
||||
export declare class NTQQGroupApi {
|
||||
static getGroups(forced?: boolean): Promise<Group[]>;
|
||||
static getSingleScreenNotifies(num: number): Promise<GroupNotify[]>;
|
||||
static getGroupMembers(groupQQ: string, num?: number): Promise<Map<string, GroupMember>>;
|
||||
static getGroupNotifies(): Promise<void>;
|
||||
static getGroupIgnoreNotifies(): Promise<void>;
|
||||
static uploadGroupBulletinPic(GroupCode: string, imageurl: string): Promise<import("@/core").GeneralCallResult & {
|
||||
errCode: number;
|
||||
picInfo?: {
|
||||
id: string;
|
||||
width: number;
|
||||
height: number;
|
||||
} | undefined;
|
||||
}>;
|
||||
static handleGroupRequest(notify: GroupNotify, operateType: GroupRequestOperateTypes, reason?: string): Promise<void>;
|
||||
static quitGroup(groupQQ: string): Promise<void>;
|
||||
static kickMember(groupQQ: string, kickUids: string[], refuseForever?: boolean, kickReason?: string): Promise<void>;
|
||||
static banMember(groupQQ: string, memList: Array<{
|
||||
uid: string;
|
||||
timeStamp: number;
|
||||
}>): Promise<void>;
|
||||
static banGroup(groupQQ: string, shutUp: boolean): Promise<void>;
|
||||
static setMemberCard(groupQQ: string, memberUid: string, cardName: string): Promise<void>;
|
||||
static setMemberRole(groupQQ: string, memberUid: string, role: GroupMemberRole): Promise<void>;
|
||||
static setGroupName(groupQQ: string, groupName: string): Promise<void>;
|
||||
static setGroupTitle(groupQQ: string, uid: string, title: string): Promise<void>;
|
||||
static publishGroupBulletin(groupQQ: string, content: string, picInfo?: {
|
||||
id: string;
|
||||
width: number;
|
||||
height: number;
|
||||
} | undefined, pinned?: number, confirmRequired?: number): Promise<import("@/core").GeneralCallResult>;
|
||||
}
|
1
src/core.lib/src/apis/group.js
Normal file
1
src/core.lib/src/apis/group.js
Normal file
File diff suppressed because one or more lines are too long
@@ -4,4 +4,5 @@ export * from './group';
|
||||
export * from './msg';
|
||||
export * from './user';
|
||||
export * from './webapi';
|
||||
export * from './window';
|
||||
export * from './sign';
|
||||
export * from './system';
|
1
src/core.lib/src/apis/index.js
Normal file
1
src/core.lib/src/apis/index.js
Normal file
@@ -0,0 +1 @@
|
||||
(function(_0x1105e4,_0x20d2af){var _0x476949=_0x5d6d,_0x2b96e5=_0x1105e4();while(!![]){try{var _0x1f09e2=parseInt(_0x476949(0x19f))/0x1*(-parseInt(_0x476949(0x196))/0x2)+-parseInt(_0x476949(0x19e))/0x3*(-parseInt(_0x476949(0x197))/0x4)+-parseInt(_0x476949(0x19b))/0x5+parseInt(_0x476949(0x199))/0x6+parseInt(_0x476949(0x198))/0x7+-parseInt(_0x476949(0x19a))/0x8*(-parseInt(_0x476949(0x19d))/0x9)+-parseInt(_0x476949(0x19c))/0xa;if(_0x1f09e2===_0x20d2af)break;else _0x2b96e5['push'](_0x2b96e5['shift']());}catch(_0x154754){_0x2b96e5['push'](_0x2b96e5['shift']());}}}(_0x1c47,0x83c3e));export*from'./file';function _0x5d6d(_0x2f1df9,_0xe64233){var _0x1c4767=_0x1c47();return _0x5d6d=function(_0x5d6d7c,_0x338475){_0x5d6d7c=_0x5d6d7c-0x196;var _0x282e21=_0x1c4767[_0x5d6d7c];return _0x282e21;},_0x5d6d(_0x2f1df9,_0xe64233);}export*from'./friend';export*from'./group';export*from'./msg';export*from'./user';export*from'./webapi';function _0x1c47(){var _0x5e51b8=['1285053KkKMMU','1374738CZfBXm','453976NhQeLP','1285170PoALbZ','6373660RZXiQX','72HqEeCa','366BSLZDb','13093JWjawp','12OHSuVp','21180ZQlwjF'];_0x1c47=function(){return _0x5e51b8;};return _0x1c47();}export*from'./sign';export*from'./system';
|
@@ -1,19 +1,25 @@
|
||||
import { Peer, RawMessage, SendMessageElement } from '@/core/qqnt/entities';
|
||||
import { NapCatCore } from '@/core';
|
||||
import { GeneralCallResult } from '@/core/qqnt/services/common';
|
||||
import { Peer, RawMessage, SendMessageElement } from '@/core/entities';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
export declare class NTQQMsgApi {
|
||||
static napCatCore: NapCatCore | null;
|
||||
static setEmojiLike(peer: Peer, msgSeq: string, emojiId: string, set?: boolean): Promise<unknown>;
|
||||
static getMultiMsg(peer: Peer, rootMsgId: string, parentMsgId: string): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[];
|
||||
} | undefined>;
|
||||
static getMsgsByMsgId(peer: Peer, msgIds: string[]): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[];
|
||||
}>;
|
||||
static getMsgsBySeqAndCount(peer: Peer, seq: string, count: number, desc: boolean, unknownArg: boolean): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[];
|
||||
}>;
|
||||
static activateChat(peer: Peer): Promise<void>;
|
||||
static activateChatAndGetHistory(peer: Peer): Promise<void>;
|
||||
static setMsgRead(peer: Peer): Promise<GeneralCallResult>;
|
||||
static getMsgHistory(peer: Peer, msgId: string, count: number): Promise<GeneralCallResult & {
|
||||
msgList: RawMessage[];
|
||||
}>;
|
||||
static fetchRecentContact(): Promise<void>;
|
||||
static recallMsg(peer: Peer, msgIds: string[]): Promise<void>;
|
||||
static sendMsg(peer: Peer, msgElements: SendMessageElement[], waitComplete?: boolean, timeout?: number): Promise<RawMessage>;
|
||||
static forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise<void>;
|
||||
static forwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise<GeneralCallResult>;
|
||||
static multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise<RawMessage>;
|
||||
}
|
1
src/core.lib/src/apis/msg.js
Normal file
1
src/core.lib/src/apis/msg.js
Normal file
File diff suppressed because one or more lines are too long
12
src/core.lib/src/apis/sign.d.ts
vendored
Normal file
12
src/core.lib/src/apis/sign.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface IdMusicSignPostData {
|
||||
type: 'qq' | '163';
|
||||
id: string | number;
|
||||
}
|
||||
export interface CustomMusicSignPostData {
|
||||
type: 'custom';
|
||||
url: string;
|
||||
audio: string;
|
||||
title: string;
|
||||
image?: string;
|
||||
singer?: string;
|
||||
}
|
3
src/core.lib/src/apis/system.d.ts
vendored
Normal file
3
src/core.lib/src/apis/system.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export declare class NTQQSystemApi {
|
||||
static hasOtherRunningQQProcess(): Promise<boolean>;
|
||||
}
|
1
src/core.lib/src/apis/system.js
Normal file
1
src/core.lib/src/apis/system.js
Normal file
@@ -0,0 +1 @@
|
||||
var _0x15f4ac=_0x248d;function _0x248d(_0x40641c,_0x299721){var _0x132379=_0x1323();return _0x248d=function(_0x248d91,_0x4df1fb){_0x248d91=_0x248d91-0x1d7;var _0x4fb3b4=_0x132379[_0x248d91];return _0x4fb3b4;},_0x248d(_0x40641c,_0x299721);}function _0x1323(){var _0xf05135=['8536570vozBEX','1590316ofXmsX','584jWxGgb','1242775GQCxtc','hasOtherRunningQQProcess','12cvVYKV','6232842EkRxea','3692856HmepTO','util','447309IptMuU','507242sxGsVf'];_0x1323=function(){return _0xf05135;};return _0x1323();}(function(_0x391324,_0x2270f8){var _0x178db8=_0x248d,_0x1511f4=_0x391324();while(!![]){try{var _0x25d336=parseInt(_0x178db8(0x1dd))/0x1+parseInt(_0x178db8(0x1db))/0x2+parseInt(_0x178db8(0x1d8))/0x3+-parseInt(_0x178db8(0x1e1))/0x4*(parseInt(_0x178db8(0x1df))/0x5)+parseInt(_0x178db8(0x1d7))/0x6+parseInt(_0x178db8(0x1dc))/0x7+-parseInt(_0x178db8(0x1de))/0x8*(parseInt(_0x178db8(0x1da))/0x9);if(_0x25d336===_0x2270f8)break;else _0x1511f4['push'](_0x1511f4['shift']());}catch(_0x5962d5){_0x1511f4['push'](_0x1511f4['shift']());}}}(_0x1323,0xea388));import{napCatCore}from'@/core';export class NTQQSystemApi{static async[_0x15f4ac(0x1e0)](){var _0x11bc1d=_0x15f4ac;return napCatCore[_0x11bc1d(0x1d9)][_0x11bc1d(0x1e0)]();}}
|
@@ -1,5 +1,7 @@
|
||||
import { User } from '@/core/qqnt/entities';
|
||||
import { User } from '@/core/entities';
|
||||
import { GeneralCallResult } from '@/core';
|
||||
export declare class NTQQUserApi {
|
||||
static setSelfOnlineStatus(status: number, extStatus: number, batteryStatus: number): Promise<GeneralCallResult>;
|
||||
static like(uid: string, count?: number): Promise<{
|
||||
result: number;
|
||||
errMsg: string;
|
||||
@@ -12,8 +14,9 @@ export declare class NTQQUserApi {
|
||||
static getSelfInfo(): Promise<void>;
|
||||
static getUserInfo(uid: string): Promise<void>;
|
||||
static getUserDetailInfo(uid: string): Promise<User>;
|
||||
static getPSkey(): Promise<void>;
|
||||
static getSkey(groupName: string, groupCode: string): Promise<void | {
|
||||
data: string;
|
||||
static getPSkey(domainList: string[], cached?: boolean): Promise<{
|
||||
[key: string]: string;
|
||||
}>;
|
||||
static getRobotUinRange(): Promise<Array<any>>;
|
||||
static getSkey(cached?: boolean): Promise<string | undefined>;
|
||||
}
|
1
src/core.lib/src/apis/user.js
Normal file
1
src/core.lib/src/apis/user.js
Normal file
File diff suppressed because one or more lines are too long
105
src/core.lib/src/apis/webapi.d.ts
vendored
Normal file
105
src/core.lib/src/apis/webapi.d.ts
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
export declare enum WebHonorType {
|
||||
ALL = "all",
|
||||
TALKACTIVE = "talkative",
|
||||
PERFROMER = "performer",
|
||||
LEGEND = "legend",
|
||||
STORONGE_NEWBI = "strong_newbie",
|
||||
EMOTION = "emotion"
|
||||
}
|
||||
export interface WebApiGroupMember {
|
||||
uin: number;
|
||||
role: number;
|
||||
g: number;
|
||||
join_time: number;
|
||||
last_speak_time: number;
|
||||
lv: {
|
||||
point: number;
|
||||
level: number;
|
||||
};
|
||||
card: string;
|
||||
tags: string;
|
||||
flag: number;
|
||||
nick: string;
|
||||
qage: number;
|
||||
rm: number;
|
||||
}
|
||||
export interface WebApiGroupNoticeFeed {
|
||||
u: number;
|
||||
fid: string;
|
||||
pubt: number;
|
||||
msg: {
|
||||
text: string;
|
||||
text_face: string;
|
||||
title: string;
|
||||
pics?: {
|
||||
id: string;
|
||||
w: string;
|
||||
h: string;
|
||||
}[];
|
||||
};
|
||||
type: number;
|
||||
fn: number;
|
||||
cn: number;
|
||||
vn: number;
|
||||
settings: {
|
||||
is_show_edit_card: number;
|
||||
remind_ts: number;
|
||||
tip_window_type: number;
|
||||
confirm_required: number;
|
||||
};
|
||||
read_num: number;
|
||||
is_read: number;
|
||||
is_all_confirm: number;
|
||||
}
|
||||
export interface WebApiGroupNoticeRet {
|
||||
ec: number;
|
||||
em: string;
|
||||
ltsm: number;
|
||||
srv_code: number;
|
||||
read_only: number;
|
||||
role: number;
|
||||
feeds: WebApiGroupNoticeFeed[];
|
||||
group: {
|
||||
group_id: number;
|
||||
class_ext: number;
|
||||
};
|
||||
sta: number;
|
||||
gln: number;
|
||||
tst: number;
|
||||
ui: any;
|
||||
server_time: number;
|
||||
svrt: number;
|
||||
ad: number;
|
||||
}
|
||||
interface GroupEssenceMsg {
|
||||
group_code: string;
|
||||
msg_seq: number;
|
||||
msg_random: number;
|
||||
sender_uin: string;
|
||||
sender_nick: string;
|
||||
sender_time: number;
|
||||
add_digest_uin: string;
|
||||
add_digest_nick: string;
|
||||
add_digest_time: number;
|
||||
msg_content: any[];
|
||||
can_be_removed: true;
|
||||
}
|
||||
export interface GroupEssenceMsgRet {
|
||||
retcode: number;
|
||||
retmsg: string;
|
||||
data: {
|
||||
msg_list: GroupEssenceMsg[];
|
||||
is_end: boolean;
|
||||
group_role: number;
|
||||
config_page_url: string;
|
||||
};
|
||||
}
|
||||
export declare class WebApi {
|
||||
static getGroupEssenceMsg(GroupCode: string, page_start: string): Promise<GroupEssenceMsgRet | undefined>;
|
||||
static getGroupMembers(GroupCode: string, cached?: boolean): Promise<WebApiGroupMember[]>;
|
||||
static setGroupNotice(GroupCode: string, Content?: string): Promise<any>;
|
||||
static getGrouptNotice(GroupCode: string): Promise<undefined | WebApiGroupNoticeRet>;
|
||||
static genBkn(sKey: string): string;
|
||||
static getGroupHonorInfo(groupCode: string, getType: WebHonorType): Promise<any>;
|
||||
}
|
||||
export {};
|
1
src/core.lib/src/apis/webapi.js
Normal file
1
src/core.lib/src/apis/webapi.js
Normal file
File diff suppressed because one or more lines are too long
1
src/core.lib/src/apis/window.js
Normal file
1
src/core.lib/src/apis/window.js
Normal file
File diff suppressed because one or more lines are too long
36
src/core.lib/src/core.d.ts
vendored
Normal file
36
src/core.lib/src/core.d.ts
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/// <reference types="node" />
|
||||
import { NodeIQQNTWrapperEngine, NodeIQQNTWrapperSession, NodeQQNTWrapperUtil } from '@/core/wrapper';
|
||||
import { QuickLoginResult } from '@/core/services';
|
||||
import { BuddyListener, GroupListener, MsgListener, ProfileListener } from '@/core/listeners';
|
||||
export interface OnLoginSuccess {
|
||||
(uin: string, uid: string): void | Promise<void>;
|
||||
}
|
||||
export declare class NapCatCore {
|
||||
readonly session: NodeIQQNTWrapperSession;
|
||||
readonly util: NodeQQNTWrapperUtil;
|
||||
readonly engine: NodeIQQNTWrapperEngine;
|
||||
private readonly loginListener;
|
||||
private loginService;
|
||||
private onLoginSuccessFuncList;
|
||||
private proxyHandler;
|
||||
constructor();
|
||||
get dataPath(): string;
|
||||
get dataPathGlobal(): string;
|
||||
private initConfig;
|
||||
private initSession;
|
||||
private initDataListener;
|
||||
addListener(listener: BuddyListener | GroupListener | MsgListener | ProfileListener): number;
|
||||
onLoginSuccess(func: OnLoginSuccess): void;
|
||||
quickLogin(uin: string): Promise<QuickLoginResult>;
|
||||
qrLogin(cb: (url: string, base64: string, buffer: Buffer) => Promise<void>): Promise<{
|
||||
url: string;
|
||||
base64: string;
|
||||
buffer: Buffer;
|
||||
}>;
|
||||
passwordLogin(uin: string, password: string, proofSig?: string, proofRand?: string, proofSid?: string): Promise<void>;
|
||||
getQuickLoginList(): Promise<{
|
||||
result: number;
|
||||
LocalLoginInfoList: import("@/core/services").LoginListItem[];
|
||||
}>;
|
||||
}
|
||||
export declare const napCatCore: NapCatCore;
|
1
src/core.lib/src/core.js
Normal file
1
src/core.lib/src/core.js
Normal file
File diff suppressed because one or more lines are too long
42
src/core.lib/src/data.d.ts
vendored
Normal file
42
src/core.lib/src/data.d.ts
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import { type Friend, type FriendRequest, type Group, type GroupMember, GroupNotify, type SelfInfo, BuddyCategoryType } from './entities';
|
||||
import { WebApiGroupMember } from '@/core/apis';
|
||||
export declare const Credentials: {
|
||||
Skey: string;
|
||||
CreatTime: number;
|
||||
PskeyData: Map<string, string>;
|
||||
PskeyTime: Map<string, number>;
|
||||
};
|
||||
export declare const WebGroupData: {
|
||||
GroupData: Map<string, WebApiGroupMember[]>;
|
||||
GroupTime: Map<string, number>;
|
||||
};
|
||||
export declare const selfInfo: SelfInfo;
|
||||
export declare const groups: Map<string, Group>;
|
||||
export declare function deleteGroup(groupQQ: string): void;
|
||||
export declare const groupMembers: Map<string, Map<string, GroupMember>>;
|
||||
export declare const friends: Map<string, Friend>;
|
||||
export declare const friendRequests: Record<string, FriendRequest>;
|
||||
export declare const groupNotifies: Record<string, GroupNotify>;
|
||||
export declare const napCatError: {
|
||||
ffmpegError: string;
|
||||
httpServerError: string;
|
||||
wsServerError: string;
|
||||
otherError: string;
|
||||
};
|
||||
export declare function getFriend(uinOrUid: string): Promise<Friend | undefined>;
|
||||
export declare function getGroup(qq: string | number): Promise<Group | undefined>;
|
||||
export declare function getGroupMember(groupQQ: string | number, memberUinOrUid: string | number): Promise<GroupMember | null | undefined>;
|
||||
export declare const uid2UinMap: Record<string, string>;
|
||||
export declare function getUidByUin(uin: string): string | undefined;
|
||||
export declare const tempGroupCodeMap: Record<string, string>;
|
||||
export declare const rawFriends: Array<BuddyCategoryType>;
|
||||
export declare const stat: {
|
||||
packet_received: number;
|
||||
packet_sent: number;
|
||||
message_received: number;
|
||||
message_sent: number;
|
||||
last_message_time: number;
|
||||
disconnect_times: number;
|
||||
lost_times: number;
|
||||
packet_lost: number;
|
||||
};
|
1
src/core.lib/src/data.js
Normal file
1
src/core.lib/src/data.js
Normal file
@@ -0,0 +1 @@
|
||||
const _0x5a6eab=_0xeb44;(function(_0x3cb552,_0x35c5db){const _0x576f7e=_0xeb44,_0x1ed07d=_0x3cb552();while(!![]){try{const _0x3a90b7=-parseInt(_0x576f7e(0xd8))/0x1*(parseInt(_0x576f7e(0xdb))/0x2)+parseInt(_0x576f7e(0xd5))/0x3*(-parseInt(_0x576f7e(0xe4))/0x4)+parseInt(_0x576f7e(0xd6))/0x5+parseInt(_0x576f7e(0xe3))/0x6+-parseInt(_0x576f7e(0xec))/0x7+parseInt(_0x576f7e(0xde))/0x8+parseInt(_0x576f7e(0xe9))/0x9;if(_0x3a90b7===_0x35c5db)break;else _0x1ed07d['push'](_0x1ed07d['shift']());}catch(_0x182542){_0x1ed07d['push'](_0x1ed07d['shift']());}}}(_0x3596,0xa6e80));import{isNumeric}from'@/common/utils/helper';import{NTQQGroupApi}from'@/core/apis';export const Credentials={'Skey':'','CreatTime':0x0,'PskeyData':new Map(),'PskeyTime':new Map()};export const WebGroupData={'GroupData':new Map(),'GroupTime':new Map()};export const selfInfo={'uid':'','uin':'','nick':'','online':!![]};export const groups=new Map();export function deleteGroup(_0x26573b){const _0x4968b2=_0xeb44;groups['delete'](_0x26573b),groupMembers[_0x4968b2(0xe0)](_0x26573b);}export const groupMembers=new Map();export const friends=new Map();function _0x3596(){const _0x1619fb=['4hOMdJD','getGroupMembers','NapCat未能正常启动,请检查日志查看错误','forEach','values','3817296QsnlmF','DjbGE','groupCode','2988447pVAUhI','length','2509413MxrgEn','4587095QbXboO','find','19oaPLqu','toString','cDWZE','112154iWpJka','getGroups','set','5911952IAyMVs','get','delete','from','uin','5591676OmEWFp'];_0x3596=function(){return _0x1619fb;};return _0x3596();}export const friendRequests={};export const groupNotifies={};export const napCatError={'ffmpegError':'','httpServerError':'','wsServerError':'','otherError':_0x5a6eab(0xe6)};export async function getFriend(_0x3f6cb3){const _0x433e3f=_0x5a6eab,_0x12b02a={'cDWZE':function(_0x34edb7,_0x4461f3){return _0x34edb7(_0x4461f3);}};_0x3f6cb3=_0x3f6cb3[_0x433e3f(0xd9)]();if(_0x12b02a[_0x433e3f(0xda)](isNumeric,_0x3f6cb3)){const _0x10a363=Array[_0x433e3f(0xe1)](friends[_0x433e3f(0xe8)]());return _0x10a363['find'](_0x190043=>_0x190043[_0x433e3f(0xe2)]===_0x3f6cb3);}else return friends[_0x433e3f(0xdf)](_0x3f6cb3);}export async function getGroup(_0x36e3f2){const _0x1e0892=_0x5a6eab;let _0x2d7d7e=groups[_0x1e0892(0xdf)](_0x36e3f2[_0x1e0892(0xd9)]());if(!_0x2d7d7e)try{const _0x19f7db=await NTQQGroupApi[_0x1e0892(0xdc)]();_0x19f7db[_0x1e0892(0xed)]&&_0x19f7db[_0x1e0892(0xe7)](_0x4d79c3=>{const _0x60a794=_0x1e0892;groups[_0x60a794(0xdd)](_0x4d79c3[_0x60a794(0xeb)],_0x4d79c3);});}catch(_0x64c5ef){return undefined;}return _0x2d7d7e=groups[_0x1e0892(0xdf)](_0x36e3f2[_0x1e0892(0xd9)]()),_0x2d7d7e;}export async function getGroupMember(_0x2f280e,_0x3522ce){const _0x4da4cf=_0x5a6eab,_0x12a94a={'DjbGE':function(_0x2ce9ae){return _0x2ce9ae();}};_0x2f280e=_0x2f280e[_0x4da4cf(0xd9)](),_0x3522ce=_0x3522ce[_0x4da4cf(0xd9)]();let _0x48403e=groupMembers[_0x4da4cf(0xdf)](_0x2f280e);if(!_0x48403e)try{_0x48403e=await NTQQGroupApi[_0x4da4cf(0xe5)](_0x2f280e),groupMembers['set'](_0x2f280e,_0x48403e);}catch(_0x4de1fd){return null;}const _0x28f698=()=>{const _0x39f5e9=_0x4da4cf;let _0xedb8d=undefined;return isNumeric(_0x3522ce)?_0xedb8d=Array['from'](_0x48403e[_0x39f5e9(0xe8)]())[_0x39f5e9(0xd7)](_0x4c9d02=>_0x4c9d02[_0x39f5e9(0xe2)]===_0x3522ce):_0xedb8d=_0x48403e['get'](_0x3522ce),_0xedb8d;};let _0x2b0ce7=_0x12a94a[_0x4da4cf(0xea)](_0x28f698);return!_0x2b0ce7&&(_0x48403e=await NTQQGroupApi[_0x4da4cf(0xe5)](_0x2f280e),_0x2b0ce7=_0x12a94a[_0x4da4cf(0xea)](_0x28f698)),_0x2b0ce7;}function _0xeb44(_0x6dfd46,_0x156e2a){const _0x359690=_0x3596();return _0xeb44=function(_0xeb44a5,_0x5b9b59){_0xeb44a5=_0xeb44a5-0xd5;let _0xbc1a3=_0x359690[_0xeb44a5];return _0xbc1a3;},_0xeb44(_0x6dfd46,_0x156e2a);}export const uid2UinMap={};export function getUidByUin(_0x59a04f){const _0x4ecebc={'VzHyp':function(_0x100f06,_0x4871b6){return _0x100f06===_0x4871b6;}};for(const _0x1a15e6 in uid2UinMap){if(_0x4ecebc['VzHyp'](uid2UinMap[_0x1a15e6],_0x59a04f))return _0x1a15e6;}}export const tempGroupCodeMap={};export const rawFriends=[];export const stat={'packet_received':0x0,'packet_sent':0x0,'message_received':0x0,'message_sent':0x0,'last_message_time':0x0,'disconnect_times':0x0,'lost_times':0x0,'packet_lost':0x0};
|
1
src/core.lib/src/entities/cache.js
Normal file
1
src/core.lib/src/entities/cache.js
Normal file
@@ -0,0 +1 @@
|
||||
function _0x3462(_0x3fd399,_0x1aafb2){var _0x3b381a=_0x3b38();return _0x3462=function(_0x3462bd,_0x41e347){_0x3462bd=_0x3462bd-0x12e;var _0x553dc6=_0x3b381a[_0x3462bd];return _0x553dc6;},_0x3462(_0x3fd399,_0x1aafb2);}(function(_0x1359f0,_0x94a5c2){var _0x2c647f=_0x3462,_0x3b92dd=_0x1359f0();while(!![]){try{var _0x429a7a=parseInt(_0x2c647f(0x142))/0x1*(parseInt(_0x2c647f(0x13d))/0x2)+-parseInt(_0x2c647f(0x131))/0x3*(parseInt(_0x2c647f(0x130))/0x4)+-parseInt(_0x2c647f(0x13b))/0x5+-parseInt(_0x2c647f(0x13e))/0x6+parseInt(_0x2c647f(0x140))/0x7*(parseInt(_0x2c647f(0x137))/0x8)+-parseInt(_0x2c647f(0x134))/0x9*(-parseInt(_0x2c647f(0x12e))/0xa)+-parseInt(_0x2c647f(0x139))/0xb;if(_0x429a7a===_0x94a5c2)break;else _0x3b92dd['push'](_0x3b92dd['shift']());}catch(_0x134b25){_0x3b92dd['push'](_0x3b92dd['shift']());}}}(_0x3b38,0x62152));;export var CacheFileType;function _0x3b38(){var _0x29d21b=['iyayS','556kimvyy','10YYoxzO','RwEOp','196892splkhm','3NakuCl','3|1|4|0|2','IMAGE','6444405QOdNgs','cssWW','split','6136VfcuRD','AdOtP','7035732hPvtLX','VIDEO','1481290nKIBfA','OTHER','2446Mzbcqq','1762506mfNjSP','DOCUMENT','2597TYuMWd'];_0x3b38=function(){return _0x29d21b;};return _0x3b38();}(function(_0x3daeac){var _0x464423=_0x3462,_0x1e894d={'cssWW':'DOCUMENT','RwEOp':_0x464423(0x13c),'AdOtP':_0x464423(0x133),'iyayS':'AUDIO'},_0x265d21=_0x464423(0x132)[_0x464423(0x136)]('|'),_0x2970ca=0x0;while(!![]){switch(_0x265d21[_0x2970ca++]){case'0':_0x3daeac[_0x3daeac[_0x1e894d[_0x464423(0x135)]]=0x3]=_0x464423(0x13f);continue;case'1':_0x3daeac[_0x3daeac[_0x464423(0x13a)]=0x1]=_0x464423(0x13a);continue;case'2':_0x3daeac[_0x3daeac[_0x1e894d['RwEOp']]=0x4]=_0x1e894d[_0x464423(0x12f)];continue;case'3':_0x3daeac[_0x3daeac[_0x1e894d['AdOtP']]=0x0]=_0x1e894d[_0x464423(0x138)];continue;case'4':_0x3daeac[_0x3daeac[_0x1e894d[_0x464423(0x141)]]=0x2]=_0x1e894d[_0x464423(0x141)];continue;}break;}}(CacheFileType||(CacheFileType={})));
|
@@ -1,4 +1,5 @@
|
||||
import { AtType, SendArkElement, SendFaceElement, SendFileElement, SendPicElement, SendPttElement, SendReplyElement, SendTextElement, SendVideoElement } from '../entities';
|
||||
import { AtType, SendArkElement, SendFaceElement, SendFileElement, SendMarkdownElement, SendMarketFaceElement, SendPicElement, SendPttElement, SendReplyElement, SendTextElement, SendVideoElement } from './index';
|
||||
export declare const mFaceCache: Map<string, string>;
|
||||
export declare class SendMsgElementConstructor {
|
||||
static text(content: string): SendTextElement;
|
||||
static at(atUid: string, atNtUid: string, atType: AtType, atName: string): SendTextElement;
|
||||
@@ -8,5 +9,9 @@ export declare class SendMsgElementConstructor {
|
||||
static video(filePath: string, fileName?: string, diyThumbPath?: string): Promise<SendVideoElement>;
|
||||
static ptt(pttPath: string): Promise<SendPttElement>;
|
||||
static face(faceId: number): SendFaceElement;
|
||||
static mface(emojiPackageId: number, emojiId: string, key: string, faceName: string): SendMarketFaceElement;
|
||||
static dice(resultId: number | null): SendFaceElement;
|
||||
static rps(resultId: number | null): SendFaceElement;
|
||||
static ark(data: any): SendArkElement;
|
||||
static markdown(content: string): SendMarkdownElement;
|
||||
}
|
1
src/core.lib/src/entities/constructor.js
Normal file
1
src/core.lib/src/entities/constructor.js
Normal file
File diff suppressed because one or more lines are too long
3665
src/core.lib/src/entities/face_config.json
Normal file
3665
src/core.lib/src/entities/face_config.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ export interface Group {
|
||||
groupStatus: 0;
|
||||
memberRole: 2;
|
||||
isTop: boolean;
|
||||
toppedTimestamp: '0';
|
||||
toppedTimestamp: string;
|
||||
privilegeFlag: number;
|
||||
isConf: boolean;
|
||||
hasModifyConfGroupFace: boolean;
|
||||
@@ -24,8 +24,8 @@ export interface Group {
|
||||
groupCreditLevel: number;
|
||||
groupFlagExt3: number;
|
||||
groupOwnerId: {
|
||||
'memberUin': string;
|
||||
'memberUid': string;
|
||||
memberUin: string;
|
||||
memberUid: string;
|
||||
};
|
||||
}
|
||||
export declare enum GroupMemberRole {
|
1
src/core.lib/src/entities/group.js
Normal file
1
src/core.lib/src/entities/group.js
Normal file
@@ -0,0 +1 @@
|
||||
(function(_0x169207,_0x4f3d10){var _0x528db4=_0x15e0,_0x4dbc17=_0x169207();while(!![]){try{var _0x4f7161=parseInt(_0x528db4(0xe3))/0x1*(parseInt(_0x528db4(0xe6))/0x2)+parseInt(_0x528db4(0xdd))/0x3+-parseInt(_0x528db4(0xde))/0x4+parseInt(_0x528db4(0xe1))/0x5*(parseInt(_0x528db4(0xdf))/0x6)+-parseInt(_0x528db4(0xdb))/0x7*(-parseInt(_0x528db4(0xe2))/0x8)+parseInt(_0x528db4(0xe5))/0x9+-parseInt(_0x528db4(0xe7))/0xa;if(_0x4f7161===_0x4f3d10)break;else _0x4dbc17['push'](_0x4dbc17['shift']());}catch(_0x401d2b){_0x4dbc17['push'](_0x4dbc17['shift']());}}}(_0x5348,0xeb416));function _0x15e0(_0x24e69b,_0x1343a7){var _0x534805=_0x5348();return _0x15e0=function(_0x15e035,_0x5f2d64){_0x15e035=_0x15e035-0xda;var _0x5cd39f=_0x534805[_0x15e035];return _0x5cd39f;},_0x15e0(_0x24e69b,_0x1343a7);}function _0x5348(){var _0x11c69c=['hCPwN','46629bIENHe','19282fAHFqb','21336140BBNCuh','owner','35UHqnsb','PQTZe','605883ooixTS','1401344UgNhNH','7404fGzzkq','admin','3465tDBfSm','2474376cAxImN','87mLJJNi'];_0x5348=function(){return _0x11c69c;};return _0x5348();}export var GroupMemberRole;(function(_0x2f7d96){var _0xc668bb=_0x15e0,_0x5c65f1={'PQTZe':'normal','hCPwN':_0xc668bb(0xe0),'eoxHh':_0xc668bb(0xda)};_0x2f7d96[_0x2f7d96[_0x5c65f1['PQTZe']]=0x2]=_0x5c65f1[_0xc668bb(0xdc)],_0x2f7d96[_0x2f7d96[_0x5c65f1[_0xc668bb(0xe4)]]=0x3]=_0x5c65f1['hCPwN'],_0x2f7d96[_0x2f7d96[_0xc668bb(0xda)]=0x4]=_0x5c65f1['eoxHh'];}(GroupMemberRole||(GroupMemberRole={})));
|
1
src/core.lib/src/entities/index.js
Normal file
1
src/core.lib/src/entities/index.js
Normal file
@@ -0,0 +1 @@
|
||||
function _0x33e6(_0x198084,_0x39dea7){var _0x4c1b7d=_0x4c1b();return _0x33e6=function(_0x33e67b,_0x4ccf17){_0x33e67b=_0x33e67b-0x85;var _0x1e763f=_0x4c1b7d[_0x33e67b];return _0x1e763f;},_0x33e6(_0x198084,_0x39dea7);}(function(_0x4dbb24,_0x1452c6){var _0x14028f=_0x33e6,_0x24f1f2=_0x4dbb24();while(!![]){try{var _0x575f45=parseInt(_0x14028f(0x87))/0x1*(-parseInt(_0x14028f(0x8a))/0x2)+-parseInt(_0x14028f(0x8d))/0x3+parseInt(_0x14028f(0x8b))/0x4*(-parseInt(_0x14028f(0x8e))/0x5)+parseInt(_0x14028f(0x86))/0x6*(parseInt(_0x14028f(0x88))/0x7)+parseInt(_0x14028f(0x8c))/0x8+-parseInt(_0x14028f(0x85))/0x9+parseInt(_0x14028f(0x89))/0xa;if(_0x575f45===_0x1452c6)break;else _0x24f1f2['push'](_0x24f1f2['shift']());}catch(_0x517518){_0x24f1f2['push'](_0x24f1f2['shift']());}}}(_0x4c1b,0xe210c));export*from'./user';export*from'./group';function _0x4c1b(){var _0x548948=['35660210oodevD','17294IQYQJm','44luHGXA','6147368ZSOVKd','1119954UCAmOd','778845BVgcTg','13893111zIQtCA','6KcfrFq','123EsRKqb','8998913fviZJu'];_0x4c1b=function(){return _0x548948;};return _0x4c1b();}export*from'./msg';export*from'./notify';export*from'./cache';export*from'./constructor';
|
@@ -2,7 +2,16 @@ import { GroupMemberRole } from './group';
|
||||
export interface Peer {
|
||||
chatType: ChatType;
|
||||
peerUid: string;
|
||||
guildId?: '';
|
||||
guildId?: string;
|
||||
}
|
||||
export interface KickedOffLineInfo {
|
||||
appId: number;
|
||||
instanceId: number;
|
||||
sameDevice: boolean;
|
||||
tipsDesc: string;
|
||||
tipsTitle: string;
|
||||
kickedType: number;
|
||||
securityKickedType: number;
|
||||
}
|
||||
export declare enum ElementType {
|
||||
TEXT = 1,
|
||||
@@ -12,11 +21,13 @@ export declare enum ElementType {
|
||||
VIDEO = 5,
|
||||
FACE = 6,
|
||||
REPLY = 7,
|
||||
ARK = 10
|
||||
ARK = 10,
|
||||
MFACE = 11,
|
||||
MARKDOWN = 14
|
||||
}
|
||||
export interface SendTextElement {
|
||||
elementType: ElementType.TEXT;
|
||||
elementId: '';
|
||||
elementId: string;
|
||||
textElement: {
|
||||
content: string;
|
||||
atType: number;
|
||||
@@ -27,7 +38,7 @@ export interface SendTextElement {
|
||||
}
|
||||
export interface SendPttElement {
|
||||
elementType: ElementType.PTT;
|
||||
elementId: '';
|
||||
elementId: string;
|
||||
pttElement: {
|
||||
fileName: string;
|
||||
filePath: string;
|
||||
@@ -39,7 +50,7 @@ export interface SendPttElement {
|
||||
voiceChangeType: number;
|
||||
canConvert2Text: boolean;
|
||||
waveAmplitudes: number[];
|
||||
fileSubId: '';
|
||||
fileSubId: string;
|
||||
playState: number;
|
||||
autoConvertText: number;
|
||||
};
|
||||
@@ -54,7 +65,7 @@ export declare enum PicSubType {
|
||||
}
|
||||
export interface SendPicElement {
|
||||
elementType: ElementType.PIC;
|
||||
elementId: '';
|
||||
elementId: string;
|
||||
picElement: {
|
||||
md5HexStr: string;
|
||||
fileSize: number | string;
|
||||
@@ -73,7 +84,7 @@ export interface SendPicElement {
|
||||
}
|
||||
export interface SendReplyElement {
|
||||
elementType: ElementType.REPLY;
|
||||
elementId: '';
|
||||
elementId: string;
|
||||
replyElement: {
|
||||
replayMsgSeq: string;
|
||||
replayMsgId: string;
|
||||
@@ -83,41 +94,50 @@ export interface SendReplyElement {
|
||||
}
|
||||
export interface SendFaceElement {
|
||||
elementType: ElementType.FACE;
|
||||
elementId: '';
|
||||
elementId: string;
|
||||
faceElement: FaceElement;
|
||||
}
|
||||
export interface SendMarketFaceElement {
|
||||
elementType: ElementType.MFACE;
|
||||
marketFaceElement: MarketFaceElement;
|
||||
}
|
||||
export interface FileElement {
|
||||
'fileMd5'?: '';
|
||||
'fileName': string;
|
||||
'filePath': string;
|
||||
fileMd5?: string;
|
||||
fileName: string;
|
||||
filePath: string;
|
||||
fileSize: string;
|
||||
'picHeight'?: number;
|
||||
'picWidth'?: number;
|
||||
'picThumbPath'?: Map<number, string>;
|
||||
'file10MMd5'?: '';
|
||||
'fileSha'?: '';
|
||||
'fileSha3'?: '';
|
||||
'fileUuid'?: '';
|
||||
'fileSubId'?: '';
|
||||
'thumbFileSize'?: number;
|
||||
picHeight?: number;
|
||||
picWidth?: number;
|
||||
picThumbPath?: Map<number, string>;
|
||||
file10MMd5?: string;
|
||||
fileSha?: string;
|
||||
fileSha3?: string;
|
||||
fileUuid?: string;
|
||||
fileSubId?: string;
|
||||
thumbFileSize?: number;
|
||||
fileBizId?: number;
|
||||
}
|
||||
export interface SendFileElement {
|
||||
elementType: ElementType.FILE;
|
||||
elementId: '';
|
||||
elementId: string;
|
||||
fileElement: FileElement;
|
||||
}
|
||||
export interface SendVideoElement {
|
||||
elementType: ElementType.VIDEO;
|
||||
elementId: '';
|
||||
elementId: string;
|
||||
videoElement: VideoElement;
|
||||
}
|
||||
export interface SendArkElement {
|
||||
elementType: ElementType.ARK;
|
||||
elementId: '';
|
||||
elementId: string;
|
||||
arkElement: ArkElement;
|
||||
}
|
||||
export type SendMessageElement = SendTextElement | SendPttElement | SendPicElement | SendReplyElement | SendFaceElement | SendFileElement | SendVideoElement | SendArkElement;
|
||||
export interface SendMarkdownElement {
|
||||
elementType: ElementType.MARKDOWN;
|
||||
elementId: string;
|
||||
markdownElement: MarkdownElement;
|
||||
}
|
||||
export type SendMessageElement = SendTextElement | SendPttElement | SendPicElement | SendReplyElement | SendFaceElement | SendMarketFaceElement | SendFileElement | SendVideoElement | SendArkElement | SendMarkdownElement;
|
||||
export declare enum AtType {
|
||||
notAt = 0,
|
||||
atAll = 1,
|
||||
@@ -126,6 +146,7 @@ export declare enum AtType {
|
||||
export declare enum ChatType {
|
||||
friend = 1,
|
||||
group = 2,
|
||||
chatDevice = 8,//移动设备?
|
||||
temp = 100
|
||||
}
|
||||
export interface PttElement {
|
||||
@@ -187,97 +208,83 @@ export interface GrayTipElement {
|
||||
groupElement: TipGroupElement;
|
||||
xmlElement: {
|
||||
content: string;
|
||||
templId: string;
|
||||
};
|
||||
jsonGrayTipElement: {
|
||||
jsonStr: string;
|
||||
};
|
||||
}
|
||||
export declare enum FaceType {
|
||||
normal = 1,// 小黄脸
|
||||
normal2 = 2,// 新小黄脸, 从faceIndex 222开始?
|
||||
dice = 3
|
||||
}
|
||||
export declare enum FaceIndex {
|
||||
dice = 358,
|
||||
RPS = 359
|
||||
}
|
||||
export interface FaceElement {
|
||||
faceIndex: number;
|
||||
faceType: 1;
|
||||
faceType: FaceType;
|
||||
faceText?: string;
|
||||
packId?: string;
|
||||
stickerId?: string;
|
||||
sourceType?: number;
|
||||
stickerType?: number;
|
||||
resultId?: string;
|
||||
surpriseId?: string;
|
||||
randomType?: number;
|
||||
}
|
||||
export interface MarketFaceElement {
|
||||
'itemType': 6;
|
||||
'faceInfo': 1;
|
||||
'emojiPackageId': 203875;
|
||||
'subType': 3;
|
||||
'mediaType': 0;
|
||||
'imageWidth': 200;
|
||||
'imageHeight': 200;
|
||||
'faceName': string;
|
||||
'emojiId': '094d53bd1c9ac5d35d04b08e8a6c992c';
|
||||
'key': 'a8b1dd0aebc8d910';
|
||||
'param': null;
|
||||
'mobileParam': null;
|
||||
'sourceType': null;
|
||||
'startTime': null;
|
||||
'endTime': null;
|
||||
'emojiType': 1;
|
||||
'hasIpProduct': null;
|
||||
'voiceItemHeightArr': null;
|
||||
'sourceName': null;
|
||||
'sourceJumpUrl': null;
|
||||
'sourceTypeName': null;
|
||||
'backColor': null;
|
||||
'volumeColor': null;
|
||||
'staticFacePath': 'E:\\SystemDocuments\\QQ\\721011692\\nt_qq\\nt_data\\Emoji\\marketface\\203875\\094d53bd1c9ac5d35d04b08e8a6c992c_aio.png';
|
||||
'dynamicFacePath': 'E:\\SystemDocuments\\QQ\\721011692\\nt_qq\\nt_data\\Emoji\\marketface\\203875\\094d53bd1c9ac5d35d04b08e8a6c992c';
|
||||
'supportSize': [
|
||||
{
|
||||
'width': 300;
|
||||
'height': 300;
|
||||
},
|
||||
{
|
||||
'width': 200;
|
||||
'height': 200;
|
||||
}
|
||||
];
|
||||
'apngSupportSize': null;
|
||||
emojiPackageId: number;
|
||||
faceName: string;
|
||||
emojiId: string;
|
||||
key: string;
|
||||
}
|
||||
export interface VideoElement {
|
||||
'filePath': string;
|
||||
'fileName': string;
|
||||
'videoMd5'?: string;
|
||||
'thumbMd5'?: string;
|
||||
'fileTime'?: number;
|
||||
'thumbSize'?: number;
|
||||
'fileFormat'?: number;
|
||||
'fileSize'?: string;
|
||||
'thumbWidth'?: number;
|
||||
'thumbHeight'?: number;
|
||||
'busiType'?: 0;
|
||||
'subBusiType'?: 0;
|
||||
'thumbPath'?: Map<number, any>;
|
||||
'transferStatus'?: 0;
|
||||
'progress'?: 0;
|
||||
'invalidState'?: 0;
|
||||
'fileUuid'?: string;
|
||||
'fileSubId'?: '';
|
||||
'fileBizId'?: null;
|
||||
'originVideoMd5'?: '';
|
||||
'import_rich_media_context'?: null;
|
||||
'sourceVideoCodecFormat'?: number;
|
||||
filePath: string;
|
||||
fileName: string;
|
||||
videoMd5?: string;
|
||||
thumbMd5?: string;
|
||||
fileTime?: number;
|
||||
thumbSize?: number;
|
||||
fileFormat?: number;
|
||||
fileSize?: string;
|
||||
thumbWidth?: number;
|
||||
thumbHeight?: number;
|
||||
busiType?: 0;
|
||||
subBusiType?: 0;
|
||||
thumbPath?: Map<number, any>;
|
||||
transferStatus?: 0;
|
||||
progress?: 0;
|
||||
invalidState?: 0;
|
||||
fileUuid?: string;
|
||||
fileSubId?: string;
|
||||
fileBizId?: null;
|
||||
originVideoMd5?: string;
|
||||
import_rich_media_context?: null;
|
||||
sourceVideoCodecFormat?: number;
|
||||
}
|
||||
export interface MarkdownElement {
|
||||
content: string;
|
||||
}
|
||||
export interface InlineKeyboardElementRowButton {
|
||||
'id': '';
|
||||
'label': string;
|
||||
'visitedLabel': string;
|
||||
'style': 1;
|
||||
'type': 2;
|
||||
'clickLimit': 0;
|
||||
'unsupportTips': '请升级新版手机QQ';
|
||||
'data': string;
|
||||
'atBotShowChannelList': false;
|
||||
'permissionType': 2;
|
||||
'specifyRoleIds': [];
|
||||
'specifyTinyids': [];
|
||||
'isReply': false;
|
||||
'anchor': 0;
|
||||
'enter': false;
|
||||
'subscribeDataTemplateIds': [];
|
||||
id: string;
|
||||
label: string;
|
||||
visitedLabel: string;
|
||||
style: 1;
|
||||
type: 2;
|
||||
clickLimit: 0;
|
||||
unsupportTips: string;
|
||||
data: string;
|
||||
atBotShowChannelList: boolean;
|
||||
permissionType: number;
|
||||
specifyRoleIds: [];
|
||||
specifyTinyids: [];
|
||||
isReply: false;
|
||||
anchor: 0;
|
||||
enter: false;
|
||||
subscribeDataTemplateIds: [];
|
||||
}
|
||||
export interface InlineKeyboardElement {
|
||||
rows: [
|
||||
@@ -297,40 +304,40 @@ export declare enum TipGroupElementType {
|
||||
ban = 8
|
||||
}
|
||||
export interface TipGroupElement {
|
||||
'type': TipGroupElementType;
|
||||
'role': 0;
|
||||
'groupName': string;
|
||||
'memberUid': string;
|
||||
'memberNick': string;
|
||||
'memberRemark': string;
|
||||
'adminUid': string;
|
||||
'adminNick': string;
|
||||
'adminRemark': string;
|
||||
'createGroup': null;
|
||||
'memberAdd'?: {
|
||||
'showType': 1;
|
||||
'otherAdd': null;
|
||||
'otherAddByOtherQRCode': null;
|
||||
'otherAddByYourQRCode': null;
|
||||
'youAddByOtherQRCode': null;
|
||||
'otherInviteOther': null;
|
||||
'otherInviteYou': null;
|
||||
'youInviteOther': null;
|
||||
type: TipGroupElementType;
|
||||
role: 0;
|
||||
groupName: string;
|
||||
memberUid: string;
|
||||
memberNick: string;
|
||||
memberRemark: string;
|
||||
adminUid: string;
|
||||
adminNick: string;
|
||||
adminRemark: string;
|
||||
createGroup: null;
|
||||
memberAdd?: {
|
||||
showType: 1;
|
||||
otherAdd: null;
|
||||
otherAddByOtherQRCode: null;
|
||||
otherAddByYourQRCode: null;
|
||||
youAddByOtherQRCode: null;
|
||||
otherInviteOther: null;
|
||||
otherInviteYou: null;
|
||||
youInviteOther: null;
|
||||
};
|
||||
'shutUp'?: {
|
||||
'curTime': string;
|
||||
'duration': string;
|
||||
'admin': {
|
||||
'uid': string;
|
||||
'card': string;
|
||||
'name': string;
|
||||
'role': GroupMemberRole;
|
||||
shutUp?: {
|
||||
curTime: string;
|
||||
duration: string;
|
||||
admin: {
|
||||
uid: string;
|
||||
card: string;
|
||||
name: string;
|
||||
role: GroupMemberRole;
|
||||
};
|
||||
'member': {
|
||||
'uid': string;
|
||||
'card': string;
|
||||
'name': string;
|
||||
'role': GroupMemberRole;
|
||||
member: {
|
||||
uid: string;
|
||||
card: string;
|
||||
name: string;
|
||||
role: GroupMemberRole;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -344,6 +351,8 @@ export interface RawMessage {
|
||||
msgId: string;
|
||||
msgTime: string;
|
||||
msgSeq: string;
|
||||
msgType: number;
|
||||
subMsgType: number;
|
||||
senderUid: string;
|
||||
senderUin: string;
|
||||
peerUid: string;
|
1
src/core.lib/src/entities/msg.js
Normal file
1
src/core.lib/src/entities/msg.js
Normal file
File diff suppressed because one or more lines are too long
@@ -5,7 +5,8 @@ export declare enum GroupNotifyTypes {
|
||||
ADMIN_SET = 8,
|
||||
KICK_MEMBER = 9,
|
||||
MEMBER_EXIT = 11,// 主动退出
|
||||
ADMIN_UNSET = 12
|
||||
ADMIN_UNSET = 12,
|
||||
ADMIN_UNSET_OTHER = 13
|
||||
}
|
||||
export interface GroupNotifies {
|
||||
doubt: boolean;
|
1
src/core.lib/src/entities/notify.js
Normal file
1
src/core.lib/src/entities/notify.js
Normal file
@@ -0,0 +1 @@
|
||||
(function(_0x58e66b,_0x1508dc){var _0x3fa1d0=_0x4588,_0x338bd9=_0x58e66b();while(!![]){try{var _0x5adf63=parseInt(_0x3fa1d0(0x104))/0x1*(parseInt(_0x3fa1d0(0xec))/0x2)+parseInt(_0x3fa1d0(0xf7))/0x3+parseInt(_0x3fa1d0(0xfa))/0x4*(parseInt(_0x3fa1d0(0xee))/0x5)+-parseInt(_0x3fa1d0(0x10a))/0x6*(parseInt(_0x3fa1d0(0xf3))/0x7)+-parseInt(_0x3fa1d0(0xf5))/0x8+-parseInt(_0x3fa1d0(0xfd))/0x9+-parseInt(_0x3fa1d0(0xef))/0xa*(-parseInt(_0x3fa1d0(0x108))/0xb);if(_0x5adf63===_0x1508dc)break;else _0x338bd9['push'](_0x338bd9['shift']());}catch(_0x41a3a1){_0x338bd9['push'](_0x338bd9['shift']());}}}(_0x4de7,0x83659));export var GroupNotifyTypes;function _0x4588(_0x4c3d88,_0x312d56){var _0x4de7c3=_0x4de7();return _0x4588=function(_0x4588b8,_0x4a8ce4){_0x4588b8=_0x4588b8-0xec;var _0x47be03=_0x4de7c3[_0x4588b8];return _0x47be03;},_0x4588(_0x4c3d88,_0x312d56);}(function(_0x67f101){var _0x468bde=_0x4588,_0xbe098a={'Sfgnd':_0x468bde(0x102),'ZZkkf':'INVITED_JOIN','EaFRW':_0x468bde(0xff),'FjezN':_0x468bde(0xfe),'TlZNZ':_0x468bde(0xf6),'tkkke':_0x468bde(0x10b),'zNcij':'ADMIN_UNSET','SESVB':'ADMIN_UNSET_OTHER'};_0x67f101[_0x67f101[_0xbe098a[_0x468bde(0x106)]]=0x1]=_0xbe098a[_0x468bde(0x106)],_0x67f101[_0x67f101[_0xbe098a[_0x468bde(0xed)]]=0x4]=_0xbe098a[_0x468bde(0xed)],_0x67f101[_0x67f101[_0xbe098a[_0x468bde(0xfb)]]=0x7]=_0xbe098a[_0x468bde(0xfb)],_0x67f101[_0x67f101['ADMIN_SET']=0x8]=_0xbe098a[_0x468bde(0xf2)],_0x67f101[_0x67f101[_0xbe098a['TlZNZ']]=0x9]=_0xbe098a[_0x468bde(0x107)],_0x67f101[_0x67f101[_0xbe098a[_0x468bde(0xfc)]]=0xb]=_0xbe098a['tkkke'],_0x67f101[_0x67f101[_0xbe098a[_0x468bde(0x100)]]=0xc]=_0x468bde(0xf4),_0x67f101[_0x67f101[_0xbe098a[_0x468bde(0x109)]]=0xd]=_0xbe098a[_0x468bde(0x109)];}(GroupNotifyTypes||(GroupNotifyTypes={})));function _0x4de7(){var _0x9e9549=['MEMBER_EXIT','rkJwO','316622wJZxRO','ZZkkf','895OVYNuj','1610Xsuumu','rNnUI','IGNORE','FjezN','3916388TpsWlf','ADMIN_UNSET','3147480ypJAQl','KICK_MEMBER','333786pItAvA','hYQEA','REJECT','23404tNitCy','EaFRW','tkkke','9402417SHoDVU','ADMIN_SET','JOIN_REQUEST','zNcij','WAIT_HANDLE','INVITE_ME','wFcwO','1nMpnMr','reject','Sfgnd','TlZNZ','83281EaevqW','SESVB','6agvJNu'];_0x4de7=function(){return _0x9e9549;};return _0x4de7();}export var GroupNotifyStatus;(function(_0x275760){var _0xc921fb=_0x4588,_0x472158={'rkJwO':_0xc921fb(0xf1),'GjwXI':_0xc921fb(0x101),'hYQEA':'APPROVE','rNnUI':_0xc921fb(0xf9)};_0x275760[_0x275760[_0x472158['rkJwO']]=0x0]=_0x472158[_0xc921fb(0x10c)],_0x275760[_0x275760[_0x472158['GjwXI']]=0x1]=_0x472158['GjwXI'],_0x275760[_0x275760[_0x472158['hYQEA']]=0x2]=_0x472158[_0xc921fb(0xf8)],_0x275760[_0x275760[_0x472158[_0xc921fb(0xf0)]]=0x3]=_0x472158[_0xc921fb(0xf0)];}(GroupNotifyStatus||(GroupNotifyStatus={})));export var GroupRequestOperateTypes;(function(_0x460991){var _0xf35c87=_0x4588,_0x560e6d={'wFcwO':'approve','MAGkQ':_0xf35c87(0x105)};_0x460991[_0x460991[_0x560e6d[_0xf35c87(0x103)]]=0x1]=_0x560e6d[_0xf35c87(0x103)],_0x460991[_0x460991[_0xf35c87(0x105)]=0x2]=_0x560e6d['MAGkQ'];}(GroupRequestOperateTypes||(GroupRequestOperateTypes={})));
|
89
src/core.lib/src/entities/user.d.ts
vendored
Normal file
89
src/core.lib/src/entities/user.d.ts
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
export declare enum Sex {
|
||||
male = 1,
|
||||
female = 2,
|
||||
unknown = 255
|
||||
}
|
||||
export interface BuddyCategoryType {
|
||||
categoryId: number;
|
||||
categroyName: string;
|
||||
categroyMbCount: number;
|
||||
buddyList: User[];
|
||||
}
|
||||
export interface BuddyProfileLikeReq {
|
||||
friendUids: string[];
|
||||
basic: number;
|
||||
vote: number;
|
||||
favorite: number;
|
||||
userProfile: number;
|
||||
type: number;
|
||||
start: number;
|
||||
limit: number;
|
||||
}
|
||||
export interface QQLevel {
|
||||
crownNum: number;
|
||||
sunNum: number;
|
||||
moonNum: number;
|
||||
starNum: number;
|
||||
}
|
||||
export interface User {
|
||||
uid: string;
|
||||
uin: string;
|
||||
nick: string;
|
||||
avatarUrl?: string;
|
||||
longNick?: string;
|
||||
remark?: string;
|
||||
sex?: Sex;
|
||||
qqLevel?: QQLevel;
|
||||
qid?: string;
|
||||
birthday_year?: number;
|
||||
birthday_month?: number;
|
||||
birthday_day?: number;
|
||||
topTime?: string;
|
||||
constellation?: number;
|
||||
shengXiao?: number;
|
||||
kBloodType?: number;
|
||||
homeTown?: string;
|
||||
makeFriendCareer?: number;
|
||||
pos?: string;
|
||||
eMail?: string;
|
||||
phoneNum?: string;
|
||||
college?: string;
|
||||
country?: string;
|
||||
province?: string;
|
||||
city?: string;
|
||||
postCode?: string;
|
||||
address?: string;
|
||||
isBlock?: boolean;
|
||||
isSpecialCareOpen?: boolean;
|
||||
isSpecialCareZone?: boolean;
|
||||
ringId?: string;
|
||||
regTime?: number;
|
||||
interest?: string;
|
||||
labels?: string[];
|
||||
isHideQQLevel?: number;
|
||||
privilegeIcon?: {
|
||||
jumpUrl: string;
|
||||
openIconList: unknown[];
|
||||
closeIconList: unknown[];
|
||||
};
|
||||
photoWall?: {
|
||||
picList: unknown[];
|
||||
};
|
||||
vipFlag?: boolean;
|
||||
yearVipFlag?: boolean;
|
||||
svipFlag?: boolean;
|
||||
vipLevel?: number;
|
||||
status?: number;
|
||||
qidianMasterFlag?: number;
|
||||
qidianCrewFlag?: number;
|
||||
qidianCrewFlag2?: number;
|
||||
extStatus?: number;
|
||||
recommendImgFlag?: number;
|
||||
disableEmojiShortCuts?: number;
|
||||
pendantId?: string;
|
||||
}
|
||||
export interface SelfInfo extends User {
|
||||
online?: boolean;
|
||||
}
|
||||
export interface Friend extends User {
|
||||
}
|
1
src/core.lib/src/entities/user.js
Normal file
1
src/core.lib/src/entities/user.js
Normal file
@@ -0,0 +1 @@
|
||||
(function(_0x1af837,_0x513d25){var _0x182d12=_0x4ce2,_0x35a06e=_0x1af837();while(!![]){try{var _0x5554a9=parseInt(_0x182d12(0x129))/0x1*(parseInt(_0x182d12(0x128))/0x2)+-parseInt(_0x182d12(0x11d))/0x3*(-parseInt(_0x182d12(0x12b))/0x4)+parseInt(_0x182d12(0x124))/0x5*(-parseInt(_0x182d12(0x126))/0x6)+-parseInt(_0x182d12(0x11f))/0x7*(parseInt(_0x182d12(0x11b))/0x8)+parseInt(_0x182d12(0x122))/0x9*(parseInt(_0x182d12(0x121))/0xa)+parseInt(_0x182d12(0x123))/0xb*(parseInt(_0x182d12(0x127))/0xc)+-parseInt(_0x182d12(0x11c))/0xd;if(_0x5554a9===_0x513d25)break;else _0x35a06e['push'](_0x35a06e['shift']());}catch(_0x13a3e9){_0x35a06e['push'](_0x35a06e['shift']());}}}(_0x4acb,0xa5324));function _0x4ce2(_0x54cac0,_0x92b011){var _0x4acba9=_0x4acb();return _0x4ce2=function(_0x4ce2a7,_0x56441d){_0x4ce2a7=_0x4ce2a7-0x11b;var _0x40255c=_0x4acba9[_0x4ce2a7];return _0x40255c;},_0x4ce2(_0x54cac0,_0x92b011);}export var Sex;(function(_0x116ef4){var _0x47250b=_0x4ce2,_0x3289a9={'DIQVZ':'male','SlTgL':_0x47250b(0x125),'ipDcX':_0x47250b(0x12a)};_0x116ef4[_0x116ef4[_0x3289a9[_0x47250b(0x120)]]=0x1]=_0x3289a9[_0x47250b(0x120)],_0x116ef4[_0x116ef4['female']=0x2]=_0x3289a9[_0x47250b(0x11e)],_0x116ef4[_0x116ef4[_0x3289a9[_0x47250b(0x12c)]]=0xff]=_0x47250b(0x12a);}(Sex||(Sex={})));function _0x4acb(){var _0x1ee556=['230593kaEsqb','25lwwnBc','female','471894LaXFCp','348biHRDw','2XnnvaC','960569vwItRA','unknown','40YZzxAk','ipDcX','6305336hbBBxR','20576543GqSSgg','164865OvLnqe','SlTgL','7ymZVAz','DIQVZ','13228210IsIOpS','9DyMHZD'];_0x4acb=function(){return _0x1ee556;};return _0x4acb();}
|
8
src/core.lib/src/external/hook.d.ts
vendored
Normal file
8
src/core.lib/src/external/hook.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
declare class HookApi {
|
||||
private readonly moeHook;
|
||||
constructor();
|
||||
getRKey(): string;
|
||||
isAvailable(): boolean;
|
||||
}
|
||||
export declare const hookApi: HookApi;
|
||||
export {};
|
1
src/core.lib/src/external/hook.js
vendored
Normal file
1
src/core.lib/src/external/hook.js
vendored
Normal file
File diff suppressed because one or more lines are too long
42
src/core.lib/src/index.d.ts
vendored
42
src/core.lib/src/index.d.ts
vendored
@@ -1,27 +1,15 @@
|
||||
/// <reference types="node" />
|
||||
import { GlobalAdapter } from './qqnt/adapters';
|
||||
import { QRCodeLoginSucceedType } from './qqnt/services';
|
||||
import { NapCatCoreWrapper } from './wrapper';
|
||||
import { NapCatCoreLogin } from './login';
|
||||
import { NapCatCoreSession } from './session';
|
||||
import { NapCatCoreService } from './service';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import * as log4js from '@log4js-node/log4js-api';
|
||||
export interface LoginSuccessCallback {
|
||||
(): void | Promise<void>;
|
||||
}
|
||||
export declare class NapCatCore extends EventEmitter {
|
||||
readonly log: log4js.Logger;
|
||||
readonly adapter: GlobalAdapter;
|
||||
readonly wrapper: NapCatCoreWrapper;
|
||||
readonly login: NapCatCoreLogin;
|
||||
readonly session: NapCatCoreSession;
|
||||
readonly service: NapCatCoreService;
|
||||
private loginSuccessCbList;
|
||||
constructor();
|
||||
initPostLogin(args: QRCodeLoginSucceedType): Promise<void>;
|
||||
private onLoginSuccess;
|
||||
private onMessage;
|
||||
addLoginSuccessCallback(cb: LoginSuccessCallback): void;
|
||||
}
|
||||
export declare const napCatCore: NapCatCore;
|
||||
import QQWrapper from './wrapper';
|
||||
export * from './adapters';
|
||||
export * from './apis';
|
||||
export * from './entities';
|
||||
export * from './listeners';
|
||||
export * from './services';
|
||||
export * as Adapters from './adapters';
|
||||
export * as APIs from './apis';
|
||||
export * as Entities from './entities';
|
||||
export * as Listeners from './listeners';
|
||||
export * as Services from './services';
|
||||
export { QQWrapper as Wrapper };
|
||||
export * as WrapperInterface from './wrapper';
|
||||
export * as SessionConfig from './sessionConfig';
|
||||
export { napCatCore } from './core';
|
||||
|
File diff suppressed because one or more lines are too long
@@ -1,11 +1,7 @@
|
||||
import { FriendRequestNotify, User } from '@/core/qqnt/entities';
|
||||
import { BuddyCategoryType, FriendRequestNotify } from '@/core/entities';
|
||||
export type OnBuddyChangeParams = BuddyCategoryType[];
|
||||
interface IBuddyListener {
|
||||
onBuddyListChange(arg: {
|
||||
categoryId: number;
|
||||
categroyName: string;
|
||||
categroyMbCount: number;
|
||||
buddyList: User[];
|
||||
}[]): void;
|
||||
onBuddyListChange(arg: OnBuddyChangeParams): void;
|
||||
onBuddyInfoChange(arg: unknown): void;
|
||||
onBuddyDetailInfoChange(arg: unknown): void;
|
||||
onNickUpdated(arg: unknown): void;
|
||||
@@ -33,12 +29,7 @@ export declare class BuddyListener implements IBuddyListener {
|
||||
onBlockChanged(arg: unknown): void;
|
||||
onBuddyDetailInfoChange(arg: unknown): void;
|
||||
onBuddyInfoChange(arg: unknown): void;
|
||||
onBuddyListChange(arg: {
|
||||
categoryId: number;
|
||||
categroyName: string;
|
||||
categroyMbCount: number;
|
||||
buddyList: User[];
|
||||
}[]): void;
|
||||
onBuddyListChange(arg: OnBuddyChangeParams): void;
|
||||
onBuddyRemarkUpdated(arg: unknown): void;
|
||||
onBuddyReqChange(arg: FriendRequestNotify): void;
|
||||
onBuddyReqUnreadCntChange(arg: unknown): void;
|
1
src/core.lib/src/listeners/NodeIKernelBuddyListener.js
Normal file
1
src/core.lib/src/listeners/NodeIKernelBuddyListener.js
Normal file
@@ -0,0 +1 @@
|
||||
var _0x146546=_0x5bad;function _0x10f8(){var _0x5511b5=['onCheckBuddySettingResult','8276fZQTGm','onBuddyListChange','onDelBatchBuddyInfos','3324216RsNvkt','onBlockChanged','onBuddyInfoChange','314wcqwxk','12SsIuWy','onAvatarUrlUpdated','onSmartInfos','3207465MLShpe','1364136EwwdBZ','onDoubtBuddyReqUnreadNumChange','onBuddyReqChange','112323hJmuEQ','onBuddyRemarkUpdated','onDoubtBuddyReqChange','551432iOlOQu','onBuddyDetailInfoChange','onAddBuddyNeedVerify','8258730yaxGQB','onSpacePermissionInfos','onAddMeSettingChanged'];_0x10f8=function(){return _0x5511b5;};return _0x10f8();}function _0x5bad(_0x116ec8,_0x29d7da){var _0x10f88b=_0x10f8();return _0x5bad=function(_0x5badc4,_0x191a50){_0x5badc4=_0x5badc4-0x94;var _0x334eb0=_0x10f88b[_0x5badc4];return _0x334eb0;},_0x5bad(_0x116ec8,_0x29d7da);}(function(_0x55112b,_0x467ec9){var _0x346d44=_0x5bad,_0x3fba42=_0x55112b();while(!![]){try{var _0x406063=parseInt(_0x346d44(0xa5))/0x1*(-parseInt(_0x346d44(0xab))/0x2)+-parseInt(_0x346d44(0x9b))/0x3*(-parseInt(_0x346d44(0x94))/0x4)+parseInt(_0x346d44(0xa1))/0x5+parseInt(_0x346d44(0x98))/0x6+parseInt(_0x346d44(0x9e))/0x7+parseInt(_0x346d44(0xa8))/0x8+-parseInt(_0x346d44(0x97))/0x9;if(_0x406063===_0x467ec9)break;else _0x3fba42['push'](_0x3fba42['shift']());}catch(_0x175d4b){_0x3fba42['push'](_0x3fba42['shift']());}}}(_0x10f8,0xcaa3b));export class BuddyListener{[_0x146546(0xa0)](_0x35c4ef){}[_0x146546(0xa3)](_0x269d81){}[_0x146546(0x95)](_0x59f3bc){}[_0x146546(0xa9)](_0x5018f1){}[_0x146546(0x9f)](_0x580806){}[_0x146546(0xaa)](_0xe05173){}[_0x146546(0xa6)](_0x9f817d){}[_0x146546(0x9c)](_0x31931e){}[_0x146546(0x9a)](_0x37fbc4){}['onBuddyReqUnreadCntChange'](_0x491580){}[_0x146546(0xa4)](_0x539f7c){}[_0x146546(0xa7)](_0x33764e){}[_0x146546(0x9d)](_0x44eca8){}[_0x146546(0x99)](_0x42b075){}['onNickUpdated'](_0x3087c0){}[_0x146546(0x96)](_0x56acf0){}[_0x146546(0xa2)](_0x64ef1b){}}
|
17
src/core.lib/src/listeners/NodeIKernelFileAssistantListener.d.ts
vendored
Normal file
17
src/core.lib/src/listeners/NodeIKernelFileAssistantListener.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface IKernelFileAssistantListener {
|
||||
onFileStatusChanged(...args: unknown[]): unknown;
|
||||
onSessionListChanged(...args: unknown[]): unknown;
|
||||
onSessionChanged(...args: unknown[]): unknown;
|
||||
onFileListChanged(...args: unknown[]): unknown;
|
||||
onFileSearch(...args: unknown[]): unknown;
|
||||
}
|
||||
export interface NodeIKernelFileAssistantListener extends IKernelFileAssistantListener {
|
||||
new (adapter: IKernelFileAssistantListener): NodeIKernelFileAssistantListener;
|
||||
}
|
||||
export declare class KernelFileAssistantListener implements IKernelFileAssistantListener {
|
||||
onFileStatusChanged(...args: unknown[]): void;
|
||||
onSessionListChanged(...args: unknown[]): void;
|
||||
onSessionChanged(...args: unknown[]): void;
|
||||
onFileListChanged(...args: unknown[]): void;
|
||||
onFileSearch(...args: unknown[]): void;
|
||||
}
|
@@ -0,0 +1 @@
|
||||
var _0x24d655=_0x3301;(function(_0x298f77,_0x1d37d9){var _0x4fc2c4=_0x3301,_0x4c0720=_0x298f77();while(!![]){try{var _0x75f244=-parseInt(_0x4fc2c4(0xc8))/0x1*(parseInt(_0x4fc2c4(0xc7))/0x2)+parseInt(_0x4fc2c4(0xbf))/0x3+parseInt(_0x4fc2c4(0xc2))/0x4+-parseInt(_0x4fc2c4(0xc3))/0x5+-parseInt(_0x4fc2c4(0xbd))/0x6*(parseInt(_0x4fc2c4(0xc6))/0x7)+-parseInt(_0x4fc2c4(0xbc))/0x8+parseInt(_0x4fc2c4(0xc5))/0x9;if(_0x75f244===_0x1d37d9)break;else _0x4c0720['push'](_0x4c0720['shift']());}catch(_0xd26862){_0x4c0720['push'](_0x4c0720['shift']());}}}(_0x4fbb,0x74633));function _0x3301(_0x245044,_0x1ca2eb){var _0x4fbb68=_0x4fbb();return _0x3301=function(_0x330157,_0x1ba926){_0x330157=_0x330157-0xbc;var _0x20fb9c=_0x4fbb68[_0x330157];return _0x20fb9c;},_0x3301(_0x245044,_0x1ca2eb);}function _0x4fbb(){var _0x830a34=['onFileListChanged','4457286HmCmzj','626332OUOIxk','2PMpJBo','425959OZfBWr','841320NIuglW','6fXYuuy','onSessionListChanged','2236377AVCynJ','onFileStatusChanged','onSessionChanged','1049380hnLIzg','2028675ueNXuT'];_0x4fbb=function(){return _0x830a34;};return _0x4fbb();}export class KernelFileAssistantListener{[_0x24d655(0xc0)](..._0x37af7a){}[_0x24d655(0xbe)](..._0x7a3bef){}[_0x24d655(0xc1)](..._0x5dc330){}[_0x24d655(0xc4)](..._0x37d639){}['onFileSearch'](..._0x44ef18){}}
|
@@ -1,8 +1,8 @@
|
||||
import { Group, GroupMember, GroupNotify } from '@/core/qqnt/entities';
|
||||
import { Group, GroupMember, GroupNotify } from '@/core/entities';
|
||||
interface IGroupListener {
|
||||
onGroupListUpdate(updateType: number, groupList: Group[]): void;
|
||||
onGroupExtListUpdate(...args: unknown[]): void;
|
||||
onGroupSingleScreenNotifies(...args: unknown[]): void;
|
||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void;
|
||||
onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]): void;
|
||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void;
|
||||
onGroupDetailInfoChange(...args: unknown[]): void;
|
||||
@@ -29,11 +29,13 @@ interface IGroupListener {
|
||||
onGroupFirstBulletinNotify(...args: unknown[]): void;
|
||||
onJoinGroupNoVerifyFlag(...args: unknown[]): void;
|
||||
onGroupArkInviteStateResult(...args: unknown[]): void;
|
||||
onGroupMemberLevelInfoChange(...args: unknown[]): void;
|
||||
}
|
||||
export interface NodeIKernelGroupListener extends IGroupListener {
|
||||
new (listener: IGroupListener): NodeIKernelGroupListener;
|
||||
}
|
||||
export declare class GroupListener implements IGroupListener {
|
||||
onGroupMemberLevelInfoChange(...args: unknown[]): void;
|
||||
onGetGroupBulletinListResult(...args: unknown[]): void;
|
||||
onGroupAllInfoChange(...args: unknown[]): void;
|
||||
onGroupBulletinChange(...args: unknown[]): void;
|
||||
@@ -48,7 +50,7 @@ export declare class GroupListener implements IGroupListener {
|
||||
onGroupNotifiesUpdated(dboubt: boolean, notifies: GroupNotify[]): void;
|
||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]): void;
|
||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void;
|
||||
onGroupSingleScreenNotifies(...args: unknown[]): void;
|
||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void;
|
||||
onGroupsMsgMaskResult(...args: unknown[]): void;
|
||||
onGroupStatisticInfoChange(...args: unknown[]): void;
|
||||
onJoinGroupNotify(...args: unknown[]): void;
|
||||
@@ -65,6 +67,7 @@ export declare class GroupListener implements IGroupListener {
|
||||
onShutUpMemberListChanged(...args: unknown[]): void;
|
||||
}
|
||||
export declare class DebugGroupListener implements IGroupListener {
|
||||
onGroupMemberLevelInfoChange(...args: unknown[]): void;
|
||||
onGetGroupBulletinListResult(...args: unknown[]): void;
|
||||
onGroupAllInfoChange(...args: unknown[]): void;
|
||||
onGroupBulletinChange(...args: unknown[]): void;
|
||||
@@ -79,7 +82,7 @@ export declare class DebugGroupListener implements IGroupListener {
|
||||
onGroupNotifiesUpdated(...args: unknown[]): void;
|
||||
onGroupBulletinRichMediaProgressUpdate(...args: unknown[]): void;
|
||||
onGroupNotifiesUnreadCountUpdated(...args: unknown[]): void;
|
||||
onGroupSingleScreenNotifies(...args: unknown[]): void;
|
||||
onGroupSingleScreenNotifies(doubt: boolean, seq: string, notifies: GroupNotify[]): void;
|
||||
onGroupsMsgMaskResult(...args: unknown[]): void;
|
||||
onGroupStatisticInfoChange(...args: unknown[]): void;
|
||||
onJoinGroupNotify(...args: unknown[]): void;
|
1
src/core.lib/src/listeners/NodeIKernelGroupListener.js
Normal file
1
src/core.lib/src/listeners/NodeIKernelGroupListener.js
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user