Compare commits

...

13 Commits

Author SHA1 Message Date
pk5ls20
e7222653fa release: 3.0.6 2024-10-20 23:54:21 +08:00
pk5ls20
014f0758f5 chore: 部分回滚 https://github.com/NapNeko/NapCatQQ/commit/bb72d70b 2024-10-20 23:52:36 +08:00
pk5ls20
0e8b416f6d Merge pull request #448 from pk5ls20/feat/friend-poke
feat: add `friend_poke` OneBot11 API
2024-10-20 23:18:26 +08:00
pk5ls20
09a60a2204 feat: add friend_poke OneBot11 API 2024-10-20 23:09:38 +08:00
手瓜一十雪
b0eae307c2 release: 3.0.5 2024-10-20 22:18:57 +08:00
手瓜一十雪
f5d2b54cca fix: 兼容晚启动 2024-10-20 22:18:34 +08:00
手瓜一十雪
3eefec3899 release: v3.0.4 2024-10-20 19:52:23 +08:00
手瓜一十雪
b6a8094554 release: v3.0.3 2024-10-20 18:56:52 +08:00
Version
4083b35436 chore:version change 2024-10-20 10:55:12 +00:00
手瓜一十雪
bb72d70baf fix: #444 尝试修复 2024-10-20 18:52:18 +08:00
手瓜一十雪
95d1a77f52 fix: remark 2024-10-20 18:30:14 +08:00
手瓜一十雪
051729886e fix 2024-10-20 17:16:05 +08:00
手瓜一十雪
0f00123dc7 fix 2024-10-20 17:01:09 +08:00
17 changed files with 86 additions and 42 deletions

View File

@@ -23,4 +23,4 @@
"isByteCodeShell": true, "isByteCodeShell": true,
"platform": "win32", "platform": "win32",
"eleArch": "x64" "eleArch": "x64"
} }

View File

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

View File

@@ -2,7 +2,7 @@
"name": "napcat", "name": "napcat",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "3.0.1", "version": "3.0.6",
"scripts": { "scripts": {
"build:framework": "vite build --mode framework", "build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell", "build:shell": "vite build --mode shell",
@@ -49,4 +49,4 @@
"silk-wasm": "^3.6.1", "silk-wasm": "^3.6.1",
"ws": "^8.18.0" "ws": "^8.18.0"
} }
} }

View File

@@ -1 +1 @@
export const napCatVersion = '3.0.1'; export const napCatVersion = '3.0.6';

View File

@@ -11,7 +11,7 @@ export class NTQQFriendApi {
this.core = core; this.core = core;
} }
async setBuddyRemark(uid: string, remark: string) { async setBuddyRemark(uid: string, remark: string) {
return this.context.session.getBuddyService().setBuddyRemark(uid, remark); return this.context.session.getBuddyService().setBuddyRemark({ uid, remark });
} }
async getBuddyV2SimpleInfoMap(refresh = false) { async getBuddyV2SimpleInfoMap(refresh = false) {
const buddyService = this.context.session.getBuddyService(); const buddyService = this.context.session.getBuddyService();

View File

@@ -1,18 +1,19 @@
import * as os from 'os'; import * as os from 'os';
import {ChatType, InstanceContext, NapCatCore} from '..'; import { ChatType, InstanceContext, NapCatCore } from '..';
import offset from '@/core/external/offset.json'; import offset from '@/core/external/offset.json';
import {PacketClient, RecvPacketData} from '@/core/packet/client'; import { PacketClient, RecvPacketData } from '@/core/packet/client';
import {PacketSession} from "@/core/packet/session"; import { PacketSession } from "@/core/packet/session";
import {PacketHexStr} from "@/core/packet/packer"; import { PacketHexStr } from "@/core/packet/packer";
import {NapProtoMsg} from '@/core/packet/proto/NapProto'; import { NapProtoMsg } from '@/core/packet/proto/NapProto';
import {OidbSvcTrpcTcp0X9067_202_Rsp_Body} from '@/core/packet/proto/oidb/Oidb.0x9067_202'; import { OidbSvcTrpcTcp0X9067_202_Rsp_Body } from '@/core/packet/proto/oidb/Oidb.0x9067_202';
import {OidbSvcTrpcTcpBase, OidbSvcTrpcTcpBaseRsp} from '@/core/packet/proto/oidb/OidbBase'; import { OidbSvcTrpcTcpBase, OidbSvcTrpcTcpBaseRsp } from '@/core/packet/proto/oidb/OidbBase';
import {OidbSvcTrpcTcp0XFE1_2RSP} from '@/core/packet/proto/oidb/Oidb.0XFE1_2'; import { OidbSvcTrpcTcp0XFE1_2RSP } from '@/core/packet/proto/oidb/Oidb.0XFE1_2';
import {LogWrapper} from "@/common/log"; import { LogWrapper } from "@/common/log";
import {SendLongMsgResp} from "@/core/packet/proto/message/action"; import { SendLongMsgResp } from "@/core/packet/proto/message/action";
import {PacketMsg} from "@/core/packet/msg/message"; import { PacketMsg } from "@/core/packet/msg/message";
import {OidbSvcTrpcTcp0x6D6Response} from "@/core/packet/proto/oidb/Oidb.0x6D6"; import { OidbSvcTrpcTcp0x6D6Response } from "@/core/packet/proto/oidb/Oidb.0x6D6";
import {PacketMsgPicElement} from "@/core/packet/msg/element"; import { PacketMsgPicElement } from "@/core/packet/msg/element";
import { c } from 'vite/dist/node/types.d-aGj9QkWt';
interface OffsetType { interface OffsetType {
[key: string]: { [key: string]: {
@@ -59,8 +60,12 @@ export class NTQQPacketApi {
if (!table) return false; if (!table) return false;
const url = 'ws://' + this.serverUrl + '/ws'; const url = 'ws://' + this.serverUrl + '/ws';
this.packetSession = new PacketSession(this.core.context.logger, new PacketClient(url, this.core)); this.packetSession = new PacketSession(this.core.context.logger, new PacketClient(url, this.core));
await this.packetSession.client.connect(); const cb = () => {
await this.packetSession.client.init(process.pid, table.recv, table.send); if (this.packetSession && this.packetSession.client) {
this.packetSession.client.init(process.pid, table.recv, table.send).then().catch(this.logger.logError.bind(this.logger));
}
}
await this.packetSession.client.connect(cb);
return true; return true;
} }
@@ -68,8 +73,8 @@ export class NTQQPacketApi {
return this.packetSession!.client.sendPacket(cmd, data, rsp); return this.packetSession!.client.sendPacket(cmd, data, rsp);
} }
async sendPokePacket(group: number, peer: number) { async sendPokePacket(peer: number, group?: number) {
const data = this.packetSession?.packer.packPokePacket(group, peer); const data = this.packetSession?.packer.packPokePacket(peer, group);
await this.sendPacket('OidbSvcTrpcTcp.0xed3_1', data!, false); await this.sendPacket('OidbSvcTrpcTcp.0xed3_1', data!, false);
} }
@@ -106,11 +111,11 @@ export class NTQQPacketApi {
await this.sendPacket('OidbSvcTrpcTcp.0x8fc_2', data!, true); await this.sendPacket('OidbSvcTrpcTcp.0x8fc_2', data!, true);
} }
private async uploadResources(msg: PacketMsg[], groupUin: number = 0){ private async uploadResources(msg: PacketMsg[], groupUin: number = 0) {
const reqList = [] const reqList = []
for (const m of msg){ for (const m of msg) {
for (const e of m.msg){ for (const e of m.msg) {
if (e instanceof PacketMsgPicElement){ if (e instanceof PacketMsgPicElement) {
reqList.push(this.packetSession?.highwaySession.uploadImage({ reqList.push(this.packetSession?.highwaySession.uploadImage({
chatType: groupUin ? ChatType.KCHATTYPEGROUP : ChatType.KCHATTYPEC2C, chatType: groupUin ? ChatType.KCHATTYPEGROUP : ChatType.KCHATTYPEC2C,
peerUid: String(groupUin) ? String(groupUin) : this.core.selfInfo.uid peerUid: String(groupUin) ? String(groupUin) : this.core.selfInfo.uid
@@ -135,7 +140,7 @@ export class NTQQPacketApi {
const ret = await this.sendPacket('OidbSvcTrpcTcp.0x6d6_2', data!, true); const ret = await this.sendPacket('OidbSvcTrpcTcp.0x6d6_2', data!, true);
const body = new NapProtoMsg(OidbSvcTrpcTcpBaseRsp).decode(Buffer.from(ret.hex_data, 'hex')).body; const body = new NapProtoMsg(OidbSvcTrpcTcpBaseRsp).decode(Buffer.from(ret.hex_data, 'hex')).body;
const resp = new NapProtoMsg(OidbSvcTrpcTcp0x6D6Response).decode(body); const resp = new NapProtoMsg(OidbSvcTrpcTcp0x6D6Response).decode(body);
if (resp.download.retCode !== 0){ if (resp.download.retCode !== 0) {
throw new Error(`sendGroupFileDownloadReq error: ${resp.download.clientWording}`); throw new Error(`sendGroupFileDownloadReq error: ${resp.download.clientWording}`);
} }
return `https://${resp.download.downloadDns}/ftn_handler/${Buffer.from(resp.download.downloadUrl).toString('hex')}/?fname=` return `https://${resp.download.downloadDns}/ftn_handler/${Buffer.from(resp.download.downloadUrl).toString('hex')}/?fname=`

View File

@@ -517,6 +517,12 @@ export enum AtType {
atAll = 1, atAll = 1,
atUser = 2 atUser = 2
} }
export enum MsgSourceType {
K_DOWN_SOURCETYPE_AIOINNER = 1,
K_DOWN_SOURCETYPE_BIGSCREEN = 2,
K_DOWN_SOURCETYPE_HISTORY = 3,
K_DOWN_SOURCETYPE_UNKNOWN = 0
}
// 来自Android分析 // 来自Android分析
export enum ChatType { export enum ChatType {
@@ -874,6 +880,8 @@ export interface RawMessage {
/** /**
* 扩展字段,与 Ob11 msg ID 有关 * 扩展字段,与 Ob11 msg ID 有关
*/ */
id?: number; id?: number;
guildId: string; guildId: string;
@@ -950,6 +958,8 @@ export interface RawMessage {
records: RawMessage[]; records: RawMessage[];
elements: MessageElement[]; elements: MessageElement[];
sourceType: MsgSourceType;
} }
export interface QueryMsgsParams { export interface QueryMsgsParams {
chatInfo: Peer; chatInfo: Peer;

View File

@@ -22,7 +22,7 @@ export class PacketClient {
private websocket: WebSocket | undefined; private websocket: WebSocket | undefined;
private isConnected: boolean = false; private isConnected: boolean = false;
private reconnectAttempts: number = 0; private reconnectAttempts: number = 0;
private readonly maxReconnectAttempts: number = 5;//现在暂时不可配置 private readonly maxReconnectAttempts: number = 60;//现在暂时不可配置
private readonly cb = new LRUCache<string, (json: RecvPacketData) => Promise<void>>(500); // trace_id-type callback private readonly cb = new LRUCache<string, (json: RecvPacketData) => Promise<void>>(500); // trace_id-type callback
private readonly clientUrl: string = ''; private readonly clientUrl: string = '';
readonly napCatCore: NapCatCore; readonly napCatCore: NapCatCore;
@@ -47,16 +47,17 @@ export class PacketClient {
return text; return text;
} }
connect(): Promise<void> { connect(cb: any): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
//this.logger.log.bind(this.logger)(`[Core] [Packet Server] Attempting to connect to ${this.clientUrl}`); //this.logger.log.bind(this.logger)(`[Core] [Packet Server] Attempting to connect to ${this.clientUrl}`);
this.websocket = new WebSocket(this.clientUrl); this.websocket = new WebSocket(this.clientUrl);
this.websocket.on('error', (err) => {}/*this.logger.logError.bind(this.logger)('[Core] [Packet Server] Error:', err.message)*/); this.websocket.on('error', (err) => { }/*this.logger.logError.bind(this.logger)('[Core] [Packet Server] Error:', err.message)*/);
this.websocket.onopen = () => { this.websocket.onopen = () => {
this.isConnected = true; this.isConnected = true;
this.reconnectAttempts = 0; this.reconnectAttempts = 0;
this.logger.log.bind(this.logger)(`[Core] [Packet Server] Connected to ${this.clientUrl}`); this.logger.log.bind(this.logger)(`[Core] [Packet Server] Connected to ${this.clientUrl}`);
cb();
resolve(); resolve();
}; };
@@ -74,17 +75,17 @@ export class PacketClient {
this.websocket.onclose = () => { this.websocket.onclose = () => {
this.isConnected = false; this.isConnected = false;
//this.logger.logWarn.bind(this.logger)(`[Core] [Packet Server] Disconnected from ${this.clientUrl}`); //this.logger.logWarn.bind(this.logger)(`[Core] [Packet Server] Disconnected from ${this.clientUrl}`);
this.attemptReconnect(); this.attemptReconnect(cb);
}; };
}); });
} }
private attemptReconnect(): void { private attemptReconnect(cb: any): void {
try { try {
if (this.reconnectAttempts < this.maxReconnectAttempts) { if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++; this.reconnectAttempts++;
setTimeout(() => { setTimeout(() => {
this.connect().catch((error) => { this.connect(cb).catch((error) => {
this.logger.logError.bind(this.logger)(`[Core] [Packet Server] Reconnecting attempt failed,${error.message}`); this.logger.logError.bind(this.logger)(`[Core] [Packet Server] Reconnecting attempt failed,${error.message}`);
}); });
}, 5000 * this.reconnectAttempts); }, 5000 * this.reconnectAttempts);

View File

@@ -47,11 +47,11 @@ export class PacketPacker {
}); });
} }
packPokePacket(group: number, peer: number): PacketHexStr { packPokePacket(peer: number, group?: number): PacketHexStr {
const oidb_0xed3 = new NapProtoMsg(OidbSvcTrpcTcp0XED3_1).encode({ const oidb_0xed3 = new NapProtoMsg(OidbSvcTrpcTcp0XED3_1).encode({
uin: peer, uin: peer,
groupUin: group, groupUin: group,
friendUin: group, friendUin: group ?? peer,
ext: 0 ext: 0
}); });
return this.toHexStr(this.packOidbPacket(0xed3, 1, oidb_0xed3)); return this.toHexStr(this.packOidbPacket(0xed3, 1, oidb_0xed3));

View File

@@ -36,7 +36,7 @@ export interface NodeIKernelBuddyService {
getBuddyRemark(uid: number): string; getBuddyRemark(uid: number): string;
setBuddyRemark(uid: string, remark: string): void; setBuddyRemark(param: { uid: string, remark: string, signInfo?: unknown }): void;
getAvatarUrl(uid: number): string; getAvatarUrl(uid: number): string;

View File

@@ -18,6 +18,6 @@ export class GroupPoke extends GetPacketStatusDepends<Payload, any> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
await this.core.apis.PacketApi.sendPokePacket(+payload.group_id, +payload.user_id); await this.core.apis.PacketApi.sendPokePacket(+payload.user_id, +payload.group_id);
} }
} }

View File

@@ -91,6 +91,7 @@ import { GetGroupShutList } from './group/GetGroupShutList';
import { GetGroupMemberList } from './group/GetGroupMemberList'; import { GetGroupMemberList } from './group/GetGroupMemberList';
import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl"; import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl";
import {GetPacketStatus} from "@/onebot/action/packet/GetPacketStatus"; import {GetPacketStatus} from "@/onebot/action/packet/GetPacketStatus";
import {FriendPoke} from "@/onebot/action/user/FriendPoke";
export type ActionMap = Map<string, BaseAction<any, any>>; export type ActionMap = Map<string, BaseAction<any, any>>;
@@ -189,6 +190,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new FetchUserProfileLike(obContext, core), new FetchUserProfileLike(obContext, core),
new GetPacketStatus(obContext, core), new GetPacketStatus(obContext, core),
new GroupPoke(obContext, core), new GroupPoke(obContext, core),
new FriendPoke(obContext, core),
new GetUserStatus(obContext, core), new GetUserStatus(obContext, core),
new GetRkey(obContext, core), new GetRkey(obContext, core),
new SetSpecialTittle(obContext, core), new SetSpecialTittle(obContext, core),

View File

@@ -17,6 +17,7 @@ export enum ActionName {
// 以下为扩展napcat扩展 // 以下为扩展napcat扩展
Unknown = 'unknown', Unknown = 'unknown',
GroupPoke = 'group_poke', GroupPoke = 'group_poke',
FriendPoke = 'friend_poke',
SharePeer = 'ArkSharePeer', SharePeer = 'ArkSharePeer',
ShareGroupEx = 'ArkShareGroup', ShareGroupEx = 'ArkShareGroup',
RebootNormal = 'reboot_normal',//无快速登录重新启动 RebootNormal = 'reboot_normal',//无快速登录重新启动

View File

@@ -0,0 +1,22 @@
import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import {GetPacketStatusDepends} from "@/onebot/action/packet/GetPacketStatus";
const SchemaData = {
type: 'object',
properties: {
user_id: { type: ['number', 'string'] },
},
required: ['user_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class FriendPoke extends GetPacketStatusDepends<Payload, any> {
actionName = ActionName.FriendPoke;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
await this.core.apis.PacketApi.sendPokePacket(+payload.user_id);
}
}

View File

@@ -6,6 +6,7 @@ import {
GroupNotifyMsgStatus, GroupNotifyMsgStatus,
GroupNotifyMsgType, GroupNotifyMsgType,
InstanceContext, InstanceContext,
MsgSourceType,
NapCatCore, NapCatCore,
NodeIKernelBuddyListener, NodeIKernelBuddyListener,
NodeIKernelGroupListener, NodeIKernelGroupListener,
@@ -303,8 +304,10 @@ export class NapCatOneBot11Adapter {
}, },
m.msgId, m.msgId,
); );
await this.emitMsg(m) // if (m.sourceType == MsgSourceType.K_DOWN_SOURCETYPE_AIOINNER) {
.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));
// }
} }
}; };

View File

@@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) {
SettingItem( SettingItem(
'<span id="napcat-update-title">Napcat</span>', '<span id="napcat-update-title">Napcat</span>',
undefined, undefined,
SettingButton('V3.0.1', 'napcat-update-button', 'secondary'), SettingButton('V3.0.6', 'napcat-update-button', 'secondary'),
), ),
]), ]),
SettingList([ SettingList([

View File

@@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) {
SettingItem( SettingItem(
'<span id="napcat-update-title">Napcat</span>', '<span id="napcat-update-title">Napcat</span>',
void 0, void 0,
SettingButton("V3.0.1", "napcat-update-button", "secondary") SettingButton("V3.0.6", "napcat-update-button", "secondary")
) )
]), ]),
SettingList([ SettingList([