mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-07-19 12:03:37 +00:00
Compare commits
397 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
18892379de | ||
![]() |
620d61c8dc | ||
![]() |
9f91398875 | ||
![]() |
34d19a471a | ||
![]() |
2ef6477d7c | ||
![]() |
26e6800836 | ||
![]() |
9dbbcf3872 | ||
![]() |
6b3343e1e4 | ||
![]() |
ef48f754a5 | ||
![]() |
3be1ede847 | ||
![]() |
7bff1b61e8 | ||
![]() |
6affd0eb68 | ||
![]() |
0a112d15e0 | ||
![]() |
4e03f582bb | ||
![]() |
8f186c1c5e | ||
![]() |
cd1bae9a1f | ||
![]() |
60796c26ca | ||
![]() |
28927f950d | ||
![]() |
95f16ebc8c | ||
![]() |
25bca8385d | ||
![]() |
965c7f23b4 | ||
![]() |
33082af9cc | ||
![]() |
1f7f3565b0 | ||
![]() |
f784363696 | ||
![]() |
37bd51e138 | ||
![]() |
c367728c43 | ||
![]() |
61f0f5d884 | ||
![]() |
5f2ebeead7 | ||
![]() |
7646037fc7 | ||
![]() |
eac6d285ff | ||
![]() |
b921d5e734 | ||
![]() |
831d808e63 | ||
![]() |
451b88d7e3 | ||
![]() |
f916682a71 | ||
![]() |
2d76bcf0cf | ||
![]() |
8db294efe6 | ||
![]() |
5cc5149aed | ||
![]() |
7ecb01dc9f | ||
![]() |
8bf1a545d9 | ||
![]() |
efb2be2f94 | ||
![]() |
bd2edda494 | ||
![]() |
991172eae4 | ||
![]() |
fc7631f9aa | ||
![]() |
a21efb7d2f | ||
![]() |
03bc844ad0 | ||
![]() |
f7bdc35ed6 | ||
![]() |
0efdffd857 | ||
![]() |
6a16a42d0c | ||
![]() |
e9c00c72b1 | ||
![]() |
ab22f36b8a | ||
![]() |
c57497cd91 | ||
![]() |
ba123236e5 | ||
![]() |
338b6e4607 | ||
![]() |
f88c717560 | ||
![]() |
f8ffc92db5 | ||
![]() |
98c23c172c | ||
![]() |
781c107d8c | ||
![]() |
186668c075 | ||
![]() |
cf9f785193 | ||
![]() |
72d2d3f224 | ||
![]() |
087c76b394 | ||
![]() |
4f9fb2c8c3 | ||
![]() |
334e43e764 | ||
![]() |
7843256402 | ||
![]() |
0522ba35fe | ||
![]() |
24d3b52e0b | ||
![]() |
3177110f0f | ||
![]() |
e1b8243a67 | ||
![]() |
b1c6ce3885 | ||
![]() |
0b4b25a11e | ||
![]() |
1176fe984a | ||
![]() |
6ca768c3ee | ||
![]() |
3da1659c8d | ||
![]() |
9aa4cd319c | ||
![]() |
5af866cdca | ||
![]() |
2b421fa447 | ||
![]() |
30ec964325 | ||
![]() |
714d7d72eb | ||
![]() |
687aa0f363 | ||
![]() |
8363ab07a7 | ||
![]() |
c46a757339 | ||
![]() |
557864395b | ||
![]() |
3f7a85d80b | ||
![]() |
8d18d2ce1f | ||
![]() |
7141ba1587 | ||
![]() |
44d350a225 | ||
![]() |
239b8e72d9 | ||
![]() |
279bdb6fb1 | ||
![]() |
a0cea819da | ||
![]() |
9ab7f60544 | ||
![]() |
aaf7191bf3 | ||
![]() |
628c9be0c8 | ||
![]() |
733052720c | ||
![]() |
a10f007194 | ||
![]() |
6fa50c58d3 | ||
![]() |
c54a58d6e4 | ||
![]() |
34cb1ea3fd | ||
![]() |
f640b0ca91 | ||
![]() |
60e16da42e | ||
![]() |
0cdceb95d6 | ||
![]() |
70bd22d925 | ||
![]() |
82462dd647 | ||
![]() |
c0466e943d | ||
![]() |
b187b4695d | ||
![]() |
b1956d2a37 | ||
![]() |
590b622e5f | ||
![]() |
3d8174396a | ||
![]() |
b8dc6e9bd9 | ||
![]() |
8ee99109dc | ||
![]() |
902041d4ee | ||
![]() |
cc34aef47e | ||
![]() |
0afbbe7c7a | ||
![]() |
8004553ba7 | ||
![]() |
0023b2846a | ||
![]() |
34775c1816 | ||
![]() |
e0759e704b | ||
![]() |
0aa225ca78 | ||
![]() |
b43b4ee5c0 | ||
![]() |
0cdb8cecbf | ||
![]() |
fd6a306742 | ||
![]() |
7f3b3d2277 | ||
![]() |
8be5b977bf | ||
![]() |
d7ddb15f9c | ||
![]() |
9a6a1798d0 | ||
![]() |
14196fd349 | ||
![]() |
941b89a523 | ||
![]() |
a5f9e5f8c0 | ||
![]() |
80c3356c8f | ||
![]() |
914136b750 | ||
![]() |
f9a60795f5 | ||
![]() |
19640927c7 | ||
![]() |
22faac7e36 | ||
![]() |
30d260ab32 | ||
![]() |
115120d066 | ||
![]() |
1327844736 | ||
![]() |
29904f3cb7 | ||
![]() |
50395594b7 | ||
![]() |
9360af88b3 | ||
![]() |
376370336c | ||
![]() |
70df6e3302 | ||
![]() |
0a1fc2dc12 | ||
![]() |
9857f6e437 | ||
![]() |
56d6ebe916 | ||
![]() |
81134ea2d4 | ||
![]() |
a9f3e7fc54 | ||
![]() |
eb84e2f8c9 | ||
![]() |
61cfa0e86d | ||
![]() |
0a01b8ade9 | ||
![]() |
1457efa9a4 | ||
![]() |
fa5c7add7a | ||
![]() |
d644eba4d1 | ||
![]() |
9c422c1a8f | ||
![]() |
b6db37202f | ||
![]() |
4ca3891089 | ||
![]() |
4c7ed01776 | ||
![]() |
45c922c377 | ||
![]() |
f854c258bd | ||
![]() |
a643fac073 | ||
![]() |
861f105bea | ||
![]() |
bf10ce9f1e | ||
![]() |
ccf521d0a8 | ||
![]() |
6075d98eaa | ||
![]() |
a3801fc243 | ||
![]() |
a1f0c05f3a | ||
![]() |
a568c96929 | ||
![]() |
d58bcf3c0e | ||
![]() |
985f2e6436 | ||
![]() |
ad441fa793 | ||
![]() |
316300cc86 | ||
![]() |
5c4f37b234 | ||
![]() |
77b51a072d | ||
![]() |
2536e1ae6a | ||
![]() |
14822c9599 | ||
![]() |
e53c37adc9 | ||
![]() |
c37539354c | ||
![]() |
ae0277f33c | ||
![]() |
b863896249 | ||
![]() |
5b42f8b743 | ||
![]() |
3883fab614 | ||
![]() |
61d6bcec4b | ||
![]() |
3b5902b033 | ||
![]() |
3a88c21a3b | ||
![]() |
91a5055dee | ||
![]() |
7befd1469f | ||
![]() |
c72ebe495c | ||
![]() |
19e06b97e6 | ||
![]() |
7519825303 | ||
![]() |
d9315bf309 | ||
![]() |
8c36c809a0 | ||
![]() |
8138aa3cb2 | ||
![]() |
87aef3ca78 | ||
![]() |
a3f1d26d6b | ||
![]() |
06cebc5670 | ||
![]() |
867fd62d77 | ||
![]() |
650cdf2916 | ||
![]() |
ebf461f2fd | ||
![]() |
27fa319b2a | ||
![]() |
d95ac894f4 | ||
![]() |
ae84a8dd11 | ||
![]() |
2fc963f986 | ||
![]() |
be1f938ebd | ||
![]() |
cccf4d503d | ||
![]() |
9dad2a8ac6 | ||
![]() |
75af104f07 | ||
![]() |
76ecba245b | ||
![]() |
3697c2ced8 | ||
![]() |
b9d1d84716 | ||
![]() |
64b2d547ce | ||
![]() |
d8d2ff7e4e | ||
![]() |
8aa5dc6482 | ||
![]() |
474ba20e61 | ||
![]() |
bdea2d02a9 | ||
![]() |
c4307481f1 | ||
![]() |
b8ac1b28bd | ||
![]() |
24038cda95 | ||
![]() |
86c82e9608 | ||
![]() |
daab5d150b | ||
![]() |
9ff82bdb90 | ||
![]() |
c6d70ef1cf | ||
![]() |
15d4bb3c76 | ||
![]() |
3e698981fd | ||
![]() |
9d45c934a5 | ||
![]() |
c2bf9cf93e | ||
![]() |
b3c6fd7f26 | ||
![]() |
ccd155de71 | ||
![]() |
1f90d2e46b | ||
![]() |
4c5d974c22 | ||
![]() |
392eda1cbc | ||
![]() |
a9da3279e8 | ||
![]() |
1ce8351180 | ||
![]() |
96c334478a | ||
![]() |
f1b0875b05 | ||
![]() |
cea9e11c83 | ||
![]() |
f098b39200 | ||
![]() |
012d948b59 | ||
![]() |
3334cd0a71 | ||
![]() |
d63d53fd88 | ||
![]() |
a7fa39b2fd | ||
![]() |
40bb42e193 | ||
![]() |
9c382c639b | ||
![]() |
a43cde38f1 | ||
![]() |
c35d2e08cd | ||
![]() |
3377c383c1 | ||
![]() |
c00e6d95cd | ||
![]() |
725fccf4ed | ||
![]() |
13129bd219 | ||
![]() |
4561977bcf | ||
![]() |
40be8a91f5 | ||
![]() |
2a04d5830b | ||
![]() |
82a38574f3 | ||
![]() |
fea3a33c2b | ||
![]() |
9a502cdf6f | ||
![]() |
4b616299cf | ||
![]() |
102243e064 | ||
![]() |
4b21ac5ebe | ||
![]() |
4dd7363dd3 | ||
![]() |
3d5e5ab78f | ||
![]() |
73045a1b21 | ||
![]() |
871173a7cf | ||
![]() |
0002313093 | ||
![]() |
948cf5cca6 | ||
![]() |
d40230879c | ||
![]() |
ab22b775f1 | ||
![]() |
42c85224ba | ||
![]() |
e57444a353 | ||
![]() |
3c6503d495 | ||
![]() |
149b518f48 | ||
![]() |
74621447ff | ||
![]() |
3280952931 | ||
![]() |
9e670e2736 | ||
![]() |
9fc6347a2f | ||
![]() |
ec7a15a192 | ||
![]() |
7f99982810 | ||
![]() |
935d83aaf8 | ||
![]() |
0ff6edd546 | ||
![]() |
94f629585a | ||
![]() |
89c04be02f | ||
![]() |
3151965ea8 | ||
![]() |
bdf5159be1 | ||
![]() |
0499ebbea3 | ||
![]() |
d5843b7236 | ||
![]() |
1c9c574a90 | ||
![]() |
39acf20e48 | ||
![]() |
52eb6ed5ab | ||
![]() |
ee78d2d59d | ||
![]() |
60dc5c4a38 | ||
![]() |
50a0dc0355 | ||
![]() |
3f681ec914 | ||
![]() |
0bf499f191 | ||
![]() |
389695a0d6 | ||
![]() |
07f1afb312 | ||
![]() |
ae91e61304 | ||
![]() |
6248991b01 | ||
![]() |
7f2d57ef62 | ||
![]() |
31f8f884f1 | ||
![]() |
4f4af5985a | ||
![]() |
a716fdf6d4 | ||
![]() |
9717f64abd | ||
![]() |
adf239183a | ||
![]() |
6cf209c79c | ||
![]() |
decc5fb3c0 | ||
![]() |
1e0820d613 | ||
![]() |
70124d5177 | ||
![]() |
269de65201 | ||
![]() |
1d11abbfb6 | ||
![]() |
700f308d6e | ||
![]() |
21b6928ca6 | ||
![]() |
998c67a649 | ||
![]() |
fb99e878b0 | ||
![]() |
1619adfc27 | ||
![]() |
5510fb473f | ||
![]() |
be1878cb2b | ||
![]() |
15ab121cbd | ||
![]() |
aa79b0e861 | ||
![]() |
b80e550bcd | ||
![]() |
dbc40b5814 | ||
![]() |
0d5696a644 | ||
![]() |
ceffa05802 | ||
![]() |
d5668920b6 | ||
![]() |
516f2da144 | ||
![]() |
33c94e1888 | ||
![]() |
51ab58cd91 | ||
![]() |
aa7798d1d1 | ||
![]() |
9067a1fc92 | ||
![]() |
4024b6c564 | ||
![]() |
d39730928b | ||
![]() |
e1f049229c | ||
![]() |
8f2676ec19 | ||
![]() |
32d26248dc | ||
![]() |
16f926401b | ||
![]() |
66d60d3599 | ||
![]() |
5a35ab6c34 | ||
![]() |
ba1542bd31 | ||
![]() |
453060945a | ||
![]() |
c8351be461 | ||
![]() |
9954da22a6 | ||
![]() |
907b5611eb | ||
![]() |
5f075de212 | ||
![]() |
8fcf3c5079 | ||
![]() |
07cee90c7a | ||
![]() |
75ad495b98 | ||
![]() |
0bb7288ad2 | ||
![]() |
ad72415532 | ||
![]() |
0ad0353fc0 | ||
![]() |
9fa0dcd7aa | ||
![]() |
1f2e80cd39 | ||
![]() |
6cb6034d43 | ||
![]() |
25134c6ac6 | ||
![]() |
92bf42878a | ||
![]() |
9f4582d158 | ||
![]() |
68af73970e | ||
![]() |
b6ed8d4975 | ||
![]() |
d07d3645ce | ||
![]() |
123759ab17 | ||
![]() |
f2f1f893d8 | ||
![]() |
db93a8eed2 | ||
![]() |
12ab6d4a7d | ||
![]() |
add759e889 | ||
![]() |
f315f7977d | ||
![]() |
f2f6701ebd | ||
![]() |
1a92794d33 | ||
![]() |
7640deb798 | ||
![]() |
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 |
@@ -1,21 +1,21 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf|crlf
|
||||
insert_final_newline = true
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
# Set default charset
|
||||
charset = utf-8
|
||||
|
||||
# 2 space indentation
|
||||
[*.{cjs,mjs,js,jsx,ts,tsx,css,scss,sass,html,json}]
|
||||
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.
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
# Set default charset
|
||||
charset = utf-8
|
||||
|
||||
# 2 space indentation
|
||||
[*.{cjs,mjs,js,jsx,ts,tsx,css,scss,sass,html,json}]
|
||||
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.
|
||||
|
@@ -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'
|
||||
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: "Build"
|
||||
name: "Build Action"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target_platform: [win32]
|
||||
target_arch: [x64]
|
||||
target_arch: [x64,ia32]
|
||||
steps:
|
||||
- name: Clone Main Repository
|
||||
uses: actions/checkout@v4
|
||||
|
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: "release"
|
||||
name: "Build Release"
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target_platform: [win32]
|
||||
target_arch: [x64]
|
||||
target_arch: [x64,ia32]
|
||||
steps:
|
||||
- name: Clone Main Repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -130,6 +130,7 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
body_path: CHANGELOG.md
|
||||
files: |
|
||||
NapCat.win32.ia32.zip
|
||||
NapCat.win32.x64.zip
|
||||
NapCat.linux.x64.zip
|
||||
NapCat.linux.arm64.zip
|
||||
|
69
.github/workflows/test.yml
vendored
Normal file
69
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
name: "Build Test"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: write-all
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target_platform: [linux]
|
||||
target_arch: [x64, arm64]
|
||||
steps:
|
||||
- name: Clone Main Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: 'NapNeko/NapCatQQ'
|
||||
submodules: true
|
||||
ref: main
|
||||
token: ${{ secrets.NAPCAT_BUILD }}
|
||||
- name: Use Node.js 20.X
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.x
|
||||
- name: Build NuCat Linux
|
||||
run: |
|
||||
npm i --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
|
||||
npm run build:prod
|
||||
cd dist
|
||||
npm i --omit=dev --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
|
||||
cd ..
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: NapCat.${{ matrix.target_platform }}.${{ matrix.target_arch }}
|
||||
path: dist
|
||||
build-win32:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target_platform: [win32]
|
||||
target_arch: [x64,ia32]
|
||||
steps:
|
||||
- name: Clone Main Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: 'NapNeko/NapCatQQ'
|
||||
submodules: true
|
||||
ref: main
|
||||
token: ${{ secrets.NAPCAT_BUILD }}
|
||||
- name: Use Node.js 20.X
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.x
|
||||
- name: Build NuCat Linux
|
||||
run: |
|
||||
npm i --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
|
||||
npm run build:prod
|
||||
cd dist
|
||||
npm i --omit=dev --arch=${{ matrix.target_arch }} --platform=${{ matrix.target_platform }}
|
||||
cd ..
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: NapCat.${{ matrix.target_platform }}.${{ matrix.target_arch }}
|
||||
path: dist
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -15,3 +15,4 @@ dist/
|
||||
# Build
|
||||
*.db
|
||||
checkVersion.sh
|
||||
bun.lockb
|
||||
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,4 +0,0 @@
|
||||
[submodule "src/core"]
|
||||
path = src/core
|
||||
url = https://github.com/NapNeko/core.git
|
||||
branch = master
|
20
docs/changelogs/CHANGELOG.v1.6.8.md
Normal file
20
docs/changelogs/CHANGELOG.v1.6.8.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# v1.6.8
|
||||
|
||||
QQ Version: Windows 9.9.12-26000 / Linux 3.2.9-26000
|
||||
## 使用前警告
|
||||
1. 在最近版本由于QQ本体大幅变动,为了保证NapCat可用性,NapCat近期启动与安装方式将将大幅变动,请关注文档和社群获取。
|
||||
2. 在Core上完全执行开源,请不要用于违法用途,如此可能造成NapCat完全停止更新。
|
||||
3. 针对原启动方式的围堵,NapCat研发了多种方式,除此其余理论与扩展的分析和思路将部分展示于Docs,以便各位参与开发与维护NapCat。
|
||||
## 其余·备注
|
||||
启动方式: WayBoot.03 (Electron Main进程为Node 直接注入代码 同理项目: LiteLoader)
|
||||
|
||||
## 修复与优化
|
||||
1. 移除数据库文件读写 ~ 优化性能
|
||||
2. 重构消息发送 极限速度优化 ~ 优化性能
|
||||
3. WebUi配置热重载优化 ~ 修复问题
|
||||
4. 修复偶现崩溃问题 ~ 修复问题
|
||||
|
||||
## 新增与调整
|
||||
1. 最后发言时间重构 入群时间失效 ~ 替换功能
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
15
docs/changelogs/old/CHANGELOG.v1.3.8.md
Normal file
15
docs/changelogs/old/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/old/CHANGELOG.v1.3.9.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.3.9.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.3.9
|
||||
|
||||
QQ Version: Windows 9.9.10-23873 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 修复QQ等级获取与兼容性问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
12
docs/changelogs/old/CHANGELOG.v1.4.0.md
Normal file
12
docs/changelogs/old/CHANGELOG.v1.4.0.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# v1.4.0
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
|
||||
## 新增与调整
|
||||
* 支持空间Cookies获取
|
||||
* 支持获取在线设备 API /get_online_clients
|
||||
* 支持图片OCR API: /.ocr_image /ocr_image
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
14
docs/changelogs/old/CHANGELOG.v1.4.1.md
Normal file
14
docs/changelogs/old/CHANGELOG.v1.4.1.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# v1.4.1
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 提高部分Api兼容性
|
||||
* 优化日志膨胀问题
|
||||
* 在线状态刷新问题修复
|
||||
## 新增与调整
|
||||
* 支持非管理群 本地记录时间数据 (建议 **备份配置 清空配置 重新配置**)
|
||||
* 新增英译中接口 Api: /translate_en2zh
|
||||
* 新增群文件管理相关扩展接口 Api: /get_group_file_count /get_group_file_list /set_group_file_folder /del_group_file /del_group_file_folder
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
12
docs/changelogs/old/CHANGELOG.v1.4.2.md
Normal file
12
docs/changelogs/old/CHANGELOG.v1.4.2.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# v1.4.2
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 修复获取群文件列表Api
|
||||
* 修复退群通知问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.4.3.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.4.3.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.4.3
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 修复名片通知
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
10
docs/changelogs/old/CHANGELOG.v1.4.4.md
Normal file
10
docs/changelogs/old/CHANGELOG.v1.4.4.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# v1.4.4
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 更新
|
||||
* **重大更新:**更新了版本号
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
||||
|
12
docs/changelogs/old/CHANGELOG.v1.4.5.md
Normal file
12
docs/changelogs/old/CHANGELOG.v1.4.5.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# v1.4.5
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 紧急修复二维扫码问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
||||
|
12
docs/changelogs/old/CHANGELOG.v1.4.6.md
Normal file
12
docs/changelogs/old/CHANGELOG.v1.4.6.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# v1.4.6
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 优化整体稳定性
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
||||
|
11
docs/changelogs/old/CHANGELOG.v1.4.7.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.4.7.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.4.7
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 临时扩展 Api: GoCQHTTPUploadGroupFile folder_id字段 用于选择文件夹
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
12
docs/changelogs/old/CHANGELOG.v1.4.8.md
Normal file
12
docs/changelogs/old/CHANGELOG.v1.4.8.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# v1.4.8
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 优化Guid的生成方式
|
||||
* 支持临时消息获取群来源
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.4.9.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.4.9.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.4.9
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 修复接口调用问题 接口标准化 API:set_group_add_request
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.5.0.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.5.0.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.5.0
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 修正各Api默认值
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
12
docs/changelogs/old/CHANGELOG.v1.5.1.md
Normal file
12
docs/changelogs/old/CHANGELOG.v1.5.1.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# v1.5.1
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 支持 新Api: set_self_profile 可设置个性签名
|
||||
* 修复 Api: get_group_system_msg
|
||||
* 整理日志、添加颜色、使用统一的日志函数以提高日志可读性
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
13
docs/changelogs/old/CHANGELOG.v1.5.2.md
Normal file
13
docs/changelogs/old/CHANGELOG.v1.5.2.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# v1.5.2
|
||||
|
||||
QQ Version: Windows 9.9.10-24108 / Linux 3.2.7-23361
|
||||
|
||||
## 修复与优化
|
||||
* 替换Uid/Uin为内部实现
|
||||
* 增加HttpApi调用稳定性
|
||||
* 修复 GetMsg 兼容性
|
||||
|
||||
## 新增与调整
|
||||
* 支持真正意义上的陌生人信息获取 Api: GoCQHTTP_GetStrangerInfo
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
15
docs/changelogs/old/CHANGELOG.v1.5.3.md
Normal file
15
docs/changelogs/old/CHANGELOG.v1.5.3.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# v1.5.3
|
||||
|
||||
QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-23568
|
||||
|
||||
## 修复与优化
|
||||
* 修复引用消息id问题
|
||||
* 修复添加好友的通知
|
||||
|
||||
## 新增与调整
|
||||
* 扩展群分享Json生成
|
||||
* 扩展关于收藏的一系列接口
|
||||
* 支持专属群头衔获取
|
||||
* 支持视频获取直链
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.5.4.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.5.4.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.5.4
|
||||
|
||||
QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-23568
|
||||
|
||||
## 修复与优化
|
||||
* 紧急修复视频与文件问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.5.5.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.5.5.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.5.5
|
||||
|
||||
QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-23568
|
||||
|
||||
## 修复与优化
|
||||
* 紧急修复一些问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.5.6.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.5.6.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.5.6
|
||||
|
||||
QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-24568
|
||||
|
||||
## 修复与优化
|
||||
* 修复一些问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.5.7.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.5.7.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.5.7
|
||||
|
||||
QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-24568
|
||||
|
||||
## 修复与优化
|
||||
* 修复一些问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
14
docs/changelogs/old/CHANGELOG.v1.5.8.md
Normal file
14
docs/changelogs/old/CHANGELOG.v1.5.8.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# v1.5.8
|
||||
|
||||
QQ Version: Windows 9.9.11-24568 / Linux 3.2.9-24568
|
||||
|
||||
## 修复与优化
|
||||
* 修复视频文件残留问题
|
||||
* 重构 getcookies接口 支持大部分常见域
|
||||
|
||||
## 新增与调整
|
||||
* 日志大小限制
|
||||
* 支持 QQ音乐 卡片 无签名支持时 启用内置方法(缺点没有封面 限速1min/条)
|
||||
* 支持Window X86-32机器
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
12
docs/changelogs/old/CHANGELOG.v1.5.9.md
Normal file
12
docs/changelogs/old/CHANGELOG.v1.5.9.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# v1.5.9
|
||||
|
||||
QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815
|
||||
|
||||
## 修复与优化
|
||||
* 优化缓存问题
|
||||
* 修复poke异常上报
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.6.0.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.6.0.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.6.0
|
||||
|
||||
QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815
|
||||
|
||||
## 修复与优化
|
||||
|
||||
|
||||
## 新增与调整
|
||||
* 新增图片subtype属性 区分表情图片与商城图片
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
11
docs/changelogs/old/CHANGELOG.v1.6.1.md
Normal file
11
docs/changelogs/old/CHANGELOG.v1.6.1.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# v1.6.1
|
||||
|
||||
QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815
|
||||
|
||||
## 修复与优化
|
||||
|
||||
|
||||
## 新增与调整
|
||||
* 修复poke异常事件
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
13
docs/changelogs/old/CHANGELOG.v1.6.2.md
Normal file
13
docs/changelogs/old/CHANGELOG.v1.6.2.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# v1.6.2
|
||||
|
||||
QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815
|
||||
|
||||
## 修复与优化
|
||||
* 修复获取Cookies异常崩溃问题
|
||||
* 尝试修复成员退群缓存问题
|
||||
* 修复自身退群后群缓存清理问题
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
13
docs/changelogs/old/CHANGELOG.v1.6.3.md
Normal file
13
docs/changelogs/old/CHANGELOG.v1.6.3.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# v1.6.3
|
||||
|
||||
QQ Version: Windows 9.9.11-24815 / Linux 3.2.9-24815
|
||||
|
||||
## 修复与优化
|
||||
* 修复带有groupid的私聊消息异常发送到群聊消息
|
||||
* 尝试修复rws热重载失效问题
|
||||
* 尝试修复进群事件无法正常获取uin
|
||||
|
||||
## 新增与调整
|
||||
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
18
docs/changelogs/old/CHANGELOG.v1.6.4.md
Normal file
18
docs/changelogs/old/CHANGELOG.v1.6.4.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# v1.6.4
|
||||
|
||||
QQ Version: Windows 9.9.12-26000 / Linux 3.2.9-26000
|
||||
## 使用前警告
|
||||
1. 在最近版本由于QQ本体大幅变动,为了保证NapCat可用性,NapCat近期启动与安装方式将将大幅变动,请关注文档和社群获取。
|
||||
2. 在Core上完全执行开源,请不要用于违法用途,如此可能造成NapCat完全停止更新。
|
||||
3. 针对原启动方式的围堵,NapCat研发了多种方式,除此其余理论与扩展的分析和思路将部分展示于Docs,以便各位参与开发与维护NapCat。
|
||||
## 其余·备注
|
||||
启动方式: WayBoot.03 (Electron Main进程为Node 直接注入代码 同理项目: LiteLoader)
|
||||
|
||||
## 修复与优化
|
||||
1. 支持Win平台 9.9.12
|
||||
2. 修复部分发送图片下载异常情况
|
||||
|
||||
## 新增与调整
|
||||
没有哦
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
18
docs/changelogs/old/CHANGELOG.v1.6.5.md
Normal file
18
docs/changelogs/old/CHANGELOG.v1.6.5.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# v1.6.5
|
||||
|
||||
QQ Version: Windows 9.9.12-26000 / Linux 3.2.9-26000
|
||||
## 使用前警告
|
||||
1. 在最近版本由于QQ本体大幅变动,为了保证NapCat可用性,NapCat近期启动与安装方式将将大幅变动,请关注文档和社群获取。
|
||||
2. 在Core上完全执行开源,请不要用于违法用途,如此可能造成NapCat完全停止更新。
|
||||
3. 针对原启动方式的围堵,NapCat研发了多种方式,除此其余理论与扩展的分析和思路将部分展示于Docs,以便各位参与开发与维护NapCat。
|
||||
## 其余·备注
|
||||
启动方式: WayBoot.03 (Electron Main进程为Node 直接注入代码 同理项目: LiteLoader)
|
||||
|
||||
## 修复与优化
|
||||
1. 优化了WrapperNative载入代码
|
||||
2. 优化缓存
|
||||
|
||||
## 新增与调整
|
||||
没有哦
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
17
docs/changelogs/old/CHANGELOG.v1.6.6.md
Normal file
17
docs/changelogs/old/CHANGELOG.v1.6.6.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# v1.6.6
|
||||
|
||||
QQ Version: Windows 9.9.12-26000 / Linux 3.2.9-26000
|
||||
## 使用前警告
|
||||
1. 在最近版本由于QQ本体大幅变动,为了保证NapCat可用性,NapCat近期启动与安装方式将将大幅变动,请关注文档和社群获取。
|
||||
2. 在Core上完全执行开源,请不要用于违法用途,如此可能造成NapCat完全停止更新。
|
||||
3. 针对原启动方式的围堵,NapCat研发了多种方式,除此其余理论与扩展的分析和思路将部分展示于Docs,以便各位参与开发与维护NapCat。
|
||||
## 其余·备注
|
||||
启动方式: WayBoot.03 (Electron Main进程为Node 直接注入代码 同理项目: LiteLoader)
|
||||
|
||||
## 修复与优化
|
||||
1. 修复了一些问题
|
||||
|
||||
## 新增与调整
|
||||
没有哦
|
||||
|
||||
新增的 API 详细见[API文档](https://napneko.github.io/zh-CN/develop/extends_api)
|
49
docs/develop/Image.NTAndroid.md
Normal file
49
docs/develop/Image.NTAndroid.md
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
public static final int C2C_PIC_DOWNLOAD = 1004;
|
||||
public static final String C2C_PIC_DOWNLOAD_DOMAIN = "c2cpicdw.qpic.cn";
|
||||
public static final String C2C_PIC_DOWNLOAD_QUIC_DOMAIN = "c2cpicdw.quic.qpic.cn";
|
||||
public static final int FLAG_NOT_UPLOAD = 3;
|
||||
public static final int FLAG_UPLOADINFO_ERROR = 4;
|
||||
public static final int GROUP_PIC_DOWNLOAD = 1000;
|
||||
public static final String GROUP_PIC_DOWNLOAD_DOMAIN = "gchat.qpic.cn";
|
||||
public static final String GROUP_PIC_DOWNLOAD_QUIC_DOMAIN = "gchat.quic.qpic.cn";
|
||||
public static final String GUILD_PIC_DOWNLOAD_DOMAIN = "gchat.qpic.cn/qmeetpic";
|
||||
public static final boolean NEW_STORE_FLAG = true;
|
||||
public static final String PTT_VIDEO_DOWNLOAD_DOMAIN = "grouptalk.c2c.qq.com";
|
||||
|
||||
protected static final int AVIF_DECODE_EXCEPTION = 4;
|
||||
protected static final int AVIF_DECODE_FAIL = 1;
|
||||
protected static final int AVIF_DECODE_FAIL_SO_FAIL = 2;
|
||||
protected static final int AVIF_DECODE_FAIL_UNKNOWN = 6;
|
||||
protected static final int AVIF_DECODE_FILETYPE_ERROR = 5;
|
||||
protected static final int AVIF_DECODE_OOM = 3;
|
||||
protected static final int AVIF_DECODE_RENAME_FAIL = 7;
|
||||
protected static final int AVIF_DECODE_SUC = 0;
|
||||
public static final String AVIF_FILE_SUFFIX = ".avif";
|
||||
public static final int AVIF_REQ_APPRUNTIME_NULL = 12;
|
||||
public static final int AVIF_REQ_CODEC_UNSURPPORT = 5;
|
||||
protected static final int AVIF_REQ_DENSITY_UNSURPPORT = 10;
|
||||
protected static final int AVIF_REQ_FLASH_PHOTO = 9;
|
||||
protected static final int AVIF_REQ_HAS_TMP_AVIF = 7;
|
||||
protected static final int AVIF_REQ_INVALID_MSG_RECORD = 2;
|
||||
protected static final int AVIF_REQ_IS_RAW_PHOTO = 3;
|
||||
protected static final int AVIF_REQ_OUTPUTSTREAM_UNSURPPORT = 11;
|
||||
protected static final int AVIF_REQ_OVERSIZE = 6;
|
||||
protected static final int AVIF_REQ_RETRY = 1;
|
||||
public static final int AVIF_REQ_SO_DOWNLOAD_FAILED = 8;
|
||||
protected static final int AVIF_REQ_SUC = 0;
|
||||
public static final int AVIF_REQ_SWITCH_CLOSE = 4;
|
||||
public static final String C2C_PIC_DOWNLOAD_ERROR_CODE = "C2CPicDownloadErrorCode";
|
||||
static final int DOWNLOAD_ST_COMPLETE = 1;
|
||||
static final int DOWNLOAD_ST_HEAD = 2;
|
||||
static final int DOWNLOAD_ST_LEFT = 4;
|
||||
static final int DOWNLOAD_ST_PART = 3;
|
||||
private static final int ENCRYPT_APPID = 1600000226;
|
||||
public static final String GROUP_PIC_DOWNLOAD_ERROR_CODE = "GroupPicDownloadErrorCode";
|
||||
public static final String KEY_PIC_DOWNLOAD_ERROR_CODE = "param_detail_code";
|
||||
protected static final int QUIC_FAIL_IP_LIST_EMPTY = 1;
|
||||
protected static final int QUIC_FAIL_REQUEST_HTTPS = 3;
|
||||
protected static final int QUIC_FAIL_REQUEST_QUIC = 2;
|
||||
protected static final int QUIC_FAIL_SO_LOAD = 4;
|
||||
public static final String REPORT_TAG_DIRECT_DOWNLOAD_FAIL = "report_direct_download_fail";
|
||||
public static final String REQ_PARAM_AVIF = "tp=avif";
|
444
docs/develop/Msg常量NTAndroid.md
Normal file
444
docs/develop/Msg常量NTAndroid.md
Normal file
@@ -0,0 +1,444 @@
|
||||
```java
|
||||
MsgConstant
|
||||
int ARKSTRUCTELEMENTSUBTYPETENCENTDOCFROMMINIAPP = 1;
|
||||
int ARKSTRUCTELEMENTSUBTYPETENCENTDOCFROMPLUSPANEL = 2;
|
||||
int ARKSTRUCTELEMENTSUBTYPEUNKNOWN = 0;
|
||||
int ATTYPEALL = 1;
|
||||
int ATTYPECATEGORY = 512;
|
||||
int ATTYPECHANNEL = 16;
|
||||
int ATTYPEME = 4;
|
||||
int ATTYPEONE = 2;
|
||||
int ATTYPEONLINE = 64;
|
||||
int ATTYPEROLE = 8;
|
||||
int ATTYPESUMMON = 32;
|
||||
int ATTYPESUMMONONLINE = 128;
|
||||
int ATTYPESUMMONROLE = 256;
|
||||
int ATTYPEUNKNOWN = 0;
|
||||
int CALENDARELEMSUBTYPECOMMON = 3;
|
||||
int CALENDARELEMSUBTYPESTRONG = 1;
|
||||
int CALENDARELEMSUBTYPEUNKNOWN = 0;
|
||||
int CALENDARELEMSUBTYPEWEAK = 2;
|
||||
int FACEBUBBLEELEMSUBTYPENORMAL = 1;
|
||||
int FACEBUBBLEELEMSUBTYPEUNKNOWN = 0;
|
||||
int FETCHLONGMSGERRCODEMSGEXPIRED = 196;
|
||||
int FILEELEMENTSUBTYPEAI = 16;
|
||||
int FILEELEMENTSUBTYPEAPP = 11;
|
||||
int FILEELEMENTSUBTYPEAUDIO = 3;
|
||||
int FILEELEMENTSUBTYPEDOC = 4;
|
||||
int FILEELEMENTSUBTYPEEMOTICON = 15;
|
||||
int FILEELEMENTSUBTYPEEXCEL = 6;
|
||||
int FILEELEMENTSUBTYPEFOLDER = 13;
|
||||
int FILEELEMENTSUBTYPEHTML = 10;
|
||||
int FILEELEMENTSUBTYPEIPA = 14;
|
||||
int FILEELEMENTSUBTYPENORMAL = 0;
|
||||
int FILEELEMENTSUBTYPEPDF = 7;
|
||||
int FILEELEMENTSUBTYPEPIC = 1;
|
||||
int FILEELEMENTSUBTYPEPPT = 5;
|
||||
int FILEELEMENTSUBTYPEPSD = 12;
|
||||
int FILEELEMENTSUBTYPETXT = 8;
|
||||
int FILEELEMENTSUBTYPEVIDEO = 2;
|
||||
int FILEELEMENTSUBTYPEZIP = 9;
|
||||
int GRAYTIPELEMENTSUBTYPEAIOOP = 15;
|
||||
int GRAYTIPELEMENTSUBTYPEBLOCK = 14;
|
||||
int GRAYTIPELEMENTSUBTYPEBUDDY = 5;
|
||||
int GRAYTIPELEMENTSUBTYPEBUDDYNOTIFY = 9;
|
||||
int GRAYTIPELEMENTSUBTYPEEMOJIREPLY = 3;
|
||||
int GRAYTIPELEMENTSUBTYPEESSENCE = 7;
|
||||
int GRAYTIPELEMENTSUBTYPEFEED = 6;
|
||||
int GRAYTIPELEMENTSUBTYPEFEEDCHANNELMSG = 11;
|
||||
int GRAYTIPELEMENTSUBTYPEFILE = 10;
|
||||
int GRAYTIPELEMENTSUBTYPEGROUP = 4;
|
||||
int GRAYTIPELEMENTSUBTYPEGROUPNOTIFY = 8;
|
||||
int GRAYTIPELEMENTSUBTYPEJSON = 17;
|
||||
int GRAYTIPELEMENTSUBTYPELOCALMSG = 13;
|
||||
int GRAYTIPELEMENTSUBTYPEPROCLAMATION = 2;
|
||||
int GRAYTIPELEMENTSUBTYPEREVOKE = 1;
|
||||
int GRAYTIPELEMENTSUBTYPEUNKNOWN = 0;
|
||||
int GRAYTIPELEMENTSUBTYPEWALLET = 16;
|
||||
int GRAYTIPELEMENTSUBTYPEXMLMSG = 12;
|
||||
int INLINEKEYBOARDBUTTONRENDERSTYLEBLUEBLACKGROUND = 4;
|
||||
int INLINEKEYBOARDBUTTONRENDERSTYLEBLUEBORDER = 1;
|
||||
int INLINEKEYBOARDBUTTONRENDERSTYLEGRAYBORDER = 0;
|
||||
int INLINEKEYBOARDBUTTONRENDERSTYLENOBORDER = 2;
|
||||
int INLINEKEYBOARDBUTTONRENDERSTYLEREDCHARACTER = 3;
|
||||
int INPUTSTATUSTYPECANCEL = 2;
|
||||
int INPUTSTATUSTYPESPEAK = 3;
|
||||
int INPUTSTATUSTYPETEXT = 1;
|
||||
int KACTIVITYMSG = 22;
|
||||
int KADDLOCALMSGEXTINFOTYPEPROLOGUEMSG = 1;
|
||||
int KANONYMOUSATMEMSGTYPEINMSGBOX = 1001;
|
||||
int KANONYMOUSFLAGFROMOTHERPEOPLE = 1;
|
||||
int KANONYMOUSFLAGFROMOWN = 2;
|
||||
int KANONYMOUSFLAGINVALID = 0;
|
||||
int KAPPCHANNELMSG = 16;
|
||||
int KATALLMSGTYPEINMSGBOX = 2000;
|
||||
int KATMEMSGTYPEINMSGBOX = 1000;
|
||||
int KATTRIBUTETYPEADELIEMSG = 16;
|
||||
int KATTRIBUTETYPEEXTENDBUSINESS = 13;
|
||||
int KATTRIBUTETYPEFEEDBACKSTATE = 17;
|
||||
int KATTRIBUTETYPEGROUPHONOR = 2;
|
||||
int KATTRIBUTETYPEKINGHONOR = 3;
|
||||
int KATTRIBUTETYPELONGMSG = 8;
|
||||
int KATTRIBUTETYPEMEMORYSTATEMSGINFO = 18;
|
||||
int KATTRIBUTETYPEMSG = 0;
|
||||
int KATTRIBUTETYPEMSGBOXEVENTTYPE = 14;
|
||||
int KATTRIBUTETYPEPERSONAL = 1;
|
||||
int KATTRIBUTETYPEPUBLICACCOUNT = 4;
|
||||
int KATTRIBUTETYPEQQCONNECT = 12;
|
||||
int KATTRIBUTETYPESENDMSGRSPTRANSSVRINFO = 15;
|
||||
int KATTRIBUTETYPESHAREDMSGINFO = 5;
|
||||
int KATTRIBUTETYPETEMPCHATGAMESESSION = 6;
|
||||
int KATTRIBUTETYPETOROBOTMSG = 9;
|
||||
int KATTRIBUTETYPEUININFO = 7;
|
||||
int KATTRIBUTETYPEZPLAN = 11;
|
||||
int KAUTOREPLYTEXTNONEINDEX = -1;
|
||||
int KAVRECORDMSG = 19;
|
||||
int KBUSINESSTYPGUILD = 1;
|
||||
int KBUSINESSTYPNT = 0;
|
||||
int KCHATTYPEADELIE = 42;
|
||||
int KCHATTYPEBUDDYNOTIFY = 5;
|
||||
int KCHATTYPEC2C = 1;
|
||||
int KCHATTYPECIRCLE = 113;
|
||||
int KCHATTYPEDATALINE = 8;
|
||||
int KCHATTYPEDATALINEMQQ = 134;
|
||||
int KCHATTYPEDISC = 3;
|
||||
int KCHATTYPEFAV = 41;
|
||||
int KCHATTYPEGAMEMESSAGE = 105;
|
||||
int KCHATTYPEGAMEMESSAGEFOLDER = 116;
|
||||
int KCHATTYPEGROUP = 2;
|
||||
int KCHATTYPEGROUPBLESS = 133;
|
||||
int KCHATTYPEGROUPGUILD = 9;
|
||||
int KCHATTYPEGROUPHELPER = 7;
|
||||
int KCHATTYPEGROUPNOTIFY = 6;
|
||||
int KCHATTYPEGUILD = 4;
|
||||
int KCHATTYPEGUILDMETA = 16;
|
||||
int KCHATTYPEMATCHFRIEND = 104;
|
||||
int KCHATTYPEMATCHFRIENDFOLDER = 109;
|
||||
int KCHATTYPENEARBY = 106;
|
||||
int KCHATTYPENEARBYASSISTANT = 107;
|
||||
int KCHATTYPENEARBYFOLDER = 110;
|
||||
int KCHATTYPENEARBYHELLOFOLDER = 112;
|
||||
int KCHATTYPENEARBYINTERACT = 108;
|
||||
int KCHATTYPEQQNOTIFY = 132;
|
||||
int KCHATTYPERELATEACCOUNT = 131;
|
||||
int KCHATTYPESERVICEASSISTANT = 118;
|
||||
int KCHATTYPESERVICEASSISTANTSUB = 201;
|
||||
int KCHATTYPESQUAREPUBLIC = 115;
|
||||
int KCHATTYPESUBSCRIBEFOLDER = 30;
|
||||
int KCHATTYPETEMPADDRESSBOOK = 111;
|
||||
int KCHATTYPETEMPBUSSINESSCRM = 102;
|
||||
int KCHATTYPETEMPC2CFROMGROUP = 100;
|
||||
int KCHATTYPETEMPC2CFROMUNKNOWN = 99;
|
||||
int KCHATTYPETEMPFRIENDVERIFY = 101;
|
||||
int KCHATTYPETEMPNEARBYPRO = 119;
|
||||
int KCHATTYPETEMPPUBLICACCOUNT = 103;
|
||||
int KCHATTYPETEMPWPA = 117;
|
||||
int KCHATTYPEUNKNOWN = 0;
|
||||
int KCHATTYPEWEIYUN = 40;
|
||||
int KCOMMONREDENVELOPEMSGTYPEINMSGBOX = 1007;
|
||||
int KDOWNSOURCETYPEAIOINNER = 1;
|
||||
int KDOWNSOURCETYPEBIGSCREEN = 2;
|
||||
int KDOWNSOURCETYPEHISTORY = 3;
|
||||
int KDOWNSOURCETYPEUNKNOWN = 0;
|
||||
int KELEMTYPEACTIVITY = 25;
|
||||
int KELEMTYPEACTIVITYSTATE = 41;
|
||||
int KELEMTYPEACTIVITYSUBTYPECREATEMOBATEAM = 12;
|
||||
int KELEMTYPEACTIVITYSUBTYPEDISBANDMOBATEAM = 11;
|
||||
int KELEMTYPEACTIVITYSUBTYPEFEEDSQUARE = 10001;
|
||||
int KELEMTYPEACTIVITYSUBTYPEFINISHGAME = 16;
|
||||
int KELEMTYPEACTIVITYSUBTYPEFINISHMATCHTEAM = 14;
|
||||
int KELEMTYPEACTIVITYSUBTYPEHOTCHAT = 10000;
|
||||
int KELEMTYPEACTIVITYSUBTYPEMINIGAME = 18;
|
||||
int KELEMTYPEACTIVITYSUBTYPEMUSICPLAY = 17;
|
||||
int KELEMTYPEACTIVITYSUBTYPENEWSMOBA = 9;
|
||||
int KELEMTYPEACTIVITYSUBTYPENOLIVE = 2;
|
||||
int KELEMTYPEACTIVITYSUBTYPENOSCREENSHARE = 7;
|
||||
int KELEMTYPEACTIVITYSUBTYPENOVOICE = 3;
|
||||
int KELEMTYPEACTIVITYSUBTYPEONLIVE = 1;
|
||||
int KELEMTYPEACTIVITYSUBTYPEONSCREENSHARE = 6;
|
||||
int KELEMTYPEACTIVITYSUBTYPEONVOICE = 4;
|
||||
int KELEMTYPEACTIVITYSUBTYPESTARTMATCHTEAM = 13;
|
||||
int KELEMTYPEACTIVITYSUBTYPETARTGAME = 15;
|
||||
int KELEMTYPEACTIVITYSUBTYPEUNKNOWN = 0;
|
||||
int KELEMTYPEADELIEACTIONBAR = 44;
|
||||
int KELEMTYPEADELIERECOMMENDEDMSG = 43;
|
||||
int KELEMTYPEARKSTRUCT = 10;
|
||||
int KELEMTYPEAVRECORD = 21;
|
||||
int KELEMTYPECALENDAR = 19;
|
||||
int KELEMTYPEFACE = 6;
|
||||
int KELEMTYPEFACEBUBBLE = 27;
|
||||
int KELEMTYPEFEED = 22;
|
||||
int KELEMTYPEFILE = 3;
|
||||
int KELEMTYPEGIPHY = 15;
|
||||
int KELEMTYPEGRAYTIP = 8;
|
||||
int KELEMTYPEINLINEKEYBOARD = 17;
|
||||
int KELEMTYPEINTEXTGIFT = 18;
|
||||
int KELEMTYPELIVEGIFT = 12;
|
||||
int KELEMTYPEMARKDOWN = 14;
|
||||
int KELEMTYPEMARKETFACE = 11;
|
||||
int KELEMTYPEMULTIFORWARD = 16;
|
||||
int KELEMTYPEONLINEFILE = 23;
|
||||
int KELEMTYPEPIC = 2;
|
||||
int KELEMTYPEPROLOGUE = 46;
|
||||
int KELEMTYPEPTT = 4;
|
||||
int KELEMTYPEREPLY = 7;
|
||||
int KELEMTYPESHARELOCATION = 28;
|
||||
int KELEMTYPESTRUCTLONGMSG = 13;
|
||||
int KELEMTYPETASKTOPMSG = 29;
|
||||
int KELEMTYPETEXT = 1;
|
||||
int KELEMTYPETOFU = 26;
|
||||
int KELEMTYPEUNKNOWN = 0;
|
||||
int KELEMTYPEVIDEO = 5;
|
||||
int KELEMTYPEWALLET = 9;
|
||||
int KELEMTYPEYOLOGAMERESULT = 20;
|
||||
int KENTERAIO = 1;
|
||||
int KEXITAIO = 2;
|
||||
int KFEEDBACKBUTTONTYPEDISLIKE = 2;
|
||||
int KFEEDBACKBUTTONTYPELIKE = 1;
|
||||
int KFEEDBACKBUTTONTYPEPROMPTCLICK = 5;
|
||||
int KFEEDBACKBUTTONTYPEREGENERATE = 4;
|
||||
int KFEEDBACKBUTTONTYPEUNKNOWN = 0;
|
||||
int KFEEDBACKOPTLIKE = 1;
|
||||
int KFEEDBACKOPTUNKNOWN = 0;
|
||||
int KFEEDBACKOPTUNLIKE = 2;
|
||||
int KFRIENDNEWADDEDMSGTYPEINMSGBOX = 1008;
|
||||
int KGAMEBOXNEWMSGTYPEINMSGBOX = 3000;
|
||||
int KGIFTATMEMSGTYPEINMSGBOX = 1005;
|
||||
int KGROUPFILEATALLMSGTYPEINMSGBOX = 2001;
|
||||
int KGROUPHOMEWORK = 20000;
|
||||
int KGROUPHOMEWORKTASK = 20001;
|
||||
int KGROUPKEYWORDMSGTYPEINMSGBOX = 2006;
|
||||
int KGROUPMANNOUNCEATALLMSGTYPEINMSGBOX = 2004;
|
||||
int KGROUPTASKATALLMSGTYPEINMSGBOX = 2003;
|
||||
int KGROUPUNREADTYPEINMSGBOX = 2007;
|
||||
int KGUILDCHANNELLIST = 10;
|
||||
int KHIGHLIGHTWORDINTEMPCHATTYPEINMSGBOX = 1009;
|
||||
int KHOMEWORKREMINDER = 10000;
|
||||
int KLIKEORDISLIKESTATEDISLIKE = 2;
|
||||
int KLIKEORDISLIKESTATELIKE = 1;
|
||||
int KLIKEORDISLIKESTATENONESELECTED = 0;
|
||||
int KMARKETFACE = 17;
|
||||
int KMEMORYSTATEMSGTYPEADELIEWELCOME = 1;
|
||||
int KMEMORYSTATEMSGTYPEUNKNOWN = 0;
|
||||
int KMINIPROGRAMNOTICE = 114;
|
||||
int KMSGSUBTYPEARKGROUPANNOUNCE = 3;
|
||||
int KMSGSUBTYPEARKGROUPANNOUNCECONFIRMREQUIRED = 4;
|
||||
int KMSGSUBTYPEARKGROUPGIFTATME = 5;
|
||||
int KMSGSUBTYPEARKGROUPTASKATALL = 6;
|
||||
int KMSGSUBTYPEARKMULTIMSG = 7;
|
||||
int KMSGSUBTYPEARKNORMAL = 0;
|
||||
int KMSGSUBTYPEARKTENCENTDOCFROMMINIAPP = 1;
|
||||
int KMSGSUBTYPEARKTENCENTDOCFROMPLUSPANEL = 2;
|
||||
int KMSGSUBTYPEEMOTICON = 15;
|
||||
int KMSGSUBTYPEFILEAPP = 11;
|
||||
int KMSGSUBTYPEFILEAUDIO = 3;
|
||||
int KMSGSUBTYPEFILEDOC = 4;
|
||||
int KMSGSUBTYPEFILEEXCEL = 6;
|
||||
int KMSGSUBTYPEFILEFOLDER = 13;
|
||||
int KMSGSUBTYPEFILEHTML = 10;
|
||||
int KMSGSUBTYPEFILEIPA = 14;
|
||||
int KMSGSUBTYPEFILENORMAL = 0;
|
||||
int KMSGSUBTYPEFILEPDF = 7;
|
||||
int KMSGSUBTYPEFILEPIC = 1;
|
||||
int KMSGSUBTYPEFILEPPT = 5;
|
||||
int KMSGSUBTYPEFILEPSD = 12;
|
||||
int KMSGSUBTYPEFILETXT = 8;
|
||||
int KMSGSUBTYPEFILEVIDEO = 2;
|
||||
int KMSGSUBTYPEFILEZIP = 9;
|
||||
int KMSGSUBTYPELINK = 5;
|
||||
int KMSGSUBTYPEMARKETFACE = 1;
|
||||
int KMSGSUBTYPEMIXEMOTICON = 7;
|
||||
int KMSGSUBTYPEMIXFACE = 3;
|
||||
int KMSGSUBTYPEMIXMARKETFACE = 2;
|
||||
int KMSGSUBTYPEMIXPIC = 1;
|
||||
int KMSGSUBTYPEMIXREPLY = 4;
|
||||
int KMSGSUBTYPEMIXTEXT = 0;
|
||||
int KMSGSUBTYPETENCENTDOC = 6;
|
||||
int KMSGTYPEARKSTRUCT = 11;
|
||||
int KMSGTYPEFACEBUBBLE = 24;
|
||||
int KMSGTYPEFILE = 3;
|
||||
int KMSGTYPEGIFT = 14;
|
||||
int KMSGTYPEGIPHY = 13;
|
||||
int KMSGTYPEGRAYTIPS = 5;
|
||||
int KMSGTYPEMIX = 2;
|
||||
int KMSGTYPEMULTIMSGFORWARD = 8;
|
||||
int KMSGTYPENULL = 1;
|
||||
int KMSGTYPEONLINEFILE = 21;
|
||||
int KMSGTYPEONLINEFOLDER = 27;
|
||||
int KMSGTYPEPROLOGUE = 29;
|
||||
int KMSGTYPEPTT = 6;
|
||||
int KMSGTYPEREPLY = 9;
|
||||
int KMSGTYPESHARELOCATION = 25;
|
||||
int KMSGTYPESTRUCT = 4;
|
||||
int KMSGTYPESTRUCTLONGMSG = 12;
|
||||
int KMSGTYPETEXTGIFT = 15;
|
||||
int KMSGTYPEUNKNOWN = 0;
|
||||
int KMSGTYPEVIDEO = 7;
|
||||
int KMSGTYPEWALLET = 10;
|
||||
int KNEEDCONFIRMGROUPMANNOUNCEATALLMSGTYPEINMSGBOX = 2005;
|
||||
int KNOTPASSTHROUGHEVENTTYPEUPPERBOUNDARY = 9999;
|
||||
int KPTTFORMATTYPEAMR = 0;
|
||||
int KPTTFORMATTYPESILK = 1;
|
||||
int KPTTTRANSLATESTATUSFAIL = 3;
|
||||
int KPTTTRANSLATESTATUSSUC = 2;
|
||||
int KPTTTRANSLATESTATUSTRANSLATING = 1;
|
||||
int KPTTTRANSLATESTATUSUNKNOWN = 0;
|
||||
int KPTTVIPLEVELTYPENONE = 0;
|
||||
int KPTTVIPLEVELTYPEQQVIP = 0;
|
||||
int KPTTVIPLEVELTYPESVIP = 0;
|
||||
int KPTTVOICECHANGETYPEBEASTMACHINE = 7;
|
||||
int KPTTVOICECHANGETYPEBOY = 2;
|
||||
int KPTTVOICECHANGETYPECATCHCOLD = 13;
|
||||
int KPTTVOICECHANGETYPEECHO = 5;
|
||||
int KPTTVOICECHANGETYPEFATGUY = 16;
|
||||
int KPTTVOICECHANGETYPEFLASHING = 9;
|
||||
int KPTTVOICECHANGETYPEGIRL = 1;
|
||||
int KPTTVOICECHANGETYPEHORRIBLE = 3;
|
||||
int KPTTVOICECHANGETYPEKINDERGARTEN = 6;
|
||||
int KPTTVOICECHANGETYPEMEDAROT = 15;
|
||||
int KPTTVOICECHANGETYPENONE = 0;
|
||||
int KPTTVOICECHANGETYPEOPTIMUSPRIME = 8;
|
||||
int KPTTVOICECHANGETYPEOUTOFDATE = 14;
|
||||
int KPTTVOICECHANGETYPEPAPI = 11;
|
||||
int KPTTVOICECHANGETYPEQUICK = 4;
|
||||
int KPTTVOICECHANGETYPESTUTTER = 10;
|
||||
int KPTTVOICECHANGETYPETRAPPEDBEAST = 12;
|
||||
int KPTTVOICETYPEINTERCOM = 1;
|
||||
int KPTTVOICETYPESOUNDRECORD = 2;
|
||||
int KPTTVOICETYPEUNKNOW = 0;
|
||||
int KPTTVOICETYPEVOICECHANGE = 3;
|
||||
int KPUBLICACCOUNTTIANSHUHIGHLIGHTWORDTYPEINMSGBOX = 1010;
|
||||
int KREPLYABSELEMTYPEFACE = 2;
|
||||
int KREPLYABSELEMTYPEPIC = 3;
|
||||
int KREPLYABSELEMTYPETEXT = 1;
|
||||
int KREPLYABSELEMTYPEUNKNOWN = 0;
|
||||
int KREPLYATMEMSGTYPEINMSGBOX = 1002;
|
||||
int KRMDOWNTYPEORIG = 1;
|
||||
int KRMDOWNTYPETHUMB = 2;
|
||||
int KRMDOWNTYPEUNKNOWN = 0;
|
||||
int KRMFILETHUMBSIZE128 = 128;
|
||||
int KRMFILETHUMBSIZE320 = 320;
|
||||
int KRMFILETHUMBSIZE384 = 384;
|
||||
int KRMFILETHUMBSIZE750 = 750;
|
||||
int KRMPICAIOTHUMBSIZE = 0;
|
||||
int KRMPICTHUMBSIZE198 = 198;
|
||||
int KRMPICTHUMBSIZE720 = 720;
|
||||
int KRMPICTYPEBMP = 3;
|
||||
int KRMPICTYPECHECKOTHER = 900;
|
||||
int KRMPICTYPEGIF = 2;
|
||||
int KRMPICTYPEJPG = 0;
|
||||
int KRMPICTYPENEWPICAPNG = 2001;
|
||||
int KRMPICTYPENEWPICBMP = 1005;
|
||||
int KRMPICTYPENEWPICGIF = 2000;
|
||||
int KRMPICTYPENEWPICJPEG = 1000;
|
||||
int KRMPICTYPENEWPICPNG = 1001;
|
||||
int KRMPICTYPENEWPICPROGERSSIVJPEG = 1003;
|
||||
int KRMPICTYPENEWPICSHARPP = 1004;
|
||||
int KRMPICTYPENEWPICWEBP = 1002;
|
||||
int KRMPICTYPEPNG = 1;
|
||||
int KRMPICTYPEUNKOWN = 0;
|
||||
int KRMTHUMBSIZEZERO = 0;
|
||||
int KRMTRNASFERSTATUSDOWNLOADING = 3;
|
||||
int KRMTRNASFERSTATUSFAIL = 5;
|
||||
int KRMTRNASFERSTATUSINIT = 1;
|
||||
int KRMTRNASFERSTATUSSUC = 4;
|
||||
int KRMTRNASFERSTATUSUNKOW = 0;
|
||||
int KRMTRNASFERSTATUSUPLOADING = 2;
|
||||
int KRMTRNASFERSTATUSUSERCANCEL = 6;
|
||||
int KSEEKINGPARTNERFLAGSEEKING = 1;
|
||||
int KSEEKINGPARTNERFLAGUNKNOWN = 0;
|
||||
int KSENDSTATUSFAILED = 0;
|
||||
int KSENDSTATUSSENDING = 1;
|
||||
int KSENDSTATUSSUCCESS = 2;
|
||||
int KSENDSTATUSSUCCESSNOSEQ = 3;
|
||||
int KSENDTYPEDROPPED = 6;
|
||||
int KSENDTYPELOCAL = 3;
|
||||
int KSENDTYPEOTHERDEVICE = 2;
|
||||
int KSENDTYPERECV = 0;
|
||||
int KSENDTYPESELF = 1;
|
||||
int KSENDTYPESELFFORWARD = 4;
|
||||
int KSENDTYPESELFMULTIFORWARD = 5;
|
||||
int KSESSIONTYPEADDRESSBOOK = 5;
|
||||
int KSESSIONTYPEC2C = 1;
|
||||
int KSESSIONTYPEDISC = 3;
|
||||
int KSESSIONTYPEFAV = 41;
|
||||
int KSESSIONTYPEGROUP = 2;
|
||||
int KSESSIONTYPEGROUPBLESS = 52;
|
||||
int KSESSIONTYPEGUILD = 4;
|
||||
int KSESSIONTYPEGUILDMETA = 16;
|
||||
int KSESSIONTYPENEARBYPRO = 54;
|
||||
int KSESSIONTYPEQQNOTIFY = 51;
|
||||
int KSESSIONTYPERELATEACCOUNT = 50;
|
||||
int KSESSIONTYPESERVICEASSISTANT = 19;
|
||||
int KSESSIONTYPESUBSCRIBEFOLDER = 30;
|
||||
int KSESSIONTYPETYPEBUDDYNOTIFY = 7;
|
||||
int KSESSIONTYPETYPEGROUPHELPER = 9;
|
||||
int KSESSIONTYPETYPEGROUPNOTIFY = 8;
|
||||
int KSESSIONTYPEUNKNOWN = 0;
|
||||
int KSESSIONTYPEWEIYUN = 40;
|
||||
int KSPECIALCAREMSGTYPEINMSGBOX = 1006;
|
||||
int KSPECIFIEDREDENVELOPEATMEMSGTYPEINMSGBOX = 1004;
|
||||
int KSPECIFIEDREDENVELOPEATONEMSGTYPEINMSGBOX = 1003;
|
||||
int KTENCENTDOCTYPEADDON = 110;
|
||||
int KTENCENTDOCTYPEDOC = 0;
|
||||
int KTENCENTDOCTYPEDRAWING = 89;
|
||||
int KTENCENTDOCTYPEDRIVE = 101;
|
||||
int KTENCENTDOCTYPEFILE = 100;
|
||||
int KTENCENTDOCTYPEFLOWCHART = 91;
|
||||
int KTENCENTDOCTYPEFOLDER = 3;
|
||||
int KTENCENTDOCTYPEFORM = 2;
|
||||
int KTENCENTDOCTYPEMIND = 90;
|
||||
int KTENCENTDOCTYPENOTES = 5;
|
||||
int KTENCENTDOCTYPEPDF = 6;
|
||||
int KTENCENTDOCTYPEPROGRAM = 7;
|
||||
int KTENCENTDOCTYPESHEET = 1;
|
||||
int KTENCENTDOCTYPESLIDE = 4;
|
||||
int KTENCENTDOCTYPESMARTCANVAS = 8;
|
||||
int KTENCENTDOCTYPESMARTSHEET = 9;
|
||||
int KTENCENTDOCTYPESPEECH = 102;
|
||||
int KTENCENTDOCTYPEUNKNOWN = 10;
|
||||
int KTOFURECORDMSG = 23;
|
||||
int KTOPMSGTYPETASK = 1;
|
||||
int KTOPMSGTYPEUNKNOWN = 0;
|
||||
int KTRIGGERTYPEAUTO = 1;
|
||||
int KTRIGGERTYPEMANUAL = 0;
|
||||
int KUNKNOWN = 0;
|
||||
int KUNKNOWNTYPEINMSGBOX = 0;
|
||||
int KUNREADCNTUPTYPEALLDIRECTSESSION = 4;
|
||||
int KUNREADCNTUPTYPEALLFEEDSINGUILD = 6;
|
||||
int KUNREADCNTUPTYPEALLGUILD = 3;
|
||||
int KUNREADCNTUPTYPECATEGORY = 5;
|
||||
int KUNREADCNTUPTYPECHANNEL = 1;
|
||||
int KUNREADCNTUPTYPECONTACT = 0;
|
||||
int KUNREADCNTUPTYPEGUILD = 2;
|
||||
int KUNREADCNTUPTYPEGUILDGROUP = 7;
|
||||
int KUNREADSHOWTTYPEGRAYPOINT = 2;
|
||||
int KUNREADSHOWTYPEREDPOINT = 1;
|
||||
int KUNREADSHOWTYPESMALLGRAYPOINT = 4;
|
||||
int KUNREADSHOWTYPESMALLREDPOINT = 3;
|
||||
int KUNREADSHOWTYPEUNKNOWN = 0;
|
||||
int KVASGIFTCOINTYPECOIN = 0;
|
||||
int KVASGIFTCOINTYPEMARKETCOIN = 1;
|
||||
int KYOLOGAMERESULTMSG = 18;
|
||||
int PIC_800_RECOMMENDED = 7;
|
||||
int PIC_AIGC_EMOJI = 14;
|
||||
int PIC_ALBUM_GIF = 11;
|
||||
int PIC_COMMERCIAL_ADVERTISING = 9;
|
||||
int PIC_FIND = 10;
|
||||
int PIC_HOT = 2;
|
||||
int PIC_HOT_EMOJI = 13;
|
||||
int PIC_NORMAL = 0;
|
||||
int PIC_PK = 3;
|
||||
int PIC_QQZONE = 5;
|
||||
int PIC_SELFIE_GIF = 8;
|
||||
int PIC_SEND_FROM_TAB_SEARCH_BOX = 12;
|
||||
int PIC_USER = 1;
|
||||
int PIC_WISDOM_FIGURE = 4;
|
||||
int REPLYORIGINALMSGSTATEHASRECALL = 1;
|
||||
int REPLYORIGINALMSGSTATEUNKNOWN = 0;
|
||||
int SHARELOCATIONELEMSUBTYPENORMAL = 1;
|
||||
int SHARELOCATIONELEMSUBTYPEUNKNOWN = 0;
|
||||
int TEXTELEMENTSUBTYPELINK = 1;
|
||||
int TEXTELEMENTSUBTYPETENCENTDOC = 2;
|
||||
int TEXTELEMENTSUBTYPEUNKNOWN = 0;
|
||||
```
|
16
docs/develop/NC 1.6.X的计划.md
Normal file
16
docs/develop/NC 1.6.X的计划.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 开发方向
|
||||
方向一 NativeCall/Hook:
|
||||
1. 崩溃检测机制的实现
|
||||
2. Api_Caller 的Hook 可以拿到Event/Handler 进一步提升NC 即时的拦截与处理一些事件比如ReCall拦截
|
||||
3. Node包装层 进一步分析,拿到脱离自带Listener/Adapter,可以拿到一些更加底层的数据变动 或许包括更多二进制数据
|
||||
|
||||
方向二 全新的无头启动 Way01
|
||||
1. 基于Node启动原理,借助导出符号获取函数地址 再次还原NodeMain
|
||||
|
||||
方向三 发包与收包
|
||||
1. 参考 方向一/3 大概可以收包
|
||||
2. 发包 (暂时没有计划)
|
||||
|
||||
方向四 版本控制
|
||||
1. 根据不同版本进行逻辑控制
|
||||
2. 某些参数的自动提取
|
8
docs/develop/碎碎的研究记录.md
Normal file
8
docs/develop/碎碎的研究记录.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Api方向
|
||||
## getMsgUniqueId √ 已应用
|
||||
getMsgUniqueId 传入时间 产出一个唯一ID 发送消息作为一个参数
|
||||
|
||||
# Native方向
|
||||
## magic_load
|
||||
## api_caller
|
||||
## NodeMain
|
137
package.json
137
package.json
@@ -1,67 +1,70 @@
|
||||
{
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "1.3.6",
|
||||
"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 && 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}",
|
||||
"release": "npm run build:prod",
|
||||
"depend": "cd dist && npm install --omit=dev"
|
||||
},
|
||||
"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",
|
||||
"@types/node": "^20.11.30",
|
||||
"@types/qrcode-terminal": "^0.12.2",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
||||
"@typescript-eslint/parser": "^7.4.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"i": "^0.3.7",
|
||||
"javascript-obfuscator": "^4.1.0",
|
||||
"rollup": "^4.13.2",
|
||||
"rollup-plugin-dts": "^6.1.0",
|
||||
"rollup-plugin-obfuscator": "^1.1.0",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.2.6",
|
||||
"vite-plugin-cp": "^4.0.8",
|
||||
"vite-plugin-dts": "^3.8.2",
|
||||
"vite-tsconfig-paths": "^4.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@protobuf-ts/plugin": "^2.9.4",
|
||||
"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",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"silk-wasm": "^3.3.4",
|
||||
"sqlite3": "^5.1.7",
|
||||
"uuid": "^9.0.1",
|
||||
"ws": "^8.16.0"
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "napcat",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "1.6.8",
|
||||
"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 && 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}",
|
||||
"release": "npm run build:prod",
|
||||
"depend": "cd dist && npm install --omit=dev"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.7",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.24.7",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@log4js-node/log4js-api": "^1.0.2",
|
||||
"@protobuf-ts/plugin": "^2.9.4",
|
||||
"@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",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.11.30",
|
||||
"@types/qrcode-terminal": "^0.12.2",
|
||||
"@types/ws": "^8.5.10",
|
||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
||||
"@typescript-eslint/parser": "^7.4.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"i": "^0.3.7",
|
||||
"javascript-obfuscator": "^4.1.0",
|
||||
"rollup": "^4.13.2",
|
||||
"rollup-plugin-dts": "^6.1.0",
|
||||
"rollup-plugin-obfuscator": "^1.1.0",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.2.6",
|
||||
"vite-plugin-babel": "^1.2.0",
|
||||
"vite-plugin-cp": "^4.0.8",
|
||||
"vite-plugin-dts": "^3.8.2",
|
||||
"vite-tsconfig-paths": "^4.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": "^8.13.0",
|
||||
"chalk": "^5.3.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",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"silk-wasm": "^3.6.1",
|
||||
"ws": "^8.16.0"
|
||||
}
|
||||
}
|
||||
|
45
script/BootWay.03.ps1
Normal file
45
script/BootWay.03.ps1
Normal file
@@ -0,0 +1,45 @@
|
||||
# Dont Use This Script
|
||||
# 2024.7.3
|
||||
function Get-QQpath {
|
||||
try {
|
||||
$key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ"
|
||||
$uninstallString = $key.UninstallString
|
||||
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\QQ.exe"
|
||||
}
|
||||
catch {
|
||||
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 " "
|
||||
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
|
||||
$commandInfo = Get-Command $QQpath -ErrorAction Stop
|
||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& '$($commandInfo.Path)' --enable-logging $params}"
|
28
script/NapCat.164.bat
Normal file
28
script/NapCat.164.bat
Normal file
@@ -0,0 +1,28 @@
|
||||
@echo off
|
||||
chcp 65001
|
||||
:: 检查是否有管理员权限
|
||||
net session >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo 请求管理员权限...
|
||||
powershell -Command "Start-Process '%~f0' -Verb runAs"
|
||||
exit /b
|
||||
)
|
||||
:: 如果有管理员权限,继续执行
|
||||
setlocal enabledelayedexpansion
|
||||
:loop_read
|
||||
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
||||
set "RetString=%%b"
|
||||
goto :napcat_boot
|
||||
)
|
||||
|
||||
:napcat_boot
|
||||
for %%a in ("!RetString!") do (
|
||||
set "pathWithoutUninstall=%%~dpa"
|
||||
)
|
||||
|
||||
set "QQPath=!pathWithoutUninstall!QQ.exe"
|
||||
|
||||
echo !QQPath!
|
||||
"!QQPath!" --enable-logging %*
|
||||
|
||||
pause
|
3
script/NapCat.Way01.bat
Normal file
3
script/NapCat.Way01.bat
Normal file
@@ -0,0 +1,3 @@
|
||||
REM 全新启动脚本 基于 Hook Native 预计版本1.6.0左右发布
|
||||
@echo off
|
||||
pause
|
20
script/index.js
Normal file
20
script/index.js
Normal file
@@ -0,0 +1,20 @@
|
||||
// --------------------
|
||||
// 2024.7.3 9.9.12 BootWay.03 其余方法暂不公开(此方案为临时方案 Win平台已验证)
|
||||
// 缺陷 (已知)
|
||||
// 1.与非入侵式不同 现在破坏本体代码
|
||||
// 2.重启代码与正常启动代码失效
|
||||
// 3.Win需要补丁
|
||||
// 4.更新后丢失内容 需要重写此文件
|
||||
// 5.安装难度上升与周围基础设施失效
|
||||
// --------------------
|
||||
|
||||
const path = require('path');
|
||||
const CurrentPath = path.dirname(__filename)
|
||||
const hasNapcatParam = process.argv.includes('--enable-logging');
|
||||
if (hasNapcatParam) {
|
||||
(async () => {
|
||||
await import("file://" + path.join(CurrentPath, './napcat/napcat.mjs'));
|
||||
})();
|
||||
} else {
|
||||
require('./launcher.node').load('external_index', module);
|
||||
}
|
18
script/napcat-9912-utf8.bat
Normal file
18
script/napcat-9912-utf8.bat
Normal file
@@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
chcp 65001
|
||||
:loop_read
|
||||
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
||||
set "RetString=%%b"
|
||||
goto :napcat_boot
|
||||
)
|
||||
|
||||
:napcat_boot
|
||||
for %%a in ("!RetString!") do (
|
||||
set "pathWithoutUninstall=%%~dpa"
|
||||
)
|
||||
|
||||
set "QQPath=!pathWithoutUninstall!"
|
||||
cd /d !QQPath!
|
||||
echo !QQPath!
|
||||
QQ.exe --enable-logging %*
|
41
script/napcat-9912-utf8.ps1
Normal file
41
script/napcat-9912-utf8.ps1
Normal file
@@ -0,0 +1,41 @@
|
||||
function Get-QQpath {
|
||||
try {
|
||||
$key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ"
|
||||
$uninstallString = $key.UninstallString
|
||||
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\"
|
||||
}
|
||||
catch {
|
||||
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 " "
|
||||
Try {
|
||||
$QQpath = Get-QQpath
|
||||
}
|
||||
Catch {
|
||||
$QQpath = Select-QQPath
|
||||
}
|
||||
|
||||
if (!(Test-Path $QQpath)) {
|
||||
throw "provided QQ path is invalid: $QQpath"
|
||||
}
|
||||
|
||||
Set-Location -Path $QQpath
|
||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& chcp 65001;& ./QQ.exe --enable-logging $params}"
|
17
script/napcat-9912.bat
Normal file
17
script/napcat-9912.bat
Normal file
@@ -0,0 +1,17 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
:loop_read
|
||||
for /f "tokens=2*" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ" /v "UninstallString"') do (
|
||||
set "RetString=%%b"
|
||||
goto :napcat_boot
|
||||
)
|
||||
|
||||
:napcat_boot
|
||||
for %%a in ("!RetString!") do (
|
||||
set "pathWithoutUninstall=%%~dpa"
|
||||
)
|
||||
|
||||
set QQPath=!pathWithoutUninstall!
|
||||
cd /d !QQPath!
|
||||
echo !QQPath!
|
||||
QQ.exe --enable-logging %*
|
41
script/napcat-9912.ps1
Normal file
41
script/napcat-9912.ps1
Normal file
@@ -0,0 +1,41 @@
|
||||
function Get-QQpath {
|
||||
try {
|
||||
$key = Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\QQ"
|
||||
$uninstallString = $key.UninstallString
|
||||
return [System.IO.Path]::GetDirectoryName($uninstallString) + "\"
|
||||
}
|
||||
catch {
|
||||
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 " "
|
||||
Try {
|
||||
$QQpath = Get-QQpath
|
||||
}
|
||||
Catch {
|
||||
$QQpath = Select-QQPath
|
||||
}
|
||||
|
||||
if (!(Test-Path $QQpath)) {
|
||||
throw "provided QQ path is invalid: $QQpath"
|
||||
}
|
||||
|
||||
Set-Location -Path $QQpath
|
||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& ./QQ.exe --enable-logging $params}"
|
@@ -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 %*
|
||||
|
@@ -37,7 +37,7 @@ if (!(Test-Path $QQpath)) {
|
||||
throw "provided QQ path is invalid: $QQpath"
|
||||
}
|
||||
|
||||
$Bootfile = Join-Path $PSScriptRoot "napcat.cjs"
|
||||
$Bootfile = Join-Path $PSScriptRoot "napcat.mjs"
|
||||
$env:ELECTRON_RUN_AS_NODE = 1
|
||||
$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 %*
|
||||
|
@@ -37,7 +37,7 @@ if (!(Test-Path $QQpath)) {
|
||||
throw "provided QQ path is invalid: $QQpath"
|
||||
}
|
||||
|
||||
$Bootfile = Join-Path $PSScriptRoot "napcat.cjs"
|
||||
$Bootfile = Join-Path $PSScriptRoot "napcat.mjs"
|
||||
$env:ELECTRON_RUN_AS_NODE = 1
|
||||
$commandInfo = Get-Command $QQpath -ErrorAction Stop
|
||||
Start-Process powershell -ArgumentList "-noexit", "-noprofile", "-command &{& '$($commandInfo.Path)' $Bootfile $params}"
|
@@ -18,4 +18,4 @@ if ! [ -x /opt/QQ/qq ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
/opt/QQ/qq "${SCRIPT_DIR}/napcat.cjs" "$@"
|
||||
/opt/QQ/qq "${SCRIPT_DIR}/napcat.mjs" "$@"
|
||||
|
@@ -9,7 +9,15 @@ type RegisterHandler = (res: Response, payload: any) => Promise<any>
|
||||
export abstract class HttpServerBase {
|
||||
name: string = 'NapCatQQ';
|
||||
private readonly expressAPP: Express;
|
||||
private server: http.Server | null = null;
|
||||
private _server: http.Server | null = null;
|
||||
|
||||
public get server(): http.Server | null {
|
||||
return this._server;
|
||||
}
|
||||
|
||||
private set server(value: http.Server | null) {
|
||||
this._server = value;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.expressAPP = express();
|
||||
@@ -37,14 +45,14 @@ export abstract class HttpServerBase {
|
||||
const authHeader = req.get('authorization');
|
||||
if (authHeader) {
|
||||
clientToken = authHeader.split('Bearer ').pop() || '';
|
||||
logDebug('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();
|
||||
}
|
||||
logDebug('receive http url token', clientToken);
|
||||
//logDebug('receive http url token', clientToken);
|
||||
}
|
||||
|
||||
if (serverToken && clientToken != serverToken) {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { WebSocket, WebSocketServer } from 'ws';
|
||||
import http from 'http';
|
||||
import urlParse from 'url';
|
||||
import { IncomingMessage } from 'node:http';
|
||||
import { log } from '@/common/utils/log';
|
||||
@@ -27,17 +28,36 @@ export class WebsocketServerBase {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
start(port: number, host: string = '') {
|
||||
try {
|
||||
this.ws = new WebSocketServer({
|
||||
port,
|
||||
host: '',
|
||||
maxPayload: 1024 * 1024 * 1024
|
||||
}).on('error', () => {
|
||||
});
|
||||
log(`ws服务启动成功, ${host}:${port}`);
|
||||
} catch (e: any) {
|
||||
throw Error('ws服务启动失败, 请检查监听的ip和端口' + e.toString());
|
||||
start(port: number | http.Server, host: string = '') {
|
||||
if (port instanceof http.Server) {
|
||||
try {
|
||||
const wss = new WebSocketServer({
|
||||
noServer: true,
|
||||
maxPayload: 1024 * 1024 * 1024
|
||||
}).on('error', () => {
|
||||
});
|
||||
this.ws = wss;
|
||||
port.on('upgrade', function upgrade(request, socket, head) {
|
||||
wss.handleUpgrade(request, socket, head, function done(ws) {
|
||||
wss.emit('connection', ws, request);
|
||||
});
|
||||
});
|
||||
log(`ws服务启动成功, 绑定到HTTP服务`);
|
||||
} catch (e: any) {
|
||||
throw Error('ws服务启动失败, 可能是绑定的HTTP服务异常' + e.toString());
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
this.ws = new WebSocketServer({
|
||||
port,
|
||||
host: '',
|
||||
maxPayload: 1024 * 1024 * 1024
|
||||
}).on('error', () => {
|
||||
});
|
||||
log(`ws服务启动成功, ${host}:${port}`);
|
||||
} catch (e: any) {
|
||||
throw Error('ws服务启动失败, 请检查监听的ip和端口' + e.toString());
|
||||
}
|
||||
}
|
||||
this.ws.on('connection', (wsClient, req) => {
|
||||
const url: string = req.url!.split('?').shift() || '/';
|
||||
@@ -50,10 +70,12 @@ export class WebsocketServerBase {
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.ws && this.ws.close((err) => {
|
||||
log('ws server close failed!', err);
|
||||
});
|
||||
this.ws = null;
|
||||
if (this.ws) {
|
||||
this.ws.close((err) => {
|
||||
if (err) log('ws server close failed!', err);
|
||||
});
|
||||
this.ws = null;
|
||||
}
|
||||
}
|
||||
|
||||
restart(port: number) {
|
||||
|
@@ -1,35 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,13 +1,21 @@
|
||||
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';
|
||||
import { selfInfo } from '@/core/data';
|
||||
|
||||
|
||||
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>{
|
||||
|
||||
export class ConfigBase<T> {
|
||||
public name: string = 'default_config'
|
||||
private pathName: string | null = null // 本次读取的文件路径
|
||||
constructor() {
|
||||
}
|
||||
|
||||
@@ -16,19 +24,28 @@ export class ConfigBase<T>{
|
||||
return null;
|
||||
}
|
||||
|
||||
getConfigDir(){
|
||||
getConfigDir() {
|
||||
const configDir = path.resolve(__dirname, 'config');
|
||||
fs.mkdirSync(configDir, { recursive: true });
|
||||
return configDir;
|
||||
}
|
||||
getConfigPath(): string {
|
||||
throw new Error('Method not implemented.');
|
||||
getConfigPath(pathName: string | null): string {
|
||||
const suffix = pathName ? `_${pathName}` : ''
|
||||
const filename = `${this.name}${suffix}.json`
|
||||
return path.join(this.getConfigDir(), filename);
|
||||
}
|
||||
|
||||
read() {
|
||||
const configPath = this.getConfigPath();
|
||||
// 尝试加载当前账号配置
|
||||
if (this.read_from_file(selfInfo.uin, false)) return this
|
||||
// 尝试加载默认配置
|
||||
return this.read_from_file('', true)
|
||||
}
|
||||
read_from_file(pathName: string, createIfNotExist: boolean) {
|
||||
const configPath = this.getConfigPath(pathName);
|
||||
if (!fs.existsSync(configPath)) {
|
||||
try{
|
||||
if (!createIfNotExist) return null
|
||||
this.pathName = pathName // 记录有效的设置文件
|
||||
try {
|
||||
fs.writeFileSync(configPath, JSON.stringify(this, this.getKeys(), 2));
|
||||
log(`配置文件${configPath}已创建\n如果修改此文件后需要重启 NapCat 生效`);
|
||||
}
|
||||
@@ -37,6 +54,7 @@ export class ConfigBase<T>{
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
||||
logDebug(`配置文件${configPath}已加载`, data);
|
||||
@@ -55,9 +73,13 @@ export class ConfigBase<T>{
|
||||
}
|
||||
}
|
||||
|
||||
save(config: T) {
|
||||
save(config: T, overwrite: boolean = false) {
|
||||
Object.assign(this, config);
|
||||
const configPath = this.getConfigPath();
|
||||
if (overwrite) {
|
||||
// 用户要求强制写入,则变更当前文件为目标文件
|
||||
this.pathName = `${selfInfo.uin}`
|
||||
}
|
||||
const configPath = this.getConfigPath(this.pathName);
|
||||
try {
|
||||
fs.writeFileSync(configPath, JSON.stringify(this, this.getKeys(), 2));
|
||||
} catch (e: any) {
|
||||
|
186
src/common/utils/EventTask.ts
Normal file
186
src/common/utils/EventTask.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
import { NodeIQQNTWrapperSession } from '@/core/wrapper';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
interface Internal_MapKey {
|
||||
timeout: number,
|
||||
createtime: number,
|
||||
func: (...arg: any[]) => any,
|
||||
checker: ((...args: any[]) => boolean) | undefined,
|
||||
}
|
||||
|
||||
export class ListenerClassBase {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface ListenerIBase {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-new
|
||||
new(listener: any): ListenerClassBase;
|
||||
}
|
||||
|
||||
export class NTEventWrapper {
|
||||
|
||||
private ListenerMap: { [key: string]: ListenerIBase } | undefined;//ListenerName-Unique -> Listener构造函数
|
||||
private WrapperSession: NodeIQQNTWrapperSession | undefined;//WrapperSession
|
||||
private ListenerManger: Map<string, ListenerClassBase> = new Map<string, ListenerClassBase>(); //ListenerName-Unique -> Listener实例
|
||||
private EventTask = new Map<string, Map<string, Map<string, Internal_MapKey>>>();//tasks ListenerMainName -> ListenerSubName-> uuid -> {timeout,createtime,func}
|
||||
constructor() {
|
||||
|
||||
}
|
||||
createProxyDispatch(ListenerMainName: string) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const current = this;
|
||||
return new Proxy({}, {
|
||||
get(target: any, prop: any, receiver: any) {
|
||||
// console.log('get', prop, typeof target[prop]);
|
||||
if (typeof target[prop] === 'undefined') {
|
||||
// 如果方法不存在,返回一个函数,这个函数调用existentMethod
|
||||
return (...args: any[]) => {
|
||||
current.DispatcherListener.apply(current, [ListenerMainName, prop, ...args]).then();
|
||||
};
|
||||
}
|
||||
// 如果方法存在,正常返回
|
||||
return Reflect.get(target, prop, receiver);
|
||||
}
|
||||
});
|
||||
}
|
||||
init({ ListenerMap, WrapperSession }: { ListenerMap: { [key: string]: typeof ListenerClassBase }, WrapperSession: NodeIQQNTWrapperSession }) {
|
||||
this.ListenerMap = ListenerMap;
|
||||
this.WrapperSession = WrapperSession;
|
||||
}
|
||||
CreatEventFunction<T extends (...args: any) => any>(eventName: string): T | undefined {
|
||||
const eventNameArr = eventName.split('/');
|
||||
type eventType = {
|
||||
[key: string]: () => { [key: string]: (...params: Parameters<T>) => Promise<ReturnType<T>> }
|
||||
}
|
||||
if (eventNameArr.length > 1) {
|
||||
const serviceName = 'get' + eventNameArr[0].replace('NodeIKernel', '');
|
||||
const eventName = eventNameArr[1];
|
||||
//getNodeIKernelGroupListener,GroupService
|
||||
//console.log('2', eventName);
|
||||
const services = (this.WrapperSession as unknown as eventType)[serviceName]();
|
||||
let event = services[eventName];
|
||||
//重新绑定this
|
||||
event = event.bind(services);
|
||||
if (event) {
|
||||
return event as T;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
}
|
||||
CreatListenerFunction<T>(listenerMainName: string, uniqueCode: string = ''): T {
|
||||
const ListenerType = this.ListenerMap![listenerMainName];
|
||||
let Listener = this.ListenerManger.get(listenerMainName + uniqueCode);
|
||||
if (!Listener && ListenerType) {
|
||||
Listener = new ListenerType(this.createProxyDispatch(listenerMainName));
|
||||
const ServiceSubName = listenerMainName.match(/^NodeIKernel(.*?)Listener$/)![1];
|
||||
const Service = 'NodeIKernel' + ServiceSubName + 'Service/addKernel' + ServiceSubName + 'Listener';
|
||||
const addfunc = this.CreatEventFunction<(listener: T) => number>(Service);
|
||||
addfunc!(Listener as T);
|
||||
//console.log(addfunc!(Listener as T));
|
||||
this.ListenerManger.set(listenerMainName + uniqueCode, Listener);
|
||||
}
|
||||
return Listener as T;
|
||||
}
|
||||
//统一回调清理事件
|
||||
async DispatcherListener(ListenerMainName: string, ListenerSubName: string, ...args: any[]) {
|
||||
//console.log(ListenerMainName, ListenerSubName, ...args,this.EventTask.get(ListenerMainName)?.get(ListenerSubName));
|
||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.forEach((task, uuid) => {
|
||||
//console.log(task.func, uuid, task.createtime, task.timeout);
|
||||
if (task.createtime + task.timeout < Date.now()) {
|
||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.delete(uuid);
|
||||
return;
|
||||
}
|
||||
if (task.checker && task.checker(...args)) {
|
||||
task.func(...args);
|
||||
}
|
||||
});
|
||||
}
|
||||
async CallNoListenerEvent<EventType extends (...args: any[]) => Promise<any>>(EventName = '', timeout: number = 3000, ...args: Parameters<EventType>) {
|
||||
return new Promise<Awaited<ReturnType<EventType>>>(async (resolve, reject) => {
|
||||
const EventFunc = this.CreatEventFunction<EventType>(EventName);
|
||||
let complete = false;
|
||||
const Timeouter = setTimeout(() => {
|
||||
if (!complete) {
|
||||
reject(new Error('NTEvent EventName:' + EventName + ' timeout'));
|
||||
}
|
||||
}, timeout);
|
||||
const retData = await EventFunc!(...args);
|
||||
complete = true;
|
||||
resolve(retData);
|
||||
});
|
||||
}
|
||||
async CallNormalEvent<EventType extends (...args: any[]) => Promise<any>, ListenerType extends (...args: any[]) => void>
|
||||
(EventName = '', ListenerName = '', waitTimes = 1, timeout: number = 3000, checker: (...args: Parameters<ListenerType>) => boolean, ...args: Parameters<EventType>) {
|
||||
return new Promise<[EventRet: Awaited<ReturnType<EventType>>, ...Parameters<ListenerType>]>(async (resolve, reject) => {
|
||||
const id = randomUUID();
|
||||
let complete = 0;
|
||||
let retData: Parameters<ListenerType> | undefined = undefined;
|
||||
let retEvent: any = {};
|
||||
const databack = () => {
|
||||
if (complete == 0) {
|
||||
reject(new Error('NTEvent EventName:' + EventName + ' ListenerName:' + ListenerName + ' timeout'));
|
||||
} else {
|
||||
resolve([retEvent as Awaited<ReturnType<EventType>>, ...retData!]);
|
||||
}
|
||||
};
|
||||
const Timeouter = setTimeout(databack, timeout);
|
||||
|
||||
const ListenerNameList = ListenerName.split('/');
|
||||
const ListenerMainName = ListenerNameList[0];
|
||||
const ListenerSubName = ListenerNameList[1];
|
||||
const eventCallbak = {
|
||||
timeout: timeout,
|
||||
createtime: Date.now(),
|
||||
checker: checker,
|
||||
func: (...args: any[]) => {
|
||||
complete++;
|
||||
//console.log('func', ...args);
|
||||
retData = args as Parameters<ListenerType>;
|
||||
if (complete >= waitTimes) {
|
||||
clearTimeout(Timeouter);
|
||||
databack();
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!this.EventTask.get(ListenerMainName)) {
|
||||
this.EventTask.set(ListenerMainName, new Map());
|
||||
}
|
||||
if (!(this.EventTask.get(ListenerMainName)?.get(ListenerSubName))) {
|
||||
this.EventTask.get(ListenerMainName)?.set(ListenerSubName, new Map());
|
||||
}
|
||||
this.EventTask.get(ListenerMainName)?.get(ListenerSubName)?.set(id, eventCallbak);
|
||||
this.CreatListenerFunction(ListenerMainName);
|
||||
const EventFunc = this.CreatEventFunction<EventType>(EventName);
|
||||
//console.log("测试打点", args);
|
||||
retEvent = await EventFunc!(...(args as any[]));
|
||||
});
|
||||
}
|
||||
}
|
||||
export const NTEventDispatch = new NTEventWrapper();
|
||||
|
||||
// 示例代码 快速创建事件
|
||||
// let NTEvent = new NTEventWrapper();
|
||||
// let TestEvent = NTEvent.CreatEventFunction<(force: boolean) => Promise<Number>>('NodeIKernelProfileLikeService/GetTest');
|
||||
// if (TestEvent) {
|
||||
// TestEvent(true);
|
||||
// }
|
||||
|
||||
// 示例代码 快速创建监听Listener类
|
||||
// let NTEvent = new NTEventWrapper();
|
||||
// NTEvent.CreatListenerFunction<NodeIKernelMsgListener>('NodeIKernelMsgListener', 'core')
|
||||
|
||||
|
||||
// 调用接口
|
||||
//let NTEvent = new NTEventWrapper();
|
||||
//let ret = await NTEvent.CallNormalEvent<(force: boolean) => Promise<Number>, (data1: string, data2: number) => void>('NodeIKernelProfileLikeService/GetTest', 'NodeIKernelMsgListener/onAddSendMsg', 1, 3000, true);
|
||||
|
||||
// 注册监听 解除监听
|
||||
// NTEventDispatch.RigisterListener('NodeIKernelMsgListener/onAddSendMsg','core',cb);
|
||||
// NTEventDispatch.UnRigisterListener('NodeIKernelMsgListener/onAddSendMsg','core');
|
||||
|
||||
// let GetTest = NTEventDispatch.CreatEvent('NodeIKernelProfileLikeService/GetTest','NodeIKernelMsgListener/onAddSendMsg',Mode);
|
||||
// GetTest('test');
|
||||
|
||||
// always模式
|
||||
// NTEventDispatch.CreatEvent('NodeIKernelProfileLikeService/GetTest','NodeIKernelMsgListener/onAddSendMsg',Mode,(...args:any[])=>{ console.log(args) });
|
116
src/common/utils/MessageUnique.ts
Normal file
116
src/common/utils/MessageUnique.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
import { Peer } from '@/core';
|
||||
import crypto, { randomInt, randomUUID } from 'crypto';
|
||||
import { logError } from './log';
|
||||
|
||||
class LimitedHashTable<K, V> {
|
||||
private keyToValue: Map<K, V> = new Map();
|
||||
private valueToKey: Map<V, K> = new Map();
|
||||
private maxSize: number;
|
||||
|
||||
constructor(maxSize: number) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
resize(count: number) {
|
||||
this.maxSize = count;
|
||||
}
|
||||
|
||||
set(key: K, value: V): void {
|
||||
const isExist = this.keyToValue.get(key);
|
||||
if (isExist && isExist === value) {
|
||||
return;
|
||||
}
|
||||
this.keyToValue.set(key, value);
|
||||
this.valueToKey.set(value, key);
|
||||
while (this.keyToValue.size !== this.valueToKey.size) {
|
||||
console.log('keyToValue.size !== valueToKey.size Error Atom');
|
||||
this.keyToValue.clear();
|
||||
this.valueToKey.clear();
|
||||
}
|
||||
// console.log('---------------');
|
||||
// console.log(this.keyToValue);
|
||||
// console.log(this.valueToKey);
|
||||
// console.log('---------------');
|
||||
while (this.keyToValue.size > this.maxSize || this.valueToKey.size > this.maxSize) {
|
||||
//console.log(this.keyToValue.size > this.maxSize, this.valueToKey.size > this.maxSize);
|
||||
const oldestKey = this.keyToValue.keys().next().value;
|
||||
this.valueToKey.delete(this.keyToValue.get(oldestKey)!);
|
||||
this.keyToValue.delete(oldestKey);
|
||||
}
|
||||
}
|
||||
|
||||
getValue(key: K): V | undefined {
|
||||
return this.keyToValue.get(key);
|
||||
}
|
||||
|
||||
getKey(value: V): K | undefined {
|
||||
return this.valueToKey.get(value);
|
||||
}
|
||||
|
||||
deleteByValue(value: V): void {
|
||||
const key = this.valueToKey.get(value);
|
||||
if (key !== undefined) {
|
||||
this.keyToValue.delete(key);
|
||||
this.valueToKey.delete(value);
|
||||
}
|
||||
}
|
||||
|
||||
deleteByKey(key: K): void {
|
||||
const value = this.keyToValue.get(key);
|
||||
if (value !== undefined) {
|
||||
this.keyToValue.delete(key);
|
||||
this.valueToKey.delete(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MessageUniqueWrapper {
|
||||
private msgDataMap: LimitedHashTable<string, number>;
|
||||
private msgIdMap: LimitedHashTable<string, number>;
|
||||
constructor(maxMap: number = 1000) {
|
||||
this.msgIdMap = new LimitedHashTable<string, number>(maxMap);
|
||||
this.msgDataMap = new LimitedHashTable<string, number>(maxMap);
|
||||
}
|
||||
|
||||
createMsg(peer: Peer, msgId: string): number | undefined {
|
||||
const key = `${msgId}|${peer.chatType}|${peer.peerUid}`;
|
||||
const hash = crypto.createHash('sha1').update(key);
|
||||
const shortId = parseInt(hash.digest('hex').slice(0, 8), 16);
|
||||
const isExist = this.msgIdMap.getKey(shortId);
|
||||
//console.log(`${peer.peerUid} ${msgId} ------- ${shortId}`);
|
||||
if (isExist && isExist === msgId) {
|
||||
return shortId;
|
||||
}
|
||||
this.msgIdMap.set(msgId, shortId);
|
||||
this.msgDataMap.set(key, shortId);
|
||||
return shortId;
|
||||
}
|
||||
|
||||
getMsgIdAndPeerByShortId(shortId: number): { MsgId: string; Peer: Peer } | undefined {
|
||||
const data = this.msgDataMap.getKey(shortId);
|
||||
if (data) {
|
||||
const [msgId, chatTypeStr, peerUid] = data.split('|');
|
||||
const peer: Peer = {
|
||||
chatType: parseInt(chatTypeStr),
|
||||
peerUid,
|
||||
guildId: '',
|
||||
};
|
||||
return { MsgId: msgId, Peer: peer };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getShortIdByMsgId(msgId: string): number | undefined {
|
||||
return this.msgIdMap.getValue(msgId);
|
||||
}
|
||||
getPeerByMsgId(msgId: string) {
|
||||
const shortId = this.msgIdMap.getValue(msgId);
|
||||
if (!shortId) return undefined;
|
||||
return this.getMsgIdAndPeerByShortId(shortId);
|
||||
}
|
||||
resize(maxSize: number): void {
|
||||
this.msgIdMap.resize(maxSize);
|
||||
this.msgDataMap.resize(maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
export const MessageUnique: MessageUniqueWrapper = new MessageUniqueWrapper();
|
17
src/common/utils/Packet.ts
Normal file
17
src/common/utils/Packet.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
// 方案一 MiniApp发包方案
|
||||
// 前置条件: 处于GUI环境 存在MiniApp
|
||||
|
||||
import { NTQQSystemApi } from '@/core';
|
||||
|
||||
// 前排提示: 开发验证仅Win平台开展
|
||||
export class MiniAppUtil {
|
||||
static async RunMiniAppWithGUI() {
|
||||
//process.env.ELECTRON_RUN_AS_NODE = undefined;//没用还是得自己用cpp之类的语言写个程序转发参数
|
||||
return NTQQSystemApi.BootMiniApp(process.execPath, 'miniapp://open/1007?url=https%3A%2F%2Fm.q.qq.com%2Fa%2Fs%2Fedd0a83d3b8afe233dfa07adaaf8033f%3Fscene%3D1007%26min_refer%3D10001');
|
||||
}
|
||||
}
|
||||
// 方案二 MiniApp发包方案 替代MiniApp方案
|
||||
// 前置条件: 无
|
||||
export class MojoMiniAppUtil{
|
||||
|
||||
}
|
@@ -2,6 +2,7 @@ import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import { systemPlatform } from '@/common/utils/system';
|
||||
import { logError } from '@/common/utils/log';
|
||||
|
||||
export const exePath = process.execPath;
|
||||
|
||||
@@ -37,11 +38,11 @@ type QQVersionConfigInfo = {
|
||||
}
|
||||
|
||||
let _qqVersionConfigInfo: QQVersionConfigInfo = {
|
||||
'baseVersion': '9.9.9-23361',
|
||||
'curVersion': '9.9.9-23361',
|
||||
'baseVersion': '9.9.12-25765',
|
||||
'curVersion': '9.9.12-25765',
|
||||
'prevVersion': '',
|
||||
'onErrorVersions': [],
|
||||
'buildId': '23361'
|
||||
'buildId': '25765'
|
||||
};
|
||||
|
||||
if (fs.existsSync(configVersionInfoPath)) {
|
||||
@@ -49,24 +50,28 @@ if (fs.existsSync(configVersionInfoPath)) {
|
||||
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);
|
||||
logError('Load QQ version config info failed, Use default version', e);
|
||||
}
|
||||
}
|
||||
|
||||
export const qqVersionConfigInfo: QQVersionConfigInfo = _qqVersionConfigInfo;
|
||||
|
||||
export const qqPkgInfo: QQPkgInfo = require(pkgInfoPath);
|
||||
//V1_WIN_NQ_9.9.12_25765_GW_B
|
||||
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',
|
||||
// app_version: '9.9.12-25765',
|
||||
// qua: 'V1_WIN_NQ_9.9.12_25765_GW_B',
|
||||
// appid: '537234702',
|
||||
// platVer: '10.0.26100',
|
||||
// clientVer: '9.9.9-23159',
|
||||
// clientVer: '9.9.9-25765',
|
||||
|
||||
let _appid: string = '537213803'; // 默认为 Windows 平台的 appid
|
||||
// Linux
|
||||
// app_version: '3.2.9-25765',
|
||||
// qua: 'V1_LNX_NQ_3.2.10_25765_GW_B',
|
||||
|
||||
let _appid: string = '537234702'; // 默认为 Windows 平台的 appid
|
||||
if (systemPlatform === 'linux') {
|
||||
_appid = '537213827';
|
||||
_appid = '537234773';
|
||||
}
|
||||
// todo: mac 平台的 appid
|
||||
export const appid = _appid;
|
||||
export const appid = _appid;
|
@@ -1,9 +1,9 @@
|
||||
import fs from 'fs';
|
||||
import { encode, getDuration, getWavFileInfo, isWav } from 'silk-wasm';
|
||||
import { encode, getDuration, getWavFileInfo, isWav, isSilk } from 'silk-wasm';
|
||||
import fsPromise from 'fs/promises';
|
||||
import { log, logError } from './log';
|
||||
import path from 'node:path';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { getTempDir } from '@/common/utils/file';
|
||||
|
||||
@@ -24,7 +24,7 @@ export async function encodeSilk(filePath: string) {
|
||||
const fileHeader = buffer.toString('hex', 0, bytesToRead);
|
||||
return fileHeader;
|
||||
} catch (err) {
|
||||
console.error('读取文件错误:', err);
|
||||
logError('读取文件错误:', err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -63,10 +63,11 @@ export async function encodeSilk(filePath: string) {
|
||||
// }
|
||||
|
||||
try {
|
||||
const pttPath = path.join(TEMP_DIR, uuidv4());
|
||||
if (getFileHeader(filePath) !== '02232153494c4b') {
|
||||
const file = await fsPromise.readFile(filePath);
|
||||
const pttPath = path.join(TEMP_DIR, randomUUID());
|
||||
if (!isSilk(file)) {
|
||||
log(`语音文件${filePath}需要转换成silk`);
|
||||
const _isWav = await isWavFile(filePath);
|
||||
const _isWav = isWav(file);
|
||||
const pcmPath = pttPath + '.pcm';
|
||||
let sampleRate = 0;
|
||||
const convert = () => {
|
||||
@@ -96,7 +97,7 @@ export async function encodeSilk(filePath: string) {
|
||||
if (!_isWav) {
|
||||
input = await convert();
|
||||
} else {
|
||||
input = fs.readFileSync(filePath);
|
||||
input = file;
|
||||
const allowSampleRate = [8000, 12000, 16000, 24000, 32000, 44100, 48000];
|
||||
const { fmt } = getWavFileInfo(input);
|
||||
// log(`wav文件信息`, fmt)
|
||||
@@ -113,7 +114,7 @@ export async function encodeSilk(filePath: string) {
|
||||
duration: silk.duration / 1000
|
||||
};
|
||||
} else {
|
||||
const silk = fs.readFileSync(filePath);
|
||||
const silk = file;
|
||||
let duration = 0;
|
||||
try {
|
||||
duration = getDuration(silk) / 1000;
|
||||
|
@@ -1,7 +1,11 @@
|
||||
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();
|
||||
@@ -14,6 +18,6 @@ export function cpModule(moduleName: string) {
|
||||
try {
|
||||
fs.copyFileSync(path.join(currentDir, fileName), path.join(currentDir, `${moduleName}.node`));
|
||||
} catch (e) {
|
||||
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,11 @@
|
||||
import fs from 'fs';
|
||||
import fsPromise from 'fs/promises';
|
||||
import fsPromise, { stat } from 'fs/promises';
|
||||
import crypto from 'crypto';
|
||||
import util from 'util';
|
||||
import path from 'node:path';
|
||||
import { log } from './log';
|
||||
import { dbUtil } from '@/core/utils/db';
|
||||
import { log, logError } from './log';
|
||||
import * as fileType from 'file-type';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { napCatCore } from '@/core';
|
||||
|
||||
export const getNapCatDir = () => {
|
||||
@@ -50,7 +49,40 @@ export function checkFileReceived(path: string, timeout: number = 3000): Promise
|
||||
check();
|
||||
});
|
||||
}
|
||||
// 定义一个异步函数来检查文件是否存在
|
||||
export async function checkFileReceived2(path: string, timeout: number = 3000): Promise<void> {
|
||||
// 使用 Promise.race 来同时进行文件状态检查和超时计时
|
||||
// Promise.race 会返回第一个解决(resolve)或拒绝(reject)的 Promise
|
||||
await Promise.race([
|
||||
checkFile(path),
|
||||
timeoutPromise(timeout, `文件不存在: ${path}`),
|
||||
]);
|
||||
}
|
||||
|
||||
// 转换超时时间至 Promise
|
||||
function timeoutPromise(timeout: number, errorMsg: string): Promise<void> {
|
||||
return new Promise((_, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error(errorMsg));
|
||||
}, timeout);
|
||||
});
|
||||
}
|
||||
|
||||
// 异步检查文件是否存在
|
||||
async function checkFile(path: string): Promise<void> {
|
||||
try {
|
||||
await stat(path);
|
||||
} catch (error: any) {
|
||||
if (error.code === 'ENOENT') {
|
||||
// 如果文件不存在,则抛出一个错误
|
||||
throw new Error(`文件不存在: ${path}`);
|
||||
} else {
|
||||
// 对于 stat 调用的其他错误,重新抛出
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
// 如果文件存在,则无需做任何事情,Promise 解决(resolve)自身
|
||||
}
|
||||
export async function file2base64(path: string) {
|
||||
const readFile = util.promisify(fs.readFile);
|
||||
const result = {
|
||||
@@ -115,6 +147,8 @@ export async function httpDownload(options: string | HttpDownloadOptions): Promi
|
||||
};
|
||||
if (typeof options === 'string') {
|
||||
url = options;
|
||||
const host = new URL(url).hostname;
|
||||
headers['Host'] = host;
|
||||
} else {
|
||||
url = options.url;
|
||||
if (options.headers) {
|
||||
@@ -125,7 +159,12 @@ export async function httpDownload(options: string | HttpDownloadOptions): Promi
|
||||
}
|
||||
}
|
||||
}
|
||||
const fetchRes = await fetch(url, { headers });
|
||||
const fetchRes = await fetch(url, { headers }).catch((err) => {
|
||||
if (err.cause) {
|
||||
throw err.cause;
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
if (!fetchRes.ok) throw new Error(`下载文件失败: ${fetchRes.statusText}`);
|
||||
|
||||
const blob = await fetchRes.blob();
|
||||
@@ -152,7 +191,7 @@ export async function uri2local(uri: string, fileName: string | null = null): Pr
|
||||
isLocal: false
|
||||
};
|
||||
if (!fileName) {
|
||||
fileName = uuidv4();
|
||||
fileName = randomUUID();
|
||||
}
|
||||
let filePath = path.join(getTempDir(), fileName);
|
||||
let url = null;
|
||||
@@ -195,7 +234,7 @@ export async function uri2local(uri: string, fileName: string | null = null): Pr
|
||||
}
|
||||
fileName = fileName.replace(/[/\\:*?"<>|]/g, '_');
|
||||
res.fileName = fileName;
|
||||
filePath = path.join(getTempDir(), uuidv4() + fileName);
|
||||
filePath = path.join(getTempDir(), randomUUID() + fileName);
|
||||
fs.writeFileSync(filePath, buffer);
|
||||
} catch (e: any) {
|
||||
res.errMsg = `${url}下载失败,` + e.toString();
|
||||
@@ -211,13 +250,14 @@ export async function uri2local(uri: string, fileName: string | null = null): Pr
|
||||
} else {
|
||||
filePath = pathname;
|
||||
}
|
||||
} else {
|
||||
const cache = await dbUtil.getFileCacheByName(uri);
|
||||
if (cache) {
|
||||
filePath = cache.path;
|
||||
} else {
|
||||
filePath = uri;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// const cache = await dbUtil.getFileCacheByName(uri);
|
||||
// if (cache) {
|
||||
// filePath = cache.path;
|
||||
// } else {
|
||||
// filePath = uri;
|
||||
// }
|
||||
}
|
||||
|
||||
res.isLocal = true;
|
||||
@@ -262,12 +302,12 @@ export async function copyFolder(sourcePath: string, destPath: string) {
|
||||
try {
|
||||
await fsPromise.copyFile(srcPath, dstPath);
|
||||
} catch (error) {
|
||||
console.error(`无法复制文件 '${srcPath}' 到 '${dstPath}': ${error}`);
|
||||
logError(`无法复制文件 '${srcPath}' 到 '${dstPath}': ${error}`);
|
||||
// 这里可以决定是否要继续复制其他文件
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('复制文件夹时出错:', error);
|
||||
logError('复制文件夹时出错:', error);
|
||||
}
|
||||
}
|
||||
|
@@ -2,10 +2,35 @@ 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';
|
||||
import * as fsPromise from 'node:fs/promises';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
export function sleep(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export function PromiseTimer<T>(promise: Promise<T>, ms: number): Promise<T> {
|
||||
const timeoutPromise = new Promise<T>((_, reject) =>
|
||||
setTimeout(() => reject(new Error("PromiseTimer: Operation timed out")), ms)
|
||||
);
|
||||
return Promise.race([promise, timeoutPromise]);
|
||||
}
|
||||
export async function runAllWithTimeout<T>(tasks: Promise<T>[], timeout: number): Promise<T[]> {
|
||||
const wrappedTasks = tasks.map(task =>
|
||||
PromiseTimer(task, timeout).then(
|
||||
result => ({ status: 'fulfilled', value: result }),
|
||||
error => ({ status: 'rejected', reason: error })
|
||||
)
|
||||
);
|
||||
const results = await Promise.all(wrappedTasks);
|
||||
return results
|
||||
.filter(result => result.status === 'fulfilled')
|
||||
.map(result => (result as { status: 'fulfilled'; value: T }).value);
|
||||
}
|
||||
|
||||
export function getMd5(s: string) {
|
||||
|
||||
const h = crypto.createHash('md5');
|
||||
@@ -37,8 +62,117 @@ export function truncateString(obj: any, maxLength = 500) {
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
export function simpleDecorator(target: any, context: any) {
|
||||
}
|
||||
|
||||
// export function CacheClassFunc(ttl: number = 3600 * 1000, customKey: string = '') {
|
||||
// const cache = new Map<string, { expiry: number; value: any }>();
|
||||
// return function CacheClassFuncDecorator(originalMethod: Function, context: ClassMethodDecoratorContext) {
|
||||
// async function CacheClassFuncDecoratorInternal(this: any, ...args: any[]) {
|
||||
// const key = `${customKey}${String(context.name)}.(${args.map(arg => JSON.stringify(arg)).join(', ')})`;
|
||||
// const cachedValue = cache.get(key);
|
||||
// if (cachedValue && cachedValue.expiry > Date.now()) {
|
||||
// return cachedValue.value;
|
||||
// }
|
||||
// const result = originalMethod.call(this, ...args);
|
||||
// cache.set(key, { expiry: Date.now() + ttl, value: result });
|
||||
// return result;
|
||||
// }
|
||||
// return CacheClassFuncDecoratorInternal;
|
||||
// }
|
||||
// }
|
||||
export function CacheClassFuncAsync(ttl: number = 3600 * 1000, customKey: string = '') {
|
||||
//console.log('CacheClassFuncAsync', ttl, customKey);
|
||||
function logExecutionTime(target: any, methodName: string, descriptor: PropertyDescriptor) {
|
||||
//console.log('logExecutionTime', target, methodName, descriptor);
|
||||
const cache = new Map<string, { expiry: number; value: any }>();
|
||||
const originalMethod = descriptor.value;
|
||||
descriptor.value = async function (...args: any[]) {
|
||||
const key = `${customKey}${String(methodName)}.(${args.map(arg => JSON.stringify(arg)).join(', ')})`;
|
||||
cache.forEach((value, key) => {
|
||||
if (value.expiry < Date.now()) {
|
||||
cache.delete(key);
|
||||
}
|
||||
});
|
||||
const cachedValue = cache.get(key);
|
||||
if (cachedValue && cachedValue.expiry > Date.now()) {
|
||||
return cachedValue.value;
|
||||
}
|
||||
// const start = Date.now();
|
||||
const result = await originalMethod.apply(this, args);
|
||||
// const end = Date.now();
|
||||
// console.log(`Method ${methodName} executed in ${end - start} ms.`);
|
||||
cache.set(key, { expiry: Date.now() + ttl, value: result });
|
||||
return result;
|
||||
};
|
||||
}
|
||||
return logExecutionTime;
|
||||
}
|
||||
export function CacheClassFuncAsyncExtend(ttl: number = 3600 * 1000, customKey: string = '', checker: any = (...data: any[]) => { return true; }) {
|
||||
//console.log('CacheClassFuncAsync', ttl, customKey);
|
||||
function logExecutionTime(target: any, methodName: string, descriptor: PropertyDescriptor) {
|
||||
//console.log('logExecutionTime', target, methodName, descriptor);
|
||||
const cache = new Map<string, { expiry: number; value: any }>();
|
||||
const originalMethod = descriptor.value;
|
||||
descriptor.value = async function (...args: any[]) {
|
||||
const key = `${customKey}${String(methodName)}.(${args.map(arg => JSON.stringify(arg)).join(', ')})`;
|
||||
cache.forEach((value, key) => {
|
||||
if (value.expiry < Date.now()) {
|
||||
cache.delete(key);
|
||||
}
|
||||
});
|
||||
const cachedValue = cache.get(key);
|
||||
if (cachedValue && cachedValue.expiry > Date.now()) {
|
||||
return cachedValue.value;
|
||||
}
|
||||
// const start = Date.now();
|
||||
const result = await originalMethod.apply(this, args);
|
||||
if (!checker(...args, result)) {
|
||||
return result;//丢弃缓存
|
||||
}
|
||||
// const end = Date.now();
|
||||
// console.log(`Method ${methodName} executed in ${end - start} ms.`);
|
||||
cache.set(key, { expiry: Date.now() + ttl, value: result });
|
||||
return result;
|
||||
};
|
||||
}
|
||||
return logExecutionTime;
|
||||
}
|
||||
// export function CacheClassFuncAsync(ttl: number = 3600 * 1000, customKey: string = ''): any {
|
||||
// const cache = new Map<string, { expiry: number; value: any }>();
|
||||
|
||||
// // 注意:在JavaScript装饰器中,我们通常不直接处理ClassMethodDecoratorContext这样的类型,
|
||||
// // 因为装饰器的参数通常是目标类(对于类装饰器)、属性名(对于属性装饰器)等。
|
||||
// // 对于方法装饰器,我们关注的是方法本身及其描述符。
|
||||
// // 但这里我们维持原逻辑,假设有一个自定义的处理上下文的方式。
|
||||
|
||||
// return function (originalMethod: Function): any {
|
||||
// console.log(originalMethod);
|
||||
// // 由于JavaScript装饰器原生不支持异步直接定义,我们保持async定义以便处理异步方法。
|
||||
// async function decoratorWrapper(this: any, ...args: any[]): Promise<any> {
|
||||
// console.log(...args);
|
||||
// const key = `${customKey}${originalMethod.name}.(${args.map(arg => JSON.stringify(arg)).join(', ')})`;
|
||||
// const cachedValue = cache.get(key);
|
||||
// // 遍历cache 清除expiry内容
|
||||
// cache.forEach((value, key) => {
|
||||
// if (value.expiry < Date.now()) {
|
||||
// cache.delete(key);
|
||||
// }
|
||||
// });
|
||||
// if (cachedValue && cachedValue.expiry > Date.now()) {
|
||||
// return cachedValue.value;
|
||||
// }
|
||||
|
||||
// // 直接await异步方法的结果
|
||||
// const result = await originalMethod.apply(this, args);
|
||||
// cache.set(key, { expiry: Date.now() + ttl, value: result });
|
||||
// return result;
|
||||
// }
|
||||
|
||||
// // 返回装饰后的方法,保持与原方法相同的名称和描述符(如果需要更精细的控制,可以考虑使用Object.getOwnPropertyDescriptor等)
|
||||
// return decoratorWrapper;
|
||||
// };
|
||||
// }
|
||||
|
||||
/**
|
||||
* 函数缓存装饰器,根据方法名、参数、自定义key生成缓存键,在一定时间内返回缓存结果
|
||||
@@ -132,6 +266,10 @@ export function migrateConfig(oldConfig: any) {
|
||||
enable: oldConfig.enableWsReverse,
|
||||
urls: oldConfig.wsReverseUrls,
|
||||
},
|
||||
GroupLocalTime: {
|
||||
Record: false,
|
||||
RecordList: []
|
||||
},
|
||||
debug: oldConfig.debug,
|
||||
heartInterval: oldConfig.heartInterval,
|
||||
messagePostFormat: oldConfig.messagePostFormat,
|
||||
@@ -139,6 +277,7 @@ export function migrateConfig(oldConfig: any) {
|
||||
musicSignUrl: oldConfig.musicSignUrl,
|
||||
reportSelfMessage: oldConfig.reportSelfMessage,
|
||||
token: oldConfig.token,
|
||||
|
||||
};
|
||||
return newConfig;
|
||||
}
|
||||
@@ -147,12 +286,49 @@ export async function UpdateConfig() {
|
||||
const configFiles = await fs.readdir(path.join(__dirname, 'config'));
|
||||
for (const file of configFiles) {
|
||||
if (file.match(/^onebot11_\d+.json$/)) {
|
||||
let CurrentConfig = JSON.parse(await fs.readFile(path.join(__dirname, 'config', file), 'utf8'));
|
||||
const CurrentConfig = JSON.parse(await fs.readFile(path.join(__dirname, 'config', file), 'utf8'));
|
||||
if (isValidOldConfig(CurrentConfig)) {
|
||||
log("正在迁移旧配置到新配置 File:", file);
|
||||
let NewConfig = migrateConfig(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;
|
||||
}
|
||||
|
||||
export async function deleteOldFiles(directoryPath: string, daysThreshold: number) {
|
||||
try {
|
||||
const files = await fsPromise.readdir(directoryPath);
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = path.join(directoryPath, file);
|
||||
const stats = await fsPromise.stat(filePath);
|
||||
const lastModifiedTime = stats.mtimeMs;
|
||||
const currentTime = Date.now();
|
||||
const timeDifference = currentTime - lastModifiedTime;
|
||||
const daysDifference = timeDifference / (1000 * 60 * 60 * 24);
|
||||
|
||||
if (daysDifference > daysThreshold) {
|
||||
await fsPromise.unlink(filePath); // Delete the file
|
||||
//console.log(`Deleted: ${filePath}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
//console.error('Error deleting files:', error);
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,12 @@ 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';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
export enum LogLevel {
|
||||
DEBUG = 'debug',
|
||||
@@ -33,17 +39,17 @@ const logConfig: Configuration = {
|
||||
FileAppender: { // 输出到文件的appender
|
||||
type: 'file',
|
||||
filename: logPath, // 指定日志文件的位置和文件名
|
||||
maxLoogSize: 10485760, // 日志文件的最大大小(单位:字节),这里设置为10MB
|
||||
maxLogSize: 10485760, // 日志文件的最大大小(单位:字节),这里设置为10MB
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '%d{yyyy-MM-dd hh:mm:ss} [%p] - %m'
|
||||
pattern: '%d{yyyy-MM-dd hh:mm:ss} [%p] %X{userInfo} | %m'
|
||||
}
|
||||
},
|
||||
ConsoleAppender: { // 输出到控制台的appender
|
||||
type: 'console',
|
||||
layout: {
|
||||
type: 'pattern',
|
||||
pattern: '%d{yyyy-MM-dd hh:mm:ss} [%p] - %m'
|
||||
pattern: `%d{yyyy-MM-dd hh:mm:ss} [%[%p%]] ${chalk.magenta('%X{userInfo}')} | %m`
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -55,7 +61,9 @@ const logConfig: Configuration = {
|
||||
};
|
||||
|
||||
log4js.configure(logConfig);
|
||||
|
||||
const loggerConsole = log4js.getLogger('console');
|
||||
const loggerFile = log4js.getLogger('file');
|
||||
const loggerDefault = log4js.getLogger('default');
|
||||
|
||||
export function setLogLevel(fileLogLevel: LogLevel, consoleLogLevel: LogLevel) {
|
||||
logConfig.categories.file.level = fileLogLevel;
|
||||
@@ -64,12 +72,12 @@ export function setLogLevel(fileLogLevel: LogLevel, consoleLogLevel: LogLevel) {
|
||||
}
|
||||
|
||||
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);
|
||||
const userInfo = `${selfInfo.nick}(${selfInfo.uin})`;
|
||||
loggerConsole.addContext('userInfo', userInfo);
|
||||
loggerFile.addContext('userInfo', userInfo);
|
||||
loggerDefault.addContext('userInfo', userInfo);
|
||||
}
|
||||
setLogSelfInfo({ nick: '', uin: '', uid: '' });
|
||||
|
||||
let fileLogEnabled = true;
|
||||
let consoleLogEnabled = true;
|
||||
@@ -80,26 +88,31 @@ export function enableConsoleLog(enable: boolean) {
|
||||
consoleLogEnabled = enable;
|
||||
}
|
||||
|
||||
function formatMsg(msg: any[]){
|
||||
function formatMsg(msg: any[]) {
|
||||
let logMsg = '';
|
||||
for (const msgItem of msg) {
|
||||
// 判断是否是对象
|
||||
if (typeof msgItem === 'object') {
|
||||
if (msgItem instanceof Error) { // 判断是否是错误
|
||||
logMsg += msgItem.stack + ' ';
|
||||
continue;
|
||||
} else 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';
|
||||
return logMsg;
|
||||
}
|
||||
|
||||
function _log(level: LogLevel, ...args: any[]){
|
||||
if (consoleLogEnabled){
|
||||
log4js.getLogger('console')[level](formatMsg(args));
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const colorEscape = /\x1B[@-_][0-?]*[ -/]*[@-~]/g;
|
||||
|
||||
function _log(level: LogLevel, ...args: any[]) {
|
||||
if (consoleLogEnabled) {
|
||||
loggerConsole[level](formatMsg(args));
|
||||
}
|
||||
if (fileLogEnabled){
|
||||
log4js.getLogger('file')[level](formatMsg(args));
|
||||
if (fileLogEnabled) {
|
||||
loggerFile[level](formatMsg(args).replace(colorEscape, ''));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,3 +128,11 @@ export function logDebug(...args: any[]) {
|
||||
export function logError(...args: any[]) {
|
||||
_log(LogLevel.ERROR, ...args);
|
||||
}
|
||||
|
||||
export function logWarn(...args: any[]) {
|
||||
_log(LogLevel.WARN, ...args);
|
||||
}
|
||||
|
||||
export function logFatal(...args: any[]) {
|
||||
_log(LogLevel.FATAL, ...args);
|
||||
}
|
@@ -1,37 +1,44 @@
|
||||
import { resolve } from "node:path";
|
||||
import { spawn } from "node:child_process";
|
||||
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) {
|
||||
let batScript = resolve(__dirname, './napcat.bat');
|
||||
let batUtf8Script = resolve(__dirname, './napcat-utf8.bat');
|
||||
let 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);
|
||||
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() {
|
||||
let batScript = resolve(__dirname, './napcat.bat');
|
||||
let batUtf8Script = resolve(__dirname, './napcat-utf8.bat');
|
||||
let 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
@@ -1,37 +1,60 @@
|
||||
import https from 'node:https';
|
||||
import http from 'node:http';
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { NTQQUserApi } from '@/core';
|
||||
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值
|
||||
}
|
||||
});
|
||||
static async HttpsGetCookies(url: string): Promise<{ [key: string]: string }> {
|
||||
const client = url.startsWith('https') ? https : http;
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = client.get(url, (res) => {
|
||||
let cookies: { [key: string]: string } = {};
|
||||
const handleRedirect = (res: http.IncomingMessage) => {
|
||||
//console.log(res.headers.location);
|
||||
if (res.statusCode === 301 || res.statusCode === 302) {
|
||||
if (res.headers.location) {
|
||||
const redirectUrl = new URL(res.headers.location, url);
|
||||
RequestUtil.HttpsGetCookies(redirectUrl.href).then((redirectCookies) => {
|
||||
// 合并重定向过程中的cookies
|
||||
cookies = { ...cookies, ...redirectCookies };
|
||||
resolve(cookies);
|
||||
}).catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
} else {
|
||||
resolve(cookies);
|
||||
}
|
||||
} else {
|
||||
resolve(cookies);
|
||||
}
|
||||
};
|
||||
res.on('data', () => { }); // Necessary to consume the stream
|
||||
res.on('end', () => {
|
||||
handleRedirect(res);
|
||||
});
|
||||
if (res.headers['set-cookie']) {
|
||||
//console.log(res.headers['set-cookie']);
|
||||
res.headers['set-cookie'].forEach((cookie) => {
|
||||
const parts = cookie.split(';')[0].split('=');
|
||||
const key = parts[0];
|
||||
const value = parts[1];
|
||||
if (key && value && key.length > 0 && value.length > 0) {
|
||||
cookies[key] = value;
|
||||
}
|
||||
});
|
||||
resolve(cookiesMap);
|
||||
}
|
||||
}).on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
req.on('error', (error: any) => {
|
||||
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> {
|
||||
let option = new URL(url);
|
||||
static async HttpGetJson<T>(url: string, method: string = 'GET', data?: any, headers: { [key: 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,
|
||||
@@ -40,6 +63,10 @@ export class RequestUtil {
|
||||
method: method,
|
||||
headers: headers
|
||||
};
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// 'Content-Length': Buffer.byteLength(postData),
|
||||
// },
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = protocol.request(options, (res: any) => {
|
||||
let responseBody = '';
|
||||
@@ -81,7 +108,86 @@ export class RequestUtil {
|
||||
}
|
||||
|
||||
// 请求返回都是原始内容
|
||||
static async HttpGetText(url: string, method: string = 'GET', data?: any, headers: Record<string, string> = {}) {
|
||||
static async HttpGetText(url: string, method: string = 'GET', data?: any, headers: { [key: string]: string } = {}) {
|
||||
return this.HttpGetJson<string>(url, method, data, headers, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
static async createFormData(boundary: string, filePath: string): Promise<Buffer> {
|
||||
let type = 'image/png';
|
||||
if (filePath.endsWith('.jpg')) {
|
||||
type = 'image/jpeg';
|
||||
}
|
||||
const formDataParts = [
|
||||
`------${boundary}\r\n`,
|
||||
`Content-Disposition: form-data; name="share_image"; filename="${filePath}"\r\n`,
|
||||
'Content-Type: ' + type + '\r\n\r\n'
|
||||
];
|
||||
|
||||
const fileContent = readFileSync(filePath);
|
||||
const footer = `\r\n------${boundary}--`;
|
||||
return Buffer.concat([
|
||||
Buffer.from(formDataParts.join(''), 'utf8'),
|
||||
fileContent,
|
||||
Buffer.from(footer, 'utf8')
|
||||
]);
|
||||
}
|
||||
|
||||
static async uploadImageForOpenPlatform(filePath: string): Promise<string> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
type retType = { retcode: number, result?: { url: string } };
|
||||
try {
|
||||
const cookies = Object.entries(await NTQQUserApi.getCookies('connect.qq.com')).map(([key, value]) => `${key}=${value}`).join('; ');
|
||||
const options = {
|
||||
hostname: 'cgi.connect.qq.com',
|
||||
port: 443,
|
||||
path: '/qqconnectopen/upload_share_image',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Referer': 'https://cgi.connect.qq.com',
|
||||
'Cookie': cookies,
|
||||
'Accept': '*/*',
|
||||
'Connection': 'keep-alive',
|
||||
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
|
||||
}
|
||||
};
|
||||
const req = https.request(options, async (res) => {
|
||||
let responseBody = '';
|
||||
|
||||
res.on('data', (chunk: string | Buffer) => {
|
||||
responseBody += chunk.toString();
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
try {
|
||||
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
||||
const responseJson = JSON.parse(responseBody) as retType;
|
||||
resolve(responseJson.result!.url!);
|
||||
} else {
|
||||
reject(new Error(`Unexpected status code: ${res.statusCode}`));
|
||||
}
|
||||
} catch (parseError) {
|
||||
reject(parseError);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
req.on('error', (error) => {
|
||||
reject(error);
|
||||
console.error('Error during upload:', error);
|
||||
});
|
||||
|
||||
const body = await RequestUtil.createFormData('WebKitFormBoundary7MA4YWxkTrZu0gW', filePath);
|
||||
// req.setHeader('Content-Length', Buffer.byteLength(body));
|
||||
// console.log(`Prepared data size: ${Buffer.byteLength(body)} bytes`);
|
||||
req.write(body);
|
||||
req.end();
|
||||
return;
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,17 +1,74 @@
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { networkInterfaces } from 'os';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
// 缓解Win7设备兼容性问题
|
||||
let osName: string;
|
||||
// 设备ID
|
||||
let machineId: Promise<string>;
|
||||
|
||||
try {
|
||||
osName = os.hostname();
|
||||
} catch (e) {
|
||||
osName = 'NapCat'; // + crypto.randomUUID().substring(0, 4);
|
||||
}
|
||||
|
||||
const invalidMacAddresses = new Set([
|
||||
'00:00:00:00:00:00',
|
||||
'ff:ff:ff:ff:ff:ff',
|
||||
'ac:de:48:00:11:22'
|
||||
]);
|
||||
|
||||
function validateMacAddress(candidate: string): boolean {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
const tempCandidate = candidate.replace(/\-/g, ':').toLowerCase();
|
||||
return !invalidMacAddresses.has(tempCandidate);
|
||||
}
|
||||
|
||||
export async function getMachineId(): Promise<string> {
|
||||
if (!machineId) {
|
||||
machineId = (async () => {
|
||||
const id = await getMacMachineId();
|
||||
return id || randomUUID(); // fallback, generate a UUID
|
||||
})();
|
||||
}
|
||||
|
||||
return machineId;
|
||||
}
|
||||
|
||||
export function getMac(): string {
|
||||
const ifaces = networkInterfaces();
|
||||
for (const name in ifaces) {
|
||||
const networkInterface = ifaces[name];
|
||||
if (networkInterface) {
|
||||
for (const { mac } of networkInterface) {
|
||||
if (validateMacAddress(mac)) {
|
||||
return mac;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('Unable to retrieve mac address (unexpected format)');
|
||||
}
|
||||
|
||||
async function getMacMachineId(): Promise<string | undefined> {
|
||||
try {
|
||||
const crypto = await import('crypto');
|
||||
const macAddress = getMac();
|
||||
return crypto.createHash('sha256').update(macAddress, 'utf8').digest('hex');
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const homeDir = os.homedir();
|
||||
|
||||
|
||||
export const systemPlatform = os.platform();
|
||||
export const cpuArch = os.arch();
|
||||
export const systemVersion = os.release();
|
||||
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();
|
@@ -2,30 +2,30 @@
|
||||
* 运行时类型转换与检查类
|
||||
*/
|
||||
export class TypeCheck {
|
||||
static isEmpty(value: any): boolean {
|
||||
return value === null || value === undefined || value === '' ||
|
||||
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 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 toString(value: any): string {
|
||||
return String(value);
|
||||
}
|
||||
|
||||
static toBoolean(value: any): boolean {
|
||||
return Boolean(value);
|
||||
}
|
||||
static toBoolean(value: any): boolean {
|
||||
return Boolean(value);
|
||||
}
|
||||
|
||||
static toArray(value: any): any[] {
|
||||
return Array.isArray(value) ? value : [value];
|
||||
}
|
||||
static toArray(value: any): any[] {
|
||||
return Array.isArray(value) ? value : [value];
|
||||
}
|
||||
}
|
@@ -14,7 +14,7 @@ export async function checkVersion(): Promise<string> {
|
||||
try {
|
||||
version = (await RequestUtil.HttpGetJson<{ version: string }>(url)).version;
|
||||
} catch (e) {
|
||||
logDebug(e);
|
||||
logDebug('检测更新异常',e);
|
||||
}
|
||||
if (version) {
|
||||
resolve(version);
|
||||
|
File diff suppressed because one or more lines are too long
1
src/core
1
src/core
Submodule src/core deleted from 00d059a88e
@@ -1,14 +0,0 @@
|
||||
interface IDependsAdapter {
|
||||
onMSFStatusChange(arg1: number, arg2: number): void;
|
||||
onMSFSsoError(args: unknown): void;
|
||||
getGroupCode(args: unknown): void;
|
||||
}
|
||||
export interface NodeIDependsAdapter extends IDependsAdapter {
|
||||
new (adapter: IDependsAdapter): NodeIDependsAdapter;
|
||||
}
|
||||
export declare class DependsAdapter implements IDependsAdapter {
|
||||
onMSFStatusChange(arg1: number, arg2: number): void;
|
||||
onMSFSsoError(args: unknown): void;
|
||||
getGroupCode(args: unknown): void;
|
||||
}
|
||||
export {};
|
@@ -1 +0,0 @@
|
||||
var _0x312801=_0x226a;(function(_0x2467bd,_0x1ea46c){var _0x55b3b9=_0x226a,_0xc5a225=_0x2467bd();while(!![]){try{var _0x37ca7d=-parseInt(_0x55b3b9(0xb8))/0x1*(-parseInt(_0x55b3b9(0xb7))/0x2)+parseInt(_0x55b3b9(0xbe))/0x3*(-parseInt(_0x55b3b9(0xb6))/0x4)+-parseInt(_0x55b3b9(0xba))/0x5*(parseInt(_0x55b3b9(0xbd))/0x6)+parseInt(_0x55b3b9(0xbf))/0x7+-parseInt(_0x55b3b9(0xbb))/0x8+-parseInt(_0x55b3b9(0xc0))/0x9+-parseInt(_0x55b3b9(0xbc))/0xa*(-parseInt(_0x55b3b9(0xb9))/0xb);if(_0x37ca7d===_0x1ea46c)break;else _0xc5a225['push'](_0xc5a225['shift']());}catch(_0x37c00a){_0xc5a225['push'](_0xc5a225['shift']());}}}(_0x3f33,0xa7262));function _0x226a(_0x147607,_0x4d8036){var _0x3f3311=_0x3f33();return _0x226a=function(_0x226afb,_0x3c304e){_0x226afb=_0x226afb-0xb5;var _0x4481fe=_0x3f3311[_0x226afb];return _0x4481fe;},_0x226a(_0x147607,_0x4d8036);}function _0x3f33(){var _0x49480f=['109615yGGBGb','417840uZphAj','6916336dArrkB','3280WaNFfO','84tMzoBS','2219037UDDDKL','8472464uELZIr','11638368bueewF','onMSFStatusChange','getGroupCode','4vhGRRP','546190CcHtON','1ZYSbWg'];_0x3f33=function(){return _0x49480f;};return _0x3f33();}export class DependsAdapter{[_0x312801(0xc1)](_0x1bb24c,_0x487012){}['onMSFSsoError'](_0x41a22e){}[_0x312801(0xb5)](_0x487b3b){}}
|
@@ -1,14 +0,0 @@
|
||||
interface IDispatcherAdapter {
|
||||
dispatchRequest(arg: unknown): void;
|
||||
dispatchCall(arg: unknown): void;
|
||||
dispatchCallWithJson(arg: unknown): void;
|
||||
}
|
||||
export interface NodeIDispatcherAdapter extends IDispatcherAdapter {
|
||||
new (adapter: IDispatcherAdapter): NodeIDispatcherAdapter;
|
||||
}
|
||||
export declare class DispatcherAdapter implements IDispatcherAdapter {
|
||||
dispatchRequest(arg: unknown): void;
|
||||
dispatchCall(arg: unknown): void;
|
||||
dispatchCallWithJson(arg: unknown): void;
|
||||
}
|
||||
export {};
|
@@ -1 +0,0 @@
|
||||
function _0xd918(_0x41483d,_0x889907){var _0x58bf19=_0x58bf();return _0xd918=function(_0xd918d8,_0x1ca855){_0xd918d8=_0xd918d8-0x1a8;var _0x922fac=_0x58bf19[_0xd918d8];return _0x922fac;},_0xd918(_0x41483d,_0x889907);}var _0x2ff274=_0xd918;(function(_0x4e51bb,_0x3ea197){var _0x37f53a=_0xd918,_0x443375=_0x4e51bb();while(!![]){try{var _0x1e5344=-parseInt(_0x37f53a(0x1ad))/0x1+parseInt(_0x37f53a(0x1af))/0x2+parseInt(_0x37f53a(0x1ac))/0x3*(parseInt(_0x37f53a(0x1b0))/0x4)+-parseInt(_0x37f53a(0x1b4))/0x5*(parseInt(_0x37f53a(0x1ae))/0x6)+parseInt(_0x37f53a(0x1a9))/0x7*(-parseInt(_0x37f53a(0x1ab))/0x8)+-parseInt(_0x37f53a(0x1aa))/0x9+parseInt(_0x37f53a(0x1b2))/0xa;if(_0x1e5344===_0x3ea197)break;else _0x443375['push'](_0x443375['shift']());}catch(_0x35dc93){_0x443375['push'](_0x443375['shift']());}}}(_0x58bf,0x469fd));export class DispatcherAdapter{[_0x2ff274(0x1b3)](_0x1d95f2){}[_0x2ff274(0x1a8)](_0x3ea26c){}[_0x2ff274(0x1b1)](_0x10acdf){}}function _0x58bf(){var _0x4f3322=['dispatchRequest','2046670cXvFGX','dispatchCall','21STBWCf','2445264sDyRrR','2408lpMgBD','294726nxCwLq','374542jqZJvb','6PeQMDn','1135130cwIbEO','8xmGioW','dispatchCallWithJson','5817030ZXbzaz'];_0x58bf=function(){return _0x4f3322;};return _0x58bf();}
|
@@ -1,24 +0,0 @@
|
||||
interface IGlobalAdapter {
|
||||
onLog(...args: unknown[]): void;
|
||||
onGetSrvCalTime(...args: unknown[]): void;
|
||||
onShowErrUITips(...args: unknown[]): void;
|
||||
fixPicImgType(...args: unknown[]): void;
|
||||
getAppSetting(...args: unknown[]): void;
|
||||
onInstallFinished(...args: unknown[]): void;
|
||||
onUpdateGeneralFlag(...args: unknown[]): void;
|
||||
onGetOfflineMsg(...args: unknown[]): void;
|
||||
}
|
||||
export interface NodeIGlobalAdapter extends IGlobalAdapter {
|
||||
new (adapter: IGlobalAdapter): NodeIGlobalAdapter;
|
||||
}
|
||||
export declare class GlobalAdapter implements IGlobalAdapter {
|
||||
onLog(...args: unknown[]): void;
|
||||
onGetSrvCalTime(...args: unknown[]): void;
|
||||
onShowErrUITips(...args: unknown[]): void;
|
||||
fixPicImgType(...args: unknown[]): void;
|
||||
getAppSetting(...args: unknown[]): void;
|
||||
onInstallFinished(...args: unknown[]): void;
|
||||
onUpdateGeneralFlag(...args: unknown[]): void;
|
||||
onGetOfflineMsg(...args: unknown[]): void;
|
||||
}
|
||||
export {};
|
@@ -1 +0,0 @@
|
||||
function _0x542e(_0x24d725,_0x626b2e){var _0x560aad=_0x560a();return _0x542e=function(_0x542ed4,_0x34edc1){_0x542ed4=_0x542ed4-0x76;var _0x635f00=_0x560aad[_0x542ed4];return _0x635f00;},_0x542e(_0x24d725,_0x626b2e);}var _0x12c22c=_0x542e;(function(_0x5f520f,_0x2af615){var _0x261cf6=_0x542e,_0x19e611=_0x5f520f();while(!![]){try{var _0x4f968b=parseInt(_0x261cf6(0x7c))/0x1+-parseInt(_0x261cf6(0x78))/0x2+parseInt(_0x261cf6(0x82))/0x3+parseInt(_0x261cf6(0x7e))/0x4+-parseInt(_0x261cf6(0x7b))/0x5*(-parseInt(_0x261cf6(0x7d))/0x6)+parseInt(_0x261cf6(0x7a))/0x7+parseInt(_0x261cf6(0x84))/0x8*(-parseInt(_0x261cf6(0x80))/0x9);if(_0x4f968b===_0x2af615)break;else _0x19e611['push'](_0x19e611['shift']());}catch(_0x364fba){_0x19e611['push'](_0x19e611['shift']());}}}(_0x560a,0x219d4));export class GlobalAdapter{[_0x12c22c(0x76)](..._0x2596f6){}[_0x12c22c(0x85)](..._0x5aa245){}['onShowErrUITips'](..._0x30bb0b){}[_0x12c22c(0x81)](..._0x526a26){}[_0x12c22c(0x7f)](..._0xda6e56){}[_0x12c22c(0x83)](..._0x24f600){}[_0x12c22c(0x79)](..._0x4642b6){}[_0x12c22c(0x77)](..._0x4dc1b2){}}function _0x560a(){var _0x8b3fc=['15ChtyeH','20320Tkwggx','310938UySqVX','724892uXQoPU','getAppSetting','7299JGoYfC','fixPicImgType','78327jdPzcS','onInstallFinished','3488ttTWCp','onGetSrvCalTime','onLog','onGetOfflineMsg','82140zEVtjW','onUpdateGeneralFlag','1044603ksIwqi'];_0x560a=function(){return _0x8b3fc;};return _0x560a();}
|
@@ -1 +0,0 @@
|
||||
function _0x3c69(_0x3bcbf7,_0x5062f6){var _0x18dfde=_0x18df();return _0x3c69=function(_0x3c698a,_0x2be4a1){_0x3c698a=_0x3c698a-0x18d;var _0x4fa004=_0x18dfde[_0x3c698a];return _0x4fa004;},_0x3c69(_0x3bcbf7,_0x5062f6);}(function(_0x10db25,_0x5cfed7){var _0x503822=_0x3c69,_0x22f0ac=_0x10db25();while(!![]){try{var _0x4c1fac=parseInt(_0x503822(0x192))/0x1+-parseInt(_0x503822(0x191))/0x2*(-parseInt(_0x503822(0x18d))/0x3)+-parseInt(_0x503822(0x18e))/0x4+-parseInt(_0x503822(0x18f))/0x5+parseInt(_0x503822(0x195))/0x6*(parseInt(_0x503822(0x190))/0x7)+-parseInt(_0x503822(0x193))/0x8*(-parseInt(_0x503822(0x196))/0x9)+-parseInt(_0x503822(0x194))/0xa;if(_0x4c1fac===_0x5cfed7)break;else _0x22f0ac['push'](_0x22f0ac['shift']());}catch(_0x1ef1d6){_0x22f0ac['push'](_0x22f0ac['shift']());}}}(_0x18df,0x6ee29));function _0x18df(){var _0x306bf8=['85099McqKSS','446612gfPezC','628119vRfteW','16UHyByL','9280230MKmgnk','312AXqpyn','1833957mTigZj','6zFIsSs','244244XMOWDt','3355860pyDEWQ'];_0x18df=function(){return _0x306bf8;};return _0x18df();}export*from'./NodeIDependsAdapter';export*from'./NodeIDispatcherAdapter';export*from'./NodeIGlobalAdapter';
|
37
src/core.lib/src/apis/file.d.ts
vendored
37
src/core.lib/src/apis/file.d.ts
vendored
@@ -1,37 +0,0 @@
|
||||
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>;
|
||||
}
|
File diff suppressed because one or more lines are too long
5
src/core.lib/src/apis/friend.d.ts
vendored
5
src/core.lib/src/apis/friend.d.ts
vendored
@@ -1,5 +0,0 @@
|
||||
import { FriendRequest, User } from '@/core/entities';
|
||||
export declare class NTQQFriendApi {
|
||||
static getFriends(forced?: boolean): Promise<User[]>;
|
||||
static handleFriendRequest(request: FriendRequest, accept: boolean): Promise<void>;
|
||||
}
|
@@ -1 +0,0 @@
|
||||
const _0x200bce=_0x521e;function _0xbabf(){const _0x211bb5=['addListener','2865738XvhlRl','set','66454YjOygA','uid','获取好友列表完成','reqTime','829616gfjVgA','push','3355675vCCGpI','getBuddyService','QypPz','handleFriendRequest','117iGJzXo','onBuddyListChange','delete','buddyList','获取好友列表超时','gJDqR','getFriends','friendUid','uin','onLoginSuccess','70828vHbuOz','getBuddyList','EHncv','approvalFriendRequest','session','iWgub','qlebO','开始获取好友列表','19828488yGaGlA','3392438TVQZNU'];_0xbabf=function(){return _0x211bb5;};return _0xbabf();}(function(_0x2df1dc,_0x19f282){const _0x6bf846=_0x521e,_0x80a8c=_0x2df1dc();while(!![]){try{const _0x44b977=-parseInt(_0x6bf846(0x16a))/0x1+parseInt(_0x6bf846(0x14d))/0x2+parseInt(_0x6bf846(0x153))/0x3*(-parseInt(_0x6bf846(0x15d))/0x4)+-parseInt(_0x6bf846(0x14f))/0x5+-parseInt(_0x6bf846(0x168))/0x6+-parseInt(_0x6bf846(0x166))/0x7+parseInt(_0x6bf846(0x165))/0x8;if(_0x44b977===_0x19f282)break;else _0x80a8c['push'](_0x80a8c['shift']());}catch(_0x59682b){_0x80a8c['push'](_0x80a8c['shift']());}}}(_0xbabf,0x7aca6));import{BuddyListener,napCatCore}from'@/core';import{logDebug}from'@/common/utils/log';import{uid2UinMap}from'@/core/data';import{randomUUID}from'crypto';const buddyChangeTasks=new Map(),buddyListener=new BuddyListener();function _0x521e(_0x32b35a,_0x4316c1){const _0xbabf17=_0xbabf();return _0x521e=function(_0x521e87,_0x464bc2){_0x521e87=_0x521e87-0x14a;let _0x4e917c=_0xbabf17[_0x521e87];return _0x4e917c;},_0x521e(_0x32b35a,_0x4316c1);}buddyListener[_0x200bce(0x154)]=_0xf2c49a=>{const _0x4a6b60=_0x200bce;for(const [_0x58ff70,_0x533778]of buddyChangeTasks){_0x533778(_0xf2c49a),buddyChangeTasks[_0x4a6b60(0x155)](_0x58ff70);}},setTimeout(()=>{const _0x331f78=_0x200bce;napCatCore[_0x331f78(0x15c)](()=>{const _0x148e1d=_0x331f78;napCatCore[_0x148e1d(0x167)](buddyListener);});},0x64);export class NTQQFriendApi{static async[_0x200bce(0x159)](_0x29cefa=![]){const _0x2c974d=_0x200bce,_0x1fd5d8={'qlebO':_0x2c974d(0x157),'gJDqR':function(_0x43b2bf,_0x49881f,_0x2b7903){return _0x43b2bf(_0x49881f,_0x2b7903);},'yvXxm':function(_0x10044e,_0x44494e){return _0x10044e(_0x44494e);},'EHncv':function(_0x577260,_0x33e923,_0x293431){return _0x577260(_0x33e923,_0x293431);},'iWgub':function(_0x43c87a){return _0x43c87a();}};return new Promise((_0x17a917,_0x2dd79f)=>{const _0x533a8b=_0x2c974d,_0x301724={'QypPz':function(_0x3f9258,_0x1fa332,_0x32a466){const _0x3a40f2=_0x521e;return _0x1fd5d8[_0x3a40f2(0x15f)](_0x3f9258,_0x1fa332,_0x32a466);}};let _0x3f2664=![];_0x1fd5d8[_0x533a8b(0x158)](setTimeout,()=>{const _0x51eb22=_0x533a8b;!_0x3f2664&&(logDebug(_0x1fd5d8['qlebO']),_0x2dd79f(_0x1fd5d8[_0x51eb22(0x163)]));},0x1388);const _0x21371c=[],_0x4d537d=_0x2686ce=>{const _0x258077=_0x533a8b;for(const _0x1a06c1 of _0x2686ce){for(const _0x2da3ba of _0x1a06c1[_0x258077(0x156)]){_0x21371c[_0x258077(0x14e)](_0x2da3ba),uid2UinMap[_0x2da3ba[_0x258077(0x14a)]]=_0x2da3ba[_0x258077(0x15b)];}}_0x3f2664=!![],_0x1fd5d8[_0x258077(0x158)](logDebug,_0x258077(0x14b),_0x21371c),_0x1fd5d8['yvXxm'](_0x17a917,_0x21371c);};buddyChangeTasks[_0x533a8b(0x169)](_0x1fd5d8[_0x533a8b(0x162)](randomUUID),_0x4d537d),napCatCore[_0x533a8b(0x161)]['getBuddyService']()[_0x533a8b(0x15e)](_0x29cefa)['then'](_0x1e52f8=>{const _0x1724cc=_0x533a8b;_0x301724[_0x1724cc(0x151)](logDebug,_0x1724cc(0x164),_0x1e52f8);});});}static async[_0x200bce(0x152)](_0x5c339a,_0x2b7159){const _0x223df1=_0x200bce;napCatCore[_0x223df1(0x161)][_0x223df1(0x150)]()?.[_0x223df1(0x160)]({'friendUid':_0x5c339a[_0x223df1(0x15a)],'reqTime':_0x5c339a[_0x223df1(0x14c)],'accept':_0x2b7159});}}
|
33
src/core.lib/src/apis/group.d.ts
vendored
33
src/core.lib/src/apis/group.d.ts
vendored
@@ -1,33 +0,0 @@
|
||||
import { GroupMember, GroupRequestOperateTypes, GroupMemberRole, GroupNotify, Group } from '../entities';
|
||||
export declare class NTQQGroupApi {
|
||||
static getGroups(forced?: boolean): Promise<Group[]>;
|
||||
static getSingleScreenNotifies(num: number): Promise<unknown>;
|
||||
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>;
|
||||
}
|
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
(function(_0x42ec9e,_0x3c5d53){var _0x26790a=_0x4120,_0x1cf0b9=_0x42ec9e();while(!![]){try{var _0x12ccdb=parseInt(_0x26790a(0xa1))/0x1*(-parseInt(_0x26790a(0xa8))/0x2)+parseInt(_0x26790a(0xa3))/0x3+-parseInt(_0x26790a(0xa4))/0x4+parseInt(_0x26790a(0x9e))/0x5*(-parseInt(_0x26790a(0xa5))/0x6)+parseInt(_0x26790a(0xa2))/0x7+parseInt(_0x26790a(0xa0))/0x8*(-parseInt(_0x26790a(0xa7))/0x9)+-parseInt(_0x26790a(0xa6))/0xa*(-parseInt(_0x26790a(0x9f))/0xb);if(_0x12ccdb===_0x3c5d53)break;else _0x1cf0b9['push'](_0x1cf0b9['shift']());}catch(_0xbba197){_0x1cf0b9['push'](_0x1cf0b9['shift']());}}}(_0x5bf8,0x5d7c7));export*from'./file';function _0x4120(_0x5e1952,_0x137c1b){var _0x5bf8fe=_0x5bf8();return _0x4120=function(_0x41206d,_0x213e6a){_0x41206d=_0x41206d-0x9e;var _0x9c8c9=_0x5bf8fe[_0x41206d];return _0x9c8c9;},_0x4120(_0x5e1952,_0x137c1b);}export*from'./friend';export*from'./group';function _0x5bf8(){var _0x25fec3=['1084932TAbQsr','5687800qhIJgq','1773ZjlHgT','272378dWjIPd','10DlCeMH','33tXMZNU','25336ZEgeJd','1DQMToq','976647qkfmox','941649ujvmGm','2620372YxyMrf'];_0x5bf8=function(){return _0x25fec3;};return _0x5bf8();}export*from'./msg';export*from'./user';export*from'./webapi';export*from'./sign';export*from'./system';
|
25
src/core.lib/src/apis/msg.d.ts
vendored
25
src/core.lib/src/apis/msg.d.ts
vendored
@@ -1,25 +0,0 @@
|
||||
import { Peer, RawMessage, SendMessageElement } from '@/core/entities';
|
||||
import { GeneralCallResult } from '@/core/services/common';
|
||||
export declare class NTQQMsgApi {
|
||||
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<GeneralCallResult>;
|
||||
static multiForwardMsg(srcPeer: Peer, destPeer: Peer, msgIds: string[]): Promise<RawMessage>;
|
||||
}
|
File diff suppressed because one or more lines are too long
12
src/core.lib/src/apis/sign.d.ts
vendored
12
src/core.lib/src/apis/sign.d.ts
vendored
@@ -1,12 +0,0 @@
|
||||
export interface IdMusicSignPostData {
|
||||
type: 'qq' | '163';
|
||||
id: string | number;
|
||||
}
|
||||
export interface CustomMusicSignPostData {
|
||||
type: 'custom';
|
||||
url: string;
|
||||
audio: string;
|
||||
title: string;
|
||||
image?: string;
|
||||
singer?: string;
|
||||
}
|
@@ -1 +0,0 @@
|
||||
export{};
|
3
src/core.lib/src/apis/system.d.ts
vendored
3
src/core.lib/src/apis/system.d.ts
vendored
@@ -1,3 +0,0 @@
|
||||
export declare class NTQQSystemApi {
|
||||
static hasOtherRunningQQProcess(): Promise<boolean>;
|
||||
}
|
@@ -1 +0,0 @@
|
||||
function _0xe208(_0x239302,_0x48d04f){var _0x34ef9f=_0x34ef();return _0xe208=function(_0xe20843,_0x541c07){_0xe20843=_0xe20843-0x13e;var _0x19a61e=_0x34ef9f[_0xe20843];return _0x19a61e;},_0xe208(_0x239302,_0x48d04f);}var _0x3f60c9=_0xe208;function _0x34ef(){var _0x406d51=['4900240iHNPdG','1370170vDQCth','2972523tLPDlP','4203250HeADmm','908327esyrES','4ZClBmZ','hasOtherRunningQQProcess','5169774BrFFYi','8558163ynHfmc','10JnedOb','7nGjUnb','util'];_0x34ef=function(){return _0x406d51;};return _0x34ef();}(function(_0x1f3083,_0xe1cf2e){var _0xf220e2=_0xe208,_0x6caf01=_0x1f3083();while(!![]){try{var _0x2e3826=-parseInt(_0xf220e2(0x144))/0x1+parseInt(_0xf220e2(0x141))/0x2+-parseInt(_0xf220e2(0x142))/0x3*(-parseInt(_0xf220e2(0x145))/0x4)+-parseInt(_0xf220e2(0x143))/0x5+-parseInt(_0xf220e2(0x147))/0x6*(parseInt(_0xf220e2(0x13e))/0x7)+parseInt(_0xf220e2(0x140))/0x8+-parseInt(_0xf220e2(0x148))/0x9*(-parseInt(_0xf220e2(0x149))/0xa);if(_0x2e3826===_0xe1cf2e)break;else _0x6caf01['push'](_0x6caf01['shift']());}catch(_0x5d654c){_0x6caf01['push'](_0x6caf01['shift']());}}}(_0x34ef,0x99815));import{napCatCore}from'@/core';export class NTQQSystemApi{static async[_0x3f60c9(0x146)](){var _0x1497e8=_0x3f60c9;return napCatCore[_0x1497e8(0x13f)][_0x1497e8(0x146)]();}}
|
22
src/core.lib/src/apis/user.d.ts
vendored
22
src/core.lib/src/apis/user.d.ts
vendored
@@ -1,22 +0,0 @@
|
||||
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;
|
||||
succCounts: number;
|
||||
}>;
|
||||
static setQQAvatar(filePath: string): Promise<{
|
||||
result: number;
|
||||
errMsg: string;
|
||||
}>;
|
||||
static getSelfInfo(): Promise<void>;
|
||||
static getUserInfo(uid: string): Promise<void>;
|
||||
static getUserDetailInfo(uid: string): Promise<User>;
|
||||
static getPSkey(domainList: string[], cached?: boolean): Promise<{
|
||||
[key: string]: string;
|
||||
}>;
|
||||
static getRobotUinRange(): Promise<Array<any>>;
|
||||
static getSkey(cached?: boolean): Promise<string | undefined>;
|
||||
}
|
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