diff --git a/manifest.json b/manifest.json index 05ce223a..5d62896c 100644 --- a/manifest.json +++ b/manifest.json @@ -4,7 +4,7 @@ "name": "NapCatQQ", "slug": "NapCat.Framework", "description": "高性能的 OneBot 11 协议实现", - "version": "3.1.0", + "version": "3.1.3", "icon": "./logo.png", "authors": [ { diff --git a/package.json b/package.json index 0bea4c13..db9f7aea 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "napcat", "private": true, "type": "module", - "version": "3.1.0", + "version": "3.1.3", "scripts": { "build:framework": "vite build --mode framework", "build:shell": "vite build --mode shell", @@ -37,7 +37,7 @@ "commander": "^12.1.0", "async-mutex": "^0.5.0", "file-type": "^19.0.0", - "json-schema-to-ts": "^3.1.0", + "json-schema-to-ts": "^3.1.1", "image-size": "^1.1.1", "cors": "^2.8.5" }, diff --git a/src/common/version.ts b/src/common/version.ts index 10c206b9..4ce85e80 100644 --- a/src/common/version.ts +++ b/src/common/version.ts @@ -1 +1 @@ -export const napCatVersion = '3.1.0'; +export const napCatVersion = '3.1.3'; diff --git a/src/core/apis/file.ts b/src/core/apis/file.ts index 3ce58117..64a325bd 100644 --- a/src/core/apis/file.ts +++ b/src/core/apis/file.ts @@ -30,7 +30,7 @@ export class NTQQFileApi { context: InstanceContext; core: NapCatCore; rkeyManager: RkeyManager; - packetRkey: Array<{ rkey: string; time: number; type: number; }> | undefined; + packetRkey: Array<{ rkey: string; time: number; type: number; ttl: bigint }> | undefined; constructor(context: InstanceContext, core: NapCatCore) { this.context = context; @@ -378,10 +378,12 @@ export class NTQQFileApi { }; try { if (this.core.apis.PacketApi.available) { - if ((!this.packetRkey || this.packetRkey[0].time > Date.now() / 1000)) { + let rkey_expired_private = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000; + let rkey_expired_group = !this.packetRkey || this.packetRkey[0].time + Number(this.packetRkey[0].ttl) < Date.now() / 1000; + if (rkey_expired_private || rkey_expired_group) { this.packetRkey = await this.core.apis.PacketApi.sendRkeyPacket(); } - if (this.packetRkey.length > 0) { + if (this.packetRkey && this.packetRkey.length > 0) { rkeyData.group_rkey = this.packetRkey[1].rkey.slice(6); rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6); rkeyData.online_rkey = true; diff --git a/src/core/apis/webapi.ts b/src/core/apis/webapi.ts index 6e3c1218..63cf2247 100644 --- a/src/core/apis/webapi.ts +++ b/src/core/apis/webapi.ts @@ -338,4 +338,12 @@ export class NTQQWebApi { } return (hash & 0x7FFFFFFF).toString(); } + public getBknFromSKey(sKey: string) { + let hash = 5381; + for (let i = 0; i < sKey.length; i++) { + const code = sKey.charCodeAt(i); + hash = hash + (hash << 5) + code; + } + return (hash & 0x7FFFFFFF).toString(); + } } diff --git a/src/core/packet/proto/oidb/Oidb.0x9067_202.ts b/src/core/packet/proto/oidb/Oidb.0x9067_202.ts index ca52561a..2ee31688 100644 --- a/src/core/packet/proto/oidb/Oidb.0x9067_202.ts +++ b/src/core/packet/proto/oidb/Oidb.0x9067_202.ts @@ -14,6 +14,7 @@ export const OidbSvcTrpcTcp0X9067_202Key = { //Rsp export const OidbSvcTrpcTcp0X9067_202_RkeyList = { rkey: ProtoField(1, ScalarType.STRING), + ttl: ProtoField(2, ScalarType.UINT64), time: ProtoField(4, ScalarType.UINT32), type: ProtoField(5, ScalarType.UINT32), diff --git a/src/onebot/action/extends/GetGroupAddRequest.ts b/src/onebot/action/extends/GetGroupAddRequest.ts index b015c6d1..5e1f3edb 100644 --- a/src/onebot/action/extends/GetGroupAddRequest.ts +++ b/src/onebot/action/extends/GetGroupAddRequest.ts @@ -1,3 +1,4 @@ +import { GroupNotifyMsgStatus } from '@/core'; import BaseAction from '../BaseAction'; import { ActionName } from '../types'; @@ -11,18 +12,22 @@ export default class GetGroupAddRequest extends BaseAction { - // const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies(); - // log(data); - // const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE); - // const returnData: OB11GroupRequestNotify[] = []; - // for (const notify of notifies) { - // const uin = || (await NTQQUserApi.getUserDetailInfo(notify.user1.uid))?.uin; - // returnData.push({ - // group_id: parseInt(notify.group.groupCode), - // user_id: parseInt(uin), - // flag: notify.seq - // }); - // } - return null; + const ignoredNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(true, 10); + const retData: any = { + join_requests: await Promise.all( + ignoredNotifies + .filter(notify => notify.type === 7) + .map(async SSNotify => ({ + request_id: SSNotify.seq, + requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid), + requester_nick: SSNotify.user1?.nickName, + group_id: SSNotify.group?.groupCode, + group_name: SSNotify.group?.groupName, + checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE, + actor: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2?.uid) || 0, + }))), + }; + + return retData; } } diff --git a/src/onebot/action/file/GetFile.ts b/src/onebot/action/file/GetFile.ts index 40f705ca..521d82a4 100644 --- a/src/onebot/action/file/GetFile.ts +++ b/src/onebot/action/file/GetFile.ts @@ -5,9 +5,9 @@ import { ActionName } from '../types'; import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types'; -export interface GetFilePayload { - file: string; // 文件名或者fileUuid -} +// interface GetFilePayload { +// file: string; // 文件名或者fileUuid +// } export interface GetFileResponse { file?: string; // path @@ -16,19 +16,25 @@ export interface GetFileResponse { file_name?: string; base64?: string; } - const GetFileBase_PayloadSchema = { type: 'object', properties: { file: { type: 'string' }, + file_id: { type: 'string' } }, - required: ['file'], + oneOf: [ + { required: ['file'] }, + { required: ['file_id'] } + ] } as const satisfies JSONSchema; +export type GetFilePayload = FromSchema; + export class GetFileBase extends BaseAction { - payloadSchema: any = GetFileBase_PayloadSchema; + payloadSchema = GetFileBase_PayloadSchema; async _handle(payload: GetFilePayload): Promise { + payload.file ||= payload.file_id || ''; //接收消息标记模式 const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file); if (contextMsgFile) { @@ -115,27 +121,6 @@ export class GetFileBase extends BaseAction { } } -const GetFile_PayloadSchema = { - type: 'object', - properties: { - file_id: { type: 'string' }, - file: { type: 'string' }, - }, - required: ['file_id'], -} as const satisfies JSONSchema; - -type GetFile_Payload_Internal = FromSchema; - -interface GetFile_Payload extends GetFile_Payload_Internal { - file: string; -} - export default class GetFile extends GetFileBase { actionName = ActionName.GetFile; - payloadSchema = GetFile_PayloadSchema; - - async _handle(payload: GetFile_Payload): Promise { - payload.file = payload.file_id; - return super._handle(payload); - } } diff --git a/src/onebot/action/index.ts b/src/onebot/action/index.ts index 1584d1c9..331de2c3 100644 --- a/src/onebot/action/index.ts +++ b/src/onebot/action/index.ts @@ -92,6 +92,7 @@ import { GetGroupMemberList } from './group/GetGroupMemberList'; import { GetGroupFileUrl } from "@/onebot/action/file/GetGroupFileUrl"; import { GetPacketStatus } from "@/onebot/action/packet/GetPacketStatus"; import { FriendPoke } from "@/onebot/action/user/FriendPoke"; +import { GetCredentials } from './system/GetCredentials'; export type ActionMap = Map>; @@ -180,6 +181,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo new SetModelShow(obContext, core), new SetInputStatus(obContext, core), new GetCSRF(obContext, core), + new GetCredentials(obContext, core), new DelGroupNotice(obContext, core), new DeleteGroupFile(obContext, core), new CreateGroupFileFolder(obContext, core), diff --git a/src/onebot/action/msg/MarkMsgAsRead.ts b/src/onebot/action/msg/MarkMsgAsRead.ts index bfbc0e7a..279f4966 100644 --- a/src/onebot/action/msg/MarkMsgAsRead.ts +++ b/src/onebot/action/msg/MarkMsgAsRead.ts @@ -1,7 +1,7 @@ import { ChatType, Peer } from '@/core/entities'; +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import BaseAction from '../BaseAction'; import { ActionName } from '../types'; -import { FromSchema, JSONSchema } from 'json-schema-to-ts'; const SchemaData = { type: 'object', @@ -49,23 +49,14 @@ export class MarkGroupMsgAsRead extends MarkMsgAsRead { actionName = ActionName.MarkGroupMsgAsRead; } - -interface Payload { - message_id: number; -} - -export class GoCQHTTPMarkMsgAsRead extends BaseAction { +export class GoCQHTTPMarkMsgAsRead extends MarkMsgAsRead { actionName = ActionName.GoCQHTTP_MarkMsgAsRead; - - async _handle(payload: Payload): Promise { - return null; - } } -export class MarkAllMsgAsRead extends BaseAction { +export class MarkAllMsgAsRead extends BaseAction { actionName = ActionName._MarkAllMsgAsRead; - async _handle(payload: Payload): Promise { + async _handle(): Promise { await this.core.apis.MsgApi.markAllMsgAsRead(); return null; } diff --git a/src/onebot/action/system/GetCSRF.ts b/src/onebot/action/system/GetCSRF.ts index 9cab912e..68945adf 100644 --- a/src/onebot/action/system/GetCSRF.ts +++ b/src/onebot/action/system/GetCSRF.ts @@ -5,8 +5,12 @@ export class GetCSRF extends BaseAction { actionName = ActionName.GetCSRF; async _handle(payload: any) { + const sKey = await this.core.apis.UserApi.getSKey(); + if (!sKey) { + throw new Error('SKey is undefined'); + } return { - token: '', + token: +this.core.apis.WebApi.getBknFromSKey(sKey), }; } } diff --git a/src/onebot/action/system/GetCredentials.ts b/src/onebot/action/system/GetCredentials.ts new file mode 100644 index 00000000..96293905 --- /dev/null +++ b/src/onebot/action/system/GetCredentials.ts @@ -0,0 +1,31 @@ +import BaseAction from '../BaseAction'; +import { ActionName } from '../types'; +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +interface Response { + cookies: string, + token: number +} + +const SchemaData = { + type: 'object', + properties: { + domain: { type: 'string' }, + }, + required: ['domain'], +} as const satisfies JSONSchema; + +type Payload = FromSchema; + +export class GetCredentials extends BaseAction { + actionName = ActionName.GetCredentials; + payloadSchema = SchemaData; + + async _handle(payload: Payload) { + const cookiesObject = await this.core.apis.UserApi.getCookies(payload.domain); + //把获取到的cookiesObject转换成 k=v; 格式字符串拼接在一起 + const cookies = Object.entries(cookiesObject).map(([key, value]) => `${key}=${value}`).join('; '); + const bkn = cookiesObject?.skey ? this.core.apis.WebApi.getBknFromCookie(cookiesObject) : ''; + return { cookies: cookies, token: +bkn }; + } +} diff --git a/src/onebot/action/types.ts b/src/onebot/action/types.ts index deda296f..509593b4 100644 --- a/src/onebot/action/types.ts +++ b/src/onebot/action/types.ts @@ -43,8 +43,8 @@ export enum ActionName { GetGroupMemberList = 'get_group_member_list', GetGroupHonorInfo = 'get_group_honor_info', GetCookies = 'get_cookies', - // GetCSRF = 'get_csrf_token', - // GetCredentials = 'get_credentials', + GetCSRF = 'get_csrf_token', + GetCredentials = 'get_credentials', GetRecord = 'get_record', GetImage = 'get_image', CanSendImage = 'can_send_image', @@ -59,7 +59,7 @@ export enum ActionName { // QidianGetAccountInfo = 'qidian_get_account_info', // GetModelShow = '_get_model_show', // SetModelShow = '_set_model_show', - // GetOnlineClient = 'get_online_clients', + GetOnlineClient = 'get_online_clients', // GetUnidirectionalFriendList = 'get_unidirectional_friend_list', // DeleteFriend = 'delete_friend', // DeleteUnidirectionalFriendList = 'delete_unidirectional_friend', @@ -105,11 +105,6 @@ export enum ActionName { ForwardFriendSingleMsg = 'forward_friend_single_msg', ForwardGroupSingleMsg = 'forward_group_single_msg', TranslateEnWordToZn = 'translate_en2zh', - GetGroupFileCount = 'get_group_file_count', - GetGroupFileList = 'get_group_file_list', - SetGroupFileFolder = 'set_group_file_folder', - DelGroupFile = 'del_group_file', - DelGroupFileFolder = 'del_group_file_folder', SetMsgEmojiLike = 'set_msg_emoji_like', GoCQHTTP_SendForwardMsg = 'send_forward_msg', MarkPrivateMsgAsRead = 'mark_private_msg_as_read', @@ -125,7 +120,7 @@ export enum ActionName { FetchEmojiLike = 'fetch_emoji_like', SetInputStatus = 'set_input_status', GetGroupInfoEx = 'get_group_info_ex', - GetGroupIgnoredNotifies = 'get_group_ignored_notifies', + GetGroupIgnoreAddRequest = 'get_group_ignore_add_request', DelGroupNotice = '_del_group_notice', FetchUserProfileLike = 'fetch_user_profile_like', FriendPoke = 'friend_poke', @@ -135,12 +130,9 @@ export enum ActionName { GetRkey = 'nc_get_rkey', GetGroupShutList = 'get_group_shut_list', - // GetGroupIgnoreAddRequest = 'get_group_ignore_add_request', - // GetConfig = 'get_config', - // SetConfig = 'set_config', - // Debug = 'debug', - // GetGuildList = 'get_guild_list', - // TestApi01 = 'test_api_01', - // GetGuildProfile = 'get_guild_service_profile', + GetGuildList = 'get_guild_list', + GetGuildProfile = 'get_guild_service_profile', + + GetGroupIgnoredNotifies = 'get_group_ignored_notifies', // UploadForwardMsg = "upload_forward_msg", } diff --git a/src/webui/ui/NapCat.ts b/src/webui/ui/NapCat.ts index b511b593..55ccf7c0 100644 --- a/src/webui/ui/NapCat.ts +++ b/src/webui/ui/NapCat.ts @@ -30,7 +30,7 @@ async function onSettingWindowCreated(view: Element) { SettingItem( 'Napcat', undefined, - SettingButton('V3.1.0', 'napcat-update-button', 'secondary'), + SettingButton('V3.1.3', 'napcat-update-button', 'secondary'), ), ]), SettingList([ diff --git a/static/assets/renderer.js b/static/assets/renderer.js index ed59ee5d..3ee3d4f7 100644 --- a/static/assets/renderer.js +++ b/static/assets/renderer.js @@ -164,7 +164,7 @@ async function onSettingWindowCreated(view) { SettingItem( 'Napcat', void 0, - SettingButton("V3.1.0", "napcat-update-button", "secondary") + SettingButton("V3.1.3", "napcat-update-button", "secondary") ) ]), SettingList([