Merge branch 'main' into upmain

This commit is contained in:
Alen 2024-10-23 01:08:56 +08:00
commit 0081000ef0
15 changed files with 100 additions and 79 deletions

View File

@ -4,7 +4,7 @@
"name": "NapCatQQ", "name": "NapCatQQ",
"slug": "NapCat.Framework", "slug": "NapCat.Framework",
"description": "高性能的 OneBot 11 协议实现", "description": "高性能的 OneBot 11 协议实现",
"version": "3.1.0", "version": "3.1.3",
"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.1.0", "version": "3.1.3",
"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",
@ -37,7 +37,7 @@
"commander": "^12.1.0", "commander": "^12.1.0",
"async-mutex": "^0.5.0", "async-mutex": "^0.5.0",
"file-type": "^19.0.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", "image-size": "^1.1.1",
"cors": "^2.8.5" "cors": "^2.8.5"
}, },

View File

@ -1 +1 @@
export const napCatVersion = '3.1.0'; export const napCatVersion = '3.1.3';

View File

@ -30,7 +30,7 @@ export class NTQQFileApi {
context: InstanceContext; context: InstanceContext;
core: NapCatCore; core: NapCatCore;
rkeyManager: RkeyManager; 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) { constructor(context: InstanceContext, core: NapCatCore) {
this.context = context; this.context = context;
@ -378,10 +378,12 @@ export class NTQQFileApi {
}; };
try { try {
if (this.core.apis.PacketApi.available) { 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(); 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.group_rkey = this.packetRkey[1].rkey.slice(6);
rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6); rkeyData.private_rkey = this.packetRkey[0].rkey.slice(6);
rkeyData.online_rkey = true; rkeyData.online_rkey = true;

View File

@ -338,4 +338,12 @@ export class NTQQWebApi {
} }
return (hash & 0x7FFFFFFF).toString(); 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();
}
} }

View File

@ -14,6 +14,7 @@ export const OidbSvcTrpcTcp0X9067_202Key = {
//Rsp //Rsp
export const OidbSvcTrpcTcp0X9067_202_RkeyList = { export const OidbSvcTrpcTcp0X9067_202_RkeyList = {
rkey: ProtoField(1, ScalarType.STRING), rkey: ProtoField(1, ScalarType.STRING),
ttl: ProtoField(2, ScalarType.UINT64),
time: ProtoField(4, ScalarType.UINT32), time: ProtoField(4, ScalarType.UINT32),
type: ProtoField(5, ScalarType.UINT32), type: ProtoField(5, ScalarType.UINT32),

View File

@ -1,3 +1,4 @@
import { GroupNotifyMsgStatus } from '@/core';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
@ -11,18 +12,22 @@ export default class GetGroupAddRequest extends BaseAction<null, OB11GroupReques
actionName = ActionName.GetGroupIgnoreAddRequest; actionName = ActionName.GetGroupIgnoreAddRequest;
async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> { async _handle(payload: null): Promise<OB11GroupRequestNotify[] | null> {
// const data = await this.core.apis.GroupApi.getGroupIgnoreNotifies(); const ignoredNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(true, 10);
// log(data); const retData: any = {
// const notifies: GroupNotify[] = data.notifies.filter(notify => notify.status === GroupNotifyStatus.WAIT_HANDLE); join_requests: await Promise.all(
// const returnData: OB11GroupRequestNotify[] = []; ignoredNotifies
// for (const notify of notifies) { .filter(notify => notify.type === 7)
// const uin = || (await NTQQUserApi.getUserDetailInfo(notify.user1.uid))?.uin; .map(async SSNotify => ({
// returnData.push({ request_id: SSNotify.seq,
// group_id: parseInt(notify.group.groupCode), requester_uin: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1?.uid),
// user_id: parseInt(uin), requester_nick: SSNotify.user1?.nickName,
// flag: notify.seq group_id: SSNotify.group?.groupCode,
// }); group_name: SSNotify.group?.groupName,
// } checked: SSNotify.status !== GroupNotifyMsgStatus.KUNHANDLE,
return null; actor: await this.core.apis.UserApi.getUinByUidV2(SSNotify.user2?.uid) || 0,
}))),
};
return retData;
} }
} }

View File

@ -5,9 +5,9 @@ import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts'; import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types'; import { OB11MessageImage, OB11MessageVideo } from '@/onebot/types';
export interface GetFilePayload { // interface GetFilePayload {
file: string; // 文件名或者fileUuid // file: string; // 文件名或者fileUuid
} // }
export interface GetFileResponse { export interface GetFileResponse {
file?: string; // path file?: string; // path
@ -16,19 +16,25 @@ export interface GetFileResponse {
file_name?: string; file_name?: string;
base64?: string; base64?: string;
} }
const GetFileBase_PayloadSchema = { const GetFileBase_PayloadSchema = {
type: 'object', type: 'object',
properties: { properties: {
file: { type: 'string' }, file: { type: 'string' },
file_id: { type: 'string' }
}, },
required: ['file'], oneOf: [
{ required: ['file'] },
{ required: ['file_id'] }
]
} as const satisfies JSONSchema; } as const satisfies JSONSchema;
export type GetFilePayload = FromSchema<typeof GetFileBase_PayloadSchema>;
export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> { export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
payloadSchema: any = GetFileBase_PayloadSchema; payloadSchema = GetFileBase_PayloadSchema;
async _handle(payload: GetFilePayload): Promise<GetFileResponse> { async _handle(payload: GetFilePayload): Promise<GetFileResponse> {
payload.file ||= payload.file_id || '';
//接收消息标记模式 //接收消息标记模式
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file); const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
if (contextMsgFile) { if (contextMsgFile) {
@ -115,27 +121,6 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
} }
} }
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<typeof GetFile_PayloadSchema>;
interface GetFile_Payload extends GetFile_Payload_Internal {
file: string;
}
export default class GetFile extends GetFileBase { export default class GetFile extends GetFileBase {
actionName = ActionName.GetFile; actionName = ActionName.GetFile;
payloadSchema = GetFile_PayloadSchema;
async _handle(payload: GetFile_Payload): Promise<GetFileResponse> {
payload.file = payload.file_id;
return super._handle(payload);
}
} }

View File

@ -92,6 +92,7 @@ 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"; import { FriendPoke } from "@/onebot/action/user/FriendPoke";
import { GetCredentials } from './system/GetCredentials';
export type ActionMap = Map<string, BaseAction<any, any>>; export type ActionMap = Map<string, BaseAction<any, any>>;
@ -180,6 +181,7 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new SetModelShow(obContext, core), new SetModelShow(obContext, core),
new SetInputStatus(obContext, core), new SetInputStatus(obContext, core),
new GetCSRF(obContext, core), new GetCSRF(obContext, core),
new GetCredentials(obContext, core),
new DelGroupNotice(obContext, core), new DelGroupNotice(obContext, core),
new DeleteGroupFile(obContext, core), new DeleteGroupFile(obContext, core),
new CreateGroupFileFolder(obContext, core), new CreateGroupFileFolder(obContext, core),

View File

@ -1,7 +1,7 @@
import { ChatType, Peer } from '@/core/entities'; import { ChatType, Peer } from '@/core/entities';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction'; import BaseAction from '../BaseAction';
import { ActionName } from '../types'; import { ActionName } from '../types';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
const SchemaData = { const SchemaData = {
type: 'object', type: 'object',
@ -49,23 +49,14 @@ export class MarkGroupMsgAsRead extends MarkMsgAsRead {
actionName = ActionName.MarkGroupMsgAsRead; actionName = ActionName.MarkGroupMsgAsRead;
} }
export class GoCQHTTPMarkMsgAsRead extends MarkMsgAsRead {
interface Payload {
message_id: number;
}
export class GoCQHTTPMarkMsgAsRead extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_MarkMsgAsRead; actionName = ActionName.GoCQHTTP_MarkMsgAsRead;
async _handle(payload: Payload): Promise<null> {
return null;
}
} }
export class MarkAllMsgAsRead extends BaseAction<Payload, null> { export class MarkAllMsgAsRead extends BaseAction<any, null> {
actionName = ActionName._MarkAllMsgAsRead; actionName = ActionName._MarkAllMsgAsRead;
async _handle(payload: Payload): Promise<null> { async _handle(): Promise<null> {
await this.core.apis.MsgApi.markAllMsgAsRead(); await this.core.apis.MsgApi.markAllMsgAsRead();
return null; return null;
} }

View File

@ -5,8 +5,12 @@ export class GetCSRF extends BaseAction<any, any> {
actionName = ActionName.GetCSRF; actionName = ActionName.GetCSRF;
async _handle(payload: any) { async _handle(payload: any) {
const sKey = await this.core.apis.UserApi.getSKey();
if (!sKey) {
throw new Error('SKey is undefined');
}
return { return {
token: '', token: +this.core.apis.WebApi.getBknFromSKey(sKey),
}; };
} }
} }

View File

@ -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<typeof SchemaData>;
export class GetCredentials extends BaseAction<Payload, Response> {
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 };
}
}

View File

@ -43,8 +43,8 @@ export enum ActionName {
GetGroupMemberList = 'get_group_member_list', GetGroupMemberList = 'get_group_member_list',
GetGroupHonorInfo = 'get_group_honor_info', GetGroupHonorInfo = 'get_group_honor_info',
GetCookies = 'get_cookies', GetCookies = 'get_cookies',
// GetCSRF = 'get_csrf_token', GetCSRF = 'get_csrf_token',
// GetCredentials = 'get_credentials', GetCredentials = 'get_credentials',
GetRecord = 'get_record', GetRecord = 'get_record',
GetImage = 'get_image', GetImage = 'get_image',
CanSendImage = 'can_send_image', CanSendImage = 'can_send_image',
@ -59,7 +59,7 @@ export enum ActionName {
// QidianGetAccountInfo = 'qidian_get_account_info', // QidianGetAccountInfo = 'qidian_get_account_info',
// GetModelShow = '_get_model_show', // GetModelShow = '_get_model_show',
// SetModelShow = '_set_model_show', // SetModelShow = '_set_model_show',
// GetOnlineClient = 'get_online_clients', GetOnlineClient = 'get_online_clients',
// GetUnidirectionalFriendList = 'get_unidirectional_friend_list', // GetUnidirectionalFriendList = 'get_unidirectional_friend_list',
// DeleteFriend = 'delete_friend', // DeleteFriend = 'delete_friend',
// DeleteUnidirectionalFriendList = 'delete_unidirectional_friend', // DeleteUnidirectionalFriendList = 'delete_unidirectional_friend',
@ -105,11 +105,6 @@ export enum ActionName {
ForwardFriendSingleMsg = 'forward_friend_single_msg', ForwardFriendSingleMsg = 'forward_friend_single_msg',
ForwardGroupSingleMsg = 'forward_group_single_msg', ForwardGroupSingleMsg = 'forward_group_single_msg',
TranslateEnWordToZn = 'translate_en2zh', 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', SetMsgEmojiLike = 'set_msg_emoji_like',
GoCQHTTP_SendForwardMsg = 'send_forward_msg', GoCQHTTP_SendForwardMsg = 'send_forward_msg',
MarkPrivateMsgAsRead = 'mark_private_msg_as_read', MarkPrivateMsgAsRead = 'mark_private_msg_as_read',
@ -125,7 +120,7 @@ export enum ActionName {
FetchEmojiLike = 'fetch_emoji_like', FetchEmojiLike = 'fetch_emoji_like',
SetInputStatus = 'set_input_status', SetInputStatus = 'set_input_status',
GetGroupInfoEx = 'get_group_info_ex', GetGroupInfoEx = 'get_group_info_ex',
GetGroupIgnoredNotifies = 'get_group_ignored_notifies', GetGroupIgnoreAddRequest = 'get_group_ignore_add_request',
DelGroupNotice = '_del_group_notice', DelGroupNotice = '_del_group_notice',
FetchUserProfileLike = 'fetch_user_profile_like', FetchUserProfileLike = 'fetch_user_profile_like',
FriendPoke = 'friend_poke', FriendPoke = 'friend_poke',
@ -135,12 +130,9 @@ export enum ActionName {
GetRkey = 'nc_get_rkey', GetRkey = 'nc_get_rkey',
GetGroupShutList = 'get_group_shut_list', GetGroupShutList = 'get_group_shut_list',
// GetGroupIgnoreAddRequest = 'get_group_ignore_add_request', GetGuildList = 'get_guild_list',
// GetConfig = 'get_config', GetGuildProfile = 'get_guild_service_profile',
// SetConfig = 'set_config',
// Debug = 'debug', GetGroupIgnoredNotifies = 'get_group_ignored_notifies',
// GetGuildList = 'get_guild_list',
// TestApi01 = 'test_api_01',
// GetGuildProfile = 'get_guild_service_profile',
// UploadForwardMsg = "upload_forward_msg", // UploadForwardMsg = "upload_forward_msg",
} }

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.1.0', 'napcat-update-button', 'secondary'), SettingButton('V3.1.3', '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.1.0", "napcat-update-button", "secondary") SettingButton("V3.1.3", "napcat-update-button", "secondary")
) )
]), ]),
SettingList([ SettingList([