mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2024-11-21 09:36:35 +00:00
fix: hook session init when launching as LL plugin
This commit is contained in:
parent
90a7b5e0d3
commit
0ed969fa3f
@ -1,109 +1,134 @@
|
||||
// NapCat CommonJS 入口文件
|
||||
// https://github.com/NapNeko/LiteLoader-NapCatExample/blob/main/src/common/proxy.ts
|
||||
// By Mlikiowa
|
||||
|
||||
const process = require('process');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const CurrentPath = path.dirname(__filename);
|
||||
let Process = require('process');
|
||||
let os = require('os');
|
||||
|
||||
Process.dlopenOrig = Process.dlopen;
|
||||
const currentPath = path.dirname(__filename);
|
||||
|
||||
let proxyHandler = {
|
||||
get(target, prop, receiver) {
|
||||
if (typeof target[prop] === 'undefined') {
|
||||
return (...args) => {
|
||||
console.log(`[NapCat] [Info] ${target.constructor.name} ${prop}`, ...args);
|
||||
};
|
||||
}
|
||||
return Reflect.get(target, prop, receiver);
|
||||
}
|
||||
};
|
||||
const dlopenOrig = process.dlopen;
|
||||
|
||||
let WrapperSession = undefined;//NativeNpdeSession
|
||||
let WrapperNodeApi = undefined;//NativeNpdeApi
|
||||
let WrapperLoginService = undefined;
|
||||
let wrapperSession;
|
||||
let wrapperNodeApi;
|
||||
let wrapperLoginService;
|
||||
let initCallBack;
|
||||
|
||||
Process.dlopen = function (module, filename, flags = os.constants.dlopen.RTLD_LAZY) {
|
||||
let dlopenRet = this.dlopenOrig(module, filename, flags);
|
||||
for (let export_name in module.exports) {
|
||||
// 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 ret = new target(...args);
|
||||
if (export_name === 'NodeIQQNTWrapperSession') WrapperSession = ret;
|
||||
if (export_name === 'NodeIKernelLoginService') WrapperLoginService = ret;
|
||||
return ret;
|
||||
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));
|
||||
clearHook();
|
||||
}
|
||||
//console.log("Construct-ARG-Apply", ListenerName, JSON.stringify(ListenerData, null, 2));
|
||||
} catch (error) {
|
||||
// ignored
|
||||
}
|
||||
args[ArgIndex][ListenerName](...ListenerData);
|
||||
};
|
||||
HookedArg.push(HookArg);
|
||||
}
|
||||
} else {
|
||||
// 其它类型
|
||||
//console.log("Construct-ARG-NotProxy", args[keyArg]);
|
||||
}
|
||||
|
||||
}
|
||||
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().indexOf('wrapper.node') != -1) {
|
||||
WrapperNodeApi = module.exports;
|
||||
if (filename.toLowerCase().includes('wrapper.node')) {
|
||||
wrapperNodeApi = module.exports;
|
||||
}
|
||||
return dlopenRet;
|
||||
};
|
||||
function getWrapperSession() {
|
||||
return WrapperSession;
|
||||
|
||||
/**
|
||||
* 清理 Hook
|
||||
*/
|
||||
function clearHook() {
|
||||
initCallBack = [];
|
||||
process.dlopen = dlopenOrig;
|
||||
}
|
||||
function getWrapperLoginService() {
|
||||
return WrapperLoginService;
|
||||
|
||||
function ntIsInitialized_Internal() {
|
||||
return wrapperSession !== undefined
|
||||
&& wrapperNodeApi !== undefined
|
||||
&& wrapperLoginService !== undefined;
|
||||
}
|
||||
function getWrapperNodeApi() {
|
||||
return WrapperNodeApi;
|
||||
}
|
||||
function NTIsInit() {
|
||||
return WrapperSession != undefined && WrapperNodeApi != undefined && WrapperLoginService != undefined;
|
||||
}
|
||||
function pollForNTInit() {
|
||||
|
||||
function pollForNTInitializationCheck() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let isSolve = false;
|
||||
const intervalId = setInterval(() => {
|
||||
const intervalRef = setInterval(() => {
|
||||
if (isSolve) return;
|
||||
try {
|
||||
if (NTIsInit()) {
|
||||
clearInterval(intervalId);
|
||||
if (ntIsInitialized_Internal()) {
|
||||
isSolve = true;
|
||||
resolve(true);
|
||||
}
|
||||
} catch (error) {
|
||||
clearInterval(intervalId);
|
||||
reject(error);
|
||||
} finally {
|
||||
clearInterval(intervalRef);
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
async function checkNTIsInit() {
|
||||
return Promise.race([
|
||||
pollForNTInit(),
|
||||
new Promise((_, reject) => setTimeout(() => reject(new Error("NTIsInit is false after 10 seconds")), 10000))
|
||||
]);
|
||||
export function registerInitCallback(callback) {
|
||||
if (initCallBack === undefined) {
|
||||
initCallBack = [];
|
||||
}
|
||||
initCallBack.push(callback);
|
||||
}
|
||||
|
||||
async function fetchServices(timeout = 10000) {
|
||||
return Promise.race([
|
||||
pollForNTInitializationCheck(),
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => resolve(false), timeout);
|
||||
})
|
||||
]).then(result => result ?
|
||||
{ wrapperSession, wrapperNodeApi, wrapperLoginService } :
|
||||
Promise.reject()
|
||||
);
|
||||
}
|
||||
|
||||
async function NCInit() {
|
||||
console.log("[NapCat] [Info] 开始初始化NapCat");
|
||||
const { NCoreInitLiteLoader } = await import("file://" + path.join(CurrentPath, './napcat.mjs'));
|
||||
//传入LoginService Session 其余自载入
|
||||
await NCoreInitLiteLoader(getWrapperSession(), getWrapperLoginService());
|
||||
//console.log("[NapCat] [Info] NapCat初始化完成");
|
||||
}
|
||||
(async () => {
|
||||
try {
|
||||
await checkNTIsInit();
|
||||
}
|
||||
catch (error) {
|
||||
console.log("[NapCat] [Error] 很遗憾在NTQQ初始化阶段失败");
|
||||
return;
|
||||
//阻止下一步
|
||||
}
|
||||
console.log("[NapCat] [Info] NTQQ初始化成功");
|
||||
console.log(getWrapperSession(), getWrapperLoginService());
|
||||
NCInit().then().catch(console.log);
|
||||
//NTCore.instance = new NTCoreWrapper(getWrapperNodeApi(), getWrapperSession());
|
||||
// 挂载NTQQ 到 NapCat Core
|
||||
//let NCLoginListener = {};
|
||||
// NCLoginListener.onQRCodeLoginSucceed = (arg) => {
|
||||
// //登录成功 登录成功立刻进入真正初始化
|
||||
// console.log("[NapCat] [Info] UIN: ", arg.uin, " 登录成功!")
|
||||
// NCInit().then().catch();
|
||||
// }
|
||||
// 添加Login监听
|
||||
//getWrapperLoginService().addKernelLoginListener(new (getWrapperNodeApi().NodeIKernelLoginListener)(new Proxy(NCLoginListener, proxyHandler)));
|
||||
|
||||
//await import("file://" + path.join(CurrentPath, './napcat.mjs'));
|
||||
})();
|
||||
try {
|
||||
const { wrapperSession, wrapperLoginService } = await fetchServices();
|
||||
const { NCoreInitLiteLoader } = await import('file://' + path.join(currentPath, './napcat.mjs'));
|
||||
//传入LoginService Session 其余自载入
|
||||
await NCoreInitLiteLoader(wrapperSession, wrapperLoginService, registerInitCallback);
|
||||
//console.log("[NapCat] [Info] NapCat初始化完成");
|
||||
} catch (error) {
|
||||
console.error("[NapCat] [Error] 初始化NapCat失败", error);
|
||||
}
|
||||
}
|
||||
|
||||
NCInit();
|
||||
|
@ -12,7 +12,11 @@ import { NapCatOneBot11Adapter } from "@/onebot/main";
|
||||
import { sleep } from "@/common/utils/helper";
|
||||
|
||||
//LiteLoader ES入口文件
|
||||
export async function NCoreInitLiteLoader(session: NodeIQQNTWrapperSession, loginService: NodeIKernelLoginService) {
|
||||
export async function NCoreInitLiteLoader(
|
||||
session: NodeIQQNTWrapperSession,
|
||||
loginService: NodeIKernelLoginService,
|
||||
registerInitCallback: (callback: () => void) => void
|
||||
) {
|
||||
//在进入本层前是否登录未进行判断
|
||||
console.log("NapCat LiteLoader App Loading...");
|
||||
const pathWrapper = new NapCatPathWrapper();
|
||||
@ -20,14 +24,19 @@ export async function NCoreInitLiteLoader(session: NodeIQQNTWrapperSession, logi
|
||||
const basicInfoWrapper = new QQBasicInfoWrapper({ logger });
|
||||
const wrapper = loadQQWrapper(basicInfoWrapper.getFullQQVesion());
|
||||
//直到登录成功后,执行下一步
|
||||
const selfInfo = await new Promise<SelfInfo>((resolve) => {
|
||||
const selfInfo = await new Promise<SelfInfo>((resolveSelfInfo) => {
|
||||
const loginListener = new LoginListener();
|
||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => resolve({
|
||||
uid: loginResult.uid,
|
||||
uin: loginResult.uin,
|
||||
nick: '', // 获取不到
|
||||
online: true
|
||||
});
|
||||
loginListener.onQRCodeLoginSucceed = async (loginResult) => {
|
||||
await new Promise<void>(resolvePendingInit => {
|
||||
registerInitCallback(() => resolvePendingInit());
|
||||
});
|
||||
resolveSelfInfo({
|
||||
uid: loginResult.uid,
|
||||
uin: loginResult.uin,
|
||||
nick: '', // 获取不到
|
||||
online: true,
|
||||
});
|
||||
};
|
||||
loginService.addKernelLoginListener(new wrapper.NodeIKernelLoginListener(
|
||||
proxiedListenerOf(loginListener, logger)));
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user