fix: forward msg by msg id

fix: send wav voice msg
This commit is contained in:
linyuchen 2024-03-01 02:53:33 +08:00
parent f0790b03bb
commit f4a53c5aec
12 changed files with 266 additions and 214 deletions

View File

@ -1,10 +1,10 @@
{
"manifest_version": 4,
"type": "extension",
"name": "LLOneBot",
"name": "LLOneBot v3.10.2",
"slug": "LLOneBot",
"description": "LiteLoaderQQNT的OneBotApi",
"version": "3.10.1",
"version": "3.10.2",
"thumbnail": "./icon.png",
"authors": [
{

278
package-lock.json generated
View File

@ -9,12 +9,12 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"audio-buffer-from": "^1.1.1",
"express": "^4.18.2",
"fluent-ffmpeg": "^2.1.2",
"json-bigint": "^1.0.0",
"music-metadata": "^8.1.4",
"silk-wasm": "^3.2.3",
"utf-8-validate": "^6.0.3",
"uuid": "^9.0.1",
"ws": "^8.16.0"
},
@ -22,14 +22,14 @@
"@babel/preset-env": "^7.23.2",
"@types/express": "^4.17.20",
"@types/fluent-ffmpeg": "^2.1.24",
"@types/node": "^20.11.19",
"@types/node": "^20.11.24",
"@types/uuid": "^9.0.8",
"@types/ws": "^8.5.10",
"babel-loader": "^9.1.3",
"copy-webpack-plugin": "^12.0.2",
"cross-env": "^7.0.3",
"electron": "^29.0.1",
"ts-loader": "^9.5.0",
"ts-node": "^10.9.2",
"typescript": "^5.2.2",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4"
@ -2007,6 +2007,28 @@
"node": ">=4"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@discoveryjs/json-ext": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
@ -2203,6 +2225,30 @@
"resolved": "https://mirrors.cloud.tencent.com/npm/@tokenizer/token/-/token-0.3.0.tgz",
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="
},
"node_modules/@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://mirrors.cloud.tencent.com/npm/@tsconfig/node10/-/node10-1.0.9.tgz",
"integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
"dev": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://mirrors.cloud.tencent.com/npm/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://mirrors.cloud.tencent.com/npm/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true
},
"node_modules/@types/body-parser": {
"version": "1.19.4",
"resolved": "https://mirrors.cloud.tencent.com/npm/@types/body-parser/-/body-parser-1.19.4.tgz",
@ -2327,9 +2373,9 @@
"dev": true
},
"node_modules/@types/node": {
"version": "20.11.19",
"resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-20.11.19.tgz",
"integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==",
"version": "20.11.24",
"resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-20.11.24.tgz",
"integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
@ -2637,6 +2683,15 @@
"acorn": "^8"
}
},
"node_modules/acorn-walk": {
"version": "8.3.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/acorn-walk/-/acorn-walk-8.3.2.tgz",
"integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==",
"dev": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@ -2716,6 +2771,12 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/array-flatten/-/array-flatten-1.1.1.tgz",
@ -2726,51 +2787,6 @@
"resolved": "https://mirrors.cloud.tencent.com/npm/async/-/async-3.2.5.tgz",
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
},
"node_modules/atob-lite": {
"version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/atob-lite/-/atob-lite-2.0.0.tgz",
"integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY="
},
"node_modules/audio-buffer": {
"version": "4.0.4",
"resolved": "https://mirrors.cloud.tencent.com/npm/audio-buffer/-/audio-buffer-4.0.4.tgz",
"integrity": "sha512-phH+MR3G+N/PO5ZKKxx7HlU6vJwAJFa0+FCaTjr/4lUZU/RCjUTqlk3nMJTRy5+b+6cbx8m//EtwZOVI5Ht9+w==",
"dependencies": {
"audio-context": "^1.0.0"
}
},
"node_modules/audio-buffer-from": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/audio-buffer-from/-/audio-buffer-from-1.1.1.tgz",
"integrity": "sha512-8Wcira24z+26GXDFe7ZFRF1bJm1iWrz8O+XL8iNZxZjxqAPXIoK1IrJiOqStv35ASPbRjG57ZK/T0WO92MDUSg==",
"dependencies": {
"audio-buffer": "^4.0.4",
"audio-context": "^1.0.1",
"audio-format": "^2.0.0",
"is-audio-buffer": "^1.0.11",
"is-plain-obj": "^1.1.0",
"pcm-convert": "^1.6.0",
"pick-by-alias": "^1.2.0",
"string-to-arraybuffer": "^1.0.0"
}
},
"node_modules/audio-context": {
"version": "1.0.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/audio-context/-/audio-context-1.0.3.tgz",
"integrity": "sha512-RH3/rM74f2ITlohhjgC7oYZVS97wtv/SEjXLCzEinnrIPIDxc39m2aFc6wmdkM0NYRKo1DMleYPMAIbnTRW0eA=="
},
"node_modules/audio-format": {
"version": "2.3.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/audio-format/-/audio-format-2.3.2.tgz",
"integrity": "sha512-5IA2grZhaVhpGxX6lbJm8VVh/SKQULMXXrFxuiodi0zhzDPRB8BJfieo89AclEQv4bDxZRH4lv06qNnxqkFhKQ==",
"dependencies": {
"is-audio-buffer": "^1.0.11",
"is-buffer": "^1.1.5",
"is-plain-obj": "^1.1.0",
"pick-by-alias": "^1.2.0",
"sample-rate": "^2.0.0"
}
},
"node_modules/babel-loader": {
"version": "9.1.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/babel-loader/-/babel-loader-9.1.3.tgz",
@ -3282,23 +3298,11 @@
"url": "https://opencollective.com/core-js"
}
},
"node_modules/cross-env": {
"version": "7.0.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/cross-env/-/cross-env-7.0.3.tgz",
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.1"
},
"bin": {
"cross-env": "src/bin/cross-env.js",
"cross-env-shell": "src/bin/cross-env-shell.js"
},
"engines": {
"node": ">=10.14",
"npm": ">=6",
"yarn": ">=1"
}
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"node_modules/cross-spawn": {
"version": "7.0.3",
@ -3413,6 +3417,15 @@
"dev": true,
"optional": true
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz",
@ -4302,21 +4315,6 @@
"node": ">= 0.10"
}
},
"node_modules/is-audio-buffer": {
"version": "1.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/is-audio-buffer/-/is-audio-buffer-1.1.0.tgz",
"integrity": "sha512-fmPC/dizJmP4ITCsW5oTQGMJ9wZVE+A/zAe6FQo3XwgERxmXHmm3ON5XkWDAxmyxvsrDmWx3NArpSgamp/59AA=="
},
"node_modules/is-base64": {
"version": "0.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/is-base64/-/is-base64-0.1.0.tgz",
"integrity": "sha512-WRRyllsGXJM7ZN7gPTCCQ/6wNPTRDwiWdPK66l5sJzcU/oOzcIcRRf0Rux8bkpox/1yjt0F6VJRsQOIG2qz5sg=="
},
"node_modules/is-buffer": {
"version": "1.1.6",
"resolved": "https://mirrors.cloud.tencent.com/npm/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"node_modules/is-core-module": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
@ -4359,14 +4357,6 @@
"node": ">=0.12.0"
}
},
"node_modules/is-plain-obj": {
"version": "1.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -4541,6 +4531,12 @@
"node": ">=10"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://mirrors.cloud.tencent.com/npm/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/matcher": {
"version": "3.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/matcher/-/matcher-3.0.0.tgz",
@ -4715,8 +4711,6 @@
"version": "4.8.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/node-gyp-build/-/node-gyp-build-4.8.0.tgz",
"integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==",
"optional": true,
"peer": true,
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
@ -4750,14 +4744,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.13.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/object-inspect/-/object-inspect-1.13.1.tgz",
@ -4890,17 +4876,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/pcm-convert": {
"version": "1.6.5",
"resolved": "https://mirrors.cloud.tencent.com/npm/pcm-convert/-/pcm-convert-1.6.5.tgz",
"integrity": "sha512-5CEspU4j8aEQ80AhNbcLfpT0apc93E6endFxahWd4sV70I6PN7LPdz8GoYm/1qr400K9bUVsVA+KxNgbFROZPw==",
"dependencies": {
"audio-format": "^2.3.2",
"is-audio-buffer": "^1.0.11",
"is-buffer": "^1.1.5",
"object-assign": "^4.1.1"
}
},
"node_modules/peek-readable": {
"version": "5.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/peek-readable/-/peek-readable-5.0.0.tgz",
@ -4919,11 +4894,6 @@
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
"dev": true
},
"node_modules/pick-by-alias": {
"version": "1.2.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/pick-by-alias/-/pick-by-alias-1.2.0.tgz",
"integrity": "sha1-X3yysfIabh6ISgyHhVqko3NhEHs="
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/picocolors/-/picocolors-1.0.0.tgz",
@ -5316,11 +5286,6 @@
"resolved": "https://mirrors.cloud.tencent.com/npm/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sample-rate": {
"version": "2.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/sample-rate/-/sample-rate-2.0.1.tgz",
"integrity": "sha512-AIK0vVBiAEObmpJOxQu/WCyklnWGqzTSDII4O7nBo+SJHmfgBUiYhgV/Y3Ohz76gfSlU6R5CIAKggj+nAOLSvg=="
},
"node_modules/schema-utils": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
@ -5552,15 +5517,6 @@
"safe-buffer": "~5.2.0"
}
},
"node_modules/string-to-arraybuffer": {
"version": "1.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/string-to-arraybuffer/-/string-to-arraybuffer-1.0.2.tgz",
"integrity": "sha512-DaGZidzi93dwjQen5I2osxR9ERS/R7B1PFyufNMnzhj+fmlDQAc1DSDIJVJhgI8Oq221efIMbABUBdPHDRt43Q==",
"dependencies": {
"atob-lite": "^2.0.0",
"is-base64": "^0.1.0"
}
},
"node_modules/strtok3": {
"version": "7.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/strtok3/-/strtok3-7.0.0.tgz",
@ -5765,6 +5721,49 @@
"node": ">= 8"
}
},
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/type-fest": {
"version": "0.13.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/type-fest/-/type-fest-0.13.1.tgz",
@ -5922,8 +5921,6 @@
"resolved": "https://mirrors.cloud.tencent.com/npm/utf-8-validate/-/utf-8-validate-6.0.3.tgz",
"integrity": "sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==",
"hasInstallScript": true,
"optional": true,
"peer": true,
"dependencies": {
"node-gyp-build": "^4.3.0"
},
@ -5956,6 +5953,12 @@
"uuid": "dist/bin/uuid"
}
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/vary/-/vary-1.1.2.tgz",
@ -6164,6 +6167,15 @@
"fd-slicer": "~1.1.0"
}
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/yocto-queue": {
"version": "1.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/yocto-queue/-/yocto-queue-1.0.0.tgz",

View File

@ -9,6 +9,7 @@
"build-main": "webpack --config webpack.main.config.js",
"build-preload": "webpack --config webpack.preload.config.js",
"build-renderer": "webpack --config webpack.renderer.config.js",
"build-version": "ts-node ./scripts/gen-version.ts",
"build-mac": "npm run build && cp manifest.json dist/ && npm run deploy-mac",
"deploy-mac": "cp -r dist/* ~/Library/Containers/com.tencent.qq/Data/LiteLoaderQQNT/plugins/LLOnebot/",
"build-win": "npm run build && cp manifest.json dist/ && npm run deploy-win",
@ -30,13 +31,14 @@
"@babel/preset-env": "^7.23.2",
"@types/express": "^4.17.20",
"@types/fluent-ffmpeg": "^2.1.24",
"@types/node": "^20.11.19",
"@types/node": "^20.11.24",
"@types/uuid": "^9.0.8",
"@types/ws": "^8.5.10",
"babel-loader": "^9.1.3",
"copy-webpack-plugin": "^12.0.2",
"electron": "^29.0.1",
"ts-loader": "^9.5.0",
"ts-node": "^10.9.2",
"typescript": "^5.2.2",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4"

18
scripts/gen-version.ts Normal file
View File

@ -0,0 +1,18 @@
import fs = require("fs");
import path = require("path");
import {version} from "../src/version";
const manifestPath = path.join(__dirname, "../manifest.json");
function readManifest(): any{
if (fs.existsSync(manifestPath)){
return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
}
}
function writeManifest(manifest: any){
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
}
let manifest = readManifest();
manifest.version = version;
manifest.name = `LLOneBot v${version}`;
writeManifest(manifest);

View File

@ -5,7 +5,6 @@ import {LLOneBotError} from "./types";
export let groups: Group[] = []
export let friends: Friend[] = []
export let msgHistory: Record<string, RawMessage> = {} // msgId: RawMessage
export const version = "3.10.1"
export let groupNotifies: Map<string, GroupNotify> = new Map<string, GroupNotify>();
export let friendRequests: Map<number, FriendRequest> = new Map<number, FriendRequest>();
export let llonebotError: LLOneBotError = {

View File

@ -2,10 +2,9 @@ import * as path from "path";
import {selfInfo} from "./data";
import {ConfigUtil} from "./config";
import util from "util";
import {encode, getDuration} from "silk-wasm";
import {encode, getDuration, isWav} from "silk-wasm";
import fs from 'fs';
import {v4 as uuidv4} from "uuid";
import {exec} from "node:child_process";
import ffmpeg from "fluent-ffmpeg"
export const CONFIG_DIR = global.LiteLoader.plugins["LLOneBot"].path.data;
@ -138,17 +137,20 @@ export function mergeNewProperties(newObj: any, oldObj: any) {
});
}
export function checkFFMPEG(newPath: string=null): Promise<boolean> {
export function checkFfmpeg(newPath: string = null): Promise<boolean> {
return new Promise((resolve, reject) => {
const ffmpegPath = newPath || 'ffmpeg'
exec(ffmpegPath + ' -version', (error, stdout, stderr) => {
if (error) {
log('ffmpeg is not installed or not found in PATH:', error);
resolve(false)
}
log('ffmpeg is installed. Version info:', stdout);
resolve(true);
});
if (newPath) {
ffmpeg.setFfmpegPath(newPath);
ffmpeg.getAvailableFormats((err, formats) => {
if (err) {
log('ffmpeg is not installed or not found in PATH:', err);
resolve(false)
} else {
log('ffmpeg is installed.');
resolve(true);
}
})
}
});
}
@ -172,33 +174,8 @@ export async function encodeSilk(filePath: string) {
}
}
function isWavFile(filePath: string) {
return new Promise((resolve, reject) => {
fs.open(filePath, 'r', (err, fd) => {
if (err) {
reject(err);
return;
}
// 读取前12个字节
const buffer = Buffer.alloc(12);
fs.read(fd, buffer, 0, 12, 0, (err, bytesRead, buffer) => {
if (err) {
reject(err);
return;
}
fs.close(fd, (err) => {
if (err) {
reject(err);
return;
}
// 检查RIFF头和WAVE格式标识
const isRIFF = buffer.toString('utf8', 0, 4) === 'RIFF';
const isWAVE = buffer.toString('utf8', 8, 12) === 'WAVE';
resolve(isRIFF && isWAVE);
});
});
});
});
async function isWavFile(filePath: string) {
return isWav(fs.readFileSync(filePath));
}
async function getAudioSampleRate(filePath: string) {
@ -217,15 +194,15 @@ export async function encodeSilk(filePath: string) {
const fileName = path.basename(filePath);
const pttPath = path.join(CONFIG_DIR, uuidv4());
if (getFileHeader(filePath) !== "02232153494c4b") {
log(`语音文件${filePath}需要转换`)
log(`语音文件${filePath}需要转换成silk`)
const isWav = await isWavFile(filePath);
const wavPath = pttPath + ".wav"
if (!isWav) {
log(`语音文件${filePath}正在转换成wav`)
// let voiceData = await fsp.readFile(filePath)
const wavPath = pttPath + ".wav"
await new Promise((resolve, reject) => {
const ffmpegPath = getConfigUtil().getConfig().ffmpeg;
if (ffmpegPath){
if (ffmpegPath) {
ffmpeg.setFfmpegPath(ffmpegPath);
}
ffmpeg(filePath).toFormat("wav").on('end', function () {
@ -236,31 +213,32 @@ export async function encodeSilk(filePath: string) {
reject(err);
})
.save(wavPath)
.on("end", ()=>{
.on("end", () => {
filePath = wavPath
resolve(wavPath);
});
})
const sampleRate = await getAudioSampleRate(filePath) || 44100;
const pcm = fs.readFileSync(filePath);
const silk = await encode(pcm, sampleRate);
fs.writeFileSync(pttPath, silk.data);
fs.unlink(wavPath, (err) => {});
log(`语音文件${filePath}转换成功!`, pttPath)
return {
converted: true,
path: pttPath,
duration: silk.duration,
};
} else {
const pcm = fs.readFileSync(filePath);
const duration = getDuration(pcm);
return {
converted: false,
path: filePath,
duration: duration,
};
}
const sampleRate = await getAudioSampleRate(filePath) || 44100;
const pcm = fs.readFileSync(filePath);
const silk = await encode(pcm, sampleRate);
fs.writeFileSync(pttPath, silk.data);
fs.unlink(wavPath, (err) => {
});
log(`语音文件${filePath}转换成功!`, pttPath)
return {
converted: true,
path: pttPath,
duration: silk.duration,
};
} else {
const pcm = fs.readFileSync(filePath);
const duration = getDuration(pcm);
return {
converted: false,
path: filePath,
duration: duration,
};
}
} catch (error) {
log("convert silk failed", error.stack);

View File

@ -1,7 +1,7 @@
// 运行在 Electron 主进程 下的插件入口
import {BrowserWindow, dialog, ipcMain} from 'electron';
import fs from 'fs';
import * as fs from 'fs';
import {Config} from "../common/types";
import {
CHANNEL_ERROR,
@ -11,7 +11,7 @@ import {
CHANNEL_SET_CONFIG,
} from "../common/channels";
import {ob11WebsocketServer} from "../onebot11/server/ws/WebsocketServer";
import {checkFFMPEG, CONFIG_DIR, getConfigUtil, log} from "../common/utils";
import {checkFfmpeg, CONFIG_DIR, getConfigUtil, log} from "../common/utils";
import {
addHistoryMsg,
friendRequests,
@ -140,8 +140,10 @@ function onLoad() {
// 检查ffmpeg
if (arg.ffmpeg) {
checkFFMPEG(arg.ffmpeg).then(success => {
llonebotError.ffmpegError = ''
checkFfmpeg(arg.ffmpeg).then(success => {
if (success){
llonebotError.ffmpegError = ''
}
})
}
@ -341,7 +343,7 @@ function onLoad() {
NTQQApi.getGroups(true).then()
const config = getConfigUtil().getConfig()
// 检查ffmpeg
checkFFMPEG(config.ffmpeg).then(exist => {
checkFfmpeg(config.ffmpeg).then(exist => {
if (!exist) {
llonebotError.ffmpegError = `没有找到ffmpeg,音频只能发送wav和silk`
}

View File

@ -10,7 +10,7 @@ import {
} from "./types";
import {NTQQApi} from "./ntcall";
import {encodeSilk} from "../common/utils";
import fs from "fs";
import * as fs from "fs";
export class SendMsgElementConstructor {

View File

@ -277,6 +277,7 @@ export interface RawMessage {
recallTime: string; // 撤回时间, "0"是没有撤回
elements: {
elementId: string,
elementType: ElementType;
replyElement: {
senderUid: string; // 原消息发送者QQ号
sourceMsgIsIncPic: boolean; // 原消息是否有图片

View File

@ -1,7 +1,7 @@
import BaseAction from "./BaseAction";
import {OB11Version} from "../types";
import {version} from "../../common/data";
import {ActionName} from "./types";
import {version} from "../../version";
export default class GetVersionInfo extends BaseAction<any, OB11Version>{
actionName = ActionName.GetVersionInfo

View File

@ -1,4 +1,4 @@
import {AtType, ChatType, Group, SendMessageElement} from "../../ntqqapi/types";
import {AtType, ChatType, Group, RawMessage, SendMessageElement} from "../../ntqqapi/types";
import {addHistoryMsg, friends, getGroup, getHistoryMsgByShortId, getUidByUin, selfInfo,} from "../../common/data";
import {OB11MessageData, OB11MessageDataType, OB11MessageMixType, OB11MessageNode, OB11PostSendMsg} from '../types';
import {NTQQApi, Peer} from "../../ntqqapi/ntcall";
@ -8,9 +8,7 @@ import BaseAction from "./BaseAction";
import {ActionName, BaseCheckResult} from "./types";
import * as fs from "fs";
import {log} from "../../common/utils";
import {v4 as uuidv4} from "uuid"
import {decodeCQCode} from "../cqcode";
import {Send} from "express";
function checkSendMessage(sendMsgList: OB11MessageData[]) {
function checkUri(uri: string): boolean {
@ -145,7 +143,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
chatType: ChatType.friend,
peerUid: selfInfo.uid
}
let nodeIds: string[] = []
let selfNodeMsgList: RawMessage[] = [];
let originalNodeMsgList: RawMessage[] = [];
for (const messageNode of messageNodes) {
// 一个node表示一个人的消息
let nodeId = messageNode.data.id;
@ -153,7 +152,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
if (nodeId) {
let nodeMsg = getHistoryMsgByShortId(nodeId);
if (nodeMsg) {
nodeIds.push(nodeMsg.msgId);
originalNodeMsgList.push(nodeMsg);
}
} else {
// 自定义的消息
@ -165,7 +164,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
} = await this.createSendElements(this.convertMessage2List(messageNode.data.content), group);
log("开始生成转发节点", sendElements);
const nodeMsg = await this.send(selfPeer, sendElements, deleteAfterSentFiles, true);
nodeIds.push(nodeMsg.msgId)
selfNodeMsgList.push(nodeMsg);
log("转发节点生成成功", nodeMsg.msgId);
} catch (e) {
log("生效转发消息节点失败", e)
@ -173,9 +172,49 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
}
}
let nodeIds: string[] = []
// 检查是否需要克隆直接引用消息id的节点
let needSendSelf = false;
if (selfNodeMsgList.length) {
needSendSelf = true
} else {
needSendSelf = !originalNodeMsgList.every((msg, index) => msg.peerUid === originalNodeMsgList[0].peerUid)
}
if (needSendSelf) {
nodeIds = selfNodeMsgList.map(msg => msg.msgId);
for (const originalNodeMsg of originalNodeMsgList) {
if (originalNodeMsg.peerUid === selfInfo.uid) {
nodeIds.push(originalNodeMsg.msgId)
} else { // 需要进行克隆
let sendElements: SendMessageElement[] = []
Object.keys(originalNodeMsg.elements).forEach((eleKey) => {
if (eleKey !== "elementId") {
sendElements.push(originalNodeMsg.elements[eleKey])
}
})
try {
const nodeMsg = await NTQQApi.sendMsg(selfPeer, sendElements, true);
nodeIds.push(nodeMsg.msgId)
log("克隆转发消息成功")
} catch (e) {
log("克隆转发消息失败", e)
}
}
}
} else {
nodeIds = originalNodeMsgList.map(msg => msg.msgId)
}
let srcPeer = selfPeer;
if (!needSendSelf) {
srcPeer = {
chatType: originalNodeMsgList[0].chatType === ChatType.group ? ChatType.group : ChatType.friend,
peerUid: originalNodeMsgList[0].peerUid
}
}
// 开发转发
try {
return await NTQQApi.multiForwardMsg(selfPeer, destPeer, nodeIds)
return await NTQQApi.multiForwardMsg(srcPeer, destPeer, nodeIds)
} catch (e) {
log("forward failed", e)
return null;

1
src/version.ts Normal file
View File

@ -0,0 +1 @@
export const version = "3.10.2"