feat: go-cqhttp style group file apis

This commit is contained in:
Wesley F. Young 2024-08-30 11:44:15 +08:00
parent 578f518aaf
commit 54a7cbc3f4
15 changed files with 370 additions and 17 deletions

@ -402,7 +402,7 @@ export class NTQQGroupApi {
} }
async GetGroupFileCount(Gids: Array<string>) { async getGroupFileCount(Gids: Array<string>) {
return this.context.session.getRichMediaService().batchGetGroupFileCount(Gids); return this.context.session.getRichMediaService().batchGetGroupFileCount(Gids);
} }

@ -22,6 +22,7 @@ export interface GetFileListParam {
startIndex: number; startIndex: number;
sortOrder: number; sortOrder: number;
showOnlinedocFolder: number; showOnlinedocFolder: number;
folderId?: string;
} }
export enum ElementType { export enum ElementType {

@ -29,7 +29,47 @@ export interface GroupFileInfoUpdateParamType {
retMsg: string; retMsg: string;
clientWording: string; clientWording: string;
isEnd: boolean; isEnd: boolean;
item: Array<any>; item: Array<{
peerId: string;
type: number;
folderInfo?: {
folderId: string;
parentFolderId: string;
folderName: string;
createTime: number;
modifyTime: number;
createUin: string;
creatorName: string;
totalFileCount: number;
modifyUin: string;
modifyName: string;
usedSpace: string;
},
fileInfo?: {
fileModelId: string;
fileId: string;
fileName: string;
fileSize: string;
busId: number;
uploadedSize: string;
uploadTime: number;
deadTime: number;
modifyTime: number;
downloadTimes: number;
sha: string;
sha3: string;
md5: string;
uploaderLocalPath: string;
uploaderName: string;
uploaderUin: string;
parentFolderId: string;
localPath: string;
transStatus: number;
transType: number;
elementId: string;
isFolder: boolean;
},
}>;
allFileCount: string; allFileCount: string;
nextIndex: string; nextIndex: string;
reqId: string; reqId: string;

@ -17,8 +17,7 @@ export class GetGroupFileCount extends BaseAction<Payload, { count: number }> {
payloadSchema = SchemaData; payloadSchema = SchemaData;
async _handle(payload: Payload) { async _handle(payload: Payload) {
const NTQQGroupApi = this.core.apis.GroupApi; const ret = await this.core.apis.GroupApi.getGroupFileCount([payload.group_id?.toString()]);
const ret = await NTQQGroupApi.GetGroupFileCount([payload.group_id?.toString()]);
return { count: ret.groupFileCounts[0] }; return { count: ret.groupFileCounts[0] };
} }
} }

@ -35,15 +35,13 @@ export class GetGroupFileList extends BaseAction<Payload, { FileList: Array<any>
sortOrder: 2, sortOrder: 2,
showOnlinedocFolder: 0, showOnlinedocFolder: 0,
...param ...param
}).catch((e) => { }).catch(() => {
return []; return [];
}); });
ret.forEach((e) => { ret.forEach((e) => {
let fileModelId = e?.fileInfo?.fileModelId; const fileModelId = e?.fileInfo?.fileModelId;
if (fileModelId) { if (fileModelId)
e.fileModelId = fileModelId; e.fileInfo!.fileId = FileNapCatOneBotUUID.encodeModelId({ chatType: 2, peerUid: payload.group_id.toString() }, fileModelId);
}
e.fileId = FileNapCatOneBotUUID.encodeModelId({ chatType: 2, peerUid: payload.group_id.toString() }, fileModelId);
}); });
return { FileList: ret }; return { FileList: ret };
} }

@ -0,0 +1,32 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { NapCatOneBot11Adapter } from '@/onebot';
import { NapCatCore } from '@/core';
import { SetGroupFileFolder } from '@/onebot/action/file/SetGroupFileFolder';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
folder_name: { type: 'string' },
},
required: ['group_id', 'folder_name'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class CreateGroupFileFolder extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_CreateGroupFileFolder;
payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncSetGroupFileFolderImpl: SetGroupFileFolder) {
super(obContext, core);
}
async _handle(payload: Payload) {
await this.ncSetGroupFileFolderImpl._handle(payload);
return null;
}
}

@ -0,0 +1,32 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { NapCatCore } from '@/core';
import { NapCatOneBot11Adapter } from '@/onebot';
import { DelGroupFile } from '@/onebot/action/file/DelGroupFile';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
file_id: { type: 'string' },
},
required: ['group_id', 'file_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class DeleteGroupFile extends BaseAction<Payload, null> {
actionName = ActionName.GOCQHTTP_DeleteGroupFile;
payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncDelGroupFileImpl: DelGroupFile) {
super(obContext, core);
}
async _handle(payload: Payload) {
await this.ncDelGroupFileImpl._handle(payload);
return null;
}
}

@ -0,0 +1,32 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { NapCatCore } from '@/core';
import { NapCatOneBot11Adapter } from '@/onebot';
import { DelGroupFileFolder } from '@/onebot/action/file/DelGroupFileFolder';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
folder_id: { type: 'string' },
},
required: ['group_id', 'folder_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class DeleteGroupFileFolder extends BaseAction<Payload, null> {
actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;
payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncDelGroupFileFolderImpl: DelGroupFileFolder) {
super(obContext, core);
}
async _handle(payload: Payload) {
await this.ncDelGroupFileFolderImpl._handle(payload);
return null;
}
}

@ -0,0 +1,36 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { FileNapCatOneBotUUID } from '@/common/helper';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFileSystemInfo extends BaseAction<Payload, {
file_count: number,
limit_count: number, // unimplemented
used_space: number, // todo: unimplemented, but can be implemented later
total_space: number, // unimplemented, 10 GB by default
}> {
actionName = ActionName.GoCQHTTP_GetGroupFileSystemInfo;
payloadSchema = SchemaData;
async _handle(payload: Payload) {
return {
file_count:
(await this.core.apis.GroupApi
.getGroupFileCount([payload.group_id.toString()]))
.groupFileCounts[0],
limit_count: 10000,
used_space: 0,
total_space: 10 * 1024 * 1024 * 1024,
};
}
}

@ -0,0 +1,52 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { NapCatOneBot11Adapter, OB11GroupFile } from '@/onebot';
import { NapCatCore } from '@/core';
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
import { OB11Entities } from '@/onebot/entities';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
folder_id: { type: 'string' },
},
required: ['group_id', 'folder_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupFilesByFolder extends BaseAction<Payload, {
files: OB11GroupFile[],
folders: [] // QQ does not allow nested folders
}> {
actionName = ActionName.GoCQHTTP_GetGroupFilesByFolder;
payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private getGroupRootFilesImpl: GetGroupRootFiles) {
super(obContext, core);
}
async _handle(payload: Payload) {
const folder = (await this.getGroupRootFilesImpl._handle({ group_id: payload.group_id }))
.folders.find(folder => folder.folder_id === payload.folder_id);
if (!folder) {
throw new Error('Folder not found');
}
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: folder.total_file_count,
startIndex: 0,
sortOrder: 2,
showOnlinedocFolder: 0,
folderId: payload.folder_id,
}).catch(() => []);
return {
files: ret.filter(item => item.fileInfo)
.map(item => OB11Entities.file(item.peerId, item.fileInfo!)),
folders: [] as [],
};
}
}

@ -0,0 +1,47 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
import { NapCatOneBot11Adapter, OB11GroupFile, OB11GroupFileFolder } from '@/onebot';
import { NapCatCore } from '@/core';
import { GetGroupFileCount } from '@/onebot/action/file/GetGroupFileCount';
import { OB11Entities } from '@/onebot/entities';
const SchemaData = {
type: 'object',
properties: {
group_id: { type: ['string', 'number'] },
},
required: ['group_id'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
export class GetGroupRootFiles extends BaseAction<Payload, {
files: OB11GroupFile[],
folders: OB11GroupFileFolder[],
}> {
actionName = ActionName.GoCQHTTP_GetGroupRootFiles;
payloadSchema = SchemaData;
constructor(obContext: NapCatOneBot11Adapter, core: NapCatCore,
private ncGetGroupFileCountImpl: GetGroupFileCount) {
super(obContext, core);
}
async _handle(payload: Payload) {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: (await this.ncGetGroupFileCountImpl._handle({ group_id: payload.group_id.toString() })).count,
startIndex: 0,
sortOrder: 2,
showOnlinedocFolder: 0,
}).catch(() => []);
return {
files: ret.filter(item => item.fileInfo)
.map(item => OB11Entities.file(item.peerId, item.fileInfo!)),
folders: ret.filter(item => item.folderInfo)
.map(item => OB11Entities.folder(item.peerId, item.folderInfo!)),
};
}
}

@ -82,10 +82,22 @@ import { SetInputStatus } from './extends/SetInputStatus';
import { GetCSRF } from './system/GetCSRF'; import { GetCSRF } from './system/GetCSRF';
import { DelGroupNotice } from './group/DelGroupNotice'; import { DelGroupNotice } from './group/DelGroupNotice';
import { GetGroupInfoEx } from './extends/GetGroupInfoEx'; import { GetGroupInfoEx } from './extends/GetGroupInfoEx';
import { DeleteGroupFile } from '@/onebot/action/go-cqhttp/DeleteGroupFile';
import { CreateGroupFileFolder } from '@/onebot/action/go-cqhttp/CreateGroupFileFolder';
import { DeleteGroupFileFolder } from '@/onebot/action/go-cqhttp/DeleteGroupFileFolder';
import { GetGroupFileSystemInfo } from '@/onebot/action/go-cqhttp/GetGroupFileSystemInfo';
import { GetGroupRootFiles } from '@/onebot/action/go-cqhttp/GetGroupRootFiles';
import { GetGroupFilesByFolder } from '@/onebot/action/go-cqhttp/GetGroupFilesByFolder';
export type ActionMap = Map<string, BaseAction<any, any>>; export type ActionMap = Map<string, BaseAction<any, any>>;
export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap { export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCore): ActionMap {
const ncDelGroupFile = new DelGroupFile(obContext, core);
const ncSetGroupFileFolder = new SetGroupFileFolder(obContext, core);
const ncDelGroupFileFolder = new DelGroupFileFolder(obContext, core);
const ncGetGroupFileCount = new GetGroupFileCount(obContext, core);
const goCqHttpGetGroupRootFiles = new GetGroupRootFiles(obContext, core, ncGetGroupFileCount);
const actionHandlers = [ const actionHandlers = [
new GetGroupInfoEx(obContext, core), new GetGroupInfoEx(obContext, core),
new FetchEmojiLike(obContext, core), new FetchEmojiLike(obContext, core),
@ -101,11 +113,11 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new MarkPrivateMsgAsRead(obContext, core), new MarkPrivateMsgAsRead(obContext, core),
new SetQQAvatar(obContext, core), new SetQQAvatar(obContext, core),
new TranslateEnWordToZn(obContext, core), new TranslateEnWordToZn(obContext, core),
new GetGroupFileCount(obContext, core), ncGetGroupFileCount,
new GetGroupFileList(obContext, core), new GetGroupFileList(obContext, core),
new SetGroupFileFolder(obContext, core), ncSetGroupFileFolder,
new DelGroupFile(obContext, core), ncDelGroupFile,
new DelGroupFileFolder(obContext, core), ncDelGroupFileFolder,
// onebot11 // onebot11
new SendLike(obContext, core), new SendLike(obContext, core),
new GetMsg(obContext, core), new GetMsg(obContext, core),
@ -173,6 +185,12 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new SetInputStatus(obContext, core), new SetInputStatus(obContext, core),
new GetCSRF(obContext, core), new GetCSRF(obContext, core),
new DelGroupNotice(obContext, core), new DelGroupNotice(obContext, core),
new DeleteGroupFile(obContext, core, ncDelGroupFile),
new CreateGroupFileFolder(obContext, core, ncSetGroupFileFolder),
new DeleteGroupFileFolder(obContext, core, ncDelGroupFileFolder),
new GetGroupFileSystemInfo(obContext, core),
goCqHttpGetGroupRootFiles,
new GetGroupFilesByFolder(obContext, core, goCqHttpGetGroupRootFiles),
]; ];
const actionMap = new Map(); const actionMap = new Map();
for (const action of actionHandlers) { for (const action of actionHandlers) {

@ -83,6 +83,12 @@ export enum ActionName {
MarkPrivateMsgAsRead = 'mark_private_msg_as_read', MarkPrivateMsgAsRead = 'mark_private_msg_as_read',
MarkGroupMsgAsRead = 'mark_group_msg_as_read', MarkGroupMsgAsRead = 'mark_group_msg_as_read',
GoCQHTTP_UploadGroupFile = 'upload_group_file', GoCQHTTP_UploadGroupFile = 'upload_group_file',
GOCQHTTP_DeleteGroupFile = 'delete_group_file',
GoCQHTTP_CreateGroupFileFolder = 'create_group_file_folder',
GoCQHTTP_DeleteGroupFileFolder = 'delete_group_file_folder',
GoCQHTTP_GetGroupFileSystemInfo = 'get_group_file_system_info',
GoCQHTTP_GetGroupRootFiles = 'get_group_root_files',
GoCQHTTP_GetGroupFilesByFolder = 'get_group_files_by_folder',
GoCQHTTP_DownloadFile = 'download_file', GoCQHTTP_DownloadFile = 'download_file',
GoCQHTTP_GetGroupMsgHistory = 'get_group_msg_history', GoCQHTTP_GetGroupMsgHistory = 'get_group_msg_history',
GoCQHTTP_GetForwardMsg = 'get_forward_msg', GoCQHTTP_GetForwardMsg = 'get_forward_msg',

@ -1,6 +1,14 @@
import { calcQQLevel } from '@/common/helper'; import { calcQQLevel, FileNapCatOneBotUUID } from '@/common/helper';
import { Friend, FriendV2, Group, GroupMember, SelfInfo, Sex, User } from '@/core'; import { Friend, FriendV2, Group, GroupFileInfoUpdateParamType, GroupMember, SelfInfo, Sex, User } from '@/core';
import { OB11Group, OB11GroupMember, OB11GroupMemberRole, OB11User, OB11UserSex } from './types'; import {
OB11Group,
OB11GroupFile,
OB11GroupFileFolder,
OB11GroupMember,
OB11GroupMemberRole,
OB11User,
OB11UserSex,
} from './types';
export class OB11Entities { export class OB11Entities {
static selfInfo(selfInfo: SelfInfo): OB11User { static selfInfo(selfInfo: SelfInfo): OB11User {
@ -97,4 +105,32 @@ export class OB11Entities {
static groups(groups: Group[]): OB11Group[] { static groups(groups: Group[]): OB11Group[] {
return groups.map(OB11Entities.group); return groups.map(OB11Entities.group);
} }
static file(peerId: string, file: Exclude<GroupFileInfoUpdateParamType['item'][0]['fileInfo'], undefined>): OB11GroupFile {
return {
group_id: parseInt(peerId),
file_id: FileNapCatOneBotUUID.encodeModelId({ chatType: 2, peerUid: peerId }, file.fileModelId),
file_name: file.fileName,
busid: file.busId,
size: parseInt(file.fileSize),
upload_time: file.uploadTime,
dead_time: file.deadTime,
modify_time: file.modifyTime,
download_times: file.downloadTimes,
uploader: parseInt(file.uploaderUin),
uploader_name: file.uploaderName,
};
}
static folder(peerId: string, folder: Exclude<GroupFileInfoUpdateParamType['item'][0]['folderInfo'], undefined>): OB11GroupFileFolder {
return {
group_id: parseInt(peerId),
folder_id: folder.folderId,
folder_name: folder.folderName,
create_time: folder.createTime,
creator: parseInt(folder.createUin),
creator_name: folder.creatorName,
total_file_count: folder.totalFileCount,
};
}
} }

@ -63,3 +63,27 @@ export interface OB11Sender {
level?: string, // 群等级 level?: string, // 群等级
role?: OB11GroupMemberRole role?: OB11GroupMemberRole
} }
export interface OB11GroupFile {
group_id: number,
file_id: string,
file_name: string,
busid: number,
size: number,
upload_time: number,
dead_time: number,
modify_time: number,
download_times: number,
uploader: number,
uploader_name: string
}
export interface OB11GroupFileFolder {
group_id: number,
folder_id: string,
folder_name: string,
create_time: number,
creator: number,
creator_name: string,
total_file_count: number,
}