refactor: webui network

This commit is contained in:
pk5ls20
2024-11-16 05:43:44 +08:00
parent fa87f7c8c3
commit c432799580
11 changed files with 456 additions and 414 deletions

View File

@@ -1,3 +1,5 @@
import { OneBotConfig } from '../../../src/onebot/config/config';
export class QQLoginManager {
private retCredential: string;
private readonly apiPrefix: string;
@@ -9,7 +11,7 @@ export class QQLoginManager {
}
// TODO:
public async GetOB11Config(): Promise<any> {
public async GetOB11Config(): Promise<OneBotConfig> {
try {
const ConfigResponse = await fetch(`${this.apiPrefix}/OB11Config/GetConfig`, {
method: 'POST',
@@ -21,16 +23,16 @@ export class QQLoginManager {
if (ConfigResponse.status == 200) {
const ConfigResponseJson = await ConfigResponse.json();
if (ConfigResponseJson.code == 0) {
return ConfigResponseJson?.data;
return ConfigResponseJson?.data as OneBotConfig;
}
}
} catch (error) {
console.error('Error getting OB11 config:', error);
}
return {};
return {} as OneBotConfig;
}
public async SetOB11Config(config: any): Promise<boolean> {
public async SetOB11Config(config: OneBotConfig): Promise<boolean> {
try {
const ConfigResponse = await fetch(`${this.apiPrefix}/OB11Config/SetConfig`, {
method: 'POST',

View File

@@ -1,70 +1,104 @@
<template>
<t-space>
<t-tabs v-model="value" :addable="true" theme="card" @add="showAddTabDialog" @remove="removeTab">
<t-tabs v-model="activeTab" :addable="true" theme="card" @add="showAddTabDialog" @remove="removeTab">
<t-tab-panel
v-for="data in panelData"
:key="data.value"
:label="data.label"
:removable="data.removable"
:value="data.value"
v-for="(config, idx) in clientPanelData"
:key="idx"
:label="config.name"
:removable="true"
:value="idx"
>
<component :is="data.component" :config="data.config" />
<component :is="resolveDynamicComponent(getComponent(config.key))" :config="config.data" />
<t-button @click="saveConfig">保存</t-button>
</t-tab-panel>
</t-tabs>
<t-dialog
v-model:visible="isDialogVisible"
header="添加新选项卡"
@close="isDialogVisible = false"
@confirm="addTab"
>
<t-form ref="form" :model="newTab">
<t-form-item :rules="[{ required: true, message: '请输入名称' }]" label="名称" name="name">
<t-input v-model="newTab.name" />
</t-form-item>
<t-form-item :rules="[{ required: true, message: '请选择类型' }]" label="类型" name="type">
<t-select v-model="newTab.type">
<t-option value="httpServers">HTTP 服务器</t-option>
<t-option value="httpClients">HTTP 客户端</t-option>
<t-option value="websocketServers">WebSocket 服务器</t-option>
<t-option value="websocketClients">WebSocket 客户端</t-option>
</t-select>
</t-form-item>
</t-form>
</t-dialog>
</t-space>
<t-dialog
v-model:visible="isDialogVisible"
header="添加新选项卡"
@close="isDialogVisible = false"
@confirm="addTab"
>
<t-form ref="form" :model="newTab">
<t-form-item :rules="[{ required: true, message: '请输入名称' }]" label="名称" name="name">
<t-input v-model="newTab.name" />
</t-form-item>
<t-form-item :rules="[{ required: true, message: '请选择类型' }]" label="类型" name="type">
<t-select v-model="newTab.type">
<t-option value="httpServers">HTTP 服务器</t-option>
<t-option value="httpClients">HTTP 客户端</t-option>
<t-option value="websocketServers">WebSocket 服务器</t-option>
<t-option value="websocketClients">WebSocket 客户端</t-option>
</t-select>
</t-form-item>
</t-form>
</t-dialog>
</template>
<script setup lang="ts">
import { nextTick, onMounted, ref, shallowRef, watch } from 'vue';
import { defaultOnebotConfig, mergeOnebotConfigs } from '../../../src/onebot/config/config';
import { ref, resolveDynamicComponent, nextTick, Ref, onMounted, reactive, Reactive } from 'vue';
import {
httpServerDefaultConfigs,
httpClientDefaultConfigs,
websocketServerDefaultConfigs,
websocketClientDefaultConfigs,
HttpClientConfig,
HttpServerConfig,
WebsocketClientConfig,
WebsocketServerConfig,
NetworkConfig,
OneBotConfig,
defaultOneBotConfigs,
mergeOneBotConfigs,
} from '../../../src/onebot/config/config';
import { QQLoginManager } from '@/backend/shell';
import HttpServerComponent from './network/HttpServerComponent.vue';
import HttpClientComponent from './network/HttpClientComponent.vue';
import WebsocketServerComponent from './network/WebsocketServerComponent.vue';
import WebsocketClientComponent from './network/WebsocketClientComponent.vue';
import HttpServerComponent from '@/pages/network/HttpServerComponent.vue';
import HttpClientComponent from '@/pages/network/HttpClientComponent.vue';
import WebsocketServerComponent from '@/pages/network/WebsocketServerComponent.vue';
import WebsocketClientComponent from '@/pages/network/WebsocketClientComponent.vue';
interface PanelData {
value: string;
label: string;
removable: boolean;
component: any;
config: { name: string };
}
type ConfigKey = 'httpServers' | 'httpClients' | 'websocketServers' | 'websocketClients';
let id = 0;
const value = ref<string>('first');
const panelData = ref<PanelData[]>([]);
const isDialogVisible = ref<boolean>(false);
const newTab = ref<{ name: string; type: string }>({ name: '', type: '' });
type ConfigUnion = HttpClientConfig | HttpServerConfig | WebsocketServerConfig | WebsocketClientConfig;
const componentMap: Record<string, any> = {
httpServers: shallowRef(HttpServerComponent),
httpClients: shallowRef(HttpClientComponent),
websocketServers: shallowRef(WebsocketServerComponent),
websocketClients: shallowRef(WebsocketClientComponent),
const defaultConfigs: Record<ConfigKey, ConfigUnion> = {
httpServers: httpServerDefaultConfigs,
httpClients: httpClientDefaultConfigs,
websocketServers: websocketServerDefaultConfigs,
websocketClients: websocketClientDefaultConfigs,
};
const getOB11Config = async (): Promise<any | undefined> => {
const componentMap: Record<
ConfigKey,
| typeof HttpServerComponent
| typeof HttpClientComponent
| typeof WebsocketServerComponent
| typeof WebsocketClientComponent
> = {
httpServers: HttpServerComponent,
httpClients: HttpClientComponent,
websocketServers: WebsocketServerComponent,
websocketClients: WebsocketClientComponent,
};
interface ClientPanel {
name: string;
key: ConfigKey;
data: Ref<ConfigUnion>;
}
type ComponentKey = keyof typeof componentMap;
const activeTab = ref<number>(0);
const isDialogVisible = ref(false);
const newTab = ref<{ name: string; type: ComponentKey }>({ name: '', type: 'httpServers' });
const clientPanelData: Reactive<Array<ClientPanel>> = reactive([]);
const getComponent = (type: ComponentKey) => {
return componentMap[type];
};
const getOB11Config = async (): Promise<OneBotConfig | undefined> => {
const storedCredential = localStorage.getItem('auth');
if (!storedCredential) {
console.error('No stored credential found');
@@ -74,7 +108,7 @@ const getOB11Config = async (): Promise<any | undefined> => {
return await loginManager.GetOB11Config();
};
const setOB11Config = async (config: any): Promise<boolean> => {
const setOB11Config = async (config: OneBotConfig): Promise<boolean> => {
const storedCredential = localStorage.getItem('auth');
if (!storedCredential) {
console.error('No stored credential found');
@@ -84,100 +118,74 @@ const setOB11Config = async (config: any): Promise<boolean> => {
return await loginManager.SetOB11Config(config);
};
const log = (message: string, data: any) => {
console.log(message, data);
const addToPanel = <T extends ConfigUnion>(configs: T[], key: ConfigKey) => {
configs.forEach((config) => clientPanelData.push({ name: config.name, data: config, key: key }));
};
const createPanel = (type: string, name: string, id: number): PanelData => {
return {
value: `${type}-${id}`,
label: name,
removable: true,
component: componentMap[type],
config: { name: name },
};
};
const generatePanels = (networkConfig: any): PanelData[] => {
const panels: PanelData[] = [];
Object.keys(networkConfig).forEach((key) => {
networkConfig[key].forEach((config: any, index: number) => {
const component = componentMap[key];
if (!component) {
console.error(`No component found for key: ${key}`);
return;
}
panels.push(createPanel(key, config.name, index));
});
const addConfigDataToPanel = (data: NetworkConfig) => {
Object.entries(data).forEach(([key, configs]) => {
if (key in defaultConfigs) {
addToPanel(configs as ConfigUnion[], key as ConfigKey);
}
});
return panels;
};
const parsePanelData = (): NetworkConfig => {
return {
websocketClients: clientPanelData
.filter((panel) => panel.key === 'websocketClients')
.map((panel) => panel.data as WebsocketClientConfig),
websocketServers: clientPanelData
.filter((panel) => panel.key === 'websocketServers')
.map((panel) => panel.data as WebsocketServerConfig),
httpClients: clientPanelData
.filter((panel) => panel.key === 'httpClients')
.map((panel) => panel.data as HttpClientConfig),
httpServers: clientPanelData
.filter((panel) => panel.key === 'httpServers')
.map((panel) => panel.data as HttpServerConfig),
};
};
const loadConfig = async () => {
try {
const userConfig = await getOB11Config();
if (!userConfig) return;
const mergedConfig = mergeOnebotConfigs(defaultOnebotConfig, userConfig);
const networkConfig = mergedConfig.network;
log('networkConfig:', networkConfig);
const panels = generatePanels(networkConfig);
log('panels:', panels);
panelData.value = panels;
if (panels.length > 0) {
value.value = panels[0].value;
}
const mergedConfig = mergeOneBotConfigs(defaultOneBotConfigs, userConfig);
addConfigDataToPanel(mergedConfig.network);
} catch (error) {
console.error('Error loading config:', error);
}
};
// It's better to "saveConfig" instead of using deep watch
const saveConfig = async () => {
const config = parsePanelData();
const userConfig = await getOB11Config();
if (!userConfig) return;
userConfig.network = config;
await setOB11Config(userConfig);
};
const showAddTabDialog = () => {
newTab.value = { name: '', type: '' };
newTab.value = { name: '', type: 'httpServers' };
isDialogVisible.value = true;
};
const addTab = async () => {
const { name, type } = newTab.value;
if (!name || !type) return;
const newPanel = createPanel(type, name, id);
panelData.value.push(newPanel);
id += 1;
const defaultConfig = structuredClone(defaultConfigs[type]);
clientPanelData.push({ name, data: defaultConfig, key: type });
isDialogVisible.value = false;
await nextTick(); // 确保 DOM 更新完成
value.value = newPanel.value; // 强制重新渲染选项卡
await nextTick();
activeTab.value = clientPanelData.length - 1;
};
const closeDialog = () => {
isDialogVisible.value = false;
const removeTab = (payload: { value: string; index: number; e: PointerEvent }) => {
clientPanelData.splice(payload.index, 1);
activeTab.value = Math.max(0, activeTab.value - 1);
};
const removeTab = ({ value: val, index }: { value: string; index: number }) => {
if (index < 0) return false;
panelData.value.splice(index, 1);
if (panelData.value.length === 0) return;
if (value.value === val) {
value.value = panelData.value[Math.max(index - 1, 0)].value;
}
};
const syncConfig = async () => {
const networkConfig: Record<string, any[]> = {};
panelData.value.forEach((panel) => {
const key = panel.value.split('-')[0];
if (!networkConfig[key]) {
networkConfig[key] = [];
}
networkConfig[key].push(panel.config);
});
const userConfig = await getOB11Config();
if (!userConfig) return;
const mergedConfig = mergeOnebotConfigs(defaultOnebotConfig, userConfig);
mergedConfig.network = networkConfig;
await setOB11Config(mergedConfig);
};
watch(panelData, syncConfig, { deep: true });
onMounted(() => {
loadConfig();
});

View File

@@ -22,21 +22,9 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
interface HttpClientConfig {
url: string;
messagePostFormat: string;
reportSelfMessage: boolean;
token: string;
debug: boolean;
}
const config = ref<HttpClientConfig>({
url: '',
messagePostFormat: '',
reportSelfMessage: false,
token: '',
debug: false,
});
import { defineProps } from 'vue';
import { HttpClientConfig } from '../../../../src/onebot/config/config';
defineProps<{
config: HttpClientConfig;
}>();
</script>

View File

@@ -31,27 +31,9 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
interface HttpServerConfig {
port: number;
host: string;
enableCors: boolean;
enableWebsocket: boolean;
messagePostFormat: string;
reportSelfMessage: boolean;
token: string;
debug: boolean;
}
const config = ref<HttpServerConfig>({
port: 8080,
host: '',
enableCors: false,
enableWebsocket: false,
messagePostFormat: '',
reportSelfMessage: false,
token: '',
debug: false,
});
import { defineProps } from 'vue';
import { HttpServerConfig } from '../../../../src/onebot/config/config';
defineProps<{
config: HttpServerConfig;
}>();
</script>

View File

@@ -25,23 +25,9 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
interface WsClientConfig {
url: string;
messagePostFormat: string;
reportSelfMessage: boolean;
token: string;
debug: boolean;
heartInterval: number;
}
const config = ref<WsClientConfig>({
url: '',
messagePostFormat: '',
reportSelfMessage: false,
token: '',
debug: false,
heartInterval: 0,
});
import { defineProps } from 'vue';
import { WebsocketClientConfig } from '../../../../src/onebot/config/config';
defineProps<{
config: WebsocketClientConfig;
}>();
</script>

View File

@@ -31,27 +31,9 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
interface WsServerConfig {
host: string;
port: number;
messagePostFormat: string;
reportSelfMessage: boolean;
token: string;
enablePushEvent: boolean;
debug: boolean;
heartInterval: number;
}
const config = ref<WsServerConfig>({
host: '',
port: 8080,
messagePostFormat: '',
reportSelfMessage: false,
token: '',
enablePushEvent: false,
debug: false,
heartInterval: 0,
});
import { defineProps } from 'vue';
import { WebsocketServerConfig } from '../../../../src/onebot/config/config';
defineProps<{
config: WebsocketServerConfig;
}>();
</script>

View File

@@ -6,7 +6,7 @@ export interface AdapterConfig {
const createDefaultAdapterConfig = <T extends AdapterConfig>(config: T): T => config;
const httpServerDefaultConfigs = createDefaultAdapterConfig({
export const httpServerDefaultConfigs = createDefaultAdapterConfig({
name: 'http-server',
enable: false,
port: 3000,
@@ -20,7 +20,7 @@ const httpServerDefaultConfigs = createDefaultAdapterConfig({
});
export type HttpServerConfig = typeof httpServerDefaultConfigs;
const httpClientDefaultConfigs = createDefaultAdapterConfig({
export const httpClientDefaultConfigs = createDefaultAdapterConfig({
name: 'http-client',
enable: false,
url: 'http://localhost:8080',
@@ -31,7 +31,7 @@ const httpClientDefaultConfigs = createDefaultAdapterConfig({
});
export type HttpClientConfig = typeof httpClientDefaultConfigs;
const websocketServerDefaultConfigs = createDefaultAdapterConfig({
export const websocketServerDefaultConfigs = createDefaultAdapterConfig({
name: 'websocket-server',
enable: false,
host: '0.0.0.0',
@@ -45,7 +45,7 @@ const websocketServerDefaultConfigs = createDefaultAdapterConfig({
});
export type WebsocketServerConfig = typeof websocketServerDefaultConfigs;
const websocketClientDefaultConfigs = createDefaultAdapterConfig({
export const websocketClientDefaultConfigs = createDefaultAdapterConfig({
name: 'websocket-client',
enable: false,
url: 'ws://localhost:8082',
@@ -58,34 +58,35 @@ const websocketClientDefaultConfigs = createDefaultAdapterConfig({
export type WebsocketClientConfig = typeof websocketClientDefaultConfigs;
export interface NetworkConfig {
httpServers: Array<HttpServerConfig>,
httpClients: Array<HttpClientConfig>,
websocketServers: Array<WebsocketServerConfig>,
websocketClients: Array<WebsocketClientConfig>,
};
httpServers: Array<HttpServerConfig>;
httpClients: Array<HttpClientConfig>;
websocketServers: Array<WebsocketServerConfig>;
websocketClients: Array<WebsocketClientConfig>;
}
export function mergeConfigs<T extends AdapterConfig>(defaultConfig: T, userConfig: Partial<T>): T {
return { ...defaultConfig, ...userConfig };
}
export interface OnebotConfig {
network: NetworkConfig;//网络配置
musicSignUrl: string;//音乐签名地址
enableLocalFile2Url: boolean
export interface OneBotConfig {
network: NetworkConfig; //网络配置
musicSignUrl: string; //音乐签名地址
enableLocalFile2Url: boolean;
}
const createDefaultConfig = <T>(config: T): T => config;
export const defaultOnebotConfig = createDefaultConfig<OnebotConfig>({
export const defaultOneBotConfigs = createDefaultConfig<OneBotConfig>({
network: {
httpServers: [],
httpClients: [],
websocketServers: [],
websocketClients: [],
},
musicSignUrl: "",
enableLocalFile2Url: false
musicSignUrl: '',
enableLocalFile2Url: false,
});
export const mergeNetworkDefaultConfig = {
httpServers: httpServerDefaultConfigs,
httpClients: httpClientDefaultConfigs,
@@ -95,7 +96,8 @@ export const mergeNetworkDefaultConfig = {
type NetworkConfigKeys = keyof typeof mergeNetworkDefaultConfig;
export function mergeOnebotConfigs(defaultConfig: OnebotConfig, userConfig: Partial<OnebotConfig>): OnebotConfig {
// TODO: wrong type hint in userConfig (aka old userConfig)
export function mergeOneBotConfigs(defaultConfig: OneBotConfig, userConfig: Partial<OneBotConfig>): OneBotConfig {
const mergedConfig = { ...defaultConfig };
if (userConfig.network) {
@@ -104,7 +106,9 @@ export function mergeOnebotConfigs(defaultConfig: OnebotConfig, userConfig: Part
const userNetworkConfig = userConfig.network[key as keyof NetworkConfig];
const defaultNetworkConfig = mergeNetworkDefaultConfig[key as NetworkConfigKeys];
if (Array.isArray(userNetworkConfig)) {
mergedConfig.network[key as keyof NetworkConfig] = userNetworkConfig.map<any>(e => mergeConfigs(defaultNetworkConfig, e));
mergedConfig.network[key as keyof NetworkConfig] = userNetworkConfig.map<any>((e) =>
mergeConfigs(defaultNetworkConfig, e)
);
}
}
}

View File

@@ -1,8 +1,8 @@
import { ConfigBase } from '@/common/config-base';
import { NapCatCore } from '@/core';
import { OnebotConfig } from './config';
import { OneBotConfig } from './config';
export class OB11ConfigLoader extends ConfigBase<OnebotConfig> {
export class OB11ConfigLoader extends ConfigBase<OneBotConfig> {
constructor(core: NapCatCore, configPath: string) {
super('onebot11', core, configPath, false);
}

View File

@@ -45,7 +45,7 @@ import { OB11GroupRecallNoticeEvent } from '@/onebot/event/notice/OB11GroupRecal
import { LRUCache } from '@/common/lru-cache';
import { NodeIKernelRecentContactListener } from '@/core/listeners/NodeIKernelRecentContactListener';
import { BotOfflineEvent } from './event/notice/BotOfflineEvent';
import { defaultOnebotConfig, mergeOnebotConfigs, OnebotConfig } from './config/config';
import { defaultOneBotConfigs, mergeOneBotConfigs, OneBotConfig } from './config/config';
import { OB11Message } from './types';
//OneBot实现类
@@ -63,8 +63,8 @@ export class NapCatOneBot11Adapter {
constructor(core: NapCatCore, context: InstanceContext, pathWrapper: NapCatPathWrapper) {
this.core = core;
this.context = context;
this.configLoader = new OB11ConfigLoader(core, pathWrapper.configPath,);
this.configLoader.save(mergeOnebotConfigs(defaultOnebotConfig, this.configLoader.configData));
this.configLoader = new OB11ConfigLoader(core, pathWrapper.configPath);
this.configLoader.save(mergeOneBotConfigs(defaultOneBotConfigs, this.configLoader.configData));
this.apis = {
GroupApi: new OneBotGroupApi(this, core),
UserApi: new OneBotUserApi(this, core),
@@ -75,7 +75,7 @@ export class NapCatOneBot11Adapter {
this.actions = createActionMap(this, core);
this.networkManager = new OB11NetworkManager();
}
async creatOneBotLog(ob11Config: OnebotConfig) {
async creatOneBotLog(ob11Config: OneBotConfig) {
let log = `[network] 配置加载\n`;
for (const key of ob11Config.network.httpServers) {
log += `HTTP服务: ${key.host}:${key.port}, : ${key.enable ? '已启动' : '未启动'}\n`;
@@ -95,10 +95,12 @@ export class NapCatOneBot11Adapter {
const selfInfo = this.core.selfInfo;
const ob11Config = this.configLoader.configData;
this.core.apis.UserApi.getUserDetailInfo(selfInfo.uid).then(user => {
selfInfo.nick = user.nick;
this.context.logger.setLogSelfInfo(selfInfo);
}).catch(this.context.logger.logError.bind(this.context.logger));
this.core.apis.UserApi.getUserDetailInfo(selfInfo.uid)
.then((user) => {
selfInfo.nick = user.nick;
this.context.logger.setLogSelfInfo(selfInfo);
})
.catch(this.context.logger.logError.bind(this.context.logger));
const serviceInfo = await this.creatOneBotLog(ob11Config);
this.context.logger.log(`[Notice] [OneBot11] ${serviceInfo}`);
@@ -106,30 +108,46 @@ export class NapCatOneBot11Adapter {
// //创建NetWork服务
for (const key of ob11Config.network.httpServers) {
if (key.enable) {
this.networkManager.registerAdapter(new OB11PassiveHttpAdapter(
key.name, key.port, key.token, this.core, this.actions,
));
this.networkManager.registerAdapter(
new OB11PassiveHttpAdapter(key.name, key.port, key.token, this.core, this.actions)
);
}
}
for (const key of ob11Config.network.httpClients) {
if (key.enable) {
this.networkManager.registerAdapter(new OB11ActiveHttpAdapter(
key.name, key.url, key.token, this.core, this,
));
this.networkManager.registerAdapter(
new OB11ActiveHttpAdapter(key.name, key.url, key.token, this.core, this)
);
}
}
for (const key of ob11Config.network.websocketServers) {
if (key.enable) {
this.networkManager.registerAdapter(new OB11PassiveWebSocketAdapter(
key.name, key.host, key.port, key.heartInterval, key.token, this.core, this.actions,
));
this.networkManager.registerAdapter(
new OB11PassiveWebSocketAdapter(
key.name,
key.host,
key.port,
key.heartInterval,
key.token,
this.core,
this.actions
)
);
}
}
for (const key of ob11Config.network.websocketClients) {
if (key.enable) {
this.networkManager.registerAdapter(new OB11ActiveWebSocketAdapter(
key.name, key.url, 5000, key.heartInterval, key.token, this.core, this.actions,
));
this.networkManager.registerAdapter(
new OB11ActiveWebSocketAdapter(
key.name,
key.url,
5000,
key.heartInterval,
key.token,
this.core,
this.actions
)
);
}
}
await this.networkManager.openAllAdapters();
@@ -150,7 +168,9 @@ export class NapCatOneBot11Adapter {
initRecentContactListener() {
const recentContactListener = new NodeIKernelRecentContactListener();
recentContactListener.onRecentContactNotification = function (msgList: any[] /* arg0: { msgListUnreadCnt: string }, arg1: number */) {
recentContactListener.onRecentContactNotification = function (
msgList: any[] /* arg0: { msgListUnreadCnt: string }, arg1: number */
) {
msgList.forEach((msg) => {
if (msg.chatType == ChatType.KCHATTYPEGROUP) {
// log("recent contact", msgList, arg0, arg1);
@@ -201,7 +221,6 @@ export class NapCatOneBot11Adapter {
// }
// }
// // check difference in passive websocket (Ws)
// if (prev.ws.enable !== now.ws.enable) {
// if (now.ws.enable) {
@@ -242,32 +261,38 @@ export class NapCatOneBot11Adapter {
// }
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));
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) => {
this.apis.MsgApi.parseSysMessage(msg).then((event) => {
if (event) this.networkManager.emitEvent(event);
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructSysMessage error: ', e, '\n Parse Hex:', Buffer.from(msg).toString('hex')));
this.apis.MsgApi.parseSysMessage(msg)
.then((event) => {
if (event) this.networkManager.emitEvent(event);
})
.catch((e) =>
this.context.logger.logError.bind(this.context.logger)(
'constructSysMessage error: ',
e,
'\n Parse Hex:',
Buffer.from(msg).toString('hex')
)
);
};
msgListener.onInputStatusPush = async data => {
msgListener.onInputStatusPush = async (data) => {
const uin = await this.core.apis.UserApi.getUinByUidV2(data.fromUin);
this.context.logger.log(`[Notice] [输入状态] ${uin} ${data.statusText}`);
await this.networkManager.emitEvent(new OB11InputStatusEvent(
this.core,
parseInt(uin),
data.eventType,
data.statusText,
));
await this.networkManager.emitEvent(
new OB11InputStatusEvent(this.core, parseInt(uin), data.eventType, data.statusText)
);
};
msgListener.onRecvMsg = async msg => {
msgListener.onRecvMsg = async (msg) => {
for (const m of msg) {
if (this.bootTime > parseInt(m.msgTime)) {
this.context.logger.logDebug(`消息时间${m.msgTime}早于启动时间${this.bootTime},忽略上报`);
@@ -279,50 +304,54 @@ export class NapCatOneBot11Adapter {
peerUid: m.peerUid,
guildId: '',
},
m.msgId,
m.msgId
);
await this.emitMsg(m).catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理消息失败', e)
);
await this.emitMsg(m)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
}
};
const msgIdSend = new LRUCache<string, number>(100);
const recallMsgs = new LRUCache<string, boolean>(100);
msgListener.onAddSendMsg = async msg => {
msgListener.onAddSendMsg = async (msg) => {
if (msg.sendStatus == SendStatusType.KSEND_STATUS_SENDING) {
msgIdSend.put(msg.msgId, 0);
}
};
msgListener.onMsgInfoListUpdate = async msgList => {
this.emitRecallMsg(msgList, recallMsgs)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理消息失败', e));
for (const msg of msgList.filter(e => e.senderUin == this.core.selfInfo.uin)) {
msgListener.onMsgInfoListUpdate = async (msgList) => {
this.emitRecallMsg(msgList, recallMsgs).catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理消息失败', e)
);
for (const msg of msgList.filter((e) => e.senderUin == this.core.selfInfo.uin)) {
if (msg.sendStatus == SendStatusType.KSEND_STATUS_SUCCESS && msgIdSend.get(msg.msgId) == 0) {
msgIdSend.put(msg.msgId, 1);
// 完成后再post
msg.id = MessageUnique.createUniqueMsgId({
chatType: msg.chatType,
peerUid: msg.peerUid,
guildId: '',
}, msg.msgId);
msg.id = MessageUnique.createUniqueMsgId(
{
chatType: msg.chatType,
peerUid: msg.peerUid,
guildId: '',
},
msg.msgId
);
this.emitMsg(msg);
}
}
};
msgListener.onKickedOffLine = async (kick) => {
const event = new BotOfflineEvent(this.core, kick.tipsTitle, kick.tipsDesc);
this.networkManager.emitEvent(event)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理Bot掉线失败', e));
this.networkManager
.emitEvent(event)
.catch((e) => this.context.logger.logError.bind(this.context.logger)('处理Bot掉线失败', e));
};
this.context.session.getMsgService().addKernelMsgListener(
proxiedListenerOf(msgListener, this.context.logger),
);
this.context.session.getMsgService().addKernelMsgListener(proxiedListenerOf(msgListener, this.context.logger));
}
private initBuddyListener() {
const buddyListener = new NodeIKernelBuddyListener();
buddyListener.onBuddyReqChange = async reqs => {
buddyListener.onBuddyReqChange = async (reqs) => {
this.core.apis.FriendApi.clearBuddyReqUnreadCnt();
for (let i = 0; i < reqs.unreadNums; i++) {
const req = reqs.buddyReqs[i];
@@ -331,21 +360,23 @@ export class NapCatOneBot11Adapter {
}
try {
const requesterUin = await this.core.apis.UserApi.getUinByUidV2(req.friendUid);
await this.networkManager.emitEvent(new OB11FriendRequestEvent(
this.core,
+requesterUin,
req.extWords,
req.friendUid + '|' + req.reqTime,
));
await this.networkManager.emitEvent(
new OB11FriendRequestEvent(
this.core,
+requesterUin,
req.extWords,
req.friendUid + '|' + req.reqTime
)
);
} catch (e) {
this.context.logger.logDebug('获取加好友者QQ号失败', e);
}
}
};
this.context.session.getBuddyService().addKernelBuddyListener(
proxiedListenerOf(buddyListener, this.context.logger),
);
this.context.session
.getBuddyService()
.addKernelBuddyListener(proxiedListenerOf(buddyListener, this.context.logger));
}
private initGroupListener() {
@@ -354,11 +385,13 @@ export class NapCatOneBot11Adapter {
groupListener.onGroupNotifiesUpdated = async (_, notifies) => {
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
await this.core.apis.GroupApi.clearGroupNotifiesUnreadCount(false);
if (![
GroupNotifyMsgType.SET_ADMIN,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_ADMIN,
].includes(notifies[0]?.type)) {
if (
![
GroupNotifyMsgType.SET_ADMIN,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_ADMIN,
].includes(notifies[0]?.type)
) {
for (const notify of notifies) {
const notifyTime = parseInt(notify.seq) / 1000 / 1000;
// log(`群通知时间${notifyTime}`, `启动时间${this.bootTime}`);
@@ -369,12 +402,17 @@ export class NapCatOneBot11Adapter {
const flag = notify.group.groupCode + '|' + notify.seq + '|' + notify.type;
this.context.logger.logDebug('收到群通知', notify);
if ([
GroupNotifyMsgType.SET_ADMIN,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_ADMIN,
].includes(notify.type)) {
const member1 = await this.core.apis.GroupApi.getGroupMember(notify.group.groupCode, notify.user1.uid);
if (
[
GroupNotifyMsgType.SET_ADMIN,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_ADMIN,
].includes(notify.type)
) {
const member1 = await this.core.apis.GroupApi.getGroupMember(
notify.group.groupCode,
notify.user1.uid
);
this.context.logger.logDebug('有管理员变动通知');
// refreshGroupMembers(notify.group.groupCode).then();
this.context.logger.logDebug('开始获取变动的管理员');
@@ -387,16 +425,28 @@ export class NapCatOneBot11Adapter {
[
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_CANCELED,
GroupNotifyMsgType.CANCEL_ADMIN_NOTIFY_ADMIN,
].includes(notify.type) ? 'unset' : 'set',
].includes(notify.type)
? 'unset'
: 'set'
);
this.networkManager.emitEvent(groupAdminNoticeEvent)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群管理员变动失败', e));
this.networkManager
.emitEvent(groupAdminNoticeEvent)
.catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理群管理员变动失败', e)
);
} else {
this.context.logger.logDebug('获取群通知的成员信息失败', notify, this.core.apis.GroupApi.getGroup(notify.group.groupCode));
this.context.logger.logDebug(
'获取群通知的成员信息失败',
notify,
this.core.apis.GroupApi.getGroup(notify.group.groupCode)
);
}
} else if (notify.type == GroupNotifyMsgType.MEMBER_LEAVE_NOTIFY_ADMIN || notify.type == GroupNotifyMsgType.KICK_MEMBER_NOTIFY_ADMIN) {
} else if (
notify.type == GroupNotifyMsgType.MEMBER_LEAVE_NOTIFY_ADMIN ||
notify.type == GroupNotifyMsgType.KICK_MEMBER_NOTIFY_ADMIN
) {
this.context.logger.logDebug('有成员退出通知', notify);
const member1Uin = (await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid));
const member1Uin = await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid);
let operatorId = member1Uin;
let subType: GroupDecreaseSubType = 'leave';
if (notify.user2.uid) {
@@ -412,17 +462,21 @@ export class NapCatOneBot11Adapter {
parseInt(notify.group.groupCode),
parseInt(member1Uin),
parseInt(operatorId),
subType,
subType
);
this.networkManager.emitEvent(groupDecreaseEvent)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群成员退出失败', e));
this.networkManager
.emitEvent(groupDecreaseEvent)
.catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理群成员退出失败', e)
);
// notify.status == 1 表示未处理 2表示处理完成
} else if ([
GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS,
].includes(notify.type) && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
} else if (
[GroupNotifyMsgType.REQUEST_JOIN_NEED_ADMINI_STRATOR_PASS].includes(notify.type) &&
notify.status == GroupNotifyMsgStatus.KUNHANDLE
) {
this.context.logger.logDebug('有加群请求');
try {
let requestUin = (await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid));
let requestUin = await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid);
if (isNaN(parseInt(requestUin))) {
requestUin = (await this.core.apis.UserApi.getUserDetailInfo(notify.user1.uid)).uin;
}
@@ -432,14 +486,24 @@ export class NapCatOneBot11Adapter {
parseInt(requestUin),
'add',
notify.postscript,
flag,
flag
);
this.networkManager.emitEvent(groupRequestEvent)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理加群请求失败', e));
this.networkManager
.emitEvent(groupRequestEvent)
.catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理加群请求失败', e)
);
} catch (e) {
this.context.logger.logError.bind(this.context.logger)('获取加群人QQ号失败 Uid:', notify.user1.uid, e);
this.context.logger.logError.bind(this.context.logger)(
'获取加群人QQ号失败 Uid:',
notify.user1.uid,
e
);
}
} else if (notify.type == GroupNotifyMsgType.INVITED_BY_MEMBER && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
} else if (
notify.type == GroupNotifyMsgType.INVITED_BY_MEMBER &&
notify.status == GroupNotifyMsgStatus.KUNHANDLE
) {
this.context.logger.logDebug(`收到邀请我加群通知:${notify}`);
const groupInviteEvent = new OB11GroupRequestEvent(
this.core,
@@ -447,11 +511,17 @@ export class NapCatOneBot11Adapter {
parseInt(await this.core.apis.UserApi.getUinByUidV2(notify.user2.uid)),
'invite',
notify.postscript,
flag,
flag
);
this.networkManager.emitEvent(groupInviteEvent)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理邀请本人加群失败', e));
} else if (notify.type == GroupNotifyMsgType.INVITED_NEED_ADMINI_STRATOR_PASS && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
this.networkManager
.emitEvent(groupInviteEvent)
.catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理邀请本人加群失败', e)
);
} else if (
notify.type == GroupNotifyMsgType.INVITED_NEED_ADMINI_STRATOR_PASS &&
notify.status == GroupNotifyMsgStatus.KUNHANDLE
) {
this.context.logger.logDebug(`收到群员邀请加群通知:${notify}`);
const groupInviteEvent = new OB11GroupRequestEvent(
this.core,
@@ -459,10 +529,13 @@ export class NapCatOneBot11Adapter {
parseInt(await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid)),
'add',
notify.postscript,
flag,
flag
);
this.networkManager.emitEvent(groupInviteEvent)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理邀请本人加群失败', e));
this.networkManager
.emitEvent(groupInviteEvent)
.catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理邀请本人加群失败', e)
);
}
}
}
@@ -481,88 +554,102 @@ export class NapCatOneBot11Adapter {
this.core,
parseInt(groupCode),
parseInt(member.uin),
member.role === GroupMemberRole.admin ? 'set' : 'unset',
member.role === GroupMemberRole.admin ? 'set' : 'unset'
);
this.networkManager.emitEvent(groupAdminNoticeEvent)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群管理员变动失败', e));
this.networkManager
.emitEvent(groupAdminNoticeEvent)
.catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理群管理员变动失败', e)
);
existMember.isChangeRole = false;
this.context.logger.logDebug.bind(this.context.logger)('群管理员变动处理完毕');
});
}
};
this.context.session.getGroupService().addKernelGroupListener(
proxiedListenerOf(groupListener, this.context.logger),
);
this.context.session
.getGroupService()
.addKernelGroupListener(proxiedListenerOf(groupListener, this.context.logger));
}
private async emitMsg(message: RawMessage) {
const network = Object.values(this.configLoader.configData.network) as Array<typeof this.configLoader.configData.network[keyof typeof this.configLoader.configData.network]>;
const network = Object.values(this.configLoader.configData.network) as Array<
(typeof this.configLoader.configData.network)[keyof typeof this.configLoader.configData.network]
>;
this.context.logger.logDebug('收到新消息 RawMessage', message);
this.apis.MsgApi.parseMessageV2(message).then((ob11Msg) => {
if (!ob11Msg) return;
const isSelfMsg = ob11Msg.stringMsg.user_id.toString() == this.core.selfInfo.uin || ob11Msg.arrayMsg.user_id.toString() == this.core.selfInfo.uin;
this.context.logger.logDebug('转化为 OB11Message', ob11Msg);
const msgMap: Map<string, OB11Message> = new Map();
const enable_client: string[] = [];
network.flat().filter(e => e.enable).map(e => {
enable_client.push(e.name);
if (e.messagePostFormat == 'string') {
msgMap.set(e.name, structuredClone(ob11Msg.stringMsg));
} else {
msgMap.set(e.name, structuredClone(ob11Msg.arrayMsg));
}
if (isSelfMsg) {
ob11Msg.stringMsg.target_id = parseInt(message.peerUin);
ob11Msg.arrayMsg.target_id = parseInt(message.peerUin);
}
});
const debug_network = network.flat().filter(e => e.enable && e.debug);
if (debug_network.length > 0) {
for (const adapter of debug_network) {
if (adapter.name) {
const msg = msgMap.get(adapter.name);
if (msg) {
msg.raw = message;
this.apis.MsgApi.parseMessageV2(message)
.then((ob11Msg) => {
if (!ob11Msg) return;
const isSelfMsg =
ob11Msg.stringMsg.user_id.toString() == this.core.selfInfo.uin ||
ob11Msg.arrayMsg.user_id.toString() == this.core.selfInfo.uin;
this.context.logger.logDebug('转化为 OB11Message', ob11Msg);
const msgMap: Map<string, OB11Message> = new Map();
const enable_client: string[] = [];
network
.flat()
.filter((e) => e.enable)
.map((e) => {
enable_client.push(e.name);
if (e.messagePostFormat == 'string') {
msgMap.set(e.name, structuredClone(ob11Msg.stringMsg));
} else {
msgMap.set(e.name, structuredClone(ob11Msg.arrayMsg));
}
if (isSelfMsg) {
ob11Msg.stringMsg.target_id = parseInt(message.peerUin);
ob11Msg.arrayMsg.target_id = parseInt(message.peerUin);
}
});
const debug_network = network.flat().filter((e) => e.enable && e.debug);
if (debug_network.length > 0) {
for (const adapter of debug_network) {
if (adapter.name) {
const msg = msgMap.get(adapter.name);
if (msg) {
msg.raw = message;
}
}
}
} else if (ob11Msg.stringMsg.message.length === 0 || ob11Msg.arrayMsg.message.length == 0) {
return;
}
} else if (ob11Msg.stringMsg.message.length === 0 || ob11Msg.arrayMsg.message.length == 0) {
return;
}
const notreportSelf_network = network.flat().filter(e => e.enable && !e.reportSelfMessage);
if (isSelfMsg) {
for (const adapter of notreportSelf_network) {
msgMap.delete(adapter.name);
const notreportSelf_network = network.flat().filter((e) => e.enable && !e.reportSelfMessage);
if (isSelfMsg) {
for (const adapter of notreportSelf_network) {
msgMap.delete(adapter.name);
}
}
}
this.networkManager.emitEventByNames(msgMap);
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructMessage error: ', e));
this.networkManager.emitEventByNames(msgMap);
})
.catch((e) => this.context.logger.logError.bind(this.context.logger)('constructMessage error: ', e));
this.apis.GroupApi.parseGroupEvent(message).then(groupEvent => {
if (groupEvent) {
// log("post group event", groupEvent);
this.networkManager.emitEvent(groupEvent);
}
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructGroupEvent error: ', e));
this.apis.GroupApi.parseGroupEvent(message)
.then((groupEvent) => {
if (groupEvent) {
// log("post group event", groupEvent);
this.networkManager.emitEvent(groupEvent);
}
})
.catch((e) => this.context.logger.logError.bind(this.context.logger)('constructGroupEvent error: ', e));
this.apis.MsgApi.parsePrivateMsgEvent(message).then(privateEvent => {
if (privateEvent) {
// log("post private event", privateEvent);
this.networkManager.emitEvent(privateEvent);
}
}).catch(e => this.context.logger.logError.bind(this.context.logger)('constructPrivateEvent error: ', e));
this.apis.MsgApi.parsePrivateMsgEvent(message)
.then((privateEvent) => {
if (privateEvent) {
// log("post private event", privateEvent);
this.networkManager.emitEvent(privateEvent);
}
})
.catch((e) => this.context.logger.logError.bind(this.context.logger)('constructPrivateEvent error: ', e));
}
private async emitRecallMsg(msgList: RawMessage[], cache: LRUCache<string, boolean>) {
for (const message of msgList) {
// log("message update", message.sendStatus, message.msgId, message.msgSeq)
const peer: Peer = { chatType: message.chatType, peerUid: message.peerUid, guildId: '' };
if (message.recallTime != '0' && !cache.get(message.msgId)) { //work:这个判断方法不太好,应该使用灰色消息元素来判断?
if (message.recallTime != '0' && !cache.get(message.msgId)) {
//work:这个判断方法不太好,应该使用灰色消息元素来判断?
cache.put(message.msgId, true);
// 撤回消息上报
let oriMessageId = MessageUnique.getShortIdByMsgId(message.msgId);
@@ -573,10 +660,13 @@ export class NapCatOneBot11Adapter {
const friendRecallEvent = new OB11FriendRecallNoticeEvent(
this.core,
+message.senderUin,
oriMessageId,
oriMessageId
);
this.networkManager.emitEvent(friendRecallEvent)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理好友消息撤回失败', e));
this.networkManager
.emitEvent(friendRecallEvent)
.catch((e) =>
this.context.logger.logError.bind(this.context.logger)('处理好友消息撤回失败', e)
);
} else if (message.chatType == ChatType.KCHATTYPEGROUP) {
let operatorId = message.senderUin;
for (const element of message.elements) {
@@ -592,8 +682,9 @@ export class NapCatOneBot11Adapter {
+operatorId,
oriMessageId
);
this.networkManager.emitEvent(groupRecallEvent)
.catch(e => this.context.logger.logError.bind(this.context.logger)('处理群消息撤回失败', e));
this.networkManager
.emitEvent(groupRecallEvent)
.catch((e) => this.context.logger.logError.bind(this.context.logger)('处理群消息撤回失败', e));
}
}
}

View File

@@ -1,12 +1,11 @@
import { RequestHandler } from 'express';
import { WebUiDataRuntime } from '../helper/Data';
import { existsSync, readFileSync } from 'node:fs';
import { OnebotConfig } from '@/onebot/config/config';
import { OneBotConfig } from '@/onebot/config/config';
import { resolve } from 'node:path';
import { webUiPathWrapper } from '@/webui';
const isEmpty = (data: any) =>
data === undefined || data === null || data === '';
const isEmpty = (data: any) => data === undefined || data === null || data === '';
export const OB11GetConfigHandler: RequestHandler = async (req, res) => {
const isLogin = await WebUiDataRuntime.getQQLoginStatus();
if (!isLogin) {
@@ -19,15 +18,15 @@ export const OB11GetConfigHandler: RequestHandler = async (req, res) => {
const uin = await WebUiDataRuntime.getQQLoginUin();
const configFilePath = resolve(webUiPathWrapper.configPath, `./onebot11_${uin}.json`);
//console.log(configFilePath);
let data: OnebotConfig;
let data: OneBotConfig;
try {
data = JSON.parse(
existsSync(configFilePath)
? readFileSync(configFilePath).toString()
: readFileSync(resolve(webUiPathWrapper.configPath, './onebot11.json')).toString(),
: readFileSync(resolve(webUiPathWrapper.configPath, './onebot11.json')).toString()
);
} catch (e) {
data = {} as OnebotConfig;
data = {} as OneBotConfig;
res.send({
code: -1,
message: 'Config Get Error',

View File

@@ -1,4 +1,4 @@
import { OnebotConfig } from '@/onebot/config/config';
import { OneBotConfig } from '@/onebot/config/config';
interface LoginRuntimeType {
LoginCurrentTime: number;
@@ -7,9 +7,9 @@ interface LoginRuntimeType {
QQQRCodeURL: string;
QQLoginUin: string;
NapCatHelper: {
onQuickLoginRequested: (uin: string) => Promise<{ result: boolean, message: string }>;
onOB11ConfigChanged: (ob11: OnebotConfig) => Promise<void>;
QQLoginList: string[]
onQuickLoginRequested: (uin: string) => Promise<{ result: boolean; message: string }>;
onOB11ConfigChanged: (ob11: OneBotConfig) => Promise<void>;
QQLoginList: string[];
};
}
@@ -31,62 +31,62 @@ const LoginRuntime: LoginRuntimeType = {
};
export const WebUiDataRuntime = {
checkLoginRate: async function(RateLimit: number): Promise<boolean> {
checkLoginRate: async function (RateLimit: number): Promise<boolean> {
LoginRuntime.LoginCurrentRate++;
//console.log(RateLimit, LoginRuntime.LoginCurrentRate, Date.now() - LoginRuntime.LoginCurrentTime);
if (Date.now() - LoginRuntime.LoginCurrentTime > 1000 * 60) {
LoginRuntime.LoginCurrentRate = 0;//超出时间重置限速
LoginRuntime.LoginCurrentRate = 0; //超出时间重置限速
LoginRuntime.LoginCurrentTime = Date.now();
return true;
}
return LoginRuntime.LoginCurrentRate <= RateLimit;
},
getQQLoginStatus: async function(): Promise<boolean> {
getQQLoginStatus: async function (): Promise<boolean> {
return LoginRuntime.QQLoginStatus;
},
setQQLoginStatus: async function(status: boolean): Promise<void> {
setQQLoginStatus: async function (status: boolean): Promise<void> {
LoginRuntime.QQLoginStatus = status;
},
setQQLoginQrcodeURL: async function(url: string): Promise<void> {
setQQLoginQrcodeURL: async function (url: string): Promise<void> {
LoginRuntime.QQQRCodeURL = url;
},
getQQLoginQrcodeURL: async function(): Promise<string> {
getQQLoginQrcodeURL: async function (): Promise<string> {
return LoginRuntime.QQQRCodeURL;
},
setQQLoginUin: async function(uin: string): Promise<void> {
setQQLoginUin: async function (uin: string): Promise<void> {
LoginRuntime.QQLoginUin = uin;
},
getQQLoginUin: async function(): Promise<string> {
getQQLoginUin: async function (): Promise<string> {
return LoginRuntime.QQLoginUin;
},
getQQQuickLoginList: async function(): Promise<any[]> {
getQQQuickLoginList: async function (): Promise<any[]> {
return LoginRuntime.NapCatHelper.QQLoginList;
},
setQQQuickLoginList: async function(list: string[]): Promise<void> {
setQQQuickLoginList: async function (list: string[]): Promise<void> {
LoginRuntime.NapCatHelper.QQLoginList = list;
},
setQuickLoginCall(func: (uin: string) => Promise<{ result: boolean, message: string }>): void {
setQuickLoginCall(func: (uin: string) => Promise<{ result: boolean; message: string }>): void {
LoginRuntime.NapCatHelper.onQuickLoginRequested = func;
},
requestQuickLogin: async function(uin: string): Promise<{ result: boolean, message: string }> {
requestQuickLogin: async function (uin: string): Promise<{ result: boolean; message: string }> {
return await LoginRuntime.NapCatHelper.onQuickLoginRequested(uin);
},
setOnOB11ConfigChanged: async function(func: (ob11: OnebotConfig) => Promise<void>): Promise<void> {
setOnOB11ConfigChanged: async function (func: (ob11: OneBotConfig) => Promise<void>): Promise<void> {
LoginRuntime.NapCatHelper.onOB11ConfigChanged = func;
},
setOB11Config: async function(ob11: OnebotConfig): Promise<void> {
setOB11Config: async function (ob11: OneBotConfig): Promise<void> {
await LoginRuntime.NapCatHelper.onOB11ConfigChanged(ob11);
},
};