Compare commits

...

9 Commits

Author SHA1 Message Date
手瓜一十雪
93904dcb1b fix: 删除的移除 2024-11-25 15:45:07 +08:00
手瓜一十雪
86cbdf793a Merge branch 'main' of https://github.com/NapNeko/NapCatQQ 2024-11-25 15:36:01 +08:00
手瓜一十雪
56b1b9b598 chore: 移除开发debug 2024-11-25 15:35:48 +08:00
Mlikiowa
f7ec3ae131 release: v4.1.20 2024-11-25 07:16:41 +00:00
手瓜一十雪
01d11d6213 refactor: 热重载 2024-11-25 15:16:12 +08:00
Mlikiowa
74a316e758 release: v4.1.19 2024-11-25 05:27:11 +00:00
手瓜一十雪
d20c5185a4 fix: 禁止once覆写package 2024-11-25 13:19:24 +08:00
手瓜一十雪
da965e7b39 fix: qrcode刷新 2024-11-25 13:01:42 +08:00
Mlikiowa
152be29739 release: v4.1.18 2024-11-24 04:53:06 +00:00
10 changed files with 77 additions and 78 deletions

Binary file not shown.

View File

@@ -4,7 +4,7 @@
"name": "NapCatQQ",
"slug": "NapCat.Framework",
"description": "高性能的 OneBot 11 协议实现",
"version": "4.1.16",
"version": "4.1.20",
"icon": "./logo.png",
"authors": [
{

View File

@@ -74,6 +74,26 @@ export class QQLoginManager {
}
return false;
}
public async checkQQLoginStatusWithQrcode(): Promise<{ qrcodeurl: string, isLogin: string } | undefined> {
try {
const QQLoginResponse = await fetch(`${this.apiPrefix}/QQLogin/CheckLoginStatus`, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + this.retCredential,
'Content-Type': 'application/json',
},
});
if (QQLoginResponse.status == 200) {
const QQLoginResponseJson = await QQLoginResponse.json();
if (QQLoginResponseJson.code == 0) {
return QQLoginResponseJson.data;
}
}
} catch (error) {
console.error('Error checking QQ login status:', error);
}
return undefined;
}
public async checkWebUiLogined(): Promise<boolean> {
try {

View File

@@ -2,28 +2,14 @@
<div class="login-container">
<h2 class="sotheby-font">QQ Login</h2>
<div class="login-methods">
<t-button
id="quick-login"
class="login-method"
:class="{ active: loginMethod === 'quick' }"
@click="loginMethod = 'quick'"
>Quick Login</t-button
>
<t-button
id="qrcode-login"
class="login-method"
:class="{ active: loginMethod === 'qrcode' }"
@click="loginMethod = 'qrcode'"
>QR Code</t-button
>
<t-button id="quick-login" class="login-method" :class="{ active: loginMethod === 'quick' }"
@click="loginMethod = 'quick'">Quick Login</t-button>
<t-button id="qrcode-login" class="login-method" :class="{ active: loginMethod === 'qrcode' }"
@click="loginMethod = 'qrcode'">QR Code</t-button>
</div>
<div v-show="loginMethod === 'quick'" id="quick-login-dropdown" class="login-form">
<t-select
id="quick-login-select"
v-model="selectedAccount"
placeholder="Select Account"
@change="selectAccount"
>
<t-select id="quick-login-select" v-model="selectedAccount" placeholder="Select Account"
@change="selectAccount">
<t-option v-for="account in quickLoginList" :key="account" :value="account">{{ account }}</t-option>
</t-select>
</div>
@@ -47,7 +33,7 @@ const selectedAccount = ref<string>('');
const qrcodeCanvas = ref<HTMLCanvasElement | null>(null);
const qqLoginManager = new QQLoginManager(localStorage.getItem('auth') || '');
let heartBeatTimer: number | null = null;
let qrcodeUrl: string = '';
const selectAccount = async (accountName: string): Promise<void> => {
const { result, errMsg } = await qqLoginManager.setQuickLogin(accountName);
if (result) {
@@ -73,19 +59,26 @@ const generateQrCode = (data: string, canvas: HTMLCanvasElement | null): void =>
};
const HeartBeat = async (): Promise<void> => {
const isLogined = await qqLoginManager.checkQQLoginStatus();
if (isLogined) {
const isLogined = await qqLoginManager.checkQQLoginStatusWithQrcode();
if (isLogined?.isLogin) {
if (heartBeatTimer) {
clearInterval(heartBeatTimer);
}
//判断是否已经调转
if (router.currentRoute.value.path !== '/dashboard/basic-info') {
return;
}
await router.push({ path: '/dashboard/basic-info' });
} else if (isLogined?.qrcodeurl && qrcodeUrl !== isLogined.qrcodeurl) {
qrcodeUrl = isLogined.qrcodeurl;
generateQrCode(qrcodeUrl, qrcodeCanvas.value);
}
};
const InitPages = async (): Promise<void> => {
quickLoginList.value = await qqLoginManager.getQQQuickLoginList();
const qrcodeData = await qqLoginManager.getQQLoginQrcode();
generateQrCode(qrcodeData, qrcodeCanvas.value);
qrcodeUrl = await qqLoginManager.getQQLoginQrcode();
generateQrCode(qrcodeUrl, qrcodeCanvas.value);
heartBeatTimer = window.setInterval(HeartBeat, 3000);
};

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "4.1.16",
"version": "4.1.20",
"scripts": {
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
"build:shell": "npm run build:webui && vite build --mode shell || exit 1",

View File

@@ -1 +1 @@
export const napCatVersion = '4.1.16';
export const napCatVersion = '4.1.20';

View File

@@ -176,67 +176,48 @@ export class NapCatOneBot11Adapter {
};
}
private async reloadNetwork(prev: OneBotConfig, now: OneBotConfig) {
private async reloadNetwork(prev: OneBotConfig, now: OneBotConfig): Promise<void> {
const prevLog = await this.creatOneBotLog(prev);
const newLog = await this.creatOneBotLog(now);
this.context.logger.log(`[Notice] [OneBot11] 配置变更前:\n${prevLog}`);
this.context.logger.log(`[Notice] [OneBot11] 配置变更后:\n${newLog}`);
const { added: addedHttpServers, removed: removedHttpServers } = this.findDifference(prev.network.httpServers, now.network.httpServers);
const { added: addedHttpClients, removed: removedHttpClients } = this.findDifference(prev.network.httpClients, now.network.httpClients);
const { added: addedWebSocketServers, removed: removedWebSocketServers } = this.findDifference(prev.network.websocketServers, now.network.websocketServers);
const { added: addedWebSocketClients, removed: removedWebSocketClients } = this.findDifference(prev.network.websocketClients, now.network.websocketClients);
await this.handleRemovedAdapters(removedHttpServers);
await this.handleRemovedAdapters(removedHttpClients);
await this.handleRemovedAdapters(removedWebSocketServers);
await this.handleRemovedAdapters(removedWebSocketClients);
await this.handlerConfigChange(now.network.httpServers);
await this.handlerConfigChange(now.network.httpClients);
await this.handlerConfigChange(now.network.websocketServers);
await this.handlerConfigChange(now.network.websocketClients);
await this.handleAddedAdapters(addedHttpServers, OB11PassiveHttpAdapter);
await this.handleAddedAdapters(addedHttpClients, OB11ActiveHttpAdapter);
await this.handleAddedAdapters(addedWebSocketServers, OB11PassiveWebSocketAdapter);
await this.handleAddedAdapters(addedWebSocketClients, OB11ActiveWebSocketAdapter);
await this.handleConfigChange(prev.network.httpServers, now.network.httpServers, OB11PassiveHttpAdapter);
await this.handleConfigChange(prev.network.httpClients, now.network.httpClients, OB11ActiveHttpAdapter);
await this.handleConfigChange(prev.network.websocketServers, now.network.websocketServers, OB11PassiveWebSocketAdapter);
await this.handleConfigChange(prev.network.websocketClients, now.network.websocketClients, OB11ActiveWebSocketAdapter);
}
private async handlerConfigChange(adapters: Array<NetworkConfigAdapter>) {
for (const adapterConfig of adapters) {
private async handleConfigChange(
prevConfig: NetworkConfigAdapter[],
nowConfig: NetworkConfigAdapter[],
adapterClass: new (...args: any[]) => IOB11NetworkAdapter
): Promise<void> {
// 通知新配置重载 删除关闭的 加入新开的
for (const adapterConfig of nowConfig) {
const existingAdapter = this.networkManager.findSomeAdapter(adapterConfig.name);
if (existingAdapter) {
const networkChange = await existingAdapter.reload(adapterConfig);
if (networkChange === OB11NetworkReloadType.NetWorkClose) {
this.networkManager.closeSomeAdapters([existingAdapter]);
await this.networkManager.closeSomeAdaterWhenOpen([existingAdapter]);
}
} else {
const newAdapter = new adapterClass(adapterConfig.name, adapterConfig, this.core, this.actions);
await this.networkManager.registerAdapterAndOpen(newAdapter);
}
}
// 比较旧的找不到的回收
for (const adapterConfig of prevConfig) {
const existingAdapter = nowConfig.find((e) => e.name === adapterConfig.name);
if (!existingAdapter) {
const existingAdapter = this.networkManager.findSomeAdapter(adapterConfig.name);
if (existingAdapter) {
await this.networkManager.closeSomeAdaterWhenOpen([existingAdapter]);
}
}
}
}
private async handleRemovedAdapters(adapters: Array<{ name: string }>): Promise<void> {
for (const adapter of adapters) {
await this.networkManager.closeAdapterByPredicate((existingAdapter) => existingAdapter.name === adapter.name);
}
}
private async handleAddedAdapters<T extends new (...args: any[]) => IOB11NetworkAdapter>(addedAdapters: Array<NetworkConfigAdapter>, AdapterClass: T) {
for (const adapter of addedAdapters) {
if (adapter.enable) {
const newAdapter = new AdapterClass(adapter.name, adapter, this.core, this.actions);
await newAdapter.open();
this.networkManager.registerAdapter(newAdapter);
}
}
}
private findDifference<T>(prev: T[], now: T[]): { added: T[]; removed: T[] } {
const added = now.filter((item) => !prev.includes(item));
const removed = prev.filter((item) => !now.includes(item));
return { added, removed };
}
private initMsgListener() {
const msgListener = new NodeIKernelMsgListener();
msgListener.onRecvSysMsg = (msg) => {

View File

@@ -68,6 +68,14 @@ export class OB11NetworkManager {
await adapter.close();
}
}
async closeSomeAdaterWhenOpen(adaptersToClose: IOB11NetworkAdapter[]) {
for (const adapter of adaptersToClose) {
this.adapters.delete(adapter.name);
if(adapter.isEnable){
await adapter.close();
}
}
}
findSomeAdapter(name: string) {
return this.adapters.get(name);

View File

@@ -31,13 +31,9 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
) {
this.config = structuredClone(config);
this.logger = core.context.logger;
if (this.config.host === '0.0.0.0') {
//兼容配置同时处理0.0.0.0逻辑
this.config.host = '';
}
this.wsServer = new WebSocketServer({
port: this.config.port,
host: this.config.host,
host: this.config.host === '0.0.0.0' ? '' : this.config.host,
maxPayload: 1024 * 1024 * 1024,
});
this.wsServer.on('connection', async (wsClient, wsReq) => {

View File

@@ -33,6 +33,7 @@ export const QQCheckLoginStatusHandler: RequestHandler = async (req, res) => {
message: 'success',
data: {
isLogin: await WebUiDataRuntime.getQQLoginStatus(),
qrcodeurl: await WebUiDataRuntime.getQQLoginQrcodeURL()
},
});
};