Compare commits

..

32 Commits

Author SHA1 Message Date
手瓜一十雪
b631e6f8a2 fix: 更精确的筛选 2024-12-20 19:44:57 +08:00
手瓜一十雪
b3b48b032c fix: 锁住esbuild版本 以缓解问题 2024-12-20 19:32:20 +08:00
手瓜一十雪
f3e8230eca fix: 暂时指定esbuild版本以缓解上游破坏
see https://github.com/evanw/esbuild/issues/4010
2024-12-20 19:30:30 +08:00
手瓜一十雪
cc9adf9d40 feat: 过滤空消息 2024-12-20 18:58:59 +08:00
手瓜一十雪
15a640d1dc fix: #637 2024-12-20 18:55:30 +08:00
凌莞~(=^▽^=)
c25b9f86db 优化私聊戳一戳事件上报 (#643) 2024-12-18 21:27:44 +08:00
Mlikiowa
ecfd033afb release: v4.2.37 2024-12-17 07:56:18 +00:00
手瓜一十雪
f3ed8c7dff fix #633 2024-12-17 15:55:18 +08:00
Mlikiowa
6089046721 release: v4.2.36 2024-12-17 03:37:26 +00:00
手瓜一十雪
44ff92ad4b style: lint 2024-12-17 09:25:10 +08:00
手瓜一十雪
892262eb85 Merge pull request #635 from NapNeko/ref/ob-network
refactor: adjust onebot network
2024-12-17 09:07:39 +08:00
pk5ls20
2d9cc4d198 fix: as design 2024-12-17 07:07:04 +08:00
pk5ls20
a0c479485d refactor: adjust onebot network 2024-12-17 05:26:27 +08:00
手瓜一十雪
5650f18e50 Merge pull request #634 from bietiaop/main
fix: handleQuickOperation error
2024-12-17 00:29:16 +08:00
bietiaop
553885d025 fix: handleQuickOperation 2024-12-17 00:27:56 +08:00
Mlikiowa
35de00c4af release: v4.2.35 2024-12-16 14:10:08 +00:00
手瓜一十雪
09583e5de5 fuck javascript 2024-12-16 22:09:37 +08:00
Mlikiowa
38b0b7cd00 release: v4.2.34 2024-12-16 13:17:43 +00:00
手瓜一十雪
8b9c7b0c27 Merge pull request #632 from q8018414/patch-1
Update AboutUs.vue
2024-12-16 21:16:39 +08:00
手瓜一十雪
1005619bf3 Merge pull request #630 from NapNeko/dependabot/npm_and_yarn/rollup/plugin-typescript-12.1.2
chore(deps-dev): bump @rollup/plugin-typescript from 11.1.6 to 12.1.2
2024-12-16 21:16:01 +08:00
手瓜一十雪
3e09cff9cb Merge branch 'main' into dependabot/npm_and_yarn/rollup/plugin-typescript-12.1.2 2024-12-16 21:15:52 +08:00
手瓜一十雪
c24384e454 Merge pull request #629 from NapNeko/dependabot/npm_and_yarn/rollup/plugin-node-resolve-16.0.0
chore(deps-dev): bump @rollup/plugin-node-resolve from 15.3.1 to 16.0.0
2024-12-16 21:15:23 +08:00
手瓜一十雪
f87a543406 fix: #631 2024-12-16 21:14:14 +08:00
手瓜一十雪
f752136283 fix: #631 2024-12-16 21:06:51 +08:00
my_key
7e71622a44 Update AboutUs.vue
新增用于显示New NapCat的tag,便于区分当前版本和最新版本
2024-12-16 20:09:40 +08:00
dependabot[bot]
da92afb379 chore(deps-dev): bump @rollup/plugin-typescript from 11.1.6 to 12.1.2
Bumps [@rollup/plugin-typescript](https://github.com/rollup/plugins/tree/HEAD/packages/typescript) from 11.1.6 to 12.1.2.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/typescript/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/typescript-v12.1.2/packages/typescript)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 08:44:42 +00:00
dependabot[bot]
d3062de5f9 chore(deps-dev): bump @rollup/plugin-node-resolve from 15.3.1 to 16.0.0
Bumps [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/HEAD/packages/node-resolve) from 15.3.1 to 16.0.0.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/node-resolve/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/commonjs-v16.0.0/packages/node-resolve)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-node-resolve"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-16 08:43:46 +00:00
Mlikiowa
f1440b03a8 release: v4.2.33 2024-12-16 05:03:59 +00:00
手瓜一十雪
9a8b266cef Merge pull request #627 from bietiaop/main
feat: 查看登录QQ信息&获取快速登录列表详细信息&获取nc的包信息&优化了部分写法
2024-12-16 13:03:09 +08:00
手瓜一十雪
2a9bc57120 fix: #628 2024-12-16 13:00:07 +08:00
bietiaop
2ed83a0e30 feat: 查看登录QQ信息&获取快速登录列表详细信息&获取nc的包信息&优化了部分写法 2024-12-16 12:46:27 +08:00
Mlikiowa
116e8fd30a release: v4.2.32 2024-12-14 07:03:02 +00:00
36 changed files with 295 additions and 205 deletions

View File

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

View File

@@ -89,7 +89,11 @@
<t-tag class="tag-item pgk-color"> WebUi: {{ pkg.version }} </t-tag>
<t-tag class="tag-item nc-color">
NapCat:
{{ githubReleasesData&&githubReleasesData[0] ?.tag_name ? githubReleasesData[0].tag_name : napCatVersion }}
{{ napCatVersion }}
</t-tag>
<t-tag v-if="githubReleasesData&&githubReleasesData[0] ?.tag_name" class="tag-item nc-color">
New NapCat:
{{ githubReleasesData[0].tag_name }}
</t-tag>
<t-tag class="tag-item td-color"> TDesign: {{ pkg.dependencies['tdesign-vue-next'] }} </t-tag>
</span>

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "4.2.31",
"version": "4.2.37",
"scripts": {
"build:universal": "npm run build:webui && vite build --mode universal || exit 1",
"build:framework": "npm run build:webui && vite build --mode framework || exit 1",
@@ -17,14 +17,15 @@
"dev:depend": "npm i && cd napcat.webui && npm i"
},
"devDependencies": {
"esbuild": "0.24.0",
"@babel/preset-typescript": "^7.24.7",
"@eslint/compat": "^1.2.2",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.14.0",
"@log4js-node/log4js-api": "^1.0.2",
"@napneko/nap-proto-core": "^0.0.4",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-typescript": "^11.1.6",
"@rollup/plugin-typescript": "^12.1.2",
"@rollup/plugin-node-resolve": "^16.0.0",
"@types/cors": "^2.8.17",
"@sinclair/typebox": "^0.34.9",
"@types/express": "^5.0.0",

View File

@@ -1 +1 @@
export const napCatVersion = '4.2.31';
export const napCatVersion = '4.2.37';

View File

@@ -26,7 +26,7 @@ export class NTQQGroupApi {
}
async fetchGroupDetail(groupCode: string) {
let [, detailInfo] = await this.core.eventWrapper.callNormalEventV2(
const [, detailInfo] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelGroupService/getGroupDetailInfo',
'NodeIKernelGroupListener/onGroupDetailInfoChange',
[groupCode, GroupInfoSource.KDATACARD],

View File

@@ -72,6 +72,14 @@ export const GroupChange = {
field7: ProtoField(7, ScalarType.BYTES, true),
};
export const GroupInvite = {
groupUin: ProtoField(1, ScalarType.UINT32),
field2: ProtoField(2, ScalarType.UINT32),
field3: ProtoField(2, ScalarType.UINT32),
field4: ProtoField(2, ScalarType.UINT32),
invitorUid: ProtoField(5, ScalarType.STRING),
};
export const PushMsgBody = {
responseHead: ProtoField(1, () => ResponseHead),
contentHead: ProtoField(2, () => ContentHead),

View File

@@ -508,7 +508,7 @@ export interface RawMessage {
*/
export interface QueryMsgsParams {
chatInfo: Peer;
filterMsgType: [];
filterMsgType: Array<{ type: NTMsgType, subType: Array<number> }>;
filterSendersUid: string[];
filterMsgFromTime: string;
filterMsgToTime: string;

View File

@@ -24,7 +24,7 @@ class GetGroupInfo extends OneBotAction<Payload, OB11Group> {
group_name: data.groupName,
member_count: data.memberNum,
max_member_count: data.maxMemberNum,
}
};
}
return OB11Construct.group(group);
}

View File

@@ -1,4 +1,4 @@
import {ContextMode, SendMsgBase} from '@/onebot/action/msg/SendMsg';
import { ContextMode, SendMsgBase } from '@/onebot/action/msg/SendMsg';
import { ActionName, BaseCheckResult } from '@/onebot/action/router';
import { OB11PostSendMsg } from '@/onebot/types';

View File

@@ -1,4 +1,4 @@
import {ContextMode, SendMsgBase} from './SendMsg';
import { ContextMode, SendMsgBase } from './SendMsg';
import { ActionName, BaseCheckResult } from '@/onebot/action/router';
import { OB11PostSendMsg } from '@/onebot/types';

View File

@@ -1,5 +1,5 @@
import { ActionName } from '@/onebot/action/router';
import CanSendRecord, {CanSend} from './CanSendRecord';
import CanSendRecord, { CanSend } from './CanSendRecord';
interface ReturnType {
yes: boolean;

View File

@@ -12,16 +12,17 @@ export class OneBotFriendApi {
}
//使用前预先判断 busiId 1061
async parsePrivatePokeEvent(grayTipElement: GrayTipElement) {
async parsePrivatePokeEvent(grayTipElement: GrayTipElement, uin: number) {
const json = JSON.parse(grayTipElement.jsonGrayTipElement.jsonStr);
let pokedetail: Array<{ uid: string }> = json.items;
const pokedetail: Array<{ uid: string }> = json.items;
//筛选item带有uid的元素
pokedetail = pokedetail.filter(item => item.uid);
if (pokedetail.length == 2) {
const poke_uid = pokedetail.filter(item => item.uid);
if (poke_uid.length == 2) {
return new OB11FriendPokeEvent(
this.core,
parseInt((await this.core.apis.UserApi.getUinByUidV2(pokedetail[0].uid))),
parseInt((await this.core.apis.UserApi.getUinByUidV2(pokedetail[1].uid))),
uin,
parseInt((await this.core.apis.UserApi.getUinByUidV2(poke_uid[0].uid))),
parseInt((await this.core.apis.UserApi.getUinByUidV2(poke_uid[1].uid))),
pokedetail,
);
}

View File

@@ -1,19 +1,5 @@
import type { OneBotFriendApi } from '@/onebot/api/friend';
import type { OneBotUserApi } from '@/onebot/api/user';
import type { OneBotGroupApi } from '@/onebot/api/group';
import type { OneBotMsgApi } from '@/onebot/api/msg';
import type { OneBotQuickActionApi } from '@/onebot/api/quick-action';
export * from './friend';
export * from './group';
export * from './user';
export * from './msg';
export * from './quick-action';
export interface StableOneBotApiWrapper {
FriendApi: OneBotFriendApi;
UserApi: OneBotUserApi;
GroupApi: OneBotGroupApi;
MsgApi: OneBotMsgApi;
QuickActionApi: OneBotQuickActionApi,
}
export * from './quick-action';

View File

@@ -33,7 +33,8 @@ import { OB11GroupIncreaseEvent } from '../event/notice/OB11GroupIncreaseEvent';
import { OB11GroupDecreaseEvent, GroupDecreaseSubType } from '../event/notice/OB11GroupDecreaseEvent';
import { GroupAdmin } from '@/core/packet/transformer/proto/message/groupAdmin';
import { OB11GroupAdminNoticeEvent } from '../event/notice/OB11GroupAdminNoticeEvent';
import { GroupChange, GroupChangeInfo, PushMsgBody } from '@/core/packet/transformer/proto';
import { GroupChange, GroupChangeInfo, GroupInvite, PushMsgBody } from '@/core/packet/transformer/proto';
import { OB11GroupRequestEvent } from '../event/request/OB11GroupRequest';
type RawToOb11Converters = {
[Key in keyof MessageElement as Key extends `${string}Element` ? Key : never]: (
@@ -679,7 +680,7 @@ export class OneBotMsgApi {
async parsePrivateMsgEvent(msg: RawMessage, grayTipElement: GrayTipElement) {
if (grayTipElement.subElementType == NTGrayTipElementSubTypeV2.GRAYTIP_ELEMENT_SUBTYPE_JSON) {
if (grayTipElement.jsonGrayTipElement.busiId == 1061) {
const PokeEvent = await this.obContext.apis.FriendApi.parsePrivatePokeEvent(grayTipElement);
const PokeEvent = await this.obContext.apis.FriendApi.parsePrivatePokeEvent(grayTipElement, Number(await this.core.apis.UserApi.getUinByUidV2(msg.peerUid)));
if (PokeEvent) { return PokeEvent; };
} else if (grayTipElement.jsonGrayTipElement.busiId == 19324 && msg.peerUid !== '') {
return new OB11FriendAddNoticeEvent(this.core, Number(await this.core.apis.UserApi.getUinByUidV2(msg.peerUid)));
@@ -1033,7 +1034,35 @@ export class OneBotMsgApi {
+await this.core.apis.UserApi.getUinByUidV2(uid),
enabled ? 'set' : 'unset'
);
} else if (SysMessage.contentHead.type == 528 && SysMessage.contentHead.subType == 39 && SysMessage.body?.msgContent) {
} else if (SysMessage.contentHead.type == 87 && SysMessage.body?.msgContent) {
let groupInvite = new NapProtoMsg(GroupInvite).decode(SysMessage.body.msgContent);
let request_seq = '';
await this.core.eventWrapper.registerListen('NodeIKernelMsgListener/onRecvMsg', (msgs) => {
for (const msg of msgs) {
if (msg.senderUid === groupInvite.invitorUid && msg.msgType === 11) {
let jumpUrl = JSON.parse(msg.elements.find(e => e.elementType === 10)?.arkElement?.bytesData ?? '').meta?.news?.jumpUrl;
let jumpUrlParams = new URLSearchParams(jumpUrl);
let groupcode = jumpUrlParams.get('groupcode');
let receiveruin = jumpUrlParams.get('receiveruin');
let msgseq = jumpUrlParams.get('msgseq');
request_seq = msgseq ?? '';
if (groupcode === groupInvite.groupUin.toString() && receiveruin === this.core.selfInfo.uin) {
return true;
}
}
}
return false;
}, 1, 1000);
return new OB11GroupRequestEvent(
this.core,
+groupInvite.groupUin,
+await this.core.apis.UserApi.getUinByUidV2(groupInvite.invitorUid),
'invite',
'',
request_seq
);
}
else if (SysMessage.contentHead.type == 528 && SysMessage.contentHead.subType == 39 && SysMessage.body?.msgContent) {
return await this.obContext.apis.UserApi.parseLikeEvent(SysMessage.body?.msgContent);
}
}

View File

@@ -18,8 +18,8 @@ import { ContextMode, createContext, normalize } from '@/onebot/action/msg/SendM
import { isNull } from '@/common/helper';
export class OneBotQuickActionApi {
private obContext: NapCatOneBot11Adapter;
private core: NapCatCore;
obContext: NapCatOneBot11Adapter;
core: NapCatCore;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore) {
this.obContext = obContext;
this.core = core;
@@ -91,7 +91,7 @@ export class OneBotQuickActionApi {
}
async handleGroupRequest(request: OB11GroupRequestEvent, quickAction: QuickActionGroupRequest) {
let noify = await this.findNotify(request.flag);
const noify = await this.findNotify(request.flag);
if (!isNull(quickAction.approve) && noify) {
this.core.apis.GroupApi.handleGroupRequest(

View File

@@ -38,6 +38,14 @@ export interface AdapterConfig extends AdapterConfigInner {
const createDefaultAdapterConfig = <T extends AdapterConfig>(config: T): T => config;
export interface PluginConfig extends AdapterConfig {
name: string;
enable: boolean;
messagePostFormat: string;
reportSelfMessage: boolean;
debug: boolean;
}
export const httpServerDefaultConfigs = createDefaultAdapterConfig({
name: 'http-server',
enable: false as boolean,
@@ -128,7 +136,7 @@ export const mergeNetworkDefaultConfig = {
websocketClients: websocketClientDefaultConfigs,
} as const;
export type NetworkConfigAdapter = HttpServerConfig | HttpClientConfig | WebsocketServerConfig | WebsocketClientConfig | AdapterConfig;
export type NetworkConfigAdapter = HttpServerConfig | HttpClientConfig | WebsocketServerConfig | WebsocketClientConfig | PluginConfig;
type NetworkConfigKeys = keyof typeof mergeNetworkDefaultConfig;
export function mergeOneBotConfigs(
@@ -234,4 +242,4 @@ export function getConfigBoolKey(
}
});
return result;
}
}

View File

@@ -10,12 +10,14 @@ class OB11PokeEvent extends OB11BaseNoticeEvent {
export class OB11FriendPokeEvent extends OB11PokeEvent {
raw_info: any;
sender_id: number;
//raw_message nb等框架标准为string
constructor(core: NapCatCore, user_id: number, target_id: number, raw_message: any) {
constructor(core: NapCatCore, user_id: number, sender_id: number, target_id: number, raw_message: any) {
super(core);
this.target_id = target_id;
this.user_id = user_id;
this.sender_id = sender_id;
this.raw_info = raw_message;
}
}

View File

@@ -16,7 +16,6 @@ import {
} from '@/core';
import { OB11ConfigLoader } from '@/onebot/config';
import {
IOB11NetworkAdapter,
OB11ActiveHttpAdapter,
OB11ActiveWebSocketAdapter,
OB11NetworkManager,
@@ -31,7 +30,6 @@ import {
OneBotMsgApi,
OneBotQuickActionApi,
OneBotUserApi,
StableOneBotApiWrapper,
} from '@/onebot/api';
import { ActionMap, createActionMap } from '@/onebot/action';
import { WebUiDataRuntime } from '@/webui/src/helper/Data';
@@ -45,9 +43,16 @@ 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 { AdapterConfigWrap, mergeOneBotConfigs, migrateOneBotConfigsV1, NetworkConfigAdapter, OneBotConfig } from './config/config';
import {
AdapterConfigWrap,
mergeOneBotConfigs,
migrateOneBotConfigsV1,
NetworkConfigAdapter,
OneBotConfig,
} from './config/config';
import { OB11Message } from './types';
import { OB11PluginAdapter } from './network/plugin';
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
//OneBot实现类
export class NapCatOneBot11Adapter {
@@ -55,7 +60,7 @@ export class NapCatOneBot11Adapter {
readonly context: InstanceContext;
configLoader: OB11ConfigLoader;
public readonly apis: StableOneBotApiWrapper;
public readonly apis;
networkManager: OB11NetworkManager;
actions: ActionMap;
private readonly bootTime = Date.now() / 1000;
@@ -72,7 +77,7 @@ export class NapCatOneBot11Adapter {
UserApi: new OneBotUserApi(this, core),
FriendApi: new OneBotFriendApi(this, core),
MsgApi: new OneBotMsgApi(this, core),
QuickActionApi: new OneBotQuickActionApi(this, core),
QuickActionApi: new OneBotQuickActionApi(this, core)
} as const;
this.actions = createActionMap(this, core);
this.networkManager = new OB11NetworkManager();
@@ -111,12 +116,12 @@ export class NapCatOneBot11Adapter {
// 注册Plugin 如果需要基于NapCat进行快速开发
// this.networkManager.registerAdapter(
// new OB11PluginAdapter('plugin', this.core, this,this.actions)
// new OB11PluginAdapter('myPlugin', this.core, this,this.actions)
// );
for (const key of ob11Config.network.httpServers) {
if (key.enable) {
this.networkManager.registerAdapter(
new OB11PassiveHttpAdapter(key.name, key, this.core, this.actions)
new OB11PassiveHttpAdapter(key.name, key, this.core, this, this.actions)
);
}
}
@@ -134,6 +139,7 @@ export class NapCatOneBot11Adapter {
key.name,
key,
this.core,
this,
this.actions
)
);
@@ -146,6 +152,7 @@ export class NapCatOneBot11Adapter {
key.name,
key,
this.core,
this,
this.actions
)
);
@@ -157,9 +164,9 @@ export class NapCatOneBot11Adapter {
this.initBuddyListener();
this.initGroupListener();
await WebUiDataRuntime.setQQLoginUin(selfInfo.uin.toString());
await WebUiDataRuntime.setQQLoginStatus(true);
await WebUiDataRuntime.setOnOB11ConfigChanged(async (newConfig) => {
WebUiDataRuntime.setQQLoginInfo(selfInfo);
WebUiDataRuntime.setQQLoginStatus(true);
WebUiDataRuntime.setOnOB11ConfigChanged(async (newConfig) => {
const prev = this.configLoader.configData;
this.configLoader.save(newConfig);
this.context.logger.log(`OneBot11 配置更改:${JSON.stringify(prev)} -> ${JSON.stringify(newConfig)}`);
@@ -192,10 +199,12 @@ export class NapCatOneBot11Adapter {
await this.handleConfigChange(prev.network.websocketClients, now.network.websocketClients, OB11ActiveWebSocketAdapter);
}
private async handleConfigChange(
private async handleConfigChange<CT extends NetworkConfigAdapter>(
prevConfig: NetworkConfigAdapter[],
nowConfig: NetworkConfigAdapter[],
adapterClass: new (...args: any[]) => IOB11NetworkAdapter
adapterClass: new (
...args: ConstructorParameters<typeof IOB11NetworkAdapter<CT>>
) => IOB11NetworkAdapter<CT>
): Promise<void> {
// 比较旧的在新的找不到的回收
for (const adapterConfig of prevConfig) {
@@ -207,7 +216,7 @@ export class NapCatOneBot11Adapter {
}
}
}
// 通知新配置重载 删除关闭的 加入新开的
// 通知新配置重载 删除关闭的 加入新开的
for (const adapterConfig of nowConfig) {
const existingAdapter = this.networkManager.findSomeAdapter(adapterConfig.name);
if (existingAdapter) {
@@ -216,7 +225,7 @@ export class NapCatOneBot11Adapter {
await this.networkManager.closeSomeAdaterWhenOpen([existingAdapter]);
}
} else if (adapterConfig.enable) {
const newAdapter = new adapterClass(adapterConfig.name, adapterConfig, this.core, this.actions);
const newAdapter = new adapterClass(adapterConfig.name, adapterConfig as CT, this.core, this, this.actions);
await this.networkManager.registerAdapterAndOpen(newAdapter);
}
}
@@ -301,7 +310,7 @@ export class NapCatOneBot11Adapter {
guildId: ''
};
const msg = (await this.core.apis.MsgApi.queryMsgsWithFilterExWithSeq(peer, msgSeq)).msgList.find(e => e.msgType == NTMsgType.KMSGTYPEGRAYTIPS);
const element = msg?.elements[0];
const element = msg?.elements.find(e => !!e.grayTipElement?.revokeElement);
if (msg && element) {
const recallEvent = await this.emitRecallMsg(msg, element);
try {
@@ -458,6 +467,10 @@ export class NapCatOneBot11Adapter {
}
private async handleMsg(message: RawMessage, network: Array<AdapterConfigWrap>) {
// 过滤无效消息
if (message.msgType === NTMsgType.KMSGTYPENULL) {
return;
}
try {
const ob11Msg = await this.apis.MsgApi.parseMessageV2(message, this.configLoader.configData.parseMultMsg);
if (ob11Msg) {

View File

@@ -1,27 +1,18 @@
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
import { OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
import { createHmac } from 'crypto';
import { LogWrapper } from '@/common/log';
import { QuickAction, QuickActionEvent } from '@/onebot/types';
import { NapCatCore } from '@/core';
import { NapCatOneBot11Adapter } from '..';
import { RequestUtil } from '@/common/request';
import { HttpClientConfig } from '@/onebot/config/config';
import { ActionMap } from '@/onebot/action';
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
logger: LogWrapper;
isEnable: boolean = false;
config: HttpClientConfig;
export class OB11ActiveHttpAdapter extends IOB11NetworkAdapter<HttpClientConfig> {
constructor(
public name: string,
config: HttpClientConfig,
public core: NapCatCore,
public obContext: NapCatOneBot11Adapter,
public actions: ActionMap,
name: string, config: HttpClientConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
) {
this.logger = core.context.logger;
this.config = structuredClone(config);
super(name, config, core, obContext, actions);
}
onEvent<T extends OB11EmitEventContent>(event: T) {
@@ -30,7 +21,6 @@ export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
async emitEventAsync<T extends OB11EmitEventContent>(event: T) {
if (!this.isEnable) return;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
'x-self-id': this.core.selfInfo.uin,
@@ -44,7 +34,8 @@ export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
}
const data = await RequestUtil.HttpGetText(this.config.url, 'POST', msgStr, headers);
const resJson: QuickAction = JSON.parse(data);
const resJson: QuickAction = data ? JSON.parse(data) : {};
await this.obContext.apis.QuickActionApi.handleQuickOperation(event as QuickActionEvent, resJson);
}
@@ -75,4 +66,4 @@ export class OB11ActiveHttpAdapter implements IOB11NetworkAdapter {
return OB11NetworkReloadType.Normal;
}
}
}

View File

@@ -1,29 +1,21 @@
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
import { OB11EmitEventContent, OB11NetworkReloadType } from '@/onebot/network/index';
import { WebSocket } from 'ws';
import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent';
import { NapCatCore } from '@/core';
import { ActionName } from '@/onebot/action/router';
import { OB11Response } from '@/onebot/action/OneBotAction';
import { LogWrapper } from '@/common/log';
import { ActionMap } from '@/onebot/action';
import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent';
import { WebsocketClientConfig } from '@/onebot/config/config';
import { NapCatOneBot11Adapter } from "@/onebot";
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
isEnable: boolean = false;
logger: LogWrapper;
export class OB11ActiveWebSocketAdapter extends IOB11NetworkAdapter<WebsocketClientConfig> {
private connection: WebSocket | null = null;
private heartbeatRef: NodeJS.Timeout | null = null;
public config: WebsocketClientConfig;
constructor(
public name: string,
confg: WebsocketClientConfig,
public core: NapCatCore,
public actions: ActionMap,
) {
this.logger = core.context.logger;
this.config = structuredClone(confg);
constructor(name: string, config: WebsocketClientConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
super(name, config, core, obContext, actions);
}
onEvent<T extends OB11EmitEventContent>(event: T) {
@@ -133,7 +125,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
}
private async handleMessage(message: any) {
let receiveData: { action: ActionName, params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
let receiveData: { action: typeof ActionName[keyof typeof ActionName], params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
let echo = undefined;
try {
@@ -145,7 +137,7 @@ export class OB11ActiveWebSocketAdapter implements IOB11NetworkAdapter {
return;
}
receiveData.params = (receiveData?.params) ? receiveData.params : {};// 兼容类型验证
const action = this.actions.get(receiveData.action);
const action = this.actions.get(receiveData.action as any);
if (!action) {
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的Api ' + receiveData.action);
this.checkStateAndReply<any>(OB11Response.error('不支持的Api ' + receiveData.action, 1404, echo));

View File

@@ -0,0 +1,33 @@
import { NetworkConfigAdapter } from "@/onebot/config/config";
import { LogWrapper } from "@/common/log";
import { NapCatCore } from "@/core";
import { NapCatOneBot11Adapter } from "@/onebot";
import { ActionMap } from "@/onebot/action";
import { OB11EmitEventContent, OB11NetworkReloadType } from "@/onebot/network/index";
export abstract class IOB11NetworkAdapter<CT extends NetworkConfigAdapter> {
name: string;
isEnable: boolean = false;
config: CT;
readonly logger: LogWrapper;
readonly core: NapCatCore;
readonly obContext: NapCatOneBot11Adapter;
readonly actions: ActionMap;
constructor(name: string, config: CT, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
this.name = name;
this.config = structuredClone(config);
this.core = core;
this.obContext = obContext;
this.actions = actions;
this.logger = core.context.logger;
}
abstract onEvent<T extends OB11EmitEventContent>(event: T): void;
abstract open(): void | Promise<void>;
abstract close(): void | Promise<void>;
abstract reload(config: any): OB11NetworkReloadType | Promise<OB11NetworkReloadType>;
}

View File

@@ -1,7 +1,7 @@
import { OneBotEvent } from '@/onebot/event/OneBotEvent';
import { OB11Message } from '@/onebot';
import { ActionMap } from '@/onebot/action';
import { NetworkConfigAdapter } from '@/onebot/config/config';
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export type OB11EmitEventContent = OneBotEvent | OB11Message;
export enum OB11NetworkReloadType {
@@ -11,23 +11,9 @@ export enum OB11NetworkReloadType {
NetWorkClose = 3,
NetWorkOpen = 4
}
export interface IOB11NetworkAdapter {
actions: ActionMap;
name: string;
isEnable: boolean;
config: NetworkConfigAdapter;
onEvent<T extends OB11EmitEventContent>(event: T): void;
open(): void | Promise<void>;
close(): void | Promise<void>;
reload(config: any): OB11NetworkReloadType | Promise<OB11NetworkReloadType>;
}
export class OB11NetworkManager {
adapters: Map<string, IOB11NetworkAdapter> = new Map();
adapters: Map<string, IOB11NetworkAdapter<NetworkConfigAdapter>> = new Map();
async openAllAdapters() {
return Promise.all(Array.from(this.adapters.values()).map(adapter => adapter.open()));
@@ -63,22 +49,22 @@ export class OB11NetworkManager {
}));
}
registerAdapter(adapter: IOB11NetworkAdapter) {
registerAdapter<CT extends NetworkConfigAdapter>(adapter: IOB11NetworkAdapter<CT>) {
this.adapters.set(adapter.name, adapter);
}
async registerAdapterAndOpen(adapter: IOB11NetworkAdapter) {
async registerAdapterAndOpen<CT extends NetworkConfigAdapter>(adapter: IOB11NetworkAdapter<CT>) {
this.registerAdapter(adapter);
await adapter.open();
}
async closeSomeAdapters(adaptersToClose: IOB11NetworkAdapter[]) {
async closeSomeAdapters<CT extends NetworkConfigAdapter>(adaptersToClose: IOB11NetworkAdapter<CT>[]) {
for (const adapter of adaptersToClose) {
this.adapters.delete(adapter.name);
await adapter.close();
}
}
async closeSomeAdaterWhenOpen(adaptersToClose: IOB11NetworkAdapter[]) {
async closeSomeAdaterWhenOpen<CT extends NetworkConfigAdapter>(adaptersToClose: IOB11NetworkAdapter<CT>[]) {
for (const adapter of adaptersToClose) {
this.adapters.delete(adapter.name);
if (adapter.isEnable) {
@@ -91,7 +77,7 @@ export class OB11NetworkManager {
return this.adapters.get(name);
}
async closeAdapterByPredicate(closeFilter: (adapter: IOB11NetworkAdapter) => boolean) {
async closeAdapterByPredicate(closeFilter: (adapter: IOB11NetworkAdapter<NetworkConfigAdapter>) => boolean) {
const adaptersToClose = Array.from(this.adapters.values()).filter(closeFilter);
await this.closeSomeAdapters(adaptersToClose);
}
@@ -118,4 +104,4 @@ export class OB11NetworkManager {
export * from './active-http';
export * from './active-websocket';
export * from './passive-http';
export * from './passive-websocket';
export * from './passive-websocket';

View File

@@ -1,4 +1,4 @@
import { IOB11NetworkAdapter, OB11NetworkReloadType } from './index';
import { OB11NetworkReloadType } from './index';
import express, { Express, Request, Response } from 'express';
import http from 'http';
import { NapCatCore } from '@/core';
@@ -6,20 +6,15 @@ import { OB11Response } from '@/onebot/action/OneBotAction';
import { ActionMap } from '@/onebot/action';
import cors from 'cors';
import { HttpServerConfig } from '@/onebot/config/config';
import { NapCatOneBot11Adapter } from "@/onebot";
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11PassiveHttpAdapter implements IOB11NetworkAdapter {
export class OB11PassiveHttpAdapter extends IOB11NetworkAdapter<HttpServerConfig> {
private app: Express | undefined;
private server: http.Server | undefined;
isEnable: boolean = false;
public config: HttpServerConfig;
constructor(
public name: string,
config: HttpServerConfig,
public core: NapCatCore,
public actions: ActionMap,
) {
this.config = structuredClone(config);
constructor(name: string, config: HttpServerConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap) {
super(name, config, core, obContext, actions);
}
onEvent() {

View File

@@ -1,36 +1,29 @@
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from './index';
import { OB11EmitEventContent, OB11NetworkReloadType } from './index';
import urlParse from 'url';
import { WebSocket, WebSocketServer } from 'ws';
import { Mutex } from 'async-mutex';
import { OB11Response } from '@/onebot/action/OneBotAction';
import { ActionName } from '@/onebot/action/router';
import { NapCatCore } from '@/core';
import { LogWrapper } from '@/common/log';
import { OB11HeartbeatEvent } from '@/onebot/event/meta/OB11HeartbeatEvent';
import { IncomingMessage } from 'http';
import { ActionMap } from '@/onebot/action';
import { LifeCycleSubType, OB11LifeCycleEvent } from '@/onebot/event/meta/OB11LifeCycleEvent';
import { WebsocketServerConfig } from '@/onebot/config/config';
import { NapCatOneBot11Adapter } from "@/onebot";
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
export class OB11PassiveWebSocketAdapter extends IOB11NetworkAdapter<WebsocketServerConfig> {
wsServer: WebSocketServer;
wsClients: WebSocket[] = [];
wsClientsMutex = new Mutex();
isEnable: boolean = false;
heartbeatInterval: number = 0;
logger: LogWrapper;
public config: WebsocketServerConfig;
private heartbeatIntervalId: NodeJS.Timeout | null = null;
wsClientWithEvent: WebSocket[] = [];
constructor(
public name: string,
config: WebsocketServerConfig,
public core: NapCatCore,
public actions: ActionMap,
name: string, config: WebsocketServerConfig, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
) {
this.config = structuredClone(config);
this.logger = core.context.logger;
super(name, config, core, obContext, actions);
this.wsServer = new WebSocketServer({
port: this.config.port,
host: this.config.host === '0.0.0.0' ? '' : this.config.host,
@@ -106,7 +99,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
this.logger.log('[OneBot] [WebSocket Server] Server Started', typeof (addressInfo) === 'string' ? addressInfo : addressInfo?.address + ':' + addressInfo?.port);
this.isEnable = true;
if (this.heartbeatInterval > 0) {
if (this.config.heartInterval > 0) {
this.registerHeartBeat();
}
@@ -140,11 +133,11 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
this.wsClientsMutex.runExclusive(async () => {
this.wsClientWithEvent.forEach((wsClient) => {
if (wsClient.readyState === WebSocket.OPEN) {
wsClient.send(JSON.stringify(new OB11HeartbeatEvent(this.core, this.heartbeatInterval, this.core.selfInfo.online ?? true, true)));
wsClient.send(JSON.stringify(new OB11HeartbeatEvent(this.core, this.config.heartInterval, this.core.selfInfo.online ?? true, true)));
}
});
});
}, this.heartbeatInterval);
}, this.config.heartInterval);
}
private authorize(token: string | undefined, wsClient: WebSocket, wsReq: IncomingMessage) {
@@ -166,7 +159,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
}
private async handleMessage(wsClient: WebSocket, message: any) {
let receiveData: { action: ActionName, params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
let receiveData: { action: typeof ActionName[keyof typeof ActionName], params?: any, echo?: any } = { action: ActionName.Unknown, params: {} };
let echo = undefined;
try {
receiveData = JSON.parse(message.toString());
@@ -177,7 +170,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
return;
}
receiveData.params = (receiveData?.params) ? receiveData.params : {};//兼容类型验证 不然类型校验爆炸
const action = this.actions.get(receiveData.action);
const action = this.actions.get(receiveData.action as any);
if (!action) {
this.logger.logError('[OneBot] [WebSocket Client] 发生错误', '不支持的API ' + receiveData.action);
this.checkStateAndReply<any>(OB11Response.error('不支持的API ' + receiveData.action, 1404, echo), wsClient);
@@ -191,7 +184,7 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
const wasEnabled = this.isEnable;
const oldPort = this.config.port;
const oldHost = this.config.host;
const oldHeartbeatInterval = this.heartbeatInterval;
const oldHeartbeatInterval = this.config.heartInterval;
this.config = newConfig;
if (newConfig.enable && !wasEnabled) {
@@ -220,7 +213,6 @@ export class OB11PassiveWebSocketAdapter implements IOB11NetworkAdapter {
clearInterval(this.heartbeatIntervalId);
this.heartbeatIntervalId = null;
}
this.heartbeatInterval = newConfig.heartInterval;
if (newConfig.heartInterval > 0 && this.isEnable) {
this.registerHeartBeat();
}

View File

@@ -1,42 +1,37 @@
import { IOB11NetworkAdapter, OB11EmitEventContent, OB11NetworkReloadType } from './index';
import { OB11EmitEventContent, OB11NetworkReloadType } from './index';
import { NapCatOneBot11Adapter, OB11Message } from '@/onebot';
import { NapCatCore } from '@/core';
import { AdapterConfig } from '../config/config';
import { PluginConfig } from '../config/config';
import { plugin_onmessage } from '@/plugin';
import { ActionMap } from '../action';
import { IOB11NetworkAdapter } from "@/onebot/network/adapter";
export class OB11PluginAdapter implements IOB11NetworkAdapter {
isEnable: boolean = true;
public config: AdapterConfig;
export class OB11PluginAdapter extends IOB11NetworkAdapter<PluginConfig> {
constructor(
public name: string,
public core: NapCatCore,
public obCore: NapCatOneBot11Adapter,
public actions: ActionMap,
name: string, core: NapCatCore, obContext: NapCatOneBot11Adapter, actions: ActionMap
) {
// 基础配置
this.config = {
const config = {
name: name,
messagePostFormat: 'array',
reportSelfMessage: false,
enable: true,
debug: false,
}
};
super(name, config, core, obContext, actions);
}
onEvent<T extends OB11EmitEventContent>(event: T) {
if (event.post_type === 'message') {
plugin_onmessage(this.config.name, this.core, this.obCore, event as OB11Message,this.actions).then().catch();
plugin_onmessage(this.config.name, this.core, this.obContext, event as OB11Message,this.actions).then().catch();
}
}
open() {
this.isEnable = true;
}
async close() {
this.isEnable = false;
}
async reload() {

View File

@@ -1,10 +1,10 @@
import { NapCatOneBot11Adapter, OB11Message } from "@/onebot";
import { NapCatCore } from "../core";
import { NapCatCore } from "@/core";
import { ActionMap } from "@/onebot/action";
export const plugin_onmessage = async (adapter: string, core: NapCatCore, obCore: NapCatOneBot11Adapter, message: OB11Message, action: ActionMap) => {
export const plugin_onmessage = async (adapter: string, core: NapCatCore, obCtx: NapCatOneBot11Adapter, message: OB11Message, action: ActionMap) => {
if (message.raw_message === 'ping') {
const ret = await action.get('send_group_msg')?.handle({ group_id: String(message.group_id), message: 'pong' }, adapter);
console.log(ret);
}
}
};

View File

@@ -175,7 +175,9 @@ async function handleLogin(
loginService.getLoginList().then((res) => {
// 遍历 res.LocalLoginInfoList[x].isQuickLogin是否可以 res.LocalLoginInfoList[x].uin 转为string 加入string[] 最后遍历完成调用WebUiDataRuntime.setQQQuickLoginList
WebUiDataRuntime.setQQQuickLoginList(res.LocalLoginInfoList.filter((item) => item.isQuickLogin).map((item) => item.uin.toString()));
const list = res.LocalLoginInfoList.filter((item) => item.isQuickLogin);
WebUiDataRuntime.setQQQuickLoginList(list.map((item) => item.uin.toString()));
WebUiDataRuntime.setQQNewLoginList(list);
});
WebUiDataRuntime.setQuickLoginCall(async (uin: string) => {
@@ -285,7 +287,7 @@ export async function NCoreInitShell() {
await initializeEngine(engine, basicInfoWrapper, dataPathGlobal, systemPlatform, systemVersion);
await initializeLoginService(loginService, basicInfoWrapper, dataPathGlobal, systemVersion, hostname);
program.option('-q, --qq [number]', 'QQ号').parse(process.argv);
const cmdOptions = program.opts();
const quickLoginUin = cmdOptions.qq;

View File

@@ -18,7 +18,7 @@ export const LoginHandler: RequestHandler = async (req, res) => {
return sendError(res, 'token is empty');
}
// 检查登录频率
if (!(await WebUiDataRuntime.checkLoginRate(WebUiConfigData.loginRate))) {
if (!WebUiDataRuntime.checkLoginRate(WebUiConfigData.loginRate)) {
return sendError(res, 'login rate limit');
}
//验证config.token是否等于token

View File

@@ -1,15 +1,9 @@
import { RequestHandler } from 'express';
import { WebUiDataRuntime } from '@webapi/helper/Data';
import { sendSuccess } from '@webapi/utils/response';
// TODO: Implement LogFileListHandler
export const LogFileListHandler: RequestHandler = async (_, res) => {
const fakeData = {
uin: 0,
nick: 'NapCat',
avatar: 'https://q1.qlogo.cn/g?b=qq&nk=0&s=640',
status: 'online',
boottime: Date.now(),
};
sendSuccess(res, fakeData);
export const PackageInfoHandler: RequestHandler = (_, res) => {
const data = WebUiDataRuntime.getPackageJson();
sendSuccess(res, data);
};

View File

@@ -10,15 +10,15 @@ import { sendError, sendSuccess } from '@webapi/utils/response';
import { isEmpty } from '@webapi/utils/check';
// 获取OneBot11配置
export const OB11GetConfigHandler: RequestHandler = async (_, res) => {
export const OB11GetConfigHandler: RequestHandler = (_, res) => {
// 获取QQ登录状态
const isLogin = await WebUiDataRuntime.getQQLoginStatus();
const isLogin = WebUiDataRuntime.getQQLoginStatus();
// 如果未登录,返回错误
if (!isLogin) {
return sendError(res, 'Not Login');
}
// 获取登录的QQ号
const uin = await WebUiDataRuntime.getQQLoginUin();
const uin = WebUiDataRuntime.getQQLoginUin();
// 读取配置文件
const configFilePath = resolve(webUiPathWrapper.configPath, `./onebot11_${uin}.json`);
// 尝试解析配置文件
@@ -39,7 +39,7 @@ export const OB11GetConfigHandler: RequestHandler = async (_, res) => {
// 写入OneBot11配置
export const OB11SetConfigHandler: RequestHandler = async (req, res) => {
// 获取QQ登录状态
const isLogin = await WebUiDataRuntime.getQQLoginStatus();
const isLogin = WebUiDataRuntime.getQQLoginStatus();
// 如果未登录,返回错误
if (!isLogin) {
return sendError(res, 'Not Login');

View File

@@ -7,12 +7,12 @@ import { sendError, sendSuccess } from '@webapi/utils/response';
// 获取QQ登录二维码
export const QQGetQRcodeHandler: RequestHandler = async (req, res) => {
// 判断是否已经登录
if (await WebUiDataRuntime.getQQLoginStatus()) {
if (WebUiDataRuntime.getQQLoginStatus()) {
// 已经登录
return sendError(res, 'QQ Is Logined');
}
// 获取二维码
const qrcodeUrl = await WebUiDataRuntime.getQQLoginQrcodeURL();
const qrcodeUrl = WebUiDataRuntime.getQQLoginQrcodeURL();
// 判断二维码是否为空
if (isEmpty(qrcodeUrl)) {
return sendError(res, 'QRCode Get Error');
@@ -27,8 +27,8 @@ export const QQGetQRcodeHandler: RequestHandler = async (req, res) => {
// 获取QQ登录状态
export const QQCheckLoginStatusHandler: RequestHandler = async (req, res) => {
const data = {
isLogin: await WebUiDataRuntime.getQQLoginStatus(),
qrcodeurl: await WebUiDataRuntime.getQQLoginQrcodeURL(),
isLogin: WebUiDataRuntime.getQQLoginStatus(),
qrcodeurl: WebUiDataRuntime.getQQLoginQrcodeURL(),
};
return sendSuccess(res, data);
};
@@ -38,7 +38,7 @@ export const QQSetQuickLoginHandler: RequestHandler = async (req, res) => {
// 获取QQ号
const { uin } = req.body;
// 判断是否已经登录
const isLogin = await WebUiDataRuntime.getQQLoginStatus();
const isLogin = WebUiDataRuntime.getQQLoginStatus();
if (isLogin) {
return sendError(res, 'QQ Is Logined');
}
@@ -53,12 +53,24 @@ export const QQSetQuickLoginHandler: RequestHandler = async (req, res) => {
return sendError(res, message);
}
//本来应该验证 但是http不宜这么搞 建议前端验证
//isLogin = await WebUiDataRuntime.getQQLoginStatus();
//isLogin = WebUiDataRuntime.getQQLoginStatus();
return sendSuccess(res, null);
};
// 获取快速登录列表
export const QQGetQuickLoginListHandler: RequestHandler = async (_, res) => {
const quickLoginList = await WebUiDataRuntime.getQQQuickLoginList();
const quickLoginList = WebUiDataRuntime.getQQQuickLoginList();
return sendSuccess(res, quickLoginList);
};
// 获取快速登录列表(新)
export const QQGetLoginListNewHandler: RequestHandler = async (_, res) => {
const newLoginList = WebUiDataRuntime.getQQNewLoginList();
return sendSuccess(res, newLoginList);
};
// 获取登录的QQ的信息
export const getQQLoginInfoHandler: RequestHandler = async (_, res) => {
const data = WebUiDataRuntime.getQQLoginInfo();
return sendSuccess(res, data);
};

View File

@@ -1,11 +1,16 @@
import { OneBotConfig } from '@/onebot/config/config';
import type { LoginRuntimeType } from '../types/data';
import packageJson from '../../../../package.json';
const LoginRuntime: LoginRuntimeType = {
LoginCurrentTime: Date.now(),
LoginCurrentRate: 0,
QQLoginStatus: false, //已实现 但太傻了 得去那边注册个回调刷新
QQQRCodeURL: '',
QQLoginUin: '',
QQLoginInfo: {
uid: '',
uin: '',
nick: '',
},
NapCatHelper: {
onOB11ConfigChanged: async () => {
return;
@@ -14,11 +19,13 @@ const LoginRuntime: LoginRuntimeType = {
return { result: false, message: '' };
},
QQLoginList: [],
NewQQLoginList: [],
},
packageJson: packageJson,
};
export const WebUiDataRuntime = {
checkLoginRate: async function (RateLimit: number): Promise<boolean> {
checkLoginRate(RateLimit: number): boolean {
LoginRuntime.LoginCurrentRate++;
//console.log(RateLimit, LoginRuntime.LoginCurrentRate, Date.now() - LoginRuntime.LoginCurrentTime);
if (Date.now() - LoginRuntime.LoginCurrentTime > 1000 * 60) {
@@ -29,51 +36,68 @@ export const WebUiDataRuntime = {
return LoginRuntime.LoginCurrentRate <= RateLimit;
},
getQQLoginStatus: async function (): Promise<boolean> {
getQQLoginStatus(): LoginRuntimeType['QQLoginStatus'] {
return LoginRuntime.QQLoginStatus;
},
setQQLoginStatus: async function (status: boolean): Promise<void> {
setQQLoginStatus(status: LoginRuntimeType['QQLoginStatus']): void {
LoginRuntime.QQLoginStatus = status;
},
setQQLoginQrcodeURL: async function (url: string): Promise<void> {
setQQLoginQrcodeURL(url: LoginRuntimeType['QQQRCodeURL']): void {
LoginRuntime.QQQRCodeURL = url;
},
getQQLoginQrcodeURL: async function (): Promise<string> {
getQQLoginQrcodeURL(): LoginRuntimeType['QQQRCodeURL'] {
return LoginRuntime.QQQRCodeURL;
},
setQQLoginUin: async function (uin: string): Promise<void> {
LoginRuntime.QQLoginUin = uin;
setQQLoginInfo(info: LoginRuntimeType['QQLoginInfo']): void {
LoginRuntime.QQLoginInfo = info;
LoginRuntime.QQLoginUin = info.uin.toString();
},
getQQLoginUin: async function (): Promise<string> {
getQQLoginInfo(): LoginRuntimeType['QQLoginInfo'] {
return LoginRuntime.QQLoginInfo;
},
getQQLoginUin(): LoginRuntimeType['QQLoginUin'] {
return LoginRuntime.QQLoginUin;
},
getQQQuickLoginList: async function (): Promise<any[]> {
getQQQuickLoginList(): LoginRuntimeType['NapCatHelper']['QQLoginList'] {
return LoginRuntime.NapCatHelper.QQLoginList;
},
setQQQuickLoginList: async function (list: string[]): Promise<void> {
setQQQuickLoginList(list: LoginRuntimeType['NapCatHelper']['QQLoginList']): void {
LoginRuntime.NapCatHelper.QQLoginList = list;
},
setQuickLoginCall(func: (uin: string) => Promise<{ result: boolean; message: string }>): void {
getQQNewLoginList(): LoginRuntimeType['NapCatHelper']['NewQQLoginList'] {
return LoginRuntime.NapCatHelper.NewQQLoginList;
},
setQQNewLoginList(list: LoginRuntimeType['NapCatHelper']['NewQQLoginList']): void {
LoginRuntime.NapCatHelper.NewQQLoginList = list;
},
setQuickLoginCall(func: LoginRuntimeType['NapCatHelper']['onQuickLoginRequested']): void {
LoginRuntime.NapCatHelper.onQuickLoginRequested = func;
},
requestQuickLogin: async function (uin: string): Promise<{ result: boolean; message: string }> {
return await LoginRuntime.NapCatHelper.onQuickLoginRequested(uin);
},
requestQuickLogin: function (uin) {
return LoginRuntime.NapCatHelper.onQuickLoginRequested(uin);
} as LoginRuntimeType['NapCatHelper']['onQuickLoginRequested'],
setOnOB11ConfigChanged: async function (func: (ob11: OneBotConfig) => Promise<void>): Promise<void> {
setOnOB11ConfigChanged(func: LoginRuntimeType['NapCatHelper']['onOB11ConfigChanged']): void {
LoginRuntime.NapCatHelper.onOB11ConfigChanged = func;
},
setOB11Config: async function (ob11: OneBotConfig): Promise<void> {
await LoginRuntime.NapCatHelper.onOB11ConfigChanged(ob11);
setOB11Config: function (ob11) {
return LoginRuntime.NapCatHelper.onOB11ConfigChanged(ob11);
} as LoginRuntimeType['NapCatHelper']['onOB11ConfigChanged'],
getPackageJson() {
return LoginRuntime.packageJson;
},
};

View File

@@ -0,0 +1,8 @@
import { Router } from 'express';
import { PackageInfoHandler } from '../api/BaseInfo';
const router = Router();
// router: 获取nc的package.json信息
router.get('/PackageInfo', PackageInfoHandler);
export { router as BaseRouter };

View File

@@ -5,16 +5,22 @@ import {
QQGetQRcodeHandler,
QQGetQuickLoginListHandler,
QQSetQuickLoginHandler,
QQGetLoginListNewHandler,
getQQLoginInfoHandler,
} from '@webapi/api/QQLogin';
const router = Router();
// router:获取快速登录列表
router.all('/GetQuickLoginList', QQGetQuickLoginListHandler);
// router:获取快速登录列表(新)
router.all('/GetQuickLoginListNew', QQGetLoginListNewHandler);
// router:检查QQ登录状态
router.post('/CheckLoginStatus', QQCheckLoginStatusHandler);
// router:获取QQ登录二维码
router.post('/GetQQLoginQrcode', QQGetQRcodeHandler);
// router:设置QQ快速登录
router.post('/SetQuickLogin', QQSetQuickLoginHandler);
// router:获取QQ登录信息
router.post('/GetQQLoginInfo', getQQLoginInfoHandler);
export { router as QQLoginRouter };

View File

@@ -11,6 +11,7 @@ import { sendSuccess } from '@webapi/utils/response';
import { QQLoginRouter } from '@webapi/router/QQLogin';
import { AuthRouter } from '@webapi/router/auth';
import { LogRouter } from '@webapi/router/Log';
import { BaseRouter } from '@webapi/router/Base';
const router = Router();
@@ -21,6 +22,8 @@ router.use(auth);
router.all('/test', (_, res) => {
return sendSuccess(res);
});
// router:基础信息相关路由
router.use('/base', BaseRouter);
// router:WebUI登录相关路由
router.use('/auth', AuthRouter);
// router:QQ登录相关路由

View File

@@ -1,12 +1,17 @@
import type { LoginListItem, SelfInfo } from '@/core';
interface LoginRuntimeType {
LoginCurrentTime: number;
LoginCurrentRate: number;
QQLoginStatus: boolean;
QQQRCodeURL: string;
QQLoginUin: string;
QQLoginInfo: SelfInfo;
NapCatHelper: {
onQuickLoginRequested: (uin: string) => Promise<{ result: boolean; message: string }>;
onOB11ConfigChanged: (ob11: OneBotConfig) => Promise<void>;
QQLoginList: string[];
NewQQLoginList: LoginListItem[];
};
packageJson: object;
}