Add payload and return schemas to OneBot actions

Introduced explicit payloadSchema and returnSchema definitions for all OneBotAction classes using @sinclair/typebox. This improves type safety, API documentation, and validation for action payloads and return values. Also refactored method signatures and types for consistency across the codebase.
This commit is contained in:
手瓜一十雪 2026-01-25 14:50:58 +08:00
parent 81e4e54f25
commit b69352f6a1
150 changed files with 2015 additions and 1235 deletions

View File

@ -7,7 +7,7 @@ import { TSchema } from '@sinclair/typebox';
import { StreamPacket, StreamPacketBasic, StreamStatus } from './stream/StreamBasic';
export class OB11Response {
private static createResponse<T>(data: T, status: string, retcode: number, message: string = '', echo: unknown = null, useStream: boolean = false): OB11Return<T> {
private static createResponse<T> (data: T, status: string, retcode: number, message: string = '', echo: unknown = null, useStream: boolean = false): OB11Return<T> {
return {
status,
retcode,
@ -19,11 +19,11 @@ export class OB11Response {
};
}
static res<T>(data: T, status: string, retcode: number, message: string = '', echo: unknown = null, useStream: boolean = false): OB11Return<T> {
static res<T> (data: T, status: string, retcode: number, message: string = '', echo: unknown = null, useStream: boolean = false): OB11Return<T> {
return this.createResponse(data, status, retcode, message, echo, useStream);
}
static ok<T>(data: T, echo: unknown = null, useStream: boolean = false): OB11Return<T> {
static ok<T> (data: T, echo: unknown = null, useStream: boolean = false): OB11Return<T> {
return this.createResponse(data, 'ok', 0, '', echo, useStream);
}
@ -32,13 +32,14 @@ export class OB11Response {
}
}
export abstract class OneBotRequestToolkit {
abstract send<T>(packet: StreamPacket<T>): Promise<void>;
abstract send<T> (packet: StreamPacket<T>): Promise<void>;
}
export abstract class OneBotAction<PayloadType, ReturnDataType> {
actionName: typeof ActionName[keyof typeof ActionName] = ActionName.Unknown;
core: NapCatCore;
private validate?: ValidateFunction<unknown> = undefined;
payloadSchema?: TSchema = undefined;
returnSchema?: TSchema = undefined;
obContext: NapCatOneBot11Adapter;
useStream: boolean = false;

View File

@ -1,8 +1,11 @@
import { ActionName } from '@/napcat-onebot/action/router';
import { OneBotAction } from '../OneBotAction';
import { Type } from '@sinclair/typebox';
export class BotExit extends OneBotAction<void, void> {
override actionName = ActionName.Exit;
override payloadSchema = Type.Void();
override returnSchema = Type.Void();
async _handle () {
process.exit(0);

View File

@ -2,21 +2,26 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { OneBotAction } from '../OneBotAction';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
bot_appid: Type.String(),
button_id: Type.String({ default: '' }),
callback_data: Type.String({ default: '' }),
msg_seq: Type.String({ default: '10086' }),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
bot_appid: Type.String({ description: '机器人AppID' }),
button_id: Type.String({ default: '', description: '按钮ID' }),
callback_data: Type.String({ default: '', description: '回调数据' }),
msg_seq: Type.String({ default: '10086', description: '消息序列号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class ClickInlineKeyboardButton extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '点击结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class ClickInlineKeyboardButton extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.ClickInlineKeyboardButton;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.MsgApi.clickInlineKeyboardButton({
buttonId: payload.button_id,
peerId: payload.group_id.toString(),

View File

@ -2,18 +2,23 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Type, Static } from '@sinclair/typebox';
const SchemaData = Type.Object({
rawData: Type.String(),
brief: Type.String(),
const PayloadSchema = Type.Object({
rawData: Type.String({ description: '原始数据' }),
brief: Type.String({ description: '简要描述' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class CreateCollection extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '创建结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class CreateCollection extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.CreateCollection;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.CollectionApi.createCollection(
this.core.selfInfo.uin,
this.core.selfInfo.uid,

View File

@ -2,19 +2,24 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
album_id: Type.String(),
lloc: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
album_id: Type.String({ description: '相册ID' }),
lloc: Type.String({ description: '媒体ID (lloc)' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class DelGroupAlbumMedia extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '删除结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class DelGroupAlbumMedia extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.DelGroupAlbumMedia;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.WebApi.deleteAlbumMediaByNTQQ(
payload.group_id,
payload.album_id,

View File

@ -2,20 +2,21 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
album_id: Type.String(),
lloc: Type.String(),
content: Type.String(),
export const DoGroupAlbumCommentPayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
album_id: Type.String({ description: '相册 ID' }),
lloc: Type.String({ description: '图片 ID' }),
content: Type.String({ description: '评论内容' }),
});
type Payload = Static<typeof SchemaData>;
export type DoGroupAlbumCommentPayload = Static<typeof DoGroupAlbumCommentPayloadSchema>;
export class DoGroupAlbumComment extends OneBotAction<Payload, unknown> {
export class DoGroupAlbumComment extends OneBotAction<DoGroupAlbumCommentPayload, any> {
override actionName = ActionName.DoGroupAlbumComment;
override payloadSchema = SchemaData;
override payloadSchema = DoGroupAlbumCommentPayloadSchema;
override returnSchema = Type.Any({ description: '评论结果' });
async _handle (payload: Payload) {
async _handle (payload: DoGroupAlbumCommentPayload) {
return await this.core.apis.WebApi.doAlbumMediaPlainCommentByNTQQ(
payload.group_id,
payload.album_id,

View File

@ -2,17 +2,22 @@ import { Type, Static } from '@sinclair/typebox';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
const SchemaData = Type.Object({
count: Type.Union([Type.Number(), Type.String()], { default: 48 }),
const PayloadSchema = Type.Object({
count: Type.Union([Type.Number(), Type.String()], { default: 48, description: '获取数量' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class FetchCustomFace extends OneBotAction<Payload, string[]> {
const ReturnSchema = Type.Array(Type.String(), { description: '表情URL列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class FetchCustomFace extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.FetchCustomFace;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const ret = await this.core.apis.MsgApi.fetchFavEmojiList(+payload.count);
return ret.emojiInfoList.map(e => e.url);
}

View File

@ -2,29 +2,45 @@ import { Type, Static } from '@sinclair/typebox';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { MessageUnique } from 'napcat-common/src/message-unique';
import { type NTQQMsgApi } from 'napcat-core/apis';
const SchemaData = Type.Object({
message_id: Type.Union([Type.Number(), Type.String()]),
emojiId: Type.Union([Type.Number(), Type.String()]),
emojiType: Type.Union([Type.Number(), Type.String()]),
count: Type.Union([Type.Number(), Type.String()], { default: 20 }),
cookie: Type.String({ default: '' })
const PayloadSchema = Type.Object({
message_id: Type.Union([Type.Number(), Type.String()], { description: '消息ID' }),
emojiId: Type.Union([Type.Number(), Type.String()], { description: '表情ID' }),
emojiType: Type.Union([Type.Number(), Type.String()], { description: '表情类型' }),
count: Type.Union([Type.Number(), Type.String()], { default: 20, description: '获取数量' }),
cookie: Type.String({ default: '', description: '分页Cookie' })
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class FetchEmojiLike extends OneBotAction<Payload, Awaited<ReturnType<NTQQMsgApi['getMsgEmojiLikesList']>>> {
const ReturnSchema = Type.Object({
emojiLikesList: Type.Array(Type.Object({
tinyId: Type.String({ description: 'TinyID' }),
nickName: Type.String({ description: '昵称' }),
headUrl: Type.String({ description: '头像URL' }),
}), { description: '表情回应列表' }),
cookie: Type.String({ description: '分页Cookie' }),
isLastPage: Type.Boolean({ description: '是否最后一页' }),
isFirstPage: Type.Boolean({ description: '是否第一页' }),
result: Type.Number({ description: '结果状态码' }),
errMsg: Type.String({ description: '错 误信息' }),
}, { description: '表情回应详情' });
type ReturnType = Static<typeof ReturnSchema>;
export class FetchEmojiLike extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.FetchEmojiLike;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType): Promise<ReturnType> {
const msgIdPeer = MessageUnique.getMsgIdAndPeerByShortId(+payload.message_id);
if (!msgIdPeer) throw new Error('消息不存在');
const msg = (await this.core.apis.MsgApi.getMsgsByMsgId(msgIdPeer.Peer, [msgIdPeer.MsgId])).msgList[0];
if (!msg) throw new Error('消息不存在');
return await this.core.apis.MsgApi.getMsgEmojiLikesList(
const res = await this.core.apis.MsgApi.getMsgEmojiLikesList(
msgIdPeer.Peer, msg.msgSeq, payload.emojiId.toString(), payload.emojiType.toString(), payload.cookie, +payload.count
);
return res;
}
}

View File

@ -3,27 +3,36 @@ import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketS
import { AIVoiceChatType } from 'napcat-core/packet/entities/aiChat';
import { Type, Static } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
chat_type: Type.Union([Type.Union([Type.Number(), Type.String()])], { default: 1 }),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
chat_type: Type.Union([Type.Number(), Type.String()], { default: 1, description: '聊天类型' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
interface GetAiCharactersResponse {
type: string;
characters: {
character_id: string;
character_name: string;
preview_url: string;
}[];
}
const ReturnSchema = Type.Array(
Type.Object({
type: Type.String({ description: '角色类型' }),
characters: Type.Array(
Type.Object({
character_id: Type.String({ description: '角色ID' }),
character_name: Type.String({ description: '角色名称' }),
preview_url: Type.String({ description: '预览URL' }),
}),
{ description: '角色列表' }
),
}),
{ description: 'AI角色列表' }
);
export class GetAiCharacters extends GetPacketStatusDepends<Payload, GetAiCharactersResponse[]> {
type ReturnType = Static<typeof ReturnSchema>;
export class GetAiCharacters extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.GetAiCharacters;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const rawList = await this.core.apis.PacketApi.pkt.operation.FetchAiVoiceList(+payload.group_id, +payload.chat_type as AIVoiceChatType);
return rawList?.map((item) => ({
type: item.category,

View File

@ -1,12 +1,17 @@
import { ActionName } from '@/napcat-onebot/action/router';
import { OneBotAction } from '../OneBotAction';
import { Type, Static } from '@sinclair/typebox';
interface GetClientkeyResponse {
clientkey?: string;
}
const ReturnSchema = Type.Object({
clientkey: Type.Optional(Type.String({ description: '客户端Key' })),
}, { description: '获取ClientKey结果' });
export class GetClientkey extends OneBotAction<void, GetClientkeyResponse> {
type ReturnType = Static<typeof ReturnSchema>;
export class GetClientkey extends OneBotAction<void, ReturnType> {
override actionName = ActionName.GetClientkey;
override payloadSchema = Type.Void();
override returnSchema = ReturnSchema;
async _handle () {
return { clientkey: (await this.core.apis.UserApi.forceFetchClientKey()).clientKey };

View File

@ -3,18 +3,23 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Type, Static } from '@sinclair/typebox';
const SchemaData = Type.Object({
category: Type.Union([Type.Number(), Type.String()]),
count: Type.Union([Type.Union([Type.Number(), Type.String()])], { default: 1 }),
const PayloadSchema = Type.Object({
category: Type.Union([Type.Number(), Type.String()], { description: '分类ID' }),
count: Type.Union([Type.Number(), Type.String()], { default: 1, description: '获取数量' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetCollectionList extends OneBotAction<Payload, Awaited<ReturnType<NTQQCollectionApi['getAllCollection']>>> {
const ReturnSchema = Type.Any({ description: '收藏列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetCollectionList extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetCollectionList;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.CollectionApi.getAllCollection(+payload.category, +payload.count);
}
}

View File

@ -27,6 +27,7 @@ type ReturnType = Static<typeof ReturnSchema>;
export class GetEmojiLikes extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetEmojiLikes;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
let peer: Peer;

View File

@ -1,12 +1,29 @@
import { OB11Construct } from '@/napcat-onebot/helper/data';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Type, Static } from '@sinclair/typebox';
import { OB11UserSchema } from '../schemas';
export class GetFriendWithCategory extends OneBotAction<void, unknown> {
const ReturnSchema = Type.Array(
Type.Object({
categoryId: Type.Number({ description: '分组ID' }),
categoryName: Type.String({ description: '分组名称' }),
categoryMbCount: Type.Number({ description: '分组内好友数量' }),
buddyList: Type.Array(OB11UserSchema, { description: '好友列表' }),
}),
{ description: '带分组的好友列表' }
);
type ReturnType = Static<typeof ReturnSchema>;
export class GetFriendWithCategory extends OneBotAction<void, ReturnType> {
override actionName = ActionName.GetFriendsWithCategory;
override payloadSchema = Type.Void();
override returnSchema = ReturnSchema;
async _handle () {
return (await this.core.apis.FriendApi.getBuddyV2ExWithCate()).map(category => ({
const categories = await this.core.apis.FriendApi.getBuddyV2ExWithCate();
return categories.map(category => ({
...category,
buddyList: OB11Construct.friends(category.buddyList),
}));

View File

@ -1,16 +1,35 @@
import { GroupNotifyMsgStatus } from 'napcat-core';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Notify } from '@/napcat-onebot/types';
import { Type, Static } from '@sinclair/typebox';
export default class GetGroupAddRequest extends OneBotAction<null, Notify[] | null> {
const ReturnSchema = Type.Array(
Type.Object({
request_id: Type.Number({ description: '请求ID' }),
invitor_uin: Type.Number({ description: '邀请者QQ' }),
invitor_nick: Type.Optional(Type.String({ description: '邀请者昵称' })),
group_id: Type.Number({ description: '群号' }),
message: Type.Optional(Type.String({ description: '验证信息' })),
group_name: Type.Optional(Type.String({ description: '群名称' })),
checked: Type.Boolean({ description: '是否已处理' }),
actor: Type.Number({ description: '处理者QQ' }),
requester_nick: Type.Optional(Type.String({ description: '请求者昵称' })),
}),
{ description: '群通知列表' }
);
type ReturnType = Static<typeof ReturnSchema>;
export default class GetGroupAddRequest extends OneBotAction<void, ReturnType> {
override actionName = ActionName.GetGroupIgnoreAddRequest;
override payloadSchema = Type.Void();
override returnSchema = ReturnSchema;
async _handle (): Promise<Notify[] | null> {
async _handle (): Promise<ReturnType> {
const NTQQUserApi = this.core.apis.UserApi;
const NTQQGroupApi = this.core.apis.GroupApi;
const ignoredNotifies = await NTQQGroupApi.getSingleScreenNotifies(true, 10);
const retData: Notify[] = [];
const retData: any[] = [];
const notifyPromises = ignoredNotifies
.filter(notify => notify.type === 7)

View File

@ -2,19 +2,24 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
album_id: Type.String(),
attach_info: Type.String({ default: '' }),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
album_id: Type.String({ description: '相册ID' }),
attach_info: Type.String({ default: '', description: '附加信息(用于分页)' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupAlbumMediaList extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '相册媒体列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupAlbumMediaList extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupAlbumMediaList;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.WebApi.getAlbumMediaListByNTQQ(
payload.group_id,
payload.album_id,

View File

@ -1,17 +1,22 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Type, Static } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupInfoEx extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '群扩展信息' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupInfoEx extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupInfoEx;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return (await this.core.apis.GroupApi.getGroupExtFE0Info([payload.group_id.toString()])).result.groupExtInfos.get(payload.group_id.toString());
}
}

View File

@ -4,44 +4,50 @@ import { MiniAppInfo, MiniAppInfoHelper } from 'napcat-core/packet/utils/helper/
import { MiniAppData, MiniAppRawData, MiniAppReqCustomParams, MiniAppReqParams } from 'napcat-core/packet/entities/miniApp';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Union([
const PayloadSchema = Type.Union([
Type.Object({
type: Type.Union([Type.Literal('bili'), Type.Literal('weibo')]),
title: Type.String(),
desc: Type.String(),
picUrl: Type.String(),
jumpUrl: Type.String(),
webUrl: Type.Optional(Type.String()),
rawArkData: Type.Optional(Type.Union([Type.String()])),
type: Type.Union([Type.Literal('bili'), Type.Literal('weibo')], { description: '模板类型' }),
title: Type.String({ description: '标题' }),
desc: Type.String({ description: '描述' }),
picUrl: Type.String({ description: '图片URL' }),
jumpUrl: Type.String({ description: '跳转URL' }),
webUrl: Type.Optional(Type.String({ description: '网页URL' })),
rawArkData: Type.Optional(Type.Union([Type.String()], { description: '是否返回原始Ark数据' })),
}),
Type.Object({
title: Type.String(),
desc: Type.String(),
picUrl: Type.String(),
jumpUrl: Type.String(),
iconUrl: Type.String(),
webUrl: Type.Optional(Type.String()),
appId: Type.String(),
scene: Type.Union([Type.Number(), Type.String()]),
templateType: Type.Union([Type.Number(), Type.String()]),
businessType: Type.Union([Type.Number(), Type.String()]),
verType: Type.Union([Type.Number(), Type.String()]),
shareType: Type.Union([Type.Number(), Type.String()]),
versionId: Type.String(),
sdkId: Type.String(),
withShareTicket: Type.Union([Type.Number(), Type.String()]),
rawArkData: Type.Optional(Type.Union([Type.String()])),
title: Type.String({ description: '标题' }),
desc: Type.String({ description: '描述' }),
picUrl: Type.String({ description: '图片URL' }),
jumpUrl: Type.String({ description: '跳转URL' }),
iconUrl: Type.String({ description: '图标URL' }),
webUrl: Type.Optional(Type.String({ description: '网页URL' })),
appId: Type.String({ description: '小程序AppID' }),
scene: Type.Union([Type.Number(), Type.String()], { description: '场景ID' }),
templateType: Type.Union([Type.Number(), Type.String()], { description: '模板类型' }),
businessType: Type.Union([Type.Number(), Type.String()], { description: '业务类型' }),
verType: Type.Union([Type.Number(), Type.String()], { description: '版本类型' }),
shareType: Type.Union([Type.Number(), Type.String()], { description: '分享类型' }),
versionId: Type.String({ description: '版本ID' }),
sdkId: Type.String({ description: 'SDK ID' }),
withShareTicket: Type.Union([Type.Number(), Type.String()], { description: '是否携带分享票据' }),
rawArkData: Type.Optional(Type.Union([Type.String()], { description: '是否返回原始Ark数据' })),
}),
]);
type Payload = Static<typeof SchemaData>;
], { description: '小程序Ark参数' });
export class GetMiniAppArk extends GetPacketStatusDepends<Payload, {
data: MiniAppData | MiniAppRawData
}> {
type PayloadType = Static<typeof PayloadSchema>;
const ReturnSchema = Type.Object({
data: Type.Any({ description: 'Ark数据' }),
}, { description: '获取小程序Ark结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetMiniAppArk extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.GetMiniAppArk;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
let reqParam: MiniAppReqParams;
const customParams = {
title: payload.title,

View File

@ -1,36 +1,40 @@
import { NTVoteInfo } from 'napcat-core';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Type, Static } from '@sinclair/typebox';
const SchemaData = Type.Object({
user_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
start: Type.Union([Type.Number(), Type.String()], { default: 0 }),
count: Type.Union([Type.Number(), Type.String()], { default: 10 }),
const PayloadSchema = Type.Object({
user_id: Type.Optional(Type.String({ description: 'QQ号' })),
start: Type.Union([Type.Number(), Type.String()], { default: 0, description: '起始位置' }),
count: Type.Union([Type.Number(), Type.String()], { default: 10, description: '获取数量' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetProfileLike extends OneBotAction<Payload, {
uid: string;
time: string;
favoriteInfo: {
userInfos: Array<NTVoteInfo>;
total_count: number;
last_time: number;
today_count: number;
};
voteInfo: {
total_count: number;
new_count: number;
new_nearby_count: number;
last_visit_time: number;
userInfos: Array<NTVoteInfo>;
};
}> {
const ReturnSchema = Type.Object({
uid: Type.String({ description: '用户UID' }),
time: Type.String({ description: '时间' }),
favoriteInfo: Type.Object({
userInfos: Type.Array(Type.Any(), { description: '点赞用户信息' }),
total_count: Type.Number({ description: '总点赞数' }),
last_time: Type.Number({ description: '最后点赞时间' }),
today_count: Type.Number({ description: '今日点赞数' }),
}),
voteInfo: Type.Object({
total_count: Type.Number({ description: '总点赞数' }),
new_count: Type.Number({ description: '新增点赞数' }),
new_nearby_count: Type.Number({ description: '新增附近点赞数' }),
last_visit_time: Type.Number({ description: '最后访问时间' }),
userInfos: Type.Array(Type.Any(), { description: '点赞用户信息' }),
}),
}, { description: '点赞详情' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetProfileLike extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetProfileLike;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
const isSelf = this.core.selfInfo.uin === payload.user_id || !payload.user_id;
const userUid = isSelf || !payload.user_id ? this.core.selfInfo.uid : await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
const type = isSelf ? 2 : 1;

View File

@ -2,17 +2,22 @@ import { NTQQWebApi } from 'napcat-core/apis';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetQunAlbumList extends OneBotAction<Payload, Awaited<ReturnType<NTQQWebApi['getAlbumListByNTQQ']>>['response']['album_list']> {
const ReturnSchema = Type.Array(Type.Any(), { description: '群相册列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetQunAlbumList extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetQunAlbumList;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return (await this.core.apis.WebApi.getAlbumListByNTQQ(payload.group_id)).response.album_list;
}
}

View File

@ -1,8 +1,15 @@
import { ActionName } from '@/napcat-onebot/action/router';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { Type, Static } from '@sinclair/typebox';
export class GetRkey extends GetPacketStatusDepends<void, Array<unknown>> {
const ReturnSchema = Type.Array(Type.Any(), { description: 'Rkey列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetRkey extends GetPacketStatusDepends<void, ReturnType> {
override actionName = ActionName.GetRkey;
override payloadSchema = Type.Void();
override returnSchema = ReturnSchema;
async _handle () {
return await this.core.apis.PacketApi.pkt.operation.FetchRkey();

View File

@ -1,8 +1,15 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Type, Static } from '@sinclair/typebox';
export class GetRobotUinRange extends OneBotAction<void, Array<unknown>> {
const ReturnSchema = Type.Array(Type.Any(), { description: '机器人Uin范围列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetRobotUinRange extends OneBotAction<void, ReturnType> {
override actionName = ActionName.GetRobotUinRange;
override payloadSchema = Type.Void();
override returnSchema = ReturnSchema;
async _handle () {
return await this.core.apis.UserApi.getRobotUinRange();

View File

@ -2,26 +2,25 @@ import { PacketBuf } from 'napcat-core/packet/transformer/base';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { ProtoBuf, ProtoBufBase, PBUint32, PBString } from 'napcat.protobuf';
import { Type, Static } from '@sinclair/typebox';
interface Friend {
uin: number;
uid: string;
nick_name: string;
age: number;
source: string;
}
const ReturnSchema = Type.Array(
Type.Object({
uin: Type.Number({ description: 'QQ号' }),
uid: Type.String({ description: '用户UID' }),
nick_name: Type.String({ description: '昵称' }),
age: Type.Number({ description: '年龄' }),
source: Type.String({ description: '来源' }),
}),
{ description: '单向好友列表' }
);
interface Block {
str_uid: string;
bytes_source: string;
uint32_sex: number;
uint32_age: number;
bytes_nick: string;
uint64_uin: number;
}
type ReturnType = Static<typeof ReturnSchema>;
export class GetUnidirectionalFriendList extends OneBotAction<void, Friend[]> {
export class GetUnidirectionalFriendList extends OneBotAction<void, ReturnType> {
override actionName = ActionName.GetUnidirectionalFriendList;
override payloadSchema = Type.Void();
override returnSchema = ReturnSchema;
async pack_data (data: string): Promise<Uint8Array> {
return ProtoBuf(class extends ProtoBufBase {
@ -30,7 +29,7 @@ export class GetUnidirectionalFriendList extends OneBotAction<void, Friend[]> {
}).encode();
}
async _handle (): Promise<Friend[]> {
async _handle (): Promise<ReturnType> {
const self_id = this.core.selfInfo.uin;
const req_json = {
uint64_uin: self_id,
@ -43,7 +42,7 @@ export class GetUnidirectionalFriendList extends OneBotAction<void, Friend[]> {
const rsq = { cmd: 'MQUpdateSvc_com_qq_ti.web.OidbSvc.0xe17_0', data: data as PacketBuf };
const rsp_data = await this.core.apis.PacketApi.pkt.operation.sendPacket(rsq, true);
const block_json = ProtoBuf(class extends ProtoBufBase { data = PBString(4); }).decode(rsp_data);
const block_list: Block[] = JSON.parse(block_json.data).rpt_block_list;
const block_list: any[] = JSON.parse(block_json.data).rpt_block_list;
return block_list.map((block) => ({
uin: block.uint64_uin,

View File

@ -2,17 +2,28 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: 'QQ号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetUserStatus extends GetPacketStatusDepends<Payload, { status: number; ext_status: number; } | undefined> {
const ReturnSchema = Type.Optional(
Type.Object({
status: Type.Number({ description: '在线状态' }),
ext_status: Type.Number({ description: '扩展状态' }),
}),
{ description: '用户状态' }
);
type ReturnType = Static<typeof ReturnSchema>;
export class GetUserStatus extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.GetUserStatus;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.PacketApi.pkt.operation.GetStrangerStatus(+payload.user_id);
}
}

View File

@ -3,24 +3,27 @@ import { FileNapCatOneBotUUID } from 'napcat-common/src/file-uuid';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
file_id: Type.String(),
current_parent_directory: Type.String(),
target_parent_directory: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
file_id: Type.String({ description: '文件ID' }),
current_parent_directory: Type.String({ description: '当前父目录' }),
target_parent_directory: Type.String({ description: '目标父目录' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
interface MoveGroupFileResponse {
ok: boolean;
}
const ReturnSchema = Type.Object({
ok: Type.Boolean({ description: '是否成功' }),
}, { description: '移动文件结果' });
export class MoveGroupFile extends GetPacketStatusDepends<Payload, MoveGroupFileResponse> {
type ReturnType = Static<typeof ReturnSchema>;
export class MoveGroupFile extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.MoveGroupFile;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file_id) || FileNapCatOneBotUUID.decodeModelId(payload.file_id);
if (contextMsgFile?.fileUUID) {
await this.core.apis.PacketApi.pkt.operation.MoveGroupFile(+payload.group_id, contextMsgFile.fileUUID, payload.current_parent_directory, payload.target_parent_directory);

View File

@ -3,18 +3,22 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { checkFileExist, uriToLocalFile } from 'napcat-common/src/file';
import fs from 'fs';
import { Static, Type } from '@sinclair/typebox';
import { GeneralCallResultStatus } from 'napcat-core';
const SchemaData = Type.Object({
image: Type.String(),
const PayloadSchema = Type.Object({
image: Type.String({ description: '图片路径、URL或Base64' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
class OCRImageBase extends OneBotAction<Payload, GeneralCallResultStatus> {
override payloadSchema = SchemaData;
const ReturnSchema = Type.Any({ description: 'OCR结果' });
async _handle (payload: Payload) {
type ReturnType = Static<typeof ReturnSchema>;
class OCRImageBase extends OneBotAction<PayloadType, ReturnType> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
const { path, success } = await uriToLocalFile(this.core.NapCatTempPath, payload.image);
if (!success) {
throw new Error(`OCR ${payload.image}失败, image字段可能格式不正确`);

View File

@ -3,24 +3,27 @@ import { FileNapCatOneBotUUID } from 'napcat-common/src/file-uuid';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
file_id: Type.String(),
current_parent_directory: Type.String(),
new_name: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
file_id: Type.String({ description: '文件ID' }),
current_parent_directory: Type.String({ description: '当前父目录' }),
new_name: Type.String({ description: '新文件名' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
interface RenameGroupFileResponse {
ok: boolean;
}
const ReturnSchema = Type.Object({
ok: Type.Boolean({ description: '是否成功' }),
}, { description: '重命名文件结果' });
export class RenameGroupFile extends GetPacketStatusDepends<Payload, RenameGroupFileResponse> {
type ReturnType = Static<typeof ReturnSchema>;
export class RenameGroupFile extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.RenameGroupFile;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file_id) || FileNapCatOneBotUUID.decodeModelId(payload.file_id);
if (contextMsgFile?.fileUUID) {
await this.core.apis.PacketApi.pkt.operation.RenameGroupFile(+payload.group_id, contextMsgFile.fileUUID, payload.current_parent_directory, payload.new_name);

View File

@ -3,18 +3,23 @@ import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketS
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
cmd: Type.String(),
data: Type.String(),
rsp: Type.Union([Type.String(), Type.Boolean()], { default: true }),
const PayloadSchema = Type.Object({
cmd: Type.String({ description: '命令字' }),
data: Type.String({ description: '十六进制数据' }),
rsp: Type.Union([Type.String(), Type.Boolean()], { default: true, description: '是否等待响应' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SendPacket extends GetPacketStatusDepends<Payload, string | undefined> {
override payloadSchema = SchemaData;
const ReturnSchema = Type.Optional(Type.String({ description: '响应十六进制数据' }), { description: '发包结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class SendPacket extends GetPacketStatusDepends<PayloadType, ReturnType> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
override actionName = ActionName.SendPacket;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const rsp = typeof payload.rsp === 'boolean' ? payload.rsp : payload.rsp === 'true';
const data = await this.core.apis.PacketApi.pkt.operation.sendPacket({ cmd: payload.cmd, data: Buffer.from(payload.data, 'hex') as PacketBuf }, rsp);
return typeof data === 'object' ? data.toString('hex') : undefined;

View File

@ -2,19 +2,24 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
face_id: Type.Union([Type.Number(), Type.String()]), // 参考 face_config.json 的 QSid
face_type: Type.Union([Type.Number(), Type.String()], { default: '1' }),
wording: Type.String({ default: ' ' }),
const PayloadSchema = Type.Object({
face_id: Type.Union([Type.Number(), Type.String()], { description: '图标ID' }), // 参考 face_config.json 的 QSid
face_type: Type.Union([Type.Number(), Type.String()], { default: '1', description: '图标类型' }),
wording: Type.String({ default: ' ', description: '状态文字内容' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SetDiyOnlineStatus extends OneBotAction<Payload, string> {
const ReturnSchema = Type.String({ description: '错误信息(如果有)' });
type ReturnType = Static<typeof ReturnSchema>;
export class SetDiyOnlineStatus extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetDiyOnlineStatus;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const ret = await this.core.apis.UserApi.setDiySelfOnlineStatus(
payload.face_id.toString(),
payload.wording,

View File

@ -2,19 +2,24 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
add_type: Type.Number(),
group_question: Type.Optional(Type.String()),
group_answer: Type.Optional(Type.String()),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
add_type: Type.Number({ description: '加群方式' }),
group_question: Type.Optional(Type.String({ description: '加群问题' })),
group_answer: Type.Optional(Type.String({ description: '加群答案' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class SetGroupAddOption extends OneBotAction<Payload, null> {
const ReturnSchema = Type.Null({ description: '返回结果' });
type ReturnType = Static<typeof ReturnSchema>;
export default class SetGroupAddOption extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetGroupAddOption;
override payloadSchema = SchemaData;
async _handle (payload: Payload): Promise<null> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
const ret = await this.core.apis.GroupApi.setGroupAddOption(payload.group_id, {
addOption: payload.add_type,
groupQuestion: payload.group_question,

View File

@ -2,21 +2,26 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
album_id: Type.String(),
lloc: Type.String(),
id: Type.String(), // 421_1_0_1012959257|V61Yiali4PELg90bThrH4Bo2iI1M5Kab|V5bCgAxMDEyOTU5MjU3.PyqaPndPxg!^||^421_1_0_1012959257|V61Yiali4PELg90bThrH4Bo2iI1M5Kab|17560363448^||^1
set: Type.Boolean({ default: true }), // true=点赞 false=取消点赞 未实现
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
album_id: Type.String({ description: '相册ID' }),
lloc: Type.String({ description: '媒体ID (lloc)' }),
id: Type.String({ description: '点赞ID' }), // 421_1_0_1012959257|V61Yiali4PELg90bThrH4Bo2iI1M5Kab|V5bCgAxMDEyOTU5MjU3.PyqaPndPxg!^||^421_1_0_1012959257|V61Yiali4PELg90bThrH4Bo2iI1M5Kab|17560363448^||^1
set: Type.Boolean({ default: true, description: '是否点赞' }), // true=点赞 false=取消点赞 未实现
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SetGroupAlbumMediaLike extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '操作结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class SetGroupAlbumMediaLike extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetGroupAlbumMediaLike;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.WebApi.doAlbumMediaLikeByNTQQ(
payload.group_id,
payload.album_id,

View File

@ -2,19 +2,24 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
user_id: Type.Array(Type.String()),
reject_add_request: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
user_id: Type.Array(Type.String(), { description: 'QQ号列表' }),
reject_add_request: Type.Optional(Type.Union([Type.Boolean(), Type.String()], { description: '是否拒绝加群请求' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class SetGroupKickMembers extends OneBotAction<Payload, null> {
const ReturnSchema = Type.Null({ description: '返回结果' });
type ReturnType = Static<typeof ReturnSchema>;
export default class SetGroupKickMembers extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetGroupKickMembers;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload): Promise<null> {
async _handle (payload: PayloadType): Promise<ReturnType> {
const rejectReq = payload.reject_add_request?.toString() === 'true';
const uids: string[] = await Promise.all(payload.user_id.map(async uin => await this.core.apis.UserApi.getUidByUinV2(uin)));
await this.core.apis.GroupApi.kickMember(payload.group_id.toString(), uids.filter(uid => !!uid), rejectReq);

View File

@ -2,17 +2,22 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
remark: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
remark: Type.String({ description: '备注' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class SetGroupRemark extends OneBotAction<Payload, null> {
const ReturnSchema = Type.Null({ description: '返回结果' });
type ReturnType = Static<typeof ReturnSchema>;
export default class SetGroupRemark extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetGroupRemark;
override payloadSchema = SchemaData;
async _handle (payload: Payload): Promise<null> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
const ret = await this.core.apis.GroupApi.setGroupRemark(payload.group_id, payload.remark);
if (ret.result !== 0) {
throw new Error(`设置群备注失败, ${ret.result}:${ret.errMsg}`);

View File

@ -2,18 +2,23 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
robot_member_switch: Type.Optional(Type.Number()),
robot_member_examine: Type.Optional(Type.Number()),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
robot_member_switch: Type.Optional(Type.Number({ description: '机器人成员开关' })),
robot_member_examine: Type.Optional(Type.Number({ description: '机器人成员审核' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class SetGroupRobotAddOption extends OneBotAction<Payload, null> {
const ReturnSchema = Type.Null({ description: '返回结果' });
type ReturnType = Static<typeof ReturnSchema>;
export default class SetGroupRobotAddOption extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetGroupRobotAddOption;
override payloadSchema = SchemaData;
async _handle (payload: Payload): Promise<null> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
const ret = await this.core.apis.GroupApi.setGroupRobotAddOption(
payload.group_id,
payload.robot_member_switch,

View File

@ -2,18 +2,23 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.String(),
no_code_finger_open: Type.Optional(Type.Number()),
no_finger_open: Type.Optional(Type.Number()),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
no_code_finger_open: Type.Optional(Type.Number({ description: '是否开启无码指纹' })),
no_finger_open: Type.Optional(Type.Number({ description: '是否开启无指纹' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class SetGroupSearch extends OneBotAction<Payload, null> {
const ReturnSchema = Type.Null({ description: '返回结果' });
type ReturnType = Static<typeof ReturnSchema>;
export default class SetGroupSearch extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetGroupSearch;
override payloadSchema = SchemaData;
async _handle (payload: Payload): Promise<null> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
const ret = await this.core.apis.GroupApi.setGroupSearch(payload.group_id, {
noCodeFingerOpenFlag: payload.no_code_finger_open,
noFingerOpenFlag: payload.no_finger_open,

View File

@ -2,16 +2,21 @@ import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketS
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
class SetGroupSignBase extends GetPacketStatusDepends<Payload, void> {
override payloadSchema = SchemaData;
const ReturnSchema = Type.Void({ description: '打卡结果' });
async _handle (payload: Payload) {
type ReturnType = Static<typeof ReturnSchema>;
class SetGroupSignBase extends GetPacketStatusDepends<PayloadType, ReturnType> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
return await this.core.apis.PacketApi.pkt.operation.GroupSign(+payload.group_id);
}
}

View File

@ -3,17 +3,22 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { ChatType } from 'napcat-core';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
event_type: Type.Number(),
const PayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: 'QQ号' }),
event_type: Type.Number({ description: '事件类型' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SetInputStatus extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '设置结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class SetInputStatus extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetInputStatus;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('uid is empty');
const peer = {

View File

@ -2,17 +2,22 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
longNick: Type.String(),
const PayloadSchema = Type.Object({
longNick: Type.String({ description: '签名内容' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SetLongNick extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '设置结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class SetLongNick extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetLongNick;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.UserApi.setLongNick(payload.longNick);
}
}

View File

@ -2,19 +2,24 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
status: Type.Union([Type.Number(), Type.String()]),
ext_status: Type.Union([Type.Number(), Type.String()]),
battery_status: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
status: Type.Union([Type.Number(), Type.String()], { description: '在线状态' }),
ext_status: Type.Union([Type.Number(), Type.String()], { description: '扩展状态' }),
battery_status: Type.Union([Type.Number(), Type.String()], { description: '电量状态' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SetOnlineStatus extends OneBotAction<Payload, null> {
const ReturnSchema = Type.Null({ description: '设置结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class SetOnlineStatus extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetOnlineStatus;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const ret = await this.core.apis.UserApi.setSelfOnlineStatus(
+payload.status,
+payload.ext_status,

View File

@ -4,16 +4,21 @@ import fs from 'node:fs/promises';
import { checkFileExist, uriToLocalFile } from 'napcat-common/src/file';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
file: Type.String(),
const PayloadSchema = Type.Object({
file: Type.String({ description: '图片路径、URL或Base64' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class SetAvatar extends OneBotAction<Payload, null> {
const ReturnSchema = Type.Null({ description: '设置结果' });
type ReturnType = Static<typeof ReturnSchema>;
export default class SetAvatar extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.SetQQAvatar;
override payloadSchema = SchemaData;
async _handle (payload: Payload): Promise<null> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
const { path, success } = (await uriToLocalFile(this.core.NapCatTempPath, payload.file));
if (!success) {
throw new Error(`头像${payload.file}设置失败,file字段可能格式不正确`);

View File

@ -2,19 +2,24 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
user_id: Type.Union([Type.Number(), Type.String()]),
special_title: Type.String({ default: '' }),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
user_id: Type.Union([Type.Number(), Type.String()], { description: 'QQ号' }),
special_title: Type.String({ default: '', description: '专属头衔' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SetSpecialTitle extends GetPacketStatusDepends<Payload, void> {
const ReturnSchema = Type.Void({ description: '设置结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class SetSpecialTitle extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.SetSpecialTitle;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('User not found');
await this.core.apis.PacketApi.pkt.operation.SetGroupSpecialTitle(+payload.group_id, uid, payload.special_title);

View File

@ -3,22 +3,24 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
user_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
group_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
phone_number: Type.String({ default: '' }),
const PayloadSchema = Type.Object({
user_id: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: 'QQ号' })),
group_id: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: '群号' })),
phone_number: Type.String({ default: '', description: '手机号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SharePeerBase extends OneBotAction<Payload, GeneralCallResult & {
arkMsg?: string;
arkJson?: string;
}> {
const ReturnSchema = Type.Any({ description: '分享结果' });
override payloadSchema = SchemaData;
type ReturnType = Static<typeof ReturnSchema>;
async _handle (payload: Payload) {
export class SharePeerBase extends OneBotAction<PayloadType, ReturnType> {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
if (payload.group_id) {
return await this.core.apis.GroupApi.getGroupRecommendContactArkJson(payload.group_id.toString());
} else if (payload.user_id) {
@ -28,18 +30,23 @@ export class SharePeerBase extends OneBotAction<Payload, GeneralCallResult & {
}
}
const SchemaDataGroupEx = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchemaGroupEx = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
});
export class SharePeer extends SharePeerBase {
override actionName = ActionName.SharePeer;
}
type PayloadGroupEx = Static<typeof SchemaDataGroupEx>;
type PayloadTypeGroupEx = Static<typeof PayloadSchemaGroupEx>;
export class ShareGroupExBase extends OneBotAction<PayloadGroupEx, string> {
override payloadSchema = SchemaDataGroupEx;
const ReturnSchemaGroupEx = Type.String({ description: 'Ark Json内容' });
async _handle (payload: PayloadGroupEx) {
type ReturnTypeGroupEx = Static<typeof ReturnSchemaGroupEx>;
export class ShareGroupExBase extends OneBotAction<PayloadTypeGroupEx, ReturnTypeGroupEx> {
override payloadSchema = PayloadSchemaGroupEx;
override returnSchema = ReturnSchemaGroupEx;
async _handle (payload: PayloadTypeGroupEx) {
return await this.core.apis.GroupApi.getArkJsonGroupShare(payload.group_id.toString());
}
}

View File

@ -3,22 +3,25 @@ import { FileNapCatOneBotUUID } from 'napcat-common/src/file-uuid';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
file_id: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
file_id: Type.String({ description: '文件ID' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
interface TransGroupFileResponse {
ok: boolean;
}
const ReturnSchema = Type.Object({
ok: Type.Boolean({ description: '是否成功' }),
}, { description: '转发文件结果' });
export class TransGroupFile extends GetPacketStatusDepends<Payload, TransGroupFileResponse> {
type ReturnType = Static<typeof ReturnSchema>;
export class TransGroupFile extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.TransGroupFile;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file_id) || FileNapCatOneBotUUID.decodeModelId(payload.file_id);
if (contextMsgFile?.fileUUID) {
const result = await this.core.apis.GroupApi.transGroupFile(payload.group_id.toString(), contextMsgFile.fileUUID);

View File

@ -2,17 +2,22 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
words: Type.Array(Type.String()),
const PayloadSchema = Type.Object({
words: Type.Array(Type.String(), { description: '待翻译单词列表' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class TranslateEnWordToZn extends OneBotAction<Payload, Array<unknown> | null> {
const ReturnSchema = Type.Optional(Type.Array(Type.Any()), { description: '翻译结果列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class TranslateEnWordToZn extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.TranslateEnWordToZn;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType): Promise<ReturnType> {
const ret = await this.core.apis.SystemApi.translateEnWordToZn(payload.words);
if (ret.result !== 0) {
throw new Error('翻译失败');

View File

@ -5,20 +5,25 @@ import { Static, Type } from '@sinclair/typebox';
import { existsSync } from 'node:fs';
import { unlink } from 'node:fs/promises';
const SchemaData = Type.Object({
group_id: Type.String(),
album_id: Type.String(),
album_name: Type.String(),
file: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
album_id: Type.String({ description: '相册ID' }),
album_name: Type.String({ description: '相册名称' }),
file: Type.String({ description: '图片路径、URL或Base64' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class UploadImageToQunAlbum extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Any({ description: '上传结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class UploadImageToQunAlbum extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.UploadImageToQunAlbum;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const downloadResult = await uriToLocalFile(this.core.NapCatTempPath, payload.file);
try {
return await this.core.apis.WebApi.uploadImageToQunAlbum(payload.group_id, payload.album_id, payload.album_name, downloadResult.path);

View File

@ -5,23 +5,26 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { OB11MessageImage, OB11MessageVideo } from '@/napcat-onebot/types';
import { Static, Type } from '@sinclair/typebox';
export interface GetFileResponse {
file?: string; // path
url?: string;
file_size?: string;
file_name?: string;
base64?: string;
}
const GetFileBase_PayloadSchema = Type.Object({
file: Type.Optional(Type.String()),
file_id: Type.Optional(Type.String()),
export const GetFilePayloadSchema = Type.Object({
file: Type.Optional(Type.String({ description: '文件路径、URL或Base64' })),
file_id: Type.Optional(Type.String({ description: '文件ID' })),
});
export type GetFilePayload = Static<typeof GetFileBase_PayloadSchema>;
export type GetFilePayload = Static<typeof GetFilePayloadSchema>;
export const GetFileReturnSchema = Type.Object({
file: Type.Optional(Type.String({ description: '本地路径' })),
url: Type.Optional(Type.String({ description: '下载URL' })),
file_size: Type.Optional(Type.String({ description: '文件大小' })),
file_name: Type.Optional(Type.String({ description: '文件名' })),
base64: Type.Optional(Type.String({ description: 'Base64编码' })),
}, { description: '文件信息' });
export type GetFileResponse = Static<typeof GetFileReturnSchema>;
export class GetFileBase extends OneBotAction<GetFilePayload, GetFileResponse> {
override payloadSchema = GetFileBase_PayloadSchema;
override payloadSchema = GetFilePayloadSchema;
override returnSchema = GetFileReturnSchema;
async _handle (payload: GetFilePayload): Promise<GetFileResponse> {
payload.file ||= payload.file_id || '';
@ -40,12 +43,12 @@ export class GetFileBase extends OneBotAction<GetFilePayload, GetFileResponse> {
let url = '';
if (mixElement?.picElement && rawMessage) {
const tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.picElement?.(mixElement?.picElement, rawMessage, mixElement, { parseMultMsg: false, disableGetUrl: false, quick_reply: true }) as OB11MessageImage | undefined;
await this.obContext.apis.MsgApi.rawToOb11Converters.picElement?.(mixElement?.picElement, rawMessage, mixElement, { parseMultMsg: false, disableGetUrl: false, quick_reply: true }) as OB11MessageImage | undefined;
url = tempData?.data.url ?? '';
}
if (mixElement?.videoElement && rawMessage) {
const tempData =
await this.obContext.apis.MsgApi.rawToOb11Converters.videoElement?.(mixElement?.videoElement, rawMessage, mixElement, { parseMultMsg: false, disableGetUrl: false, quick_reply: true }) as OB11MessageVideo | undefined;
await this.obContext.apis.MsgApi.rawToOb11Converters.videoElement?.(mixElement?.videoElement, rawMessage, mixElement, { parseMultMsg: false, disableGetUrl: false, quick_reply: true }) as OB11MessageVideo | undefined;
url = tempData?.data.url ?? '';
}
const res: GetFileResponse = {

View File

@ -3,22 +3,25 @@ import { FileNapCatOneBotUUID } from 'napcat-common/src/file-uuid';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
file_id: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
file_id: Type.String({ description: '文件ID' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
interface GetGroupFileUrlResponse {
url?: string;
}
const ReturnSchema = Type.Object({
url: Type.Optional(Type.String({ description: '文件下载链接' })),
}, { description: '群文件URL信息' });
export class GetGroupFileUrl extends GetPacketStatusDepends<Payload, GetGroupFileUrlResponse> {
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupFileUrl extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.GOCQHTTP_GetGroupFileUrl;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file_id) || FileNapCatOneBotUUID.decodeModelId(payload.file_id);
if (contextMsgFile?.fileUUID) {
return {

View File

@ -3,21 +3,24 @@ import { FileNapCatOneBotUUID } from 'napcat-common/src/file-uuid';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
file_id: Type.String(),
const PayloadSchema = Type.Object({
file_id: Type.String({ description: '文件ID' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
interface GetPrivateFileUrlResponse {
url?: string;
}
const ReturnSchema = Type.Object({
url: Type.Optional(Type.String({ description: '文件下载链接' })),
}, { description: '私聊文件URL信息' });
export class GetPrivateFileUrl extends GetPacketStatusDepends<Payload, GetPrivateFileUrlResponse> {
type ReturnType = Static<typeof ReturnSchema>;
export class GetPrivateFileUrl extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.NapCat_GetPrivateFileUrl;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const contextMsgFile = FileNapCatOneBotUUID.decode(payload.file_id);
if (contextMsgFile?.fileUUID && contextMsgFile.msgId) {

View File

@ -2,22 +2,28 @@ import { GetFileBase, GetFilePayload, GetFileResponse } from './GetFile';
import { ActionName } from '@/napcat-onebot/action/router';
import { promises as fs } from 'fs';
import { FFmpegService } from '@/napcat-core/helper/ffmpeg/ffmpeg';
import { Static, Type } from '@sinclair/typebox';
const out_format = ['mp3', 'amr', 'wma', 'm4a', 'spx', 'ogg', 'wav', 'flac'];
const out_format_list = ['mp3', 'amr', 'wma', 'm4a', 'spx', 'ogg', 'wav', 'flac'];
type Payload = {
out_format: string;
} & GetFilePayload;
const PayloadSchema = Type.Object({
file: Type.Optional(Type.String({ description: '文件路径、URL或Base64' })),
file_id: Type.Optional(Type.String({ description: '文件ID' })),
out_format: Type.String({ description: '输出格式' }),
});
type PayloadType = Static<typeof PayloadSchema>;
export default class GetRecord extends GetFileBase {
override actionName = ActionName.GetRecord;
override payloadSchema = PayloadSchema;
override async _handle (payload: Payload): Promise<GetFileResponse> {
const res = await super._handle(payload);
override async _handle (payload: PayloadType): Promise<GetFileResponse> {
const res = await super._handle(payload as GetFilePayload);
if (payload.out_format && typeof payload.out_format === 'string') {
const inputFile = res.file;
if (!inputFile) throw new Error('file not found');
if (!out_format.includes(payload.out_format)) {
if (!out_format_list.includes(payload.out_format)) {
throw new Error('转换失败 out_format 字段可能格式不正确');
}
const outputFile = `${inputFile}.${payload.out_format}`;

View File

@ -1,6 +1,6 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type, Optional } from '@sinclair/typebox';
import { Static, Type } from '@sinclair/typebox';
import path from 'node:path';
const richMediaList = [
@ -8,22 +8,22 @@ const richMediaList = [
'.png', '.gif', '.jpg', '.jpeg', '.webp', '.bmp',
];
// 不全部使用json因为一个文件解析Form-data会变字符串 但是api文档就写List
const SchemaData = Type.Object({
export const CreateFlashTaskPayloadSchema = Type.Object({
files: Type.Union([
Type.Array(Type.String()),
Type.String(),
]),
name: Optional(Type.String()),
thumb_path: Optional(Type.String()),
], { description: '文件列表或单个文件路径' }),
name: Type.Optional(Type.String({ description: '任务名称' })),
thumb_path: Type.Optional(Type.String({ description: '缩略图路径' })),
});
type Payload = Static<typeof SchemaData>;
export type CreateFlashTaskPayload = Static<typeof CreateFlashTaskPayloadSchema>;
export class CreateFlashTask extends OneBotAction<Payload, unknown> {
export class CreateFlashTask extends OneBotAction<CreateFlashTaskPayload, any> {
override actionName = ActionName.CreateFlashTask;
override payloadSchema = SchemaData;
override payloadSchema = CreateFlashTaskPayloadSchema;
override returnSchema = Type.Any({ description: '任务创建结果' });
async _handle (payload: Payload) {
async _handle (payload: CreateFlashTaskPayload) {
const fileList = Array.isArray(payload.files) ? payload.files : [payload.files];
let thumbPath: string = '';

View File

@ -2,17 +2,18 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
fileset_id: Type.String(),
export const DownloadFilesetPayloadSchema = Type.Object({
fileset_id: Type.String({ description: '文件集 ID' }),
});
type Payload = Static<typeof SchemaData>;
export type DownloadFilesetPayload = Static<typeof DownloadFilesetPayloadSchema>;
export class DownloadFileset extends OneBotAction<Payload, unknown> {
export class DownloadFileset extends OneBotAction<DownloadFilesetPayload, any> {
override actionName = ActionName.DownloadFileset;
override payloadSchema = SchemaData;
override payloadSchema = DownloadFilesetPayloadSchema;
override returnSchema = Type.Any({ description: '下载结果' });
async _handle (payload: Payload) {
async _handle (payload: DownloadFilesetPayload) {
// 默认路径 / fileset_id /为下载路径
return await this.core.apis.FlashApi.downloadFileSetBySetId(payload.fileset_id);
}

View File

@ -2,17 +2,18 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
share_code: Type.String(),
export const GetFilesetIdPayloadSchema = Type.Object({
share_code: Type.String({ description: '分享码或分享链接' }),
});
type Payload = Static<typeof SchemaData>;
export type GetFilesetIdPayload = Static<typeof GetFilesetIdPayloadSchema>;
export class GetFilesetId extends OneBotAction<Payload, unknown> {
export class GetFilesetId extends OneBotAction<GetFilesetIdPayload, any> {
override actionName = ActionName.GetFilesetId;
override payloadSchema = SchemaData;
override payloadSchema = GetFilesetIdPayloadSchema;
override returnSchema = Type.Any({ description: '文件集 ID' });
async _handle (payload: Payload) {
async _handle (payload: GetFilesetIdPayload) {
// 适配share_link 防止被传 Link无法解析
const code = payload.share_code.includes('=') ? payload.share_code.split('=').slice(1).join('=') : payload.share_code;
return await this.core.apis.FlashApi.fromShareLinkFindSetId(code);

View File

@ -2,17 +2,18 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
fileset_id: Type.String(),
export const GetFilesetInfoPayloadSchema = Type.Object({
fileset_id: Type.String({ description: '文件集 ID' }),
});
type Payload = Static<typeof SchemaData>;
export type GetFilesetInfoPayload = Static<typeof GetFilesetInfoPayloadSchema>;
export class GetFilesetInfo extends OneBotAction<Payload, unknown> {
export class GetFilesetInfo extends OneBotAction<GetFilesetInfoPayload, any> {
override actionName = ActionName.GetFilesetInfo;
override payloadSchema = SchemaData;
override payloadSchema = GetFilesetInfoPayloadSchema;
override returnSchema = Type.Any({ description: '文件集信息' });
async _handle (payload: Payload) {
async _handle (payload: GetFilesetInfoPayload) {
return await this.core.apis.FlashApi.getFileSetIndoBySetId(payload.fileset_id);
}
}

View File

@ -2,17 +2,18 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
fileset_id: Type.String(),
export const GetFlashFileListPayloadSchema = Type.Object({
fileset_id: Type.String({ description: '文件集 ID' }),
});
type Payload = Static<typeof SchemaData>;
export type GetFlashFileListPayload = Static<typeof GetFlashFileListPayloadSchema>;
export class GetFlashFileList extends OneBotAction<Payload, unknown> {
export class GetFlashFileList extends OneBotAction<GetFlashFileListPayload, any> {
override actionName = ActionName.GetFlashFileList;
override payloadSchema = SchemaData;
override payloadSchema = GetFlashFileListPayloadSchema;
override returnSchema = Type.Any({ description: '文件列表' });
async _handle (payload: Payload) {
async _handle (payload: GetFlashFileListPayload) {
return await this.core.apis.FlashApi.getFileListBySetId(payload.fileset_id);
}
}

View File

@ -2,19 +2,20 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
fileset_id: Type.String(),
file_name: Type.Optional(Type.String()),
file_index: Type.Optional(Type.Number()),
export const GetFlashFileUrlPayloadSchema = Type.Object({
fileset_id: Type.String({ description: '文件集 ID' }),
file_name: Type.Optional(Type.String({ description: '文件名' })),
file_index: Type.Optional(Type.Number({ description: '文件索引' })),
});
type Payload = Static<typeof SchemaData>;
export type GetFlashFileUrlPayload = Static<typeof GetFlashFileUrlPayloadSchema>;
export class GetFlashFileUrl extends OneBotAction<Payload, unknown> {
export class GetFlashFileUrl extends OneBotAction<GetFlashFileUrlPayload, any> {
override actionName = ActionName.GetFlashFileUrl;
override payloadSchema = SchemaData;
override payloadSchema = GetFlashFileUrlPayloadSchema;
override returnSchema = Type.Any({ description: '文件下载链接' });
async _handle (payload: Payload) {
async _handle (payload: GetFlashFileUrlPayload) {
// 文件的索引依旧从0开始
return await this.core.apis.FlashApi.getFileTransUrl(payload.fileset_id, {
fileName: payload.file_name,

View File

@ -2,17 +2,18 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
fileset_id: Type.String(),
export const GetShareLinkPayloadSchema = Type.Object({
fileset_id: Type.String({ description: '文件集 ID' }),
});
type Payload = Static<typeof SchemaData>;
export type GetShareLinkPayload = Static<typeof GetShareLinkPayloadSchema>;
export class GetShareLink extends OneBotAction<Payload, unknown> {
export class GetShareLink extends OneBotAction<GetShareLinkPayload, any> {
override actionName = ActionName.GetShareLink;
override payloadSchema = SchemaData;
override payloadSchema = GetShareLinkPayloadSchema;
override returnSchema = Type.Any({ description: '分享链接' });
async _handle (payload: Payload) {
async _handle (payload: GetShareLinkPayload) {
return await this.core.apis.FlashApi.getShareLinkBySetId(payload.fileset_id);
}
}

View File

@ -3,19 +3,20 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { ChatType, Peer } from 'napcat-core/types';
const SchemaData = Type.Object({
fileset_id: Type.String(),
user_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
group_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
export const SendFlashMsgPayloadSchema = Type.Object({
fileset_id: Type.String({ description: '文件集 ID' }),
user_id: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: '用户 QQ' })),
group_id: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: '群号' })),
});
type Payload = Static<typeof SchemaData>;
export type SendFlashMsgPayload = Static<typeof SendFlashMsgPayloadSchema>;
export class SendFlashMsg extends OneBotAction<Payload, unknown> {
export class SendFlashMsg extends OneBotAction<SendFlashMsgPayload, any> {
override actionName = ActionName.SendFlashMsg;
override payloadSchema = SchemaData;
override payloadSchema = SendFlashMsgPayloadSchema;
override returnSchema = Type.Any({ description: '发送结果' });
async _handle (payload: Payload) {
async _handle (payload: SendFlashMsgPayload) {
let peer: Peer;
if (payload.group_id) {

View File

@ -3,18 +3,19 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { ChatType } from 'napcat-core/types';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
msg_id: Type.String(),
export const CancelOnlineFilePayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: '用户 QQ' }),
msg_id: Type.String({ description: '消息 ID' }),
});
type Payload = Static<typeof SchemaData>;
export type CancelOnlineFilePayload = Static<typeof CancelOnlineFilePayloadSchema>;
export class CancelOnlineFile extends OneBotAction<Payload, unknown> {
export class CancelOnlineFile extends OneBotAction<CancelOnlineFilePayload, any> {
override actionName = ActionName.CancelOnlineFile;
override payloadSchema = SchemaData;
override payloadSchema = CancelOnlineFilePayloadSchema;
override returnSchema = Type.Any({ description: '取消结果' });
async _handle (payload: Payload) {
async _handle (payload: CancelOnlineFilePayload) {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('User not found');

View File

@ -3,17 +3,18 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { ChatType } from 'napcat-core/types';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
export const GetOnlineFileMessagesPayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: '用户 QQ' }),
});
type Payload = Static<typeof SchemaData>;
export type GetOnlineFileMessagesPayload = Static<typeof GetOnlineFileMessagesPayloadSchema>;
export class GetOnlineFileMessages extends OneBotAction<Payload, unknown> {
export class GetOnlineFileMessages extends OneBotAction<GetOnlineFileMessagesPayload, any> {
override actionName = ActionName.GetOnlineFileMessages;
override payloadSchema = SchemaData;
override payloadSchema = GetOnlineFileMessagesPayloadSchema;
override returnSchema = Type.Any({ description: '在线文件消息列表' });
async _handle (payload: Payload) {
async _handle (payload: GetOnlineFileMessagesPayload) {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('User not found');

View File

@ -3,19 +3,20 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { ChatType } from 'napcat-core/types';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
msg_id: Type.String(),
element_id: Type.String(),
export const ReceiveOnlineFilePayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: '用户 QQ' }),
msg_id: Type.String({ description: '消息 ID' }),
element_id: Type.String({ description: '元素 ID' }),
});
type Payload = Static<typeof SchemaData>;
export type ReceiveOnlineFilePayload = Static<typeof ReceiveOnlineFilePayloadSchema>;
export class ReceiveOnlineFile extends OneBotAction<Payload, unknown> {
export class ReceiveOnlineFile extends OneBotAction<ReceiveOnlineFilePayload, any> {
override actionName = ActionName.ReceiveOnlineFile;
override payloadSchema = SchemaData;
override payloadSchema = ReceiveOnlineFilePayloadSchema;
override returnSchema = Type.Any({ description: '接收结果' });
async _handle (payload: Payload) {
async _handle (payload: ReceiveOnlineFilePayload) {
// 默认下载路径
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('User not found');

View File

@ -3,19 +3,20 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { ChatType } from 'napcat-core/types';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
msg_id: Type.String(),
element_id: Type.String(),
export const RefuseOnlineFilePayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: '用户 QQ' }),
msg_id: Type.String({ description: '消息 ID' }),
element_id: Type.String({ description: '元素 ID' }),
});
type Payload = Static<typeof SchemaData>;
export type RefuseOnlineFilePayload = Static<typeof RefuseOnlineFilePayloadSchema>;
export class RefuseOnlineFile extends OneBotAction<Payload, unknown> {
export class RefuseOnlineFile extends OneBotAction<RefuseOnlineFilePayload, any> {
override actionName = ActionName.RefuseOnlineFile;
override payloadSchema = SchemaData;
override payloadSchema = RefuseOnlineFilePayloadSchema;
override returnSchema = Type.Any({ description: '拒绝结果' });
async _handle (payload: Payload) {
async _handle (payload: RefuseOnlineFilePayload) {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('User not found');

View File

@ -3,19 +3,20 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { ChatType } from 'napcat-core/types';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
file_path: Type.String(),
file_name: Type.Optional(Type.String()),
export const SendOnlineFilePayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: '用户 QQ' }),
file_path: Type.String({ description: '本地文件路径' }),
file_name: Type.Optional(Type.String({ description: '文件名 (可选)' })),
});
type Payload = Static<typeof SchemaData>;
export type SendOnlineFilePayload = Static<typeof SendOnlineFilePayloadSchema>;
export class SendOnlineFile extends OneBotAction<Payload, unknown> {
export class SendOnlineFile extends OneBotAction<SendOnlineFilePayload, any> {
override actionName = ActionName.SendOnlineFile;
override payloadSchema = SchemaData;
override payloadSchema = SendOnlineFilePayloadSchema;
override returnSchema = Type.Any({ description: '发送结果' });
async _handle (payload: Payload) {
async _handle (payload: SendOnlineFilePayload) {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('User not found');

View File

@ -3,19 +3,20 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { ChatType } from 'napcat-core/types';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
folder_path: Type.String(),
folder_name: Type.Optional(Type.String()),
export const SendOnlineFolderPayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: '用户 QQ' }),
folder_path: Type.String({ description: '本地文件夹路径' }),
folder_name: Type.Optional(Type.String({ description: '文件夹名称 (可选)' })),
});
type Payload = Static<typeof SchemaData>;
export type SendOnlineFolderPayload = Static<typeof SendOnlineFolderPayloadSchema>;
export class SendOnlineFolder extends OneBotAction<Payload, unknown> {
export class SendOnlineFolder extends OneBotAction<SendOnlineFolderPayload, any> {
override actionName = ActionName.SendOnlineFolder;
override payloadSchema = SchemaData;
override payloadSchema = SendOnlineFolderPayloadSchema;
override returnSchema = Type.Any({ description: '发送结果' });
async _handle (payload: Payload) {
async _handle (payload: SendOnlineFolderPayload) {
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error('User not found');

View File

@ -2,23 +2,28 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
// 兼容gocq 与name二选一
folder_name: Type.Optional(Type.String()),
folder_name: Type.Optional(Type.String({ description: '文件夹名称' })),
// 兼容gocq 与folder_name二选一
name: Type.Optional(Type.String()),
name: Type.Optional(Type.String({ description: '文件夹名称' })),
});
type Payload = Static<typeof SchemaData>;
interface ResponseType {
result: unknown;
groupItem: unknown;
}
export class CreateGroupFileFolder extends OneBotAction<Payload, ResponseType> {
type PayloadType = Static<typeof PayloadSchema>;
const ReturnSchema = Type.Object({
result: Type.Any({ description: '操作结果' }),
groupItem: Type.Any({ description: '群项信息' }),
}, { description: '创建文件夹结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class CreateGroupFileFolder extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_CreateGroupFileFolder;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
const folderName = payload.folder_name || payload.name;
return (await this.core.apis.GroupApi.creatGroupFileFolder(payload.group_id.toString(), folderName!)).resultWithGroupItem;
}

View File

@ -4,17 +4,22 @@ import { FileNapCatOneBotUUID } from 'napcat-common/src/file-uuid';
import { Static, Type } from '@sinclair/typebox';
import { NTQQGroupApi } from 'napcat-core/apis';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
file_id: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
file_id: Type.String({ description: '文件ID' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class DeleteGroupFile extends OneBotAction<Payload, Awaited<ReturnType<NTQQGroupApi['delGroupFile']>>> {
const ReturnSchema = Type.Any({ description: '删除结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class DeleteGroupFile extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GOCQHTTP_DeleteGroupFile;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
const data = FileNapCatOneBotUUID.decodeModelId(payload.file_id);
if (!data || !data.fileId) throw new Error('Invalid file_id');
return await this.core.apis.GroupApi.delGroupFile(payload.group_id.toString(), [data.fileId]);

View File

@ -3,18 +3,23 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { Static, Type } from '@sinclair/typebox';
import { NTQQGroupApi } from 'napcat-core/apis';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
folder_id: Type.Optional(Type.String()),
folder: Type.Optional(Type.String()),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
folder_id: Type.Optional(Type.String({ description: '文件夹ID' })),
folder: Type.Optional(Type.String({ description: '文件夹ID' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class DeleteGroupFileFolder extends OneBotAction<Payload, Awaited<ReturnType<NTQQGroupApi['delGroupFileFolder']>>['groupFileCommonResult']> {
const ReturnSchema = Type.Any({ description: '删除结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class DeleteGroupFileFolder extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_DeleteGroupFileFolder;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
return (await this.core.apis.GroupApi.delGroupFileFolder(
payload.group_id.toString(), payload.folder ?? payload.folder_id ?? '')).groupFileCommonResult;
}

View File

@ -6,24 +6,27 @@ import { calculateFileMD5, uriToLocalFile } from 'napcat-common/src/file';
import { randomUUID } from 'crypto';
import { Static, Type } from '@sinclair/typebox';
interface FileResponse {
file: string;
}
const SchemaData = Type.Object({
url: Type.Optional(Type.String()),
base64: Type.Optional(Type.String()),
name: Type.Optional(Type.String()),
headers: Type.Optional(Type.Union([Type.String(), Type.Array(Type.String())])),
const PayloadSchema = Type.Object({
url: Type.Optional(Type.String({ description: '下载链接' })),
base64: Type.Optional(Type.String({ description: 'base64数据' })),
name: Type.Optional(Type.String({ description: '文件名' })),
headers: Type.Optional(Type.Union([Type.String(), Type.Array(Type.String())], { description: '请求头' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class GoCQHTTPDownloadFile extends OneBotAction<Payload, FileResponse> {
const ReturnSchema = Type.Object({
file: Type.String({ description: '文件路径' }),
}, { description: '下载结果' });
type ReturnType = Static<typeof ReturnSchema>;
export default class GoCQHTTPDownloadFile extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_DownloadFile;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload): Promise<FileResponse> {
async _handle (payload: PayloadType): Promise<ReturnType> {
const isRandomName = !payload.name;
const name = payload.name || randomUUID();
let result: Awaited<ReturnType<typeof uriToLocalFile>>;

View File

@ -6,17 +6,23 @@ import { Static, Type } from '@sinclair/typebox';
import { ChatType, ElementType, MsgSourceType, NTMsgType, RawMessage } from 'napcat-core';
import { isNumeric } from 'napcat-common/src/helper';
const SchemaData = Type.Object({
message_id: Type.Optional(Type.String()),
id: Type.Optional(Type.String()),
const PayloadSchema = Type.Object({
message_id: Type.Optional(Type.String({ description: '消息ID' })),
id: Type.Optional(Type.String({ description: '消息ID' })),
});
type Payload = Static<typeof SchemaData>;
export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, {
messages: OB11Message[] | undefined;
}> {
type PayloadType = Static<typeof PayloadSchema>;
const ReturnSchema = Type.Object({
messages: Type.Optional(Type.Array(Type.Any(), { description: '消息列表' })),
}, { description: '合并转发消息' });
type ReturnType = Static<typeof ReturnSchema>;
export class GoCQHTTPGetForwardMsgAction extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetForwardMsg;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
private createTemplateNode (message: OB11Message): OB11MessageNode {
return {
@ -52,7 +58,7 @@ export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, {
return retMsg;
}
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
// 1. 检查消息ID是否存在
const msgId = payload.message_id || payload.id;
if (!msgId) {

View File

@ -7,27 +7,31 @@ import { MessageUnique } from 'napcat-common/src/message-unique';
import { Static, Type } from '@sinclair/typebox';
import { NetworkAdapterConfig } from '@/napcat-onebot/config/config';
interface Response {
messages: OB11Message[];
}
const SchemaData = Type.Object({
user_id: Type.String(),
message_seq: Type.Optional(Type.String()),
count: Type.Number({ default: 20 }),
reverse_order: Type.Boolean({ default: false }),
disable_get_url: Type.Boolean({ default: false }),
parse_mult_msg: Type.Boolean({ default: true }),
quick_reply: Type.Boolean({ default: false }),
reverseOrder: Type.Boolean({ default: false }),// @deprecated 兼容旧版本
const PayloadSchema = Type.Object({
user_id: Type.String({ description: '用户QQ' }),
message_seq: Type.Optional(Type.String({ description: '起始消息序号' })),
count: Type.Number({ default: 20, description: '获取消息数量' }),
reverse_order: Type.Boolean({ default: false, description: '是否反向排序' }),
disable_get_url: Type.Boolean({ default: false, description: '是否禁用获取URL' }),
parse_mult_msg: Type.Boolean({ default: true, description: '是否解析合并消息' }),
quick_reply: Type.Boolean({ default: false, description: '是否快速回复' }),
reverseOrder: Type.Boolean({ default: false, description: '是否反向排序(旧版本兼容)' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class GetFriendMsgHistory extends OneBotAction<Payload, Response> {
const ReturnSchema = Type.Object({
messages: Type.Array(Type.Any(), { description: '消息列表' }),
}, { description: '好友历史消息' });
type ReturnType = Static<typeof ReturnSchema>;
export default class GetFriendMsgHistory extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetFriendMsgHistory;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload, _adapter: string, config: NetworkAdapterConfig): Promise<Response> {
async _handle (payload: PayloadType, _adapter: string, config: NetworkAdapterConfig): Promise<ReturnType> {
// 处理参数
const uid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!uid) throw new Error(`记录${payload.user_id}不存在`);
@ -47,6 +51,6 @@ export default class GetFriendMsgHistory extends OneBotAction<Payload, Response>
const ob11MsgList = (await Promise.all(
msgList.map(msg => this.obContext.apis.MsgApi.parseMessage(msg, config.messagePostFormat, payload.parse_mult_msg, payload.disable_get_url)))
).filter(msg => msg !== undefined);
return { messages: ob11MsgList };
return { messages: ob11MsgList as OB11Message[] };
}
}

View File

@ -2,21 +2,26 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
interface ResponseType {
can_at_all: boolean;
remain_at_all_count_for_group: number;
remain_at_all_count_for_uin: number;
}
export class GoCQHTTPGetGroupAtAllRemain extends OneBotAction<Payload, ResponseType> {
override actionName = ActionName.GoCQHTTP_GetGroupAtAllRemain;
override payloadSchema = SchemaData;
type PayloadType = Static<typeof PayloadSchema>;
async _handle (payload: Payload) {
const ReturnSchema = Type.Object({
can_at_all: Type.Boolean({ description: '是否可以艾特全体' }),
remain_at_all_count_for_group: Type.Number({ description: '群艾特全体剩余次数' }),
remain_at_all_count_for_uin: Type.Number({ description: '个人艾特全体剩余次数' }),
}, { description: '群艾特全体剩余次数' });
type ReturnType = Static<typeof ReturnSchema>;
export class GoCQHTTPGetGroupAtAllRemain extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetGroupAtAllRemain;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
const ret = await this.core.apis.GroupApi.getGroupRemainAtTimes(payload.group_id.toString());
const data = {
can_at_all: ret.atInfo.canAtAll,

View File

@ -2,22 +2,27 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupFileSystemInfo extends OneBotAction<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
}> {
const ReturnSchema = Type.Object({
file_count: Type.Number({ description: '文件总数' }),
limit_count: Type.Number({ description: '文件上限' }),
used_space: Type.Number({ description: '已使用空间' }),
total_space: Type.Number({ description: '总空间' }),
}, { description: '群文件系统信息' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupFileSystemInfo extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetGroupFileSystemInfo;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const groupFileCount = (await this.core.apis.GroupApi.getGroupFileCount([payload.group_id.toString()])).groupFileCounts[0];
if (!groupFileCount) {
throw new Error('Group not found');

View File

@ -3,22 +3,27 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { OB11Construct } from '@/napcat-onebot/helper/data';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
folder_id: Type.Optional(Type.String()),
folder: Type.Optional(Type.String()),
file_count: Type.Union([Type.Number(), Type.String()], { default: 50 }),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
folder_id: Type.Optional(Type.String({ description: '文件夹ID' })),
folder: Type.Optional(Type.String({ description: '文件夹ID' })),
file_count: Type.Union([Type.Number(), Type.String()], { default: 50, description: '文件数量' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupFilesByFolder extends OneBotAction<Payload, {
files: ReturnType<typeof OB11Construct.file>[],
folders: never[],
}> {
const ReturnSchema = Type.Object({
files: Type.Array(Type.Any(), { description: '文件列表' }),
folders: Type.Array(Type.Any(), { description: '文件夹列表' }),
}, { description: '群文件夹文件列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupFilesByFolder extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetGroupFilesByFolder;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: +payload.file_count,

View File

@ -3,28 +3,31 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { WebHonorType } from 'napcat-core/types';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
type: Type.Optional(Type.Enum(WebHonorType)),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
type: Type.Optional(Type.Enum(WebHonorType, { description: '荣誉类型' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
interface HonorInfo {
group_id: number;
current_talkative: Record<string, unknown>;
talkative_list: unknown[];
performer_list: unknown[];
legend_list: unknown[];
emotion_list: unknown[];
strong_newbie_list: unknown[];
}
const ReturnSchema = Type.Object({
group_id: Type.Number({ description: '群号' }),
current_talkative: Type.Record(Type.String(), Type.Unknown(), { description: '当前龙王' }),
talkative_list: Type.Array(Type.Unknown(), { description: '龙王列表' }),
performer_list: Type.Array(Type.Unknown(), { description: '群聊之火列表' }),
legend_list: Type.Array(Type.Unknown(), { description: '群聊炽热列表' }),
emotion_list: Type.Array(Type.Unknown(), { description: '快乐源泉列表' }),
strong_newbie_list: Type.Array(Type.Unknown(), { description: '冒尖小春笋列表' }),
}, { description: '群荣誉信息' });
export class GetGroupHonorInfo extends OneBotAction<Payload, HonorInfo> {
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupHonorInfo extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupHonorInfo;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType): Promise<ReturnType> {
if (!payload.type) {
payload.type = WebHonorType.ALL;
}

View File

@ -6,28 +6,31 @@ import { MessageUnique } from 'napcat-common/src/message-unique';
import { Static, Type } from '@sinclair/typebox';
import { NetworkAdapterConfig } from '@/napcat-onebot/config/config';
interface Response {
messages: OB11Message[];
}
const SchemaData = Type.Object({
group_id: Type.String(),
message_seq: Type.Optional(Type.String()),
count: Type.Number({ default: 20 }),
reverse_order: Type.Boolean({ default: false }),
disable_get_url: Type.Boolean({ default: false }),
parse_mult_msg: Type.Boolean({ default: true }),
quick_reply: Type.Boolean({ default: false }),
reverseOrder: Type.Boolean({ default: false }),// @deprecated 兼容旧版本
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
message_seq: Type.Optional(Type.String({ description: '起始消息序号' })),
count: Type.Number({ default: 20, description: '获取消息数量' }),
reverse_order: Type.Boolean({ default: false, description: '是否反向排序' }),
disable_get_url: Type.Boolean({ default: false, description: '是否禁用获取URL' }),
parse_mult_msg: Type.Boolean({ default: true, description: '是否解析合并消息' }),
quick_reply: Type.Boolean({ default: false, description: '是否快速回复' }),
reverseOrder: Type.Boolean({ default: false, description: '是否反向排序(旧版本兼容)' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class GoCQHTTPGetGroupMsgHistory extends OneBotAction<Payload, Response> {
const ReturnSchema = Type.Object({
messages: Type.Array(Type.Any(), { description: '消息列表' }),
}, { description: '群历史消息' });
type ReturnType = Static<typeof ReturnSchema>;
export default class GoCQHTTPGetGroupMsgHistory extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetGroupMsgHistory;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload, _adapter: string, config: NetworkAdapterConfig): Promise<Response> {
async _handle (payload: PayloadType, _adapter: string, config: NetworkAdapterConfig): Promise<ReturnType> {
const peer: Peer = { chatType: ChatType.KCHATTYPEGROUP, peerUid: payload.group_id.toString() };
const hasMessageSeq = !payload.message_seq ? !!payload.message_seq : !(payload.message_seq?.toString() === '' || payload.message_seq?.toString() === '0');
// 拉取消息
@ -44,6 +47,6 @@ export default class GoCQHTTPGetGroupMsgHistory extends OneBotAction<Payload, Re
const ob11MsgList = (await Promise.all(
msgList.map(msg => this.obContext.apis.MsgApi.parseMessage(msg, config.messagePostFormat, payload.parse_mult_msg, payload.disable_get_url, payload.quick_reply)))
).filter(msg => msg !== undefined);
return { messages: ob11MsgList };
return { messages: ob11MsgList as OB11Message[] };
}
}

View File

@ -1,23 +1,27 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { OB11GroupFile, OB11GroupFileFolder } from '@/napcat-onebot/index';
import { OB11Construct } from '@/napcat-onebot/helper/data';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
file_count: Type.Union([Type.Number(), Type.String()], { default: 50 }),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
file_count: Type.Union([Type.Number(), Type.String()], { default: 50, description: '文件数量' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupRootFiles extends OneBotAction<Payload, {
files: OB11GroupFile[],
folders: OB11GroupFileFolder[],
}> {
const ReturnSchema = Type.Object({
files: Type.Array(Type.Any(), { description: '文件列表' }),
folders: Type.Array(Type.Any(), { description: '文件夹列表' }),
}, { description: '群根目录文件列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupRootFiles extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetGroupRootFiles;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: +payload.file_count,

View File

@ -2,8 +2,19 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { sleep } from 'napcat-common/src/helper';
export class GetOnlineClient extends OneBotAction<void, Array<void>> {
const PayloadSchema = Type.Object({}, { description: '在线客户端负载' });
type PayloadType = Static<typeof PayloadSchema>;
const ReturnSchema = Type.Array(Type.Any(), { description: '在线客户端列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetOnlineClient extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetOnlineClient;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle () {
// 注册监听
this.core.apis.SystemApi.getOnlineDev();

View File

@ -5,17 +5,38 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { calcQQLevel } from 'napcat-common/src/helper';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
no_cache: Type.Union([Type.Boolean(), Type.String()], { default: false }),
const PayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: '用户QQ' }),
no_cache: Type.Union([Type.Boolean(), Type.String()], { default: false, description: '是否不使用缓存' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export default class GoCQHTTPGetStrangerInfo extends OneBotAction<Payload, OB11User & { uid: string }> {
const ReturnSchema = Type.Object({
user_id: Type.Number({ description: '用户QQ' }),
uid: Type.String({ description: 'UID' }),
nickname: Type.String({ description: '昵称' }),
age: Type.Number({ description: '年龄' }),
qid: Type.String({ description: 'QID' }),
qqLevel: Type.Number({ description: 'QQ等级' }),
sex: Type.String({ description: '性别' }),
long_nick: Type.String({ description: '个性签名' }),
reg_time: Type.Number({ description: '注册时间' }),
is_vip: Type.Boolean({ description: '是否VIP' }),
is_years_vip: Type.Boolean({ description: '是否年费VIP' }),
vip_level: Type.Number({ description: 'VIP等级' }),
remark: Type.String({ description: '备注' }),
status: Type.Number({ description: '状态' }),
login_days: Type.Number({ description: '登录天数' }),
}, { description: '陌生人信息' });
type ReturnType = Static<typeof ReturnSchema>;
export default class GoCQHTTPGetStrangerInfo extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetStrangerInfo;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
const user_id = payload.user_id.toString();
const isNocache = typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache;
const extendData = await this.core.apis.UserApi.getUserDetailInfoByUin(user_id);

View File

@ -2,15 +2,22 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
url: Type.String(),
export const GoCQHTTPCheckUrlSafelyPayloadSchema = Type.Object({
url: Type.String({ description: '要检查的 URL' }),
});
type Payload = Static<typeof SchemaData>;
export type GoCQHTTPCheckUrlSafelyPayload = Static<typeof GoCQHTTPCheckUrlSafelyPayloadSchema>;
export class GoCQHTTPCheckUrlSafely extends OneBotAction<Payload, { level: number }> {
export const GoCQHTTPCheckUrlSafelyReturnSchema = Type.Object({
level: Type.Number({ description: '安全等级 (1: 安全, 2: 未知, 3: 危险)' }),
});
export type GoCQHTTPCheckUrlSafelyReturn = Static<typeof GoCQHTTPCheckUrlSafelyReturnSchema>;
export class GoCQHTTPCheckUrlSafely extends OneBotAction<GoCQHTTPCheckUrlSafelyPayload, GoCQHTTPCheckUrlSafelyReturn> {
override actionName = ActionName.GoCQHTTP_CheckUrlSafely;
override payloadSchema = SchemaData;
override payloadSchema = GoCQHTTPCheckUrlSafelyPayloadSchema;
override returnSchema = GoCQHTTPCheckUrlSafelyReturnSchema;
async _handle () {
return { level: 1 };

View File

@ -2,20 +2,21 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
friend_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
user_id: Type.Optional(Type.Union([Type.String(), Type.Number()])),
temp_block: Type.Optional(Type.Boolean()),
temp_both_del: Type.Optional(Type.Boolean()),
export const GoCQHTTPDeleteFriendPayloadSchema = Type.Object({
friend_id: Type.Optional(Type.Union([Type.String(), Type.Number()], { description: '好友 QQ 号' })),
user_id: Type.Optional(Type.Union([Type.String(), Type.Number()], { description: '用户 QQ 号' })),
temp_block: Type.Optional(Type.Boolean({ description: '是否加入黑名单' })),
temp_both_del: Type.Optional(Type.Boolean({ description: '是否双向删除' })),
});
type Payload = Static<typeof SchemaData>;
export type GoCQHTTPDeleteFriendPayload = Static<typeof GoCQHTTPDeleteFriendPayloadSchema>;
export class GoCQHTTPDeleteFriend extends OneBotAction<Payload, unknown> {
export class GoCQHTTPDeleteFriend extends OneBotAction<GoCQHTTPDeleteFriendPayload, any> {
override actionName = ActionName.GoCQHTTP_DeleteFriend;
override payloadSchema = SchemaData;
override payloadSchema = GoCQHTTPDeleteFriendPayloadSchema;
override returnSchema = Type.Any();
async _handle (payload: Payload) {
async _handle (payload: GoCQHTTPDeleteFriendPayload) {
const uin = payload.friend_id ?? payload.user_id ?? '';
const uid = await this.core.apis.UserApi.getUidByUinV2(uin.toString());

View File

@ -2,22 +2,27 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
model: Type.Optional(Type.String()),
export const GoCQHTTPGetModelShowPayloadSchema = Type.Object({
model: Type.Optional(Type.String({ description: '模型名称' })),
});
type Payload = Static<typeof SchemaData>;
export type GoCQHTTPGetModelShowPayload = Static<typeof GoCQHTTPGetModelShowPayloadSchema>;
export class GoCQHTTPGetModelShow extends OneBotAction<Payload, Array<{
variants: {
model_show: string;
need_pay: boolean;
}
}>> {
export const GoCQHTTPGetModelShowReturnSchema = Type.Array(Type.Object({
variants: Type.Object({
model_show: Type.String({ description: '显示名称' }),
need_pay: Type.Boolean({ description: '是否需要付费' }),
}),
}), { description: '模型显示列表' });
export type GoCQHTTPGetModelShowReturn = Static<typeof GoCQHTTPGetModelShowReturnSchema>;
export class GoCQHTTPGetModelShow extends OneBotAction<GoCQHTTPGetModelShowPayload, GoCQHTTPGetModelShowReturn> {
override actionName = ActionName.GoCQHTTP_GetModelShow;
override payloadSchema = SchemaData;
override payloadSchema = GoCQHTTPGetModelShowPayloadSchema;
override returnSchema = GoCQHTTPGetModelShowReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: GoCQHTTPGetModelShowPayload) {
if (!payload.model) {
payload.model = 'napcat';
}

View File

@ -1,8 +1,12 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Type } from '@sinclair/typebox';
// 兼容性代码
export class GoCQHTTPSetModelShow extends OneBotAction<void, void> {
override actionName = ActionName.GoCQHTTP_SetModelShow;
override payloadSchema = Type.Object({});
override returnSchema = Type.Null();
async _handle () {

View File

@ -1,19 +1,71 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { QuickAction, QuickActionEvent } from '@/napcat-onebot/types';
import { Static, Type } from '@sinclair/typebox';
interface Payload {
context: QuickActionEvent,
operation: QuickAction
}
const SenderSchema = Type.Object({
user_id: Type.Number({ description: '用户ID' }),
nickname: Type.String({ description: '昵称' }),
sex: Type.Optional(Type.String({ description: '性别' })),
age: Type.Optional(Type.Number({ description: '年龄' })),
card: Type.Optional(Type.String({ description: '群名片' })),
level: Type.Optional(Type.String({ description: '群等级' })),
role: Type.Optional(Type.String({ description: '群角色' })),
});
export class GoCQHTTPHandleQuickAction extends OneBotAction<Payload, null> {
// 定义 QuickAction 的详细 Schema
const QuickActionSchema = Type.Object({
reply: Type.Optional(Type.String({ description: '回复内容' })),
auto_escape: Type.Optional(Type.Boolean({ description: '是否作为纯文本发送' })),
at_sender: Type.Optional(Type.Boolean({ description: '是否 @ 发送者' })),
delete: Type.Optional(Type.Boolean({ description: '是否撤回该消息' })),
kick: Type.Optional(Type.Boolean({ description: '是否踢出发送者' })),
ban: Type.Optional(Type.Boolean({ description: '是否禁言发送者' })),
ban_duration: Type.Optional(Type.Number({ description: '禁言时长' })),
approve: Type.Optional(Type.Boolean({ description: '是否同意请求/加群' })),
remark: Type.Optional(Type.String({ description: '好友备注' })),
reason: Type.Optional(Type.String({ description: '拒绝理由' })),
}, { description: '快速操作内容' });
// 定义 QuickActionEvent 的详细 Schema
const QuickActionEventSchema = Type.Object({
time: Type.Number({ description: '事件发生时间' }),
self_id: Type.Number({ description: '收到事件的机器人 QQ 号' }),
post_type: Type.String({ description: '上报类型' }),
message_type: Type.Optional(Type.String({ description: '消息类型' })),
sub_type: Type.Optional(Type.String({ description: '消息子类型' })),
user_id: Type.Union([Type.Number(), Type.String()], { description: '发送者 QQ 号' }),
group_id: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: '群号' })),
message_id: Type.Optional(Type.Number({ description: '消息 ID' })),
message_seq: Type.Optional(Type.Number({ description: '消息序列号' })),
real_id: Type.Optional(Type.Number({ description: '真实消息 ID' })),
sender: Type.Optional(SenderSchema),
message: Type.Optional(Type.Any({ description: '消息内容' })),
message_format: Type.Optional(Type.String({ description: '消息格式' })),
raw_message: Type.Optional(Type.String({ description: '原始消息内容' })),
font: Type.Optional(Type.Number({ description: '字体' })),
notice_type: Type.Optional(Type.String({ description: '通知类型' })),
meta_event_type: Type.Optional(Type.String({ description: '元事件类型' })),
}, { description: '事件上下文' });
export const GoCQHTTPHandleQuickActionPayloadSchema = Type.Object({
context: QuickActionEventSchema,
operation: QuickActionSchema,
});
export type GoCQHTTPHandleQuickActionPayload = {
context: QuickActionEvent;
operation: QuickAction;
} & Static<typeof GoCQHTTPHandleQuickActionPayloadSchema>;
export class GoCQHTTPHandleQuickAction extends OneBotAction<GoCQHTTPHandleQuickActionPayload, void> {
override actionName = ActionName.GoCQHTTP_HandleQuickAction;
override payloadSchema = GoCQHTTPHandleQuickActionPayloadSchema;
override returnSchema = Type.Null();
async _handle (payload: Payload): Promise<null> {
async _handle (payload: GoCQHTTPHandleQuickActionPayload): Promise<void> {
this.obContext.apis.QuickActionApi
.handleQuickOperation(payload.context, payload.operation)
.catch(e => this.core.context.logger.logError(e));
return null;
}
}

View File

@ -1,32 +1,31 @@
import { ContextMode, normalize, ReturnDataType, SendMsgBase } from '@/napcat-onebot/action/msg/SendMsg';
import { OB11PostSendMsg } from '@/napcat-onebot/types';
import { ContextMode, normalize, ReturnDataType, SendMsgBase, SendMsgPayload } from '@/napcat-onebot/action/msg/SendMsg';
import { ActionName } from '@/napcat-onebot/action/router';
// 未验证
export class GoCQHTTPSendForwardMsgBase extends SendMsgBase {
protected override async check (payload: OB11PostSendMsg) {
if (payload.messages) payload.message = normalize(payload.messages);
protected override async check (payload: SendMsgPayload) {
if ((payload as any).messages) payload.message = normalize((payload as any).messages);
return super.check(payload);
}
}
export class GoCQHTTPSendForwardMsg extends GoCQHTTPSendForwardMsgBase {
override actionName = ActionName.GoCQHTTP_SendForwardMsg;
protected override async check (payload: OB11PostSendMsg) {
if (payload.messages) payload.message = normalize(payload.messages);
protected override async check (payload: SendMsgPayload) {
if ((payload as any).messages) payload.message = normalize((payload as any).messages);
return super.check(payload);
}
}
export class GoCQHTTPSendPrivateForwardMsg extends GoCQHTTPSendForwardMsgBase {
override actionName = ActionName.GoCQHTTP_SendPrivateForwardMsg;
override async _handle (payload: OB11PostSendMsg): Promise<ReturnDataType> {
override async _handle (payload: SendMsgPayload): Promise<ReturnDataType> {
return this.base_handle(payload, ContextMode.Private);
}
}
export class GoCQHTTPSendGroupForwardMsg extends GoCQHTTPSendForwardMsgBase {
override actionName = ActionName.GoCQHTTP_SendGroupForwardMsg;
override async _handle (payload: OB11PostSendMsg): Promise<ReturnDataType> {
override async _handle (payload: SendMsgPayload): Promise<ReturnDataType> {
return this.base_handle(payload, ContextMode.Group);
}
}

View File

@ -4,23 +4,24 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { unlink } from 'node:fs/promises';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
content: Type.String(),
image: Type.Optional(Type.String()),
pinned: Type.Union([Type.Number(), Type.String()], { default: 0 }),
type: Type.Union([Type.Number(), Type.String()], { default: 1 }),
confirm_required: Type.Union([Type.Number(), Type.String()], { default: 1 }),
is_show_edit_card: Type.Union([Type.Number(), Type.String()], { default: 0 }),
tip_window_type: Type.Union([Type.Number(), Type.String()], { default: 0 }),
export const SendGroupNoticePayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
content: Type.String({ description: '公告内容' }),
image: Type.Optional(Type.String({ description: '公告图片路径或 URL' })),
pinned: Type.Union([Type.Number(), Type.String()], { default: 0, description: '是否置顶 (0/1)' }),
type: Type.Union([Type.Number(), Type.String()], { default: 1, description: '类型 (默认为 1)' }),
confirm_required: Type.Union([Type.Number(), Type.String()], { default: 1, description: '是否需要确认 (0/1)' }),
is_show_edit_card: Type.Union([Type.Number(), Type.String()], { default: 0, description: '是否显示修改群名片引导 (0/1)' }),
tip_window_type: Type.Union([Type.Number(), Type.String()], { default: 0, description: '弹窗类型 (默认为 0)' }),
});
type Payload = Static<typeof SchemaData>;
export type SendGroupNoticePayload = Static<typeof SendGroupNoticePayloadSchema>;
export class SendGroupNotice extends OneBotAction<Payload, null> {
export class SendGroupNotice extends OneBotAction<SendGroupNoticePayload, void> {
override actionName = ActionName.GoCQHTTP_SendGroupNotice;
override payloadSchema = SchemaData;
async _handle (payload: Payload) {
override payloadSchema = SendGroupNoticePayloadSchema;
override returnSchema = Type.Null();
async _handle (payload: SendGroupNoticePayload) {
let UploadImage: { id: string, width: number, height: number; } | undefined;
if (payload.image) {
// 公告图逻辑

View File

@ -4,18 +4,19 @@ import { checkFileExistV2, uriToLocalFile } from 'napcat-common/src/file';
import { Static, Type } from '@sinclair/typebox';
import fs from 'node:fs/promises';
import { GeneralCallResult } from 'napcat-core';
const SchemaData = Type.Object({
file: Type.String(),
group_id: Type.Union([Type.Number(), Type.String()]),
export const SetGroupPortraitPayloadSchema = Type.Object({
file: Type.String({ description: '头像文件路径或 URL' }),
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
export type SetGroupPortraitPayload = Static<typeof SetGroupPortraitPayloadSchema>;
export default class SetGroupPortrait extends OneBotAction<Payload, GeneralCallResult> {
export default class SetGroupPortrait extends OneBotAction<SetGroupPortraitPayload, any> {
override actionName = ActionName.SetGroupPortrait;
override payloadSchema = SchemaData;
override payloadSchema = SetGroupPortraitPayloadSchema;
override returnSchema = Type.Any({ description: '设置结果' });
async _handle (payload: Payload): Promise<GeneralCallResult> {
async _handle (payload: SetGroupPortraitPayload): Promise<any> {
const { path, success } = (await uriToLocalFile(this.core.NapCatTempPath, payload.file));
if (!success) {
throw new Error(`头像${payload.file}设置失败,file字段可能格式不正确`);

View File

@ -3,18 +3,19 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
nickname: Type.String(),
personal_note: Type.Optional(Type.String()),
sex: Type.Optional(Type.Union([Type.Number(), Type.String()])), // 传Sex值建议传0
export const SetQQProfilePayloadSchema = Type.Object({
nickname: Type.String({ description: '昵称' }),
personal_note: Type.Optional(Type.String({ description: '个性签名' })),
sex: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: '性别 (0: 未知, 1: 男, 2: 女)' })), // 传Sex值建议传0
});
type Payload = Static<typeof SchemaData>;
export class SetQQProfile extends OneBotAction<Payload, Awaited<ReturnType<NTQQUserApi['modifySelfProfile']>> | null> {
export type SetQQProfilePayload = Static<typeof SetQQProfilePayloadSchema>;
export class SetQQProfile extends OneBotAction<SetQQProfilePayload, any> {
override actionName = ActionName.SetQQProfile;
override payloadSchema = SchemaData;
override payloadSchema = SetQQProfilePayloadSchema;
override returnSchema = Type.Any({ description: '设置结果' });
async _handle (payload: Payload) {
async _handle (payload: SetQQProfilePayload) {
const self = this.core.selfInfo;
const OldProfile = await this.core.apis.UserApi.getUserDetailInfo(self.uid);
return await this.core.apis.UserApi.modifySelfProfile({

View File

@ -6,26 +6,29 @@ import { uriToLocalFile } from 'napcat-common/src/file';
import { SendMessageContext } from '@/napcat-onebot/api';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
file: Type.String(),
name: Type.String(),
folder: Type.Optional(Type.String()),
folder_id: Type.Optional(Type.String()), // 临时扩展
upload_file: Type.Boolean({ default: true }),
export const GoCQHTTPUploadGroupFilePayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
file: Type.String({ description: '本地文件路径' }),
name: Type.String({ description: '文件名' }),
folder: Type.Optional(Type.String({ description: '父目录 ID' })),
folder_id: Type.Optional(Type.String({ description: '父目录 ID (兼容性字段)' })), // 临时扩展
upload_file: Type.Boolean({ default: true, description: '是否执行上传' }),
});
type Payload = Static<typeof SchemaData>;
export type GoCQHTTPUploadGroupFilePayload = Static<typeof GoCQHTTPUploadGroupFilePayloadSchema>;
interface UploadGroupFileResponse {
file_id: string | null;
}
export const GoCQHTTPUploadGroupFileReturnSchema = Type.Object({
file_id: Type.Union([Type.String(), Type.Null()], { description: '文件 ID' }),
});
export default class GoCQHTTPUploadGroupFile extends OneBotAction<Payload, UploadGroupFileResponse> {
export type GoCQHTTPUploadGroupFileResponse = Static<typeof GoCQHTTPUploadGroupFileReturnSchema>;
export default class GoCQHTTPUploadGroupFile extends OneBotAction<GoCQHTTPUploadGroupFilePayload, GoCQHTTPUploadGroupFileResponse> {
override actionName = ActionName.GoCQHTTP_UploadGroupFile;
override payloadSchema = SchemaData;
override payloadSchema = GoCQHTTPUploadGroupFilePayloadSchema;
override returnSchema = GoCQHTTPUploadGroupFileReturnSchema;
async _handle (payload: Payload): Promise<UploadGroupFileResponse> {
async _handle (payload: GoCQHTTPUploadGroupFilePayload): Promise<GoCQHTTPUploadGroupFileResponse> {
let file = payload.file;
if (fs.existsSync(file)) {
file = `file://${file}`;

View File

@ -7,24 +7,27 @@ import { SendMessageContext } from '@/napcat-onebot/api';
import { ContextMode, createContext } from '@/napcat-onebot/action/msg/SendMsg';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()]),
file: Type.String(),
name: Type.String(),
upload_file: Type.Boolean({ default: true }),
export const GoCQHTTPUploadPrivateFilePayloadSchema = Type.Object({
user_id: Type.Union([Type.Number(), Type.String()], { description: '用户 QQ' }),
file: Type.String({ description: '本地文件路径' }),
name: Type.String({ description: '文件名' }),
upload_file: Type.Boolean({ default: true, description: '是否执行上传' }),
});
type Payload = Static<typeof SchemaData>;
export type GoCQHTTPUploadPrivateFilePayload = Static<typeof GoCQHTTPUploadPrivateFilePayloadSchema>;
interface UploadPrivateFileResponse {
file_id: string | null;
}
export const GoCQHTTPUploadPrivateFileReturnSchema = Type.Object({
file_id: Type.Union([Type.String(), Type.Null()], { description: '文件 ID' }),
});
export default class GoCQHTTPUploadPrivateFile extends OneBotAction<Payload, UploadPrivateFileResponse> {
export type GoCQHTTPUploadPrivateFileResponse = Static<typeof GoCQHTTPUploadPrivateFileReturnSchema>;
export default class GoCQHTTPUploadPrivateFile extends OneBotAction<GoCQHTTPUploadPrivateFilePayload, GoCQHTTPUploadPrivateFileResponse> {
override actionName = ActionName.GOCQHTTP_UploadPrivateFile;
override payloadSchema = SchemaData;
override payloadSchema = GoCQHTTPUploadPrivateFilePayloadSchema;
override returnSchema = GoCQHTTPUploadPrivateFileReturnSchema;
async getPeer (payload: Payload): Promise<Peer> {
async getPeer (payload: GoCQHTTPUploadPrivateFilePayload): Promise<Peer> {
if (payload.user_id) {
const peerUid = await this.core.apis.UserApi.getUidByUinV2(payload.user_id.toString());
if (!peerUid) {

View File

@ -3,19 +3,25 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { MessageUnique } from 'napcat-common/src/message-unique';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
message_id: Type.Optional(Type.Union([Type.Number(), Type.String()])),
msg_seq: Type.Optional(Type.String()),
msg_random: Type.Optional(Type.String()),
group_id: Type.Optional(Type.String()),
const PayloadSchema = Type.Object({
message_id: Type.Optional(Type.Union([Type.Number(), Type.String()], { description: '消息ID' })),
msg_seq: Type.Optional(Type.String({ description: '消息序号' })),
msg_random: Type.Optional(Type.String({ description: '消息随机数' })),
group_id: Type.Optional(Type.String({ description: '群号' })),
});
type Payload = Static<typeof SchemaData>;
export default class DelEssenceMsg extends OneBotAction<Payload, unknown> {
override actionName = ActionName.DelEssenceMsg;
override payloadSchema = SchemaData;
type PayloadType = Static<typeof PayloadSchema>;
async _handle (payload: Payload): Promise<unknown> {
const ReturnSchema = Type.Any({ description: '操作结果' });
type ReturnType = Static<typeof ReturnSchema>;
export default class DelEssenceMsg extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.DelEssenceMsg;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType): Promise<ReturnType> {
// 如果直接提供了 msg_seq, msg_random, group_id,优先使用
if (payload.msg_seq && payload.msg_random && payload.group_id) {
return await this.core.apis.GroupApi.removeGroupEssenceBySeq(
@ -34,7 +40,7 @@ export default class DelEssenceMsg extends OneBotAction<Payload, unknown> {
if (!msg) {
const data = this.core.apis.GroupApi.essenceLRU.getValue(+payload.message_id);
if (!data) throw new Error('消息不存在');
const { msg_seq, msg_random, group_id } = JSON.parse(data) as { msg_seq: string, msg_random: string, group_id: string };
const { msg_seq, msg_random, group_id } = JSON.parse(data) as { msg_seq: string, msg_random: string, group_id: string; };
return await this.core.apis.GroupApi.removeGroupEssenceBySeq(group_id, msg_seq, msg_random);
}
return await this.core.apis.GroupApi.removeGroupEssence(

View File

@ -2,18 +2,23 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
notice_id: Type.String(),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
notice_id: Type.String({ description: '公告ID' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class DelGroupNotice extends OneBotAction<Payload, void> {
const ReturnSchema = Type.Any({ description: '操作结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class DelGroupNotice extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.DelGroupNotice;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const group = payload.group_id.toString();
const noticeId = payload.notice_id;
return await this.core.apis.GroupApi.deleteGroupBulletin(group, noticeId);

View File

@ -3,19 +3,24 @@ import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketS
import { AIVoiceChatType } from 'napcat-core/packet/entities/aiChat';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
character: Type.String(),
group_id: Type.Union([Type.Number(), Type.String()]),
text: Type.String(),
const PayloadSchema = Type.Object({
character: Type.String({ description: '角色ID' }),
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
text: Type.String({ description: '语音文本内容' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetAiRecord extends GetPacketStatusDepends<Payload, string> {
const ReturnSchema = Type.String({ description: '语音URL' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetAiRecord extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.GetAiRecord;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const rawRsp = await this.core.apis.PacketApi.pkt.operation.GetAiVoice(+payload.group_id, payload.character, payload.text, AIVoiceChatType.Sound);
if (!rawRsp.msgInfoBody[0]) {
throw new Error('No voice data');

View File

@ -2,17 +2,29 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupDetailInfo extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Object({
group_id: Type.Number({ description: '群号' }),
group_name: Type.String({ description: '群名称' }),
member_count: Type.Number({ description: '成员数量' }),
max_member_count: Type.Number({ description: '最大成员数量' }),
group_all_shut: Type.Number({ description: '全员禁言状态' }),
group_remark: Type.String({ description: '群备注' }),
}, { description: '群详细信息' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupDetailInfo extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupDetailInfo;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType): Promise<ReturnType> {
const data = await this.core.apis.GroupApi.fetchGroupDetail(payload.group_id.toString());
return {
...data,

View File

@ -6,15 +6,30 @@ import crypto from 'crypto';
import { Static, Type } from '@sinclair/typebox';
import { NetworkAdapterConfig } from '@/napcat-onebot/config/config';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupEssence extends OneBotAction<Payload, unknown> {
const ReturnSchema = Type.Array(Type.Object({
msg_seq: Type.Number({ description: '消息序号' }),
msg_random: Type.Number({ description: '消息随机数' }),
sender_id: Type.Number({ description: '发送者QQ' }),
sender_nick: Type.String({ description: '发送者昵称' }),
operator_id: Type.Number({ description: '操作者QQ' }),
operator_nick: Type.String({ description: '操作者昵称' }),
message_id: Type.Number({ description: '消息ID' }),
operator_time: Type.Number({ description: '操作时间' }),
content: Type.Array(Type.Any(), { description: '消息内容' }),
}), { description: '精华消息列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupEssence extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetEssenceMsg;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
private async msgSeqToMsgId (peer: Peer, msgSeq: string, msgRandom: string) {
const replyMsgList = (await this.core.apis.MsgApi.getMsgsBySeqAndCount(peer, msgSeq, 1, true, true)).msgList.find((msg) => msg.msgSeq === msgSeq && msg.msgRandom === msgRandom);
@ -27,10 +42,10 @@ export class GetGroupEssence extends OneBotAction<Payload, unknown> {
};
}
async _handle (payload: Payload, _adapter: string, config: NetworkAdapterConfig) {
async _handle (payload: PayloadType, _adapter: string, config: NetworkAdapterConfig): Promise<ReturnType> {
const msglist = (await this.core.apis.WebApi.getGroupEssenceMsgAll(payload.group_id.toString()))
.flatMap((e) => e?.data?.msg_list)
// 在群精华回空的时候会出现[null]的情况~ https://github.com/NapNeko/NapCatQQ/issues/1334
// 在群精华回空的时候会出现[null]的情况~ https://github.com/NapNeko/NapCatQQ/issues/1334
.filter(Boolean);
if (!msglist) {
throw new Error('获取失败');

View File

@ -3,18 +3,26 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Notify } from '@/napcat-onebot/types';
interface RetData {
invited_requests: Notify[];
InvitedRequest: Notify[];
join_requests: Notify[];
}
const PayloadSchema = Type.Object({}, { description: '群忽略通知负载' });
export class GetGroupIgnoredNotifies extends OneBotAction<void, RetData> {
type PayloadType = Static<typeof PayloadSchema>;
const ReturnSchema = Type.Object({
invited_requests: Type.Array(Type.Any(), { description: '邀请请求列表' }),
InvitedRequest: Type.Array(Type.Any(), { description: '邀请请求列表' }),
join_requests: Type.Array(Type.Any(), { description: '加入请求列表' }),
}, { description: '群忽略通知结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupIgnoredNotifies extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupIgnoredNotifies;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (): Promise<RetData> {
async _handle (): Promise<ReturnType> {
const SingleScreenNotifies = await this.core.apis.GroupApi.getSingleScreenNotifies(false, 50);
const retData: RetData = { invited_requests: [], InvitedRequest: [], join_requests: [] };
const retData: ReturnType = { invited_requests: [], InvitedRequest: [], join_requests: [] };
const notifyPromises = SingleScreenNotifies.map(async (SSNotify) => {
const invitorUin = SSNotify.user1?.uid ? +await this.core.apis.UserApi.getUinByUidV2(SSNotify.user1.uid) : 0;

View File

@ -1,20 +1,25 @@
import { OB11Group } from '@/napcat-onebot/index';
import { OB11Construct } from '@/napcat-onebot/helper/data';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { OB11GroupSchema } from '../schemas';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
class GetGroupInfo extends OneBotAction<Payload, OB11Group> {
const ReturnSchema = OB11GroupSchema;
type ReturnType = Static<typeof ReturnSchema>;
class GetGroupInfo extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupInfo;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const group = (await this.core.apis.GroupApi.getGroups()).find(e => e.groupCode === payload.group_id.toString());
if (!group) {
const data = await this.core.apis.GroupApi.fetchGroupDetail(payload.group_id.toString());

View File

@ -1,20 +1,25 @@
import { OB11Group } from '@/napcat-onebot/index';
import { OB11Construct } from '@/napcat-onebot/helper/data';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { OB11GroupSchema } from '../schemas';
const SchemaData = Type.Object({
no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
const PayloadSchema = Type.Object({
no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()], { description: '是否不使用缓存' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
class GetGroupList extends OneBotAction<Payload, OB11Group[]> {
const ReturnSchema = Type.Array(OB11GroupSchema, { description: '群列表' });
type ReturnType = Static<typeof ReturnSchema>;
class GetGroupList extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupList;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return OB11Construct.groups(
await this.core.apis.GroupApi.getGroups(
typeof payload.no_cache === 'string' ? payload.no_cache === 'true' : !!payload.no_cache));

View File

@ -1,20 +1,25 @@
import { OB11GroupMember } from '@/napcat-onebot/index';
import { OB11Construct } from '@/napcat-onebot/helper/data';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { OB11GroupMemberSchema } from '../schemas';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
user_id: Type.Union([Type.Number(), Type.String()]),
no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
user_id: Type.String({ description: 'QQ号' }),
no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()], { description: '是否不使用缓存' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
class GetGroupMemberInfo extends OneBotAction<Payload, OB11GroupMember> {
const ReturnSchema = OB11GroupMemberSchema;
type ReturnType = Static<typeof ReturnSchema>;
class GetGroupMemberInfo extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupMemberInfo;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
private parseBoolean (value: boolean | string): boolean {
return typeof value === 'string' ? value === 'true' : value;
@ -26,7 +31,7 @@ class GetGroupMemberInfo extends OneBotAction<Payload, OB11GroupMember> {
return uid;
}
private async getGroupMemberInfo (payload: Payload, uid: string, isNocache: boolean) {
private async getGroupMemberInfo (payload: PayloadType, uid: string, isNocache: boolean) {
const groupMemberCache = this.core.apis.GroupApi.groupMemberCache.get(payload.group_id.toString());
const groupMember = groupMemberCache?.get(uid);
@ -40,7 +45,7 @@ class GetGroupMemberInfo extends OneBotAction<Payload, OB11GroupMember> {
return info ? { ...groupMember, ...member, ...info } : member;
}
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const isNocache = this.parseBoolean(payload.no_cache ?? true);
const uid = await this.getUid(payload.user_id);
const member = await this.getGroupMemberInfo(payload, uid, isNocache);

View File

@ -5,18 +5,23 @@ import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { GroupMember } from 'napcat-core';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()])),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
no_cache: Type.Optional(Type.Union([Type.Boolean(), Type.String()], { description: '是否不使用缓存' })),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupMemberList extends OneBotAction<Payload, OB11GroupMember[]> {
const ReturnSchema = Type.Array(Type.Any(), { description: '群成员列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupMemberList extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupMemberList;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const groupIdStr = payload.group_id.toString();
const noCache = this.parseBoolean(payload.no_cache ?? false);
const groupMembers = await this.getGroupMembers(groupIdStr, noCache);

View File

@ -2,52 +2,41 @@ import { WebApiGroupNoticeFeed } from 'napcat-core';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
interface GroupNotice {
sender_id: number;
publish_time: number;
notice_id: string;
message: {
text: string;
// 保持一段时间兼容性 防止以往版本出现问题 后续版本可考虑移除
image: Array<{
height: string;
width: string;
id: string;
}>,
images: Array<{
height: string;
width: string;
id: string;
}>;
};
settings?: {
is_show_edit_card: number,
remind_ts: number,
tip_window_type: number,
confirm_required: number;
};
read_num?: number;
}
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
type ApiGroupNotice = GroupNotice & WebApiGroupNoticeFeed;
const ReturnSchema = Type.Array(Type.Object({
sender_id: Type.Number({ description: '发送者QQ' }),
publish_time: Type.Number({ description: '发布时间' }),
notice_id: Type.String({ description: '公告ID' }),
message: Type.Object({
text: Type.String({ description: '文本内容' }),
image: Type.Array(Type.Any(), { description: '图片列表' }),
images: Type.Array(Type.Any(), { description: '图片列表' }),
}, { description: '公告内容' }),
settings: Type.Optional(Type.Any({ description: '设置项' })),
read_num: Type.Optional(Type.Number({ description: '阅读数' })),
}), { description: '群公告列表' });
export class GetGroupNotice extends OneBotAction<Payload, GroupNotice[]> {
type ReturnType = Static<typeof ReturnSchema>;
type ApiGroupNotice = ReturnType[number] & WebApiGroupNoticeFeed;
export class GetGroupNotice extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetGroupNotice;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
const group = payload.group_id.toString();
const ret = await this.core.apis.WebApi.getGroupNotice(group);
if (!ret) {
throw new Error('获取公告失败');
}
const retNotices: GroupNotice[] = new Array<ApiGroupNotice>();
const retNotices: ReturnType = [];
for (const key in ret.feeds) {
if (!ret.feeds[key]) {
continue;
@ -57,7 +46,7 @@ export class GetGroupNotice extends OneBotAction<Payload, GroupNotice[]> {
return { id: pic.id, height: pic.h, width: pic.w };
}) || [];
const retNotice: GroupNotice = {
const retNotice: ReturnType[number] = {
notice_id: retApiNotice.fid,
sender_id: retApiNotice.u,
publish_time: retApiNotice.pubt,

View File

@ -3,17 +3,22 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class GetGroupShutList extends OneBotAction<Payload, ShutUpGroupMember[]> {
const ReturnSchema = Type.Array(Type.Any(), { description: '禁言成员列表' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetGroupShutList extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetGroupShutList;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.GroupApi.getGroupShutUpMemberList(payload.group_id.toString());
}
}

View File

@ -3,21 +3,26 @@ import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketS
import { AIVoiceChatType } from 'napcat-core/packet/entities/aiChat';
import { Static, Type } from '@sinclair/typebox';
const SchemaData = Type.Object({
character: Type.String(),
group_id: Type.Union([Type.Number(), Type.String()]),
text: Type.String(),
const PayloadSchema = Type.Object({
character: Type.String({ description: '角色ID' }),
group_id: Type.String({ description: '群号' }),
text: Type.String({ description: '语音文本内容' }),
});
type Payload = Static<typeof SchemaData>;
type PayloadType = Static<typeof PayloadSchema>;
export class SendGroupAiRecord extends GetPacketStatusDepends<Payload, {
message_id: number
}> {
const ReturnSchema = Type.Object({
message_id: Type.Number({ description: '消息ID' }),
}, { description: '发送结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class SendGroupAiRecord extends GetPacketStatusDepends<PayloadType, ReturnType> {
override actionName = ActionName.SendGroupAiRecord;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
await this.core.apis.PacketApi.pkt.operation.GetAiVoice(+payload.group_id, payload.character, payload.text, AIVoiceChatType.Sound);
return {
message_id: 0, // can't get message_id from GetAiVoice

Some files were not shown because too many files have changed in this diff Show More