Compare commits

..

15 Commits

Author SHA1 Message Date
Wesley F. Young
bee9095d6f release: 2.2.28 2024-08-31 10:35:33 +08:00
Wesley F. Young
92f8eaaac9 fix: get file by msgId and elemId 2024-08-31 10:34:19 +08:00
Wesley F. Young
f5e7288fe5 fix: report encoded msgId+elemId in upload event 2024-08-30 20:47:48 +08:00
Seijo Cecilia
214aa7b6e4 update(workflow): 'build' can only be triggered manually 2024-08-30 16:00:33 +08:00
Seijo Cecilia
5b5d5b41f5 build: snapshot-fix-get-file 2024-08-30 15:47:18 +08:00
Seijo Cecilia
23d613321e Revert "fix: arg3 no longer needed for downloadFileForModelId"
This reverts commit e1e4d038d9.
2024-08-30 15:41:50 +08:00
Wesley F. Young
0b6be0923f release: 2.2.27 2024-08-30 12:02:50 +08:00
Wesley F. Young
aba748ea13 Merge pull request #323 from LingLambda/main
fix: 规范 setSelfOnlineStatus 接口的参数命名
2024-08-30 11:55:22 +08:00
Wesley F. Young
f1f1ac582d chore: optimize imports 2024-08-30 11:45:58 +08:00
Wesley F. Young
54a7cbc3f4 feat: go-cqhttp style group file apis 2024-08-30 11:44:15 +08:00
ling
2f4dbaec4c fix: 规范setSelfOnlineStatus接口参数命名 2024-08-30 11:38:15 +08:00
Wesley F. Young
578f518aaf fix: others invited by others 2024-08-30 10:04:48 +08:00
Wesley F. Young
077ba74b22 fix: missing parameter for file searching 2024-08-30 09:31:18 +08:00
手瓜一十雪
e0efe635c7 release: 2.2.26 2024-08-29 22:47:24 +08:00
手瓜一十雪
1a06841de0 feat: notify.type == GroupNotifyMsgType.INVITED_NEED_ADMINI_STRATOR_PASS 2024-08-29 22:46:55 +08:00
38 changed files with 468 additions and 90 deletions

View File

@@ -1,15 +1,11 @@
name: "Build Action"
on:
workflow_dispatch:
push:
branches:
- main
permissions: write-all
jobs:
Build-LiteLoader:
if: ${{ startsWith(github.event.head_commit.message, 'build:') }}
runs-on: ubuntu-latest
steps:
- name: Clone Main Repository
@@ -37,7 +33,6 @@ jobs:
name: NapCat.Framework
path: dist
Build-Shell:
if: ${{ startsWith(github.event.head_commit.message, 'build:') }}
runs-on: ubuntu-latest
steps:
- name: Clone Main Repository
@@ -63,4 +58,4 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: NapCat.Shell
path: dist
path: dist

View File

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

View File

@@ -2,7 +2,7 @@
"name": "napcat",
"private": true,
"type": "module",
"version": "2.2.25",
"version": "2.2.28",
"scripts": {
"build:framework": "vite build --mode framework",
"build:shell": "vite build --mode shell",

View File

@@ -23,29 +23,33 @@ export async function solveAsyncProblem<T extends (...args: any[]) => Promise<an
});
});
}
export class FileNapCatOneBotUUID {
static encodeModelId(peer: Peer, modelId: string): string {
return `NapCatOneBot-ModeldFile-${peer.chatType}-${peer.peerUid}-${modelId}`;
return `NapCatOneBot-ModelIdFile-${peer.chatType}-${peer.peerUid}-${modelId}`;
}
static decodeModelId(uuid: string): undefined | {
peer: Peer,
modelId: string
} {
if (!uuid.startsWith('NapCatOneBot-ModeldFile-')) return undefined;
if (!uuid.startsWith('NapCatOneBot-ModelIdFile-')) return undefined;
const data = uuid.split('-');
if (data.length !== 5) return undefined;
const [, , chatType, peerUid, modelId] = data;
return {
peer: {
chatType: chatType as any,
peerUid: peerUid
peerUid: peerUid,
},
modelId,
};
}
static encode(peer: Peer, msgId: string, elementId: string): string {
return `NapCatOneBot-MsgFile-${peer.chatType}-${peer.peerUid}-${msgId}-${elementId}`;
}
static decode(uuid: string): undefined | {
peer: Peer,
msgId: string,
@@ -58,13 +62,14 @@ export class FileNapCatOneBotUUID {
return {
peer: {
chatType: chatType as any,
peerUid: peerUid
peerUid: peerUid,
},
msgId,
elementId,
};
}
}
export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}

View File

@@ -1 +1 @@
export const napCatVersion = '2.2.25';
export const napCatVersion = '2.2.28';

View File

@@ -302,11 +302,11 @@ export class NTQQFileApi {
async downloadMediaByUuid() {
//napCatCore.session.getRichMediaService().downloadFileForFileUuid();
}
async downloadFileForModelId(peer: Peer, modelId: string, timeout = 1000 * 60 * 2) {
async downloadFileForModelId(peer: Peer, modelId: string, unknown: string, timeout = 1000 * 60 * 2) {
const [, fileTransNotifyInfo] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelRichMediaService/downloadFileForModelId',
'NodeIKernelMsgListener/onRichMediaDownloadComplete',
[peer, [modelId]],
[peer, [modelId], unknown],
() => true,
(arg) => arg?.commonFileInfo?.fileModelId === modelId,
1,
@@ -436,6 +436,8 @@ export class NTQQFileApi {
}
async searchForFile(keys: string[]): Promise<SearchResultItem | undefined> {
const randomResultId = 100000 + Math.floor(Math.random() * 10000);
let searchId = 0;
const [, searchResult] = await this.core.eventWrapper.callNormalEventV2(
'NodeIKernelFileAssistantService/searchFile',
'NodeIKernelFileAssistantListener/onFileSearch',
@@ -444,8 +446,14 @@ export class NTQQFileApi {
{
resultType: 2,
pageLimit: 1,
}
]
},
randomResultId
],
(ret) => {
searchId = ret;
return true;
},
result => result.searchId === searchId && result.resultId === randomResultId,
);
return searchResult.resultItems[0];
}

View File

@@ -2,7 +2,6 @@ import {
ChatType,
GeneralCallResult,
Group,
GroupInfoSource,
GroupMember,
GroupMemberRole,
GroupRequestOperateTypes,
@@ -402,7 +401,7 @@ export class NTQQGroupApi {
}
async GetGroupFileCount(Gids: Array<string>) {
async getGroupFileCount(Gids: Array<string>) {
return this.context.session.getRichMediaService().batchGetGroupFileCount(Gids);
}

View File

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

View File

@@ -25,7 +25,7 @@ export class NodeIKernelFileAssistantListener {
export type SearchResultWrapper = {
searchId: number,
resultType: number,
resultId: number,
hasMore: boolean,
resultItems: SearchResultItem[],
};

View File

@@ -29,7 +29,47 @@ export interface GroupFileInfoUpdateParamType {
retMsg: string;
clientWording: string;
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;
nextIndex: string;
reqId: string;

View File

@@ -1,15 +1,15 @@
// @generated by protobuf-ts 2.9.4
// @generated from protobuf file "EmojiLikeToOthers.proto" (package "SysMessage", syntax proto3)
// tslint:disable
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
import type {
BinaryReadOptions,
BinaryWriteOptions,
IBinaryReader,
IBinaryWriter,
PartialMessage,
} from '@protobuf-ts/runtime';
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
/**
* @generated from protobuf message SysMessage.EmojiLikeToOthersWrapper1
*/

View File

@@ -1,15 +1,15 @@
// @generated by protobuf-ts 2.9.4
// @generated from protobuf file "GreyTipWrapper.proto" (package "SysMessage", syntax proto3)
// tslint:disable
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
import type {
BinaryReadOptions,
BinaryWriteOptions,
IBinaryReader,
IBinaryWriter,
PartialMessage,
} from '@protobuf-ts/runtime';
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
/**
* @generated from protobuf message SysMessage.GreyTipWrapper
*/

View File

@@ -1,15 +1,15 @@
// @generated by protobuf-ts 2.9.4
// @generated from protobuf file "SysMessage.proto" (package "SysMessage", syntax proto3)
// tslint:disable
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
import type {
BinaryReadOptions,
BinaryWriteOptions,
IBinaryReader,
IBinaryWriter,
PartialMessage,
} from '@protobuf-ts/runtime';
import { MessageType, reflectionMergePartial, UnknownFieldHandler, WireType } from '@protobuf-ts/runtime';
/**
* @generated from protobuf message SysMessage.SysMessage
*/

View File

@@ -11,7 +11,7 @@ export interface NodeIKernelFileAssistantService {
getFileSessionList(): unknown;
searchFile(keywords: string[], params: { resultType: number, pageLimit: number }): unknown;
searchFile(keywords: string[], params: { resultType: number, pageLimit: number }, resultId: number): number;
resetSearchFileSortType(arg1: unknown, arg2: unknown, arg3: unknown): unknown;

View File

@@ -155,7 +155,7 @@ export interface NodeIKernelRichMediaService {
}): unknown;
//arg3为“”
downloadFileForModelId(peer: Peer, ModelId: string[]): Promise<unknown>;
downloadFileForModelId(peer: Peer, ModelId: string[], unknown: string): Promise<unknown>;
//第三个参数 Array<Type>
// this.fileId = "";

View File

@@ -2,8 +2,7 @@ import { NapCatPathWrapper } from '@/common/path';
import { LogWrapper } from '@/common/log';
import { proxiedListenerOf } from '@/common/proxy-handler';
import { QQBasicInfoWrapper } from '@/common/qq-basic-info';
import { loadQQWrapper, NapCatCore, NapCatCoreWorkingEnv } from '@/core';
import { InstanceContext } from '@/core';
import { InstanceContext, loadQQWrapper, NapCatCore, NapCatCoreWorkingEnv } from '@/core';
import { SelfInfo } from '@/core/entities';
import { NodeIKernelLoginListener } from '@/core/listeners';
import { NodeIKernelLoginService } from '@/core/services';

View File

@@ -1,4 +1,5 @@
import { createServer } from 'node:net';
export class NewAdapterNetwork {
constructor(public host: number, public port: number) { }
async open() {
@@ -11,8 +12,8 @@ export class NewAdapterNetwork {
});
socket.on('connect', () => {
})
});
});
server.listen(this.port, this.host);
}
}
}

View File

@@ -7,10 +7,10 @@ const SchemaData = {
type: 'object',
properties: {
status: { type: ['number', 'string'] },
extStatus: { type: ['number', 'string'] },
batteryStatus: { type: ['number', 'string'] },
ext_status: { type: ['number', 'string'] },
battery_status: { type: ['number', 'string'] },
},
required: ['status', 'extStatus', 'batteryStatus'],
required: ['status', 'ext_status', 'battery_status'],
} as const satisfies JSONSchema;
type Payload = FromSchema<typeof SchemaData>;
@@ -23,8 +23,8 @@ export class SetOnlineStatus extends BaseAction<Payload, null> {
const NTQQUserApi = this.core.apis.UserApi;
const ret = await NTQQUserApi.setSelfOnlineStatus(
parseInt(payload.status.toString()),
parseInt(payload.extStatus.toString()),
parseInt(payload.batteryStatus.toString()),
parseInt(payload.ext_status.toString()),
parseInt(payload.battery_status.toString()),
);
if (ret.result !== 0) {
throw new Error('设置在线状态失败');

View File

@@ -2,7 +2,6 @@ import BaseAction from '../BaseAction';
import fs from 'fs/promises';
import { FileNapCatOneBotUUID } from '@/common/helper';
import { ActionName } from '../types';
import { ChatType, Peer, RawMessage } from '@/core/entities';
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
export interface GetFilePayload {
@@ -32,8 +31,8 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
const NTQQMsgApi = this.core.apis.MsgApi;
const NTQQFileApi = this.core.apis.FileApi;
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
//接收消息标记模式
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file);
if (contextMsgFile) {
const { peer, msgId, elementId } = contextMsgFile;
const downloadPath = await NTQQFileApi.downloadMedia(msgId, peer.chatType, peer.peerUid, elementId, '', '');
@@ -65,7 +64,7 @@ export class GetFileBase extends BaseAction<GetFilePayload, GetFileResponse> {
const contextModelIdFile = FileNapCatOneBotUUID.decodeModelId(payload.file);
if (contextModelIdFile) {
const { peer, modelId } = contextModelIdFile;
const downloadPath = await NTQQFileApi.downloadFileForModelId(peer, modelId);
const downloadPath = await NTQQFileApi.downloadFileForModelId(peer, modelId, '');
const res: GetFileResponse = {
file: downloadPath,
url: downloadPath,

View File

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

View File

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

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,35 @@
import { FromSchema, JSONSchema } from 'json-schema-to-ts';
import BaseAction from '../BaseAction';
import { ActionName } from '../types';
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,
};
}
}

View File

@@ -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 [],
};
}
}

View File

@@ -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!)),
};
}
}

View File

@@ -82,10 +82,22 @@ import { SetInputStatus } from './extends/SetInputStatus';
import { GetCSRF } from './system/GetCSRF';
import { DelGroupNotice } from './group/DelGroupNotice';
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 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 = [
new GetGroupInfoEx(obContext, core),
new FetchEmojiLike(obContext, core),
@@ -101,11 +113,11 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new MarkPrivateMsgAsRead(obContext, core),
new SetQQAvatar(obContext, core),
new TranslateEnWordToZn(obContext, core),
new GetGroupFileCount(obContext, core),
ncGetGroupFileCount,
new GetGroupFileList(obContext, core),
new SetGroupFileFolder(obContext, core),
new DelGroupFile(obContext, core),
new DelGroupFileFolder(obContext, core),
ncSetGroupFileFolder,
ncDelGroupFile,
ncDelGroupFileFolder,
// onebot11
new SendLike(obContext, core),
new GetMsg(obContext, core),
@@ -173,6 +185,12 @@ export function createActionMap(obContext: NapCatOneBot11Adapter, core: NapCatCo
new SetInputStatus(obContext, core),
new GetCSRF(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();
for (const action of actionHandlers) {

View File

@@ -83,6 +83,12 @@ export enum ActionName {
MarkPrivateMsgAsRead = 'mark_private_msg_as_read',
MarkGroupMsgAsRead = 'mark_group_msg_as_read',
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_GetGroupMsgHistory = 'get_group_msg_history',
GoCQHTTP_GetForwardMsg = 'get_forward_msg',

View File

@@ -18,6 +18,7 @@ import { OB11GroupUploadNoticeEvent } from '@/onebot/event/notice/OB11GroupUploa
import { OB11GroupPokeEvent } from '@/onebot/event/notice/OB11PokeEvent';
import { OB11GroupEssenceEvent } from '@/onebot/event/notice/OB11GroupEssenceEvent';
import { OB11GroupTitleEvent } from '@/onebot/event/notice/OB11GroupTitleEvent';
import { FileNapCatOneBotUUID } from '@/common/helper';
export class OneBotGroupApi {
obContext: NapCatOneBot11Adapter;
@@ -76,7 +77,10 @@ export class OneBotGroupApi {
this.core,
parseInt(msg.peerUid), parseInt(msg.senderUin || ''),
{
id: element.fileElement.fileUuid!,
id: FileNapCatOneBotUUID.encode({
chatType: ChatType.KCHATTYPEGROUP,
peerUid: msg.peerUid,
}, msg.msgId, element.elementId),
name: element.fileElement.fileName,
size: parseInt(element.fileElement.fileSize),
busid: element.fileElement.fileBizId || 0,
@@ -124,8 +128,8 @@ export class OneBotGroupApi {
peerUid: Group,
};
const msgData = await NTQQMsgApi.getMsgsBySeqAndCount(Peer, msgSeq.toString(), 1, true, true);
let msgList = (await this.core.apis.WebApi.getGroupEssenceMsgAll(Group)).flatMap((e) => e.data.msg_list);
let realMsg = msgList.find((e) => e.msg_seq.toString() == msgSeq);
const msgList = (await this.core.apis.WebApi.getGroupEssenceMsgAll(Group)).flatMap((e) => e.data.msg_list);
const realMsg = msgList.find((e) => e.msg_seq.toString() == msgSeq);
return new OB11GroupEssenceEvent(
this.core,
parseInt(msg.peerUid),

View File

@@ -9,7 +9,8 @@ import {
FaceType,
IdMusicSignPostData,
MessageElement,
NapCatCore, NTGrayTipElementSubTypeV2,
NapCatCore,
NTGrayTipElementSubTypeV2,
Peer,
RawMessage,
SendMessageElement,

View File

@@ -10,12 +10,12 @@ import {
QuickActionGroupMessage,
QuickActionGroupRequest,
} from '@/onebot';
import { ChatType, GroupRequestOperateTypes, NapCatCore, Peer } from '@/core';
import { GroupRequestOperateTypes, NapCatCore, Peer } from '@/core';
import { OB11FriendRequestEvent } from '@/onebot/event/request/OB11FriendRequest';
import { OB11GroupRequestEvent } from '@/onebot/event/request/OB11GroupRequest';
import { ContextMode, normalize } from '@/onebot/action/msg/SendMsg';
import { ContextMode, createContext, normalize } from '@/onebot/action/msg/SendMsg';
import { isNull } from '@/common/helper';
import { createContext } from '@/onebot/action/msg/SendMsg';
export class OneBotQuickActionApi {
constructor(
public obContext: NapCatOneBot11Adapter,

View File

@@ -1,6 +1,14 @@
import { calcQQLevel } from '@/common/helper';
import { Friend, FriendV2, Group, GroupMember, SelfInfo, Sex, User } from '@/core';
import { OB11Group, OB11GroupMember, OB11GroupMemberRole, OB11User, OB11UserSex } from './types';
import { calcQQLevel, FileNapCatOneBotUUID } from '@/common/helper';
import { Friend, FriendV2, Group, GroupFileInfoUpdateParamType, GroupMember, SelfInfo, Sex, User } from '@/core';
import {
OB11Group,
OB11GroupFile,
OB11GroupFileFolder,
OB11GroupMember,
OB11GroupMemberRole,
OB11User,
OB11UserSex,
} from './types';
export class OB11Entities {
static selfInfo(selfInfo: SelfInfo): OB11User {
@@ -97,4 +105,32 @@ export class OB11Entities {
static groups(groups: Group[]): OB11Group[] {
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,
};
}
}

View File

@@ -139,7 +139,7 @@ export class NapCatOneBot11Adapter {
initRecentContactListener() {
const recentContactListener = new NodeIKernelRecentContactListener();
recentContactListener.onRecentContactNotification = function(msgList: any[] /* arg0: { msgListUnreadCnt: string }, arg1: number */) {
recentContactListener.onRecentContactNotification = function (msgList: any[] /* arg0: { msgListUnreadCnt: string }, arg1: number */) {
msgList.forEach((msg) => {
if (msg.chatType == ChatType.KCHATTYPEGROUP) {
// log("recent contact", msgList, arg0, arg1);
@@ -248,7 +248,7 @@ export class NapCatOneBot11Adapter {
return;
}
const { msgType, subType, subSubType } = sysMsg.msgSpec[0];
if (msgType === 732 && subType === 16 && subSubType === 16 ) {
if (msgType === 732 && subType === 16 && subSubType === 16) {
const greyTip = GreyTipWrapper.fromBinary(Uint8Array.from(sysMsg.bodyWrapper!.wrappedBody.slice(7)));
if (greyTip.subTypeId === 36) {
const emojiLikeToOthers = EmojiLikeToOthersWrapper1
@@ -371,7 +371,7 @@ export class NapCatOneBot11Adapter {
private initGroupListener() {
const groupListener = new NodeIKernelGroupListener();
groupListener.onGroupNotifiesUpdated = async (_, notifies) => {
//console.log('ob11 onGroupNotifiesUpdated', notifies[0]);
await this.core.apis.GroupApi.clearGroupNotifiesUnreadCount(false);
@@ -473,6 +473,18 @@ export class NapCatOneBot11Adapter {
);
this.networkManager.emitEvent(groupInviteEvent)
.catch(e => this.context.logger.logError('处理邀请本人加群失败', e));
} else if (notify.type == GroupNotifyMsgType.INVITED_NEED_ADMINI_STRATOR_PASS && notify.status == GroupNotifyMsgStatus.KUNHANDLE) {
this.context.logger.logDebug(`收到群员邀请加群通知:${notify}`);
const groupInviteEvent = new OB11GroupRequestEvent(
this.core,
parseInt(notify.group.groupCode),
parseInt(await this.core.apis.UserApi.getUinByUidV2(notify.user1.uid)),
'add',
notify.postscript,
flag,
);
this.networkManager.emitEvent(groupInviteEvent)
.catch(e => this.context.logger.logError('处理邀请本人加群失败', e));
}
}
}

View File

@@ -63,3 +63,27 @@ export interface OB11Sender {
level?: string, // 群等级
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,
}

View File

@@ -5,8 +5,8 @@ import { NodeIKernelLoginListener, NodeIKernelSessionListener } from '@/core/lis
import { NodeIDependsAdapter, NodeIDispatcherAdapter, NodeIGlobalAdapter } from '@/core/adapters';
import { NapCatPathWrapper } from '@/common/path';
import {
InstanceContext,
genSessionConfig,
InstanceContext,
loadQQWrapper,
NapCatCore,
NapCatCoreWorkingEnv,

View File

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

View File

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