From 89c102513d063504a537e27ac95c572294493dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=8B=E7=93=9C=E4=B8=80=E5=8D=81=E9=9B=AA?= Date: Fri, 23 Aug 2024 10:55:19 +0800 Subject: [PATCH] release: 2.2.0 --- .github/workflows/release.yml | 82 ++++----- manifest.json | 2 +- package.json | 4 +- src/common/framework/napcat.ts | 2 +- src/framework/napcat.cjs | 158 +++++++++++------- .../msg/SendMsg/create-send-elements.ts | 2 +- src/webui/ui/NapCat.ts | 2 +- static/assets/renderer.js | 2 +- 8 files changed, 146 insertions(+), 108 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c9d98f52..2a266175 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,34 +30,34 @@ jobs: ls node ./script/checkVersion.cjs sh ./checkVersion.sh - # Build-LiteLoader: - # needs: [check-version] - # runs-on: ubuntu-latest - # 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 + Build-LiteLoader: + needs: [check-version] + runs-on: ubuntu-latest + 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 Framework - # run: | - # npm i - # npm run build:framework - # cd dist - # npm i --omit=dev - # cd .. - # - name: Upload Artifact - # uses: actions/upload-artifact@v4 - # with: - # name: NapCat.Framework - # path: dist + - name: Build NuCat Framework + run: | + npm i + npm run build:framework + cd dist + npm i --omit=dev + cd .. + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: NapCat.Framework + path: dist Build-Shell: runs-on: ubuntu-latest needs: [check-version] @@ -90,31 +90,30 @@ jobs: path: dist release-napcat: - needs: [Build-Shell] - # needs: [Build-LiteLoader,Build-Shell] + needs: [Build-LiteLoader,Build-Shell] runs-on: ubuntu-latest steps: - name: Download All Artifact uses: actions/download-artifact@v4 - - name: Compress subdirectories - run: | - cd ./NapCat.Shell/ - zip -q -r NapCat.Shell.zip * - cd .. - rm ./NapCat.Shell.zip -rf - mv ./NapCat.Shell/NapCat.Shell.zip ./ # - name: Compress subdirectories # run: | # cd ./NapCat.Shell/ # zip -q -r NapCat.Shell.zip * # cd .. - # cd ./NapCat.Framework/ - # zip -q -r NapCat.Framework.zip * - # cd .. # rm ./NapCat.Shell.zip -rf - # rm ./NapCat.Framework.zip -rf # mv ./NapCat.Shell/NapCat.Shell.zip ./ - # mv ./NapCat.Framework/NapCat.Framework.zip ./ + - name: Compress subdirectories + run: | + cd ./NapCat.Shell/ + zip -q -r NapCat.Shell.zip * + cd .. + cd ./NapCat.Framework/ + zip -q -r NapCat.Framework.zip * + cd .. + rm ./NapCat.Shell.zip -rf + rm ./NapCat.Framework.zip -rf + mv ./NapCat.Shell/NapCat.Shell.zip ./ + mv ./NapCat.Framework/NapCat.Framework.zip ./ - name: Extract version from tag run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV @@ -128,5 +127,6 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} body_path: CHANGELOG.md files: | + NapCat.Framework.zip NapCat.Shell.zip draft: true diff --git a/manifest.json b/manifest.json index 3651ede8..daa2e81c 100644 --- a/manifest.json +++ b/manifest.json @@ -4,7 +4,7 @@ "name": "NapCatQQ", "slug": "NapCat.Framework", "description": "高性能的 OneBot 11 协议实现", - "version": "2.1.0", + "version": "2.2.0", "icon": "./logo.png", "authors": [ { diff --git a/package.json b/package.json index c5703aeb..282db17c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "napcat", "private": true, "type": "module", - "version": "2.1.0", + "version": "2.2.0", "scripts": { "build:framework": "vite build --mode framework", "build:shell": "vite build --mode shell", @@ -48,7 +48,7 @@ "ajv": "^8.13.0", "async-mutex": "^0.5.0", "chalk": "^5.3.0", - "commander": "^12.1.0", + "commander": "^12.2.0", "cors": "^2.8.5", "express": "^5.0.0-beta.2", "fast-xml-parser": "^4.3.6", diff --git a/src/common/framework/napcat.ts b/src/common/framework/napcat.ts index d485050c..b4122f90 100644 --- a/src/common/framework/napcat.ts +++ b/src/common/framework/napcat.ts @@ -2,7 +2,7 @@ import path, { dirname } from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs'; -export const napcat_version = '2.1.0'; +export const napcat_version = '2.2.0'; export class NapCatPathWrapper { binaryPath: string; diff --git a/src/framework/napcat.cjs b/src/framework/napcat.cjs index fa6fd273..d309ec43 100644 --- a/src/framework/napcat.cjs +++ b/src/framework/napcat.cjs @@ -1,82 +1,120 @@ -// https://github.com/NapNeko/LiteLoader-NapCatExample/blob/main/src/common/proxy.ts -// By Mlikiowa +// 用于 NapCat 对QQ流程分析 +let Process = require('process'); +let os = require('os'); +let path = require('path'); +Process.dlopenOrig = Process.dlopen; -const process = require('process'); -const os = require('os'); -const path = require('path'); +let RealWrapper; +let loginService; +//Fuck LoginService +class LoginService { + constructor() { + console.log('[NapCat] Fuck LoginService Loading...'); + } +} + +//NapCat 专有逻辑 +let initCallBack; +let wrapperSession; +let wrapperLoginService; const currentPath = path.dirname(__filename); -const dlopenOrig = process.dlopen; +function CreateFuckService(ServiceName) { + return new Proxy(() => { }, { + get: function (target, FunctionName, receiver) { + console.log("Proxy... Event:", ServiceName + '/' + FunctionName); + if (ServiceName == 'NodeIKernelLoginService' && FunctionName == 'get') { + return function () { + let ret = new Proxy(new LoginService(), { + get: function (target, ClassFunName, receiver) { + return function () { + let ret = loginService[ClassFunName](...arguments); + // if (ret instanceof Promise) { + // ret.then((data) => { + // console.log("Called ", '实例方法 NodeIKernelLoginService/' + ClassFunName, ' 参数:', ...arguments, '返回:', data); + // }); + // } else { + // console.log("Called ", '实例方法 NodeIKernelLoginService/' + ClassFunName, ' 参数:', ...arguments, '返回:', ret); + // } + return ret; + } -let wrapperSession; -let wrapperNodeApi; -let wrapperLoginService; -let initCallBack; + } + }) + return ret; + } + } -// Proxy dlopen -process.dlopen = (module, filename, flags = os.constants.dlopen.RTLD_LAZY) => { - dlopenOrig(module, filename, flags); - for (const export_name in module.exports) { - module.exports[export_name] = new Proxy(module.exports[export_name], { - construct: (target, args, _newTarget) => { - let constructed; - if (export_name === 'NodeIKernelSessionListener') { - let HookedArg = []; - for (let ArgIndex in args) { - if (args[ArgIndex] instanceof Object) { - let HookArg = {}; - for (let ListenerName in args[ArgIndex]) { - HookArg[ListenerName] = function (...ListenerData) { - try { - if (ListenerName === 'onSessionInitComplete') { - //回调成功 - initCallBack.forEach((cb) => cb(...ListenerData)); + if (ServiceName == 'NodeIQQNTWrapperSession' && FunctionName == 'create') { + return new Proxy(() => { }, { + apply: function (target, thisArg, argArray) { + let Session = RealWrapper.NodeIQQNTWrapperSession[FunctionName](...argArray); + //传递Session + wrapperSession = Session; + + let ret = new Proxy(Session, { + get: function (target, ClassFunName, receiver) { + return function () { + if (ClassFunName == 'init') { + let origin = arguments[3].onSessionInitComplete; + arguments[3].onSessionInitComplete = function () { + //console.log("Listner ", '注册方法 NodeIKernelSessionListener/onSessionInitComplete', ' 参数:', ...arguments); + origin(...arguments); + initCallBack.forEach((cb) => cb(...arguments)); clearHook(); } - //console.log("Construct-ARG-Apply", ListenerName, JSON.stringify(ListenerData, null, 2)); - } catch (error) { - // ignored } - args[ArgIndex][ListenerName](...ListenerData); - }; - HookedArg.push(HookArg); + let ret = Session[ClassFunName](...arguments); + // if (ret instanceof Promise) { + // ret.then((data) => { + // console.log("Called ", '实例方法 NodeIQQNTWrapperSession/' + ClassFunName, ' 参数:', ...arguments, '返回:', data); + // }); + // } else { + // console.log("Called ", '实例方法 NodeIQQNTWrapperSession/' + ClassFunName, ' 参数:', ...arguments, '返回:', ret); + // } + + return ret; + } + } - } else { - // 其它类型 - //console.log("Construct-ARG-NotProxy", args[keyArg]); - } - + }); + return ret; } - constructed = new target(...HookedArg); - } else { - constructed = new target(...args); - } - - if (export_name === 'NodeIQQNTWrapperSession') wrapperSession = constructed; - if (export_name === 'NodeIKernelLoginService') wrapperLoginService = constructed; - - return constructed; - }, - }); - } - if (filename.toLowerCase().includes('wrapper.node')) { - wrapperNodeApi = module.exports; + }); + } + } } + ); +} +Process.dlopen = function (module, filename, flags = os.constants.dlopen.RTLD_LAZY) { + let dlopenRet = this.dlopenOrig(module, filename, flags); + if (filename.indexOf('wrapper.node') == -1) return dlopenRet; + //仅对Wrapper.node进行处理 + RealWrapper = module.exports; + //先行获取LoginService操作权 + loginService = new RealWrapper.NodeIKernelLoginService(); + wrapperLoginService = loginService; + //开始针对性处理 + module.exports = new Proxy({}, { + get: function (target, ServiceName, receiver) { + if (ServiceName == 'NodeIKernelLoginService') return CreateFuckService(ServiceName); + if (ServiceName == 'NodeIQQNTWrapperSession') return CreateFuckService(ServiceName); + return RealWrapper[ServiceName]; + } + }); + //返回预先构造的对象 + return dlopenRet; }; -/** - * 清理 Hook - */ +//辅助函数 function clearHook() { initCallBack = []; process.dlopen = dlopenOrig; } function ntIsInitialized_Internal() { - return wrapperSession !== undefined - && wrapperNodeApi !== undefined - && wrapperLoginService !== undefined; + return wrapperSession !== undefined; } function pollForNTInitializationCheck() { @@ -111,7 +149,7 @@ async function fetchServices(timeout = 10000) { setTimeout(() => resolve(false), timeout); }), ]).then(result => result ? - { wrapperSession, wrapperNodeApi, wrapperLoginService } : + { wrapperSession, wrapperLoginService } : Promise.reject("fetchServices Timeout!"), ); } diff --git a/src/onebot/action/msg/SendMsg/create-send-elements.ts b/src/onebot/action/msg/SendMsg/create-send-elements.ts index b4c657c6..57bdeee3 100644 --- a/src/onebot/action/msg/SendMsg/create-send-elements.ts +++ b/src/onebot/action/msg/SendMsg/create-send-elements.ts @@ -171,7 +171,7 @@ const _handlers: { } else { postData = data; } - // Mlikiowa V2.1.0 Refactor Todo + // Mlikiowa V2.2.0 Refactor Todo const signUrl = obContext.configLoader.configData.musicSignUrl; if (!signUrl) { if (data.type === 'qq') { diff --git a/src/webui/ui/NapCat.ts b/src/webui/ui/NapCat.ts index 868e1dd9..662b0d10 100644 --- a/src/webui/ui/NapCat.ts +++ b/src/webui/ui/NapCat.ts @@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) { SettingItem( 'Napcat', undefined, - SettingButton('V2.1.0', 'napcat-update-button', 'secondary'), + SettingButton('V2.2.0', 'napcat-update-button', 'secondary'), ), ]), SettingList([ diff --git a/static/assets/renderer.js b/static/assets/renderer.js index 335369e1..fff53bd2 100644 --- a/static/assets/renderer.js +++ b/static/assets/renderer.js @@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) { SettingItem( 'Napcat', void 0, - SettingButton("V2.1.0", "napcat-update-button", "secondary") + SettingButton("V2.2.0", "napcat-update-button", "secondary") ) ]), SettingList([