This commit is contained in:
手瓜一十雪 2026-01-25 21:09:31 +08:00 committed by GitHub
commit b0231caf1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
185 changed files with 5213 additions and 4085 deletions

View File

@ -5,9 +5,10 @@ import { NapCatOneBot11Adapter, OB11Return } from '@/napcat-onebot/index';
import { NetworkAdapterConfig } from '../config/config';
import { TSchema } from '@sinclair/typebox';
import { StreamPacket, StreamPacketBasic, StreamStatus } from './stream/StreamBasic';
import { ActionExamples } from './examples';
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 +20,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,15 +33,22 @@ 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;
payloadExample?: unknown = undefined;
returnExample?: unknown = undefined;
actionSummary: string = '';
actionDescription: string = '';
actionTags: string[] = [];
obContext: NapCatOneBot11Adapter;
useStream: boolean = false;
errorExamples: Array<{ code: number, description: string; }> = ActionExamples.Common.errors;
constructor (obContext: NapCatOneBot11Adapter, core: NapCatCore) {
this.obContext = obContext;

View File

@ -0,0 +1,365 @@
export const ActionExamples = {
GetGroupInfo: {
payload: { group_id: '123456789' },
return: {
group_id: 123456789,
group_name: '测试群',
member_count: 10,
max_member_count: 500,
group_all_shut: 0,
group_remark: ''
}
},
GetGroupList: {
payload: {},
return: [
{
group_id: 123456789,
group_name: '测试群',
member_count: 10,
max_member_count: 500,
group_all_shut: 0,
group_remark: ''
}
]
},
GetGroupMemberList: {
payload: { group_id: '123456789' },
return: [
{
group_id: 123456789,
user_id: 987654321,
nickname: '测试成员',
card: '群名片',
role: 'member'
}
]
},
SendGroupMsg: {
payload: { group_id: '123456789', message: 'hello' },
return: { message_id: 123456 }
},
SendLike: {
payload: { user_id: '123456789', times: 1 },
return: null
},
GetFriendList: {
payload: {},
return: [
{
user_id: 123456789,
nickname: '测试好友',
remark: '备注'
}
]
},
GetStrangerInfo: {
payload: { user_id: '123456789' },
return: {
user_id: 123456789,
nickname: '陌生人',
sex: 'unknown',
age: 0
}
},
SetFriendRemark: {
payload: { user_id: '123456789', remark: '新备注' },
return: null
},
GetCookies: {
payload: { domain: 'qun.qq.com' },
return: { cookies: 'p_skey=xxxx; p_uin=xxxx', bkn: '123456' }
},
SendPrivateMsg: {
payload: { user_id: '123456789', message: 'hello' },
return: { message_id: 123456 }
},
OCRImage: {
payload: { image: 'https://example.com/test.jpg' },
return: [{ text: '识别文本', confidence: 0.99 }]
},
GetClientkey: {
payload: {},
return: { clientkey: 'abcdef123456' }
},
SetQQAvatar: {
payload: { file: 'base64://...' },
return: null
},
SetGroupKickMembers: {
payload: { group_id: '123456789', user_id: ['987654321'], reject_add_request: false },
return: null
},
GetLoginInfo: {
payload: {},
return: { user_id: 123456789, nickname: '机器人' }
},
GetVersionInfo: {
payload: {},
return: {
app_name: 'NapCatQQ',
app_version: '1.0.0',
protocol_version: 'v11'
}
},
GetStatus: {
payload: {},
return: { online: true, good: true }
},
DeleteMsg: {
payload: { message_id: 123456 },
return: null
},
SetGroupWholeBan: {
payload: { group_id: '123456789', enable: true },
return: null
},
SetGroupBan: {
payload: { group_id: '123456789', user_id: '987654321', duration: 1800 },
return: null
},
SetGroupKick: {
payload: { group_id: '123456789', user_id: '987654321', reject_add_request: false },
return: null
},
SetGroupAdmin: {
payload: { group_id: '123456789', user_id: '987654321', enable: true },
return: null
},
SetGroupName: {
payload: { group_id: '123456789', group_name: '新群名' },
return: null
},
SetGroupCard: {
payload: { group_id: '123456789', user_id: '987654321', card: '新名片' },
return: null
},
GetGroupMemberInfo: {
payload: { group_id: '123456789', user_id: '987654321' },
return: {
group_id: 123456789,
user_id: 987654321,
nickname: '成员昵称',
card: '名片',
role: 'member'
}
},
SendMsg: {
payload: { message_type: 'group', group_id: '123456789', message: 'hello' },
return: { message_id: 123456 }
},
GetMsg: {
payload: { message_id: 123456 },
return: {
time: 123456789,
message_type: 'group',
message_id: 123456,
real_id: 123456,
sender: { user_id: 987654321, nickname: '昵称' },
message: 'hello'
}
},
SetGroupLeave: {
payload: { group_id: '123456789', is_dismiss: false },
return: null
},
CanSendRecord: {
payload: {},
return: { yes: true }
},
CanSendImage: {
payload: {},
return: { yes: true }
},
SetFriendAddRequest: {
payload: { flag: '12345', approve: true, remark: '好友' },
return: null
},
SetGroupAddRequest: {
payload: { flag: '12345', sub_type: 'add', approve: true },
return: null
},
DelEssenceMsg: {
payload: { message_id: 12345 },
return: null
},
SetEssenceMsg: {
payload: { message_id: 12345 },
return: null
},
GetGroupEssence: {
payload: { group_id: '123456789' },
return: [
{
msg_seq: 12345,
msg_random: 67890,
sender_id: 987654321,
sender_nick: '发送者',
operator_id: 123456789,
operator_nick: '操作者',
message_id: 123456,
operator_time: 1234567890,
content: [{ type: 'text', data: { text: '精华消息内容' } }]
}
]
},
GetGroupShutList: {
payload: { group_id: '123456789' },
return: [
{
user_id: 987654321,
nickname: '禁言成员',
card: '名片',
shut_up_time: 1234567890
}
]
},
GetGroupDetailInfo: {
payload: { group_id: '123456789' },
return: {
group_id: 123456789,
group_name: '测试群',
member_count: 10,
max_member_count: 500,
group_all_shut: 0,
group_remark: ''
}
},
DelGroupNotice: {
payload: { group_id: '123456789', notice_id: 'abc-123' },
return: null
},
GetAiRecord: {
payload: { group_id: '123456789', character: 'ai' },
return: { msg: 'AI回复内容' }
},
GetGroupNotice: {
payload: { group_id: '123456789' },
return: [
{
notice_id: 'abc-123',
sender_id: 987654321,
publish_time: 1234567890,
message: { text: '公告内容', images: [] }
}
]
},
SendGroupAiRecord: {
payload: { group_id: '123456789', character: 'ai', text: '你好' },
return: { message_id: 123456 }
},
GetFile: {
payload: { file: 'abc-123' },
return: {
file: '/path/to/file',
url: 'http://example.com/file',
file_size: '1024',
file_name: 'test.txt'
}
},
GetImage: {
payload: { file: 'abc-123' },
return: {
file: '/path/to/image.jpg',
url: 'http://example.com/image.jpg',
file_size: '1024',
file_name: 'image.jpg'
}
},
GetRecord: {
payload: { file: 'abc-123', out_format: 'mp3' },
return: {
file: '/path/to/record.mp3',
url: 'http://example.com/record.mp3',
file_size: '1024',
file_name: 'record.mp3',
base64: '...'
}
},
GetGroupFileUrl: {
payload: { group_id: '123456789', file_id: 'abc-123' },
return: { url: 'http://example.com/group_file' }
},
GetPrivateFileUrl: {
payload: { file_id: 'abc-123' },
return: { url: 'http://example.com/private_file' }
},
GetAiCharacters: {
payload: { group_id: '123456789' },
return: [
{
type: '常用',
characters: [
{ character_id: 'ai-1', character_name: 'AI助手', preview_url: 'http://...' }
]
}
]
},
SetOnlineStatus: {
payload: { status: 11, ext_status: 0, battery_status: 100 },
return: null
},
SetGroupRemark: {
payload: { group_id: '123456789', remark: '群备注' },
return: null
},
GetCollectionList: {
payload: { category: '1', count: '10' },
return: []
},
SetSpecialTitle: {
payload: { group_id: '123456789', user_id: '987654321', special_title: '群头衔' },
return: null
},
MarkMsgAsRead: {
payload: { group_id: '123456789' },
return: null
},
ForwardSingleMsg: {
payload: { message_id: 12345, group_id: '123456789' },
return: null
},
SendPoke: {
payload: { group_id: '123456789', user_id: '987654321' },
return: null
},
SetGroupTodo: {
payload: { group_id: '123456789', message_id: '12345' },
return: null
},
GetCredentials: {
payload: { domain: 'qun.qq.com' },
return: { cookies: '...', token: 123456 }
},
GetGroupSystemMsg: {
payload: { count: 10 },
return: {
invited_requests: [],
InvitedRequest: [],
join_requests: []
}
},
GetRecentContact: {
payload: { count: 10 },
return: []
},
GetCSRF: {
payload: {},
return: { token: 123456789 }
},
SetMsgEmojiLike: {
payload: { message_id: 12345, emoji_id: '124' },
return: null
},
UploadGroupFile: {
payload: { group_id: '123456789', file: '/path/to/file', name: 'test.txt' },
return: null
},
Common: {
errors: [
{ code: 1400, description: '请求参数错误或业务逻辑执行失败' },
{ code: 1401, description: '权限不足' },
{ code: 1404, description: '资源不存在' }
]
}
};

View File

@ -1,8 +1,15 @@
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();
override actionSummary = '退出登录';
override actionTags = ['系统扩展'];
override payloadExample = {};
override returnExample = null;
async _handle () {
process.exit(0);

View File

@ -2,21 +2,33 @@ 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.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;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema; override actionSummary = '点击内联键盘按钮';
override actionTags = ['消息扩展'];
override payloadExample = {
message_id: 12345,
button_id: 'btn_1'
};
override returnExample = {
result: true
};
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,33 @@ 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;
override actionSummary = '创建收藏';
override actionTags = ['扩展接口'];
override payloadExample = {
rawData: '收藏内容',
brief: '收藏标题'
};
override returnExample = {
result: 0,
errMsg: ''
};
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,33 @@ 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 actionSummary = '删除群相册媒体';
override actionTags = ['群组扩展'];
override payloadExample = {
group_code: 123456,
media_id_list: ['media_id_1', 'media_id_2']
};
override returnExample = {
result: true
};
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,31 @@ 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 actionSummary = '发表群相册评论';
override actionTags = ['群组扩展'];
override payloadExample = {
group_code: 123456,
media_id: 'media_id_1',
content: '很有意思'
};
override returnExample = {
result: true
};
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,30 @@ 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;
override actionSummary = '获取自定义表情';
override actionTags = ['系统扩展'];
override payloadExample = {
count: 10
};
override returnExample = [
'http://example.com/face1.png'
];
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,53 @@ 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 actionSummary = '获取表情点赞详情';
override actionTags = ['消息扩展'];
override payloadExample = {
message_id: 12345
};
override returnExample = {
likes: [{ emoji_id: '123', count: 10 }]
};
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

@ -1,30 +1,46 @@
import { ActionName } from '@/napcat-onebot/action/router';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
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 }),
import { ExtendsActionsExamples } from './examples';
const PayloadSchema = Type.Object({
group_id: 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;
override actionSummary = '获取AI角色列表';
override actionDescription = '获取群聊中的AI角色列表';
override actionTags = ['扩展接口'];
override payloadExample = ExtendsActionsExamples.GetAiCharacters.payload;
override returnExample = ExtendsActionsExamples.GetAiCharacters.response;
async _handle (payload: Payload) {
const rawList = await this.core.apis.PacketApi.pkt.operation.FetchAiVoiceList(+payload.group_id, +payload.chat_type as AIVoiceChatType);
async _handle (payload: PayloadType) {
const chatTypeNum = Number(payload.chat_type);
const rawList = await this.core.apis.PacketApi.pkt.operation.FetchAiVoiceList(+payload.group_id, chatTypeNum);
return rawList?.map((item) => ({
type: item.category,
characters: item.voices.map((voice) => ({

View File

@ -1,12 +1,24 @@
import { ActionName } from '@/napcat-onebot/action/router';
import { OneBotAction } from '../OneBotAction';
import { Type, Static } from '@sinclair/typebox';
interface GetClientkeyResponse {
clientkey?: string;
}
import { ExtendsActionsExamples } from './examples';
export class GetClientkey extends OneBotAction<void, GetClientkeyResponse> {
const ReturnSchema = Type.Object({
clientkey: Type.Optional(Type.String({ description: '客户端Key' })),
}, { description: '获取ClientKey结果' });
type ReturnType = Static<typeof ReturnSchema>;
export class GetClientkey extends OneBotAction<void, ReturnType> {
override actionName = ActionName.GetClientkey;
override payloadSchema = Type.Void();
override returnSchema = ReturnSchema;
override actionSummary = '获取ClientKey';
override actionDescription = '获取当前登录帐号的ClientKey';
override actionTags = ['扩展接口'];
override payloadExample = ExtendsActionsExamples.GetClientkey.payload;
override returnExample = ExtendsActionsExamples.GetClientkey.response;
async _handle () {
return { clientkey: (await this.core.apis.UserApi.forceFetchClientKey()).clientKey };

View File

@ -1,20 +1,36 @@
import { type NTQQCollectionApi } from 'napcat-core/apis/collection';
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.String({ description: '分类ID' }),
count: 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;
override actionSummary = '获取收藏列表';
override actionTags = ['系统扩展'];
override payloadExample = {
category: '1',
count: '10'
};
override returnExample = [
{
collection_id: '123',
title: '收藏标题'
}
];
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.CollectionApi.getAllCollection(+payload.category, +payload.count);
}
}

View File

@ -26,7 +26,16 @@ type ReturnType = Static<typeof ReturnSchema>;
export class GetEmojiLikes extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GetEmojiLikes;
override actionSummary = '获取消息表情点赞列表';
override actionTags = ['消息扩展'];
override payloadExample = {
message_id: 12345
};
override returnExample = {
likes: [{ emoji_id: '123', user_id: 654321 }]
};
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: PayloadType) {
let peer: Peer;

View File

@ -1,12 +1,40 @@
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;
override actionSummary = '获取带分组的好友列表';
override actionTags = ['用户扩展'];
override payloadExample = {};
override returnExample = [
{
categoryId: 1,
categoryName: '我的好友',
categoryMbCount: 1,
buddyList: []
}
];
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,51 @@
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;
override actionSummary = '获取群被忽略的加群请求';
override actionTags = ['群组接口'];
override payloadExample = {};
override returnExample = [
{
request_id: 12345,
invitor_uin: 123456789,
invitor_nick: '邀请者',
group_id: 123456789,
message: '加群请求',
group_name: '群名称',
checked: false,
actor: 0,
requester_nick: '请求者'
}
];
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: ReturnType = [];
const notifyPromises = ignoredNotifies
.filter(notify => notify.type === 7)

View File

@ -2,19 +2,35 @@ 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 actionSummary = '获取群相册媒体列表';
override actionTags = ['群组扩展'];
override payloadExample = {
group_code: 123456,
album_id: 'album_id_1'
};
override returnExample = {
media_list: [
{ media_id: 'media_id_1', url: 'http://example.com/1.jpg' }
]
};
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,32 @@
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.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 actionSummary = '获取群详细信息 (扩展)';
override actionTags = ['群组扩展'];
override payloadExample = {
group_id: 123456
};
override returnExample = {
group_id: 123456,
group_name: '测试群',
member_count: 100
};
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

@ -1,57 +1,73 @@
import { ActionName } from '@/napcat-onebot/action/router';
import { GetPacketStatusDepends } from '@/napcat-onebot/action/packet/GetPacketStatus';
import { MiniAppInfo, MiniAppInfoHelper } from 'napcat-core/packet/utils/helper/miniAppHelper';
import { MiniAppData, MiniAppRawData, MiniAppReqCustomParams, MiniAppReqParams } from 'napcat-core/packet/entities/miniApp';
import { 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.String({ description: '场景ID' }),
templateType: Type.String({ description: '模板类型' }),
businessType: Type.String({ description: '业务类型' }),
verType: Type.String({ description: '版本类型' }),
shareType: Type.String({ description: '分享类型' }),
versionId: Type.String({ description: '版本ID' }),
sdkId: Type.String({ description: 'SDK ID' }),
withShareTicket: Type.String({ description: '是否携带分享票据' }),
rawArkData: Type.Optional(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;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema; override actionSummary = '获取小程序 Ark';
override actionTags = ['系统扩展'];
override payloadExample = {
app_id: 'wx123456'
};
override returnExample = {
ark: 'ark_content'
};
async _handle (payload: PayloadType) {
let reqParam: MiniAppReqParams;
const customParams = {
const customParams: MiniAppReqCustomParams = {
title: payload.title,
desc: payload.desc,
picUrl: payload.picUrl,
jumpUrl: payload.jumpUrl,
webUrl: payload.webUrl,
} as MiniAppReqCustomParams;
webUrl: payload.webUrl ?? '',
};
if ('type' in payload) {
reqParam = MiniAppInfoHelper.generateReq(customParams, MiniAppInfo.get(payload.type)!.template);
const template = MiniAppInfo.get(payload.type)?.template;
if (!template) {
throw new Error('未知的模板类型');
}
reqParam = MiniAppInfoHelper.generateReq(customParams, template);
} else {
const { appId, scene, iconUrl, templateType, businessType, verType, shareType, versionId, withShareTicket } = payload;
reqParam = MiniAppInfoHelper.generateReq(

View File

@ -1,36 +1,65 @@
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;
override actionSummary = '获取资料点赞';
override actionTags = ['用户扩展'];
override payloadExample = {
user_id: '123456789',
start: 0,
count: 10
};
override returnExample = {
uid: 'u_123',
time: '1734567890',
favoriteInfo: {
userInfos: [],
total_count: 10,
last_time: 1734567890,
today_count: 5
},
voteInfo: {
total_count: 100,
new_count: 2,
new_nearby_count: 0,
last_visit_time: 1734567890,
userInfos: []
}
};
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

@ -1,18 +1,34 @@
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(),
import { NTQQWebApi } from 'napcat-core/apis';
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 GetQunAlbumListReturn = Awaited<globalThis.ReturnType<NTQQWebApi['getAlbumListByNTQQ']>>['response']['album_list'];
export class GetQunAlbumList extends OneBotAction<PayloadType, GetQunAlbumListReturn> {
override actionName = ActionName.GetQunAlbumList;
override payloadSchema = SchemaData;
override actionSummary = '获取群相册列表';
override actionTags = ['群组扩展'];
override payloadExample = {
group_code: 123456
};
override returnExample = {
album_list: [
{ album_id: 'album_id_1', album_name: '相册1' }
]
};
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
async _handle (payload: Payload) {
async _handle (payload: PayloadType): Promise<GetQunAlbumListReturn> {
return (await this.core.apis.WebApi.getAlbumListByNTQQ(payload.group_id)).response.album_list;
}
}

View File

@ -1,8 +1,24 @@
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;
override actionSummary = '获取 RKey';
override actionTags = ['系统扩展'];
override payloadExample = {};
override returnExample = [
{
"key": "rkey_value",
"expired": 1734567890
}
];
async _handle () {
return await this.core.apis.PacketApi.pkt.operation.FetchRkey();

View File

@ -1,8 +1,21 @@
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 actionSummary = '获取机器人 UIN 范围';
override actionTags = ['系统扩展'];
override payloadExample = {};
override returnExample = [
{ minUin: '12345678', maxUin: '87654321' }
];
override payloadSchema = Type.Void();
override returnSchema = ReturnSchema;
async _handle () {
return await this.core.apis.UserApi.getRobotUinRange();

View File

@ -2,26 +2,37 @@ 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;
override actionSummary = '获取单向好友列表';
override actionTags = ['用户扩展'];
override payloadExample = {};
override returnExample = [
{
uin: 123456789,
uid: 'u_123',
nick_name: '单向好友',
age: 20,
source: '来源'
}
];
async pack_data (data: string): Promise<Uint8Array> {
return ProtoBuf(class extends ProtoBufBase {
@ -30,7 +41,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,
@ -40,10 +51,18 @@ export class GetUnidirectionalFriendList extends OneBotAction<void, Friend[]> {
};
const packed_data = await this.pack_data(JSON.stringify(req_json));
const data = Buffer.from(packed_data);
const rsq = { cmd: 'MQUpdateSvc_com_qq_ti.web.OidbSvc.0xe17_0', data: data as PacketBuf };
const rsq = { cmd: 'MQUpdateSvc_com_qq_ti.web.OidbSvc.0xe17_0', data: data as unknown 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;
interface BlockItem {
uint64_uin: number;
str_uid: string;
bytes_nick: string;
uint32_age: number;
bytes_source: string;
}
const block_data: { rpt_block_list: BlockItem[]; } = JSON.parse(block_json.data);
const block_list = block_data.rpt_block_list;
return block_list.map((block) => ({
uin: block.uint64_uin,

View File

@ -2,17 +2,38 @@ 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.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.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;
override actionSummary = '获取用户在线状态';
override actionTags = ['系统扩展'];
override payloadExample = {
user_id: '123456789'
};
override returnExample = {
status: 10,
ext_status: 0
};
async _handle (payload: Payload) {
return await this.core.apis.PacketApi.pkt.operation.GetStrangerStatus(+payload.user_id);
async _handle (payload: PayloadType) {
const res = await this.core.apis.PacketApi.pkt.operation.GetStrangerStatus(+payload.user_id);
if (!res) {
throw new Error('无法获取用户状态');
}
return res;
}
}

View File

@ -3,24 +3,37 @@ 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.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 actionSummary = '移动群文件';
override actionTags = ['文件扩展'];
override payloadExample = {
group_id: 123456,
file_id: '/file_id',
parent_id: '/target_folder_id'
};
override returnExample = {
result: true
};
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,29 @@ 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(),
import { ExtendsActionsExamples } from './examples';
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;
override actionSummary = '图片 OCR 识别';
override actionDescription = '识别图片中的文字内容';
override actionTags = ['扩展接口'];
override payloadExample = ExtendsActionsExamples.OCRImage.payload;
override returnExample = ExtendsActionsExamples.OCRImage.response;
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字段可能格式不正确`);
@ -37,8 +48,10 @@ class OCRImageBase extends OneBotAction<Payload, GeneralCallResultStatus> {
export class OCRImage extends OCRImageBase {
override actionName = ActionName.OCRImage;
override actionSummary = '图片 OCR 识别';
}
export class IOCRImage extends OCRImageBase {
override actionName = ActionName.IOCRImage;
override actionSummary = '图片 OCR 识别 (内部)';
}

View File

@ -3,24 +3,37 @@ 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.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 actionSummary = '重命名群文件';
override actionTags = ['文件扩展'];
override payloadExample = {
group_id: 123456,
file_id: '/file_id',
name: 'new_name.jpg'
};
override returnExample = {
result: true
};
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,20 +3,35 @@ 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.Union([Type.String({ description: '响应十六进制数据' }), Type.Undefined()], { 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) {
override actionSummary = '发送原始数据包';
override actionTags = ['系统扩展'];
override payloadExample = {
cmd: 'Example.Cmd',
data: '123456',
rsp: true
};
override returnExample = '123456';
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);
const packetData = Buffer.from(payload.data, 'hex') as unknown as PacketBuf;
const data = await this.core.apis.PacketApi.pkt.operation.sendPacket({ cmd: payload.cmd, data: packetData }, rsp);
return typeof data === 'object' ? data.toString('hex') : undefined;
}
}

View File

@ -2,19 +2,31 @@ 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;
async _handle (payload: Payload) {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema; override actionSummary = '设置自定义在线状态';
override actionDescription = '设置自定义在线状态';
override actionTags = ['用户扩展'];
override payloadExample = {
status: 11
};
override returnExample = {
result: 0
};
async _handle (payload: PayloadType) {
const ret = await this.core.apis.UserApi.setDiySelfOnlineStatus(
payload.face_id.toString(),
payload.wording,

View File

@ -2,19 +2,33 @@ 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 actionSummary = '设置群加群选项';
override actionTags = ['群组扩展'];
override payloadExample = {
group_id: 123456,
option: 1
};
override returnExample = {
result: true
};
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,35 @@ 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 actionSummary = '点赞群相册媒体';
override actionTags = ['群组扩展'];
override payloadExample = {
group_code: 123456,
media_id: 'media_id_1'
};
override returnExample = {
result: true
};
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,31 @@ 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()])),
import { ExtendsActionsExamples } from './examples';
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;
override actionSummary = '批量踢出群成员';
override actionDescription = '从指定群聊中批量踢出多个成员';
override actionTags = ['扩展接口'];
override payloadExample = ExtendsActionsExamples.SetGroupKickMembers.payload;
override returnExample = ExtendsActionsExamples.SetGroupKickMembers.response;
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,31 @@ 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;
override actionSummary = '设置群备注';
override actionDescription = '设置群备注';
override actionTags = ['群组扩展'];
override payloadExample = {
group_id: '123456',
remark: '测试群备注'
};
override returnExample = {};
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,32 @@ 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 actionSummary = '设置群机器人加群选项';
override actionTags = ['群组扩展'];
override payloadExample = {
group_id: 123456,
option: 1
};
override returnExample = {
result: true
};
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,32 @@ 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 actionSummary = '设置群搜索选项';
override actionTags = ['群组扩展'];
override payloadExample = {
group_id: 123456,
is_searchable: true
};
override returnExample = {
result: true
};
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,27 @@ 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.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;
override actionSummary = '设置群签名';
override actionTags = ['群组扩展'];
override payloadExample = {
group_id: '123456789'
};
override returnExample = null;
async _handle (payload: PayloadType) {
return await this.core.apis.PacketApi.pkt.operation.GroupSign(+payload.group_id);
}
}

View File

@ -3,17 +3,30 @@ 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.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;
override actionSummary = '设置输入状态';
override actionTags = ['系统扩展'];
override payloadExample = {
user_id: '123456789',
event_type: 1
};
override returnExample = null;
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,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({
longNick: Type.String(),
import { ExtendsActionsExamples } from './examples';
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;
override actionSummary = '设置个性签名';
override actionDescription = '修改当前登录帐号的个性签名';
override actionTags = ['扩展接口'];
override payloadExample = ExtendsActionsExamples.SetLongNick.payload;
override returnExample = ExtendsActionsExamples.SetLongNick.response;
async _handle (payload: Payload) {
async _handle (payload: PayloadType) {
return await this.core.apis.UserApi.setLongNick(payload.longNick);
}
}

View File

@ -2,19 +2,33 @@ 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;
override actionSummary = '设置在线状态';
override actionDescription = '设置在线状态';
override actionTags = ['系统扩展'];
override payloadExample = {
status: 11,
ext_status: 0,
battery_status: 100
};
override returnExample = null;
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,29 @@ 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(),
import { ExtendsActionsExamples } from './examples';
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;
override actionSummary = '设置QQ头像';
override actionDescription = '修改当前账号的QQ头像';
override actionTags = ['扩展接口'];
override payloadExample = ExtendsActionsExamples.SetQQAvatar.payload;
override returnExample = ExtendsActionsExamples.SetQQAvatar.response;
async _handle (payload: PayloadType): Promise<ReturnType> {
const { path, success } = (await uriToLocalFile(this.core.NapCatTempPath, payload.file));
if (!success) {
throw new Error(`头像${payload.file}设置失败,file字段可能格式不正确`);
@ -26,7 +39,7 @@ export default class SetAvatar extends OneBotAction<Payload, null> {
throw new Error(`头像${payload.file}设置失败,api无返回`);
}
// log(`头像设置返回:${JSON.stringify(ret)}`)
if (ret.result as number === 1004022) {
if (Number(ret.result) === 1004022) {
throw new Error(`头像${payload.file}设置失败,文件可能不是图片格式`);
} else if (ret.result !== 0) {
throw new Error(`头像${payload.file}设置失败,未知的错误,${ret.result}:${ret.errMsg}`);

View File

@ -2,19 +2,31 @@ 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: '' }),
import { ExtendsActionsExamples } from './examples';
const PayloadSchema = Type.Object({
group_id: Type.String({ description: '群号' }),
user_id: 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;
override actionSummary = '设置专属头衔';
override actionDescription = '设置群聊中指定成员的专属头衔';
override actionTags = ['扩展接口'];
override payloadExample = ExtendsActionsExamples.SetSpecialTitle.payload;
override returnExample = ExtendsActionsExamples.SetSpecialTitle.response;
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

@ -1,24 +1,35 @@
import { GeneralCallResult } from 'napcat-core';
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.String({ description: 'QQ号' })),
group_id: Type.Optional(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;
override actionSummary = '分享用户 (Ark)';
override actionDescription = '获取用户推荐的 Ark 内容';
override actionTags = ['消息扩展'];
override payloadExample = {
user_id: '123456',
phone_number: ''
};
override returnExample = {
ark: '...'
};
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 +39,30 @@ 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.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;
override actionSummary = '分享群 (Ark)';
override actionDescription = '获取群分享的 Ark 内容';
override actionTags = ['消息扩展'];
override payloadExample = {
group_id: '123456'
};
override returnExample = '{"app": "com.tencent.structmsg", ...}';
async _handle (payload: PayloadTypeGroupEx) {
return await this.core.apis.GroupApi.getArkJsonGroupShare(payload.group_id.toString());
}
}

View File

@ -3,22 +3,35 @@ 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.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 actionSummary = '传输群文件';
override actionTags = ['文件扩展'];
override payloadExample = {
group_id: 123456,
file_id: '/file_id',
target_group_id: 654321
};
override returnExample = {
result: true
};
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,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({
words: Type.Array(Type.String()),
import { ExtendsActionsExamples } from './examples';
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.Union([Type.Array(Type.Any()), Type.Undefined()], { 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;
override actionSummary = '英文单词翻译';
override actionDescription = '将英文单词列表翻译为中文';
override actionTags = ['扩展接口'];
override payloadExample = ExtendsActionsExamples.TranslateEnWordToZn.payload;
override returnExample = ExtendsActionsExamples.TranslateEnWordToZn.response;
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,35 @@ 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 actionSummary = '上传图片到群相册';
override actionTags = ['群组扩展'];
override payloadExample = {
group_code: 123456,
album_id: 'album_id_1',
file: '/path/to/image.jpg'
};
override returnExample = {
result: true
};
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

@ -0,0 +1,38 @@
export const ExtendsActionsExamples = {
OCRImage: {
payload: { image: 'image_id_123' },
response: { texts: [{ text: '识别内容', coordinates: [] }] },
},
GetAiCharacters: {
payload: { group_id: '123456' },
response: { characters: [] },
},
GetClientkey: {
payload: {},
response: { clientkey: 'abcdef123456' },
},
SetQQAvatar: {
payload: { file: 'base64://...' },
response: {},
},
SetGroupKickMembers: {
payload: { group_id: '123456', user_id: ['123456789'], reject_add_request: false },
response: {},
},
TranslateEnWordToZn: {
payload: { words: ['hello'] },
response: { words: ['你好'] },
},
GetRkey: {
payload: {},
response: { rkey: '...' },
},
SetLongNick: {
payload: { longNick: '个性签名' },
response: {},
},
SetSpecialTitle: {
payload: { group_id: '123456', user_id: '123456789', special_title: '头衔' },
response: {},
},
};

View File

@ -5,23 +5,29 @@ 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;
}
import { FileActionsExamples } from './examples';
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;
override actionTags = ['文件接口'];
async _handle (payload: GetFilePayload): Promise<GetFileResponse> {
payload.file ||= payload.file_id || '';
@ -40,12 +46,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 = {
@ -113,4 +119,9 @@ export class GetFileBase extends OneBotAction<GetFilePayload, GetFileResponse> {
export default class GetFile extends GetFileBase {
override actionName = ActionName.GetFile;
override actionSummary = '获取文件';
override actionDescription = '获取指定文件的详细信息及下载路径';
override actionTags = ['文件接口'];
override payloadExample = FileActionsExamples.GetFile.payload;
override returnExample = FileActionsExamples.GetFile.response;
}

View File

@ -3,22 +3,32 @@ 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(),
import { FileActionsExamples } from './examples';
const PayloadSchema = Type.Object({
group_id: 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;
override actionSummary = '获取群文件URL';
override actionDescription = '获取指定群文件的下载链接';
override actionTags = ['文件接口'];
override payloadExample = FileActionsExamples.GetGroupFileUrl.payload;
override returnExample = FileActionsExamples.GetGroupFileUrl.response;
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

@ -1,6 +1,13 @@
import { GetFileBase } from './GetFile';
import { ActionName } from '@/napcat-onebot/action/router';
import { FileActionsExamples } from './examples';
export default class GetImage extends GetFileBase {
override actionName = ActionName.GetImage;
override actionSummary = '获取图片';
override actionDescription = '获取指定图片的信息及路径';
override actionTags = ['文件接口'];
override payloadExample = FileActionsExamples.GetImage.payload;
override returnExample = FileActionsExamples.GetImage.response;
}

View File

@ -3,21 +3,31 @@ 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(),
import { FileActionsExamples } from './examples';
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;
override actionSummary = '获取私聊文件URL';
override actionDescription = '获取指定私聊文件的下载链接';
override actionTags = ['文件接口'];
override payloadExample = FileActionsExamples.GetPrivateFileUrl.payload;
override returnExample = FileActionsExamples.GetPrivateFileUrl.response;
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,35 @@ 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'];
import { FileActionsExamples } from './examples';
type Payload = {
out_format: string;
} & GetFilePayload;
const out_format_list = ['mp3', 'amr', 'wma', 'm4a', 'spx', 'ogg', 'wav', 'flac'];
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 actionSummary = '获取语音';
override actionDescription = '获取指定语音文件的信息,并支持格式转换';
override actionTags = ['文件接口'];
override payloadExample = FileActionsExamples.GetRecord.payload;
override returnExample = FileActionsExamples.GetRecord.response;
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

@ -0,0 +1,22 @@
export const FileActionsExamples = {
GetFile: {
payload: { file: 'file_id_123' },
response: { file: '/path/to/file', url: 'http://...', file_size: 1024, file_name: 'test.jpg' },
},
GetGroupFileUrl: {
payload: { group_id: '123456', file_id: 'file_id_123', busid: 102 },
response: { url: 'http://...' },
},
GetImage: {
payload: { file: 'image_id_123' },
response: { file: '/path/to/image', url: 'http://...' },
},
GetPrivateFileUrl: {
payload: { user_id: '123456789', file_id: 'file_id_123' },
response: { url: 'http://...' },
},
GetRecord: {
payload: { file: 'record_id_123', out_format: 'mp3' },
response: { file: '/path/to/record', url: 'http://...' },
},
};

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,31 @@ 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: '任务创建结果' });
override actionSummary = '创建闪照任务';
override actionTags = ['文件扩展'];
override payloadExample = {
files: 'C:\\test.jpg',
name: 'test_task'
};
override returnExample = {
task_id: 'task_123'
};
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,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({
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: '下载结果' });
override actionSummary = '下载文件集';
override actionTags = ['文件扩展'];
override payloadExample = {
fileset_id: 'set_123'
};
override returnExample = null;
async _handle (payload: Payload) {
async _handle (payload: DownloadFilesetPayload) {
// 默认路径 / fileset_id /为下载路径
return await this.core.apis.FlashApi.downloadFileSetBySetId(payload.fileset_id);
}

View File

@ -2,19 +2,31 @@ 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, { fileset_id: string }> {
override actionName = ActionName.GetFilesetId;
override payloadSchema = SchemaData;
override payloadSchema = GetFilesetIdPayloadSchema;
override returnSchema = Type.Object({
fileset_id: Type.String({ description: '文件集 ID' })
});
override actionSummary = '获取文件集 ID';
override actionTags = ['文件扩展'];
override payloadExample = {
share_code: '123456'
};
override returnExample = {
fileset_id: 'set_123'
};
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);
const result = await this.core.apis.FlashApi.fromShareLinkFindSetId(code);
return { fileset_id: result.fileSetId };
}
}

View File

@ -2,17 +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({
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: '文件集信息' });
override actionSummary = '获取文件集信息';
override actionTags = ['文件扩展'];
override payloadExample = {
fileset_id: 'set_123'
};
override returnExample = {
fileset_id: 'set_123',
file_list: []
};
async _handle (payload: Payload) {
async _handle (payload: GetFilesetInfoPayload) {
return await this.core.apis.FlashApi.getFileSetIndoBySetId(payload.fileset_id);
}
}

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({
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: '文件列表' });
override actionSummary = '获取闪照文件列表';
override actionTags = ['文件扩展'];
override payloadExample = {
fileset_id: 'set_123'
};
override returnExample = [
{
file_name: 'test.jpg',
size: 1024
}
];
async _handle (payload: Payload) {
async _handle (payload: GetFlashFileListPayload) {
return await this.core.apis.FlashApi.getFileListBySetId(payload.fileset_id);
}
}

View File

@ -2,19 +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({
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: '文件下载链接' });
override actionSummary = '获取闪照文件链接';
override actionTags = ['文件扩展'];
override payloadExample = {
fileset_id: 'set_123'
};
override returnExample = {
url: 'http://example.com/flash.jpg'
};
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,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({
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: '分享链接' });
override actionSummary = '获取文件分享链接';
override actionTags = ['文件扩展'];
override payloadExample = {
fileset_id: 'set_123'
};
override returnExample = 'http://example.com/share';
async _handle (payload: Payload) {
async _handle (payload: GetShareLinkPayload) {
return await this.core.apis.FlashApi.getShareLinkBySetId(payload.fileset_id);
}
}

View File

@ -3,19 +3,29 @@ 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.String({ description: '用户 QQ' })),
group_id: Type.Optional(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: '发送结果' });
override actionSummary = '发送闪照消息';
override actionTags = ['文件扩展'];
override payloadExample = {
fileset_id: 'set_123',
user_id: '123456789'
};
override returnExample = {
message_id: 123456
};
async _handle (payload: Payload) {
async _handle (payload: SendFlashMsgPayload) {
let peer: Peer;
if (payload.group_id) {

View File

@ -3,18 +3,26 @@ 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.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: '取消结果' });
override actionSummary = '取消在线文件';
override actionTags = ['文件扩展'];
override payloadExample = {
user_id: '123456789',
msg_id: '123'
};
override returnExample = null;
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,24 @@ 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.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: '在线文件消息列表' });
override actionSummary = '获取在线文件消息';
override actionTags = ['文件扩展'];
override payloadExample = {
user_id: '123456789'
};
override returnExample = [];
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,28 @@ 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.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: '接收结果' });
override actionSummary = '接收在线文件';
override actionTags = ['文件扩展'];
override payloadExample = {
user_id: '123456789',
msg_id: '123',
save_path: 'C:\\save'
};
override returnExample = null;
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,27 @@ 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.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: '拒绝结果' });
override actionSummary = '拒绝在线文件';
override actionTags = ['文件扩展'];
override payloadExample = {
user_id: '123456789',
msg_id: '123'
};
override returnExample = null;
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,28 @@ 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.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: '发送结果' });
override actionSummary = '发送在线文件';
override actionTags = ['文件扩展'];
override payloadExample = {
user_id: '123456789',
file_path: 'C:\\path\\to\\file.txt',
file_name: 'test.txt'
};
override returnExample = null;
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,27 @@ 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.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: '发送结果' });
override actionSummary = '发送在线文件夹';
override actionTags = ['文件扩展'];
override payloadExample = {
user_id: '123456789',
folder_path: 'C:\\path\\to\\folder'
};
override returnExample = null;
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,40 @@ 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: '群号' }),
// 兼容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;
override actionSummary = '创建群文件目录';
override actionDescription = '在群文件系统中创建新的文件夹';
override actionTags = ['Go-CQHTTP'];
override payloadExample = {
group_id: '123456789',
folder_name: '新建文件夹'
};
override returnExample = {
result: {},
groupItem: {}
};
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

@ -2,19 +2,30 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { FileNapCatOneBotUUID } from 'napcat-common/src/file-uuid';
import { Static, Type } from '@sinclair/typebox';
import { NTQQGroupApi } from 'napcat-core/apis';
import { GoCQHTTPActionsExamples } from './examples';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
file_id: Type.String(),
const PayloadSchema = Type.Object({
group_id: 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;
override actionSummary = '删除群文件';
override actionDescription = '在群文件系统中删除指定的文件';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.DeleteGroupFile.payload;
override returnExample = GoCQHTTPActionsExamples.DeleteGroupFile.response;
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

@ -1,20 +1,31 @@
import { ActionName } from '@/napcat-onebot/action/router';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { Static, Type } from '@sinclair/typebox';
import { NTQQGroupApi } from 'napcat-core/apis';
import { GoCQHTTPActionsExamples } from './examples';
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.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;
override actionSummary = '删除群文件目录';
override actionDescription = '在群文件系统中删除指定的文件夹';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.DeleteGroupFileFolder.payload;
override returnExample = GoCQHTTPActionsExamples.DeleteGroupFileFolder.response;
async _handle (payload: PayloadType) {
return (await this.core.apis.GroupApi.delGroupFileFolder(
payload.group_id.toString(), payload.folder ?? payload.folder_id ?? '')).groupFileCommonResult;
}

View File

@ -5,28 +5,37 @@ import { join as joinPath } from 'node:path';
import { calculateFileMD5, uriToLocalFile } from 'napcat-common/src/file';
import { randomUUID } from 'crypto';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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;
override actionSummary = '下载文件';
override actionDescription = '下载网络文件到本地临时目录';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.DownloadFile.payload;
override returnExample = GoCQHTTPActionsExamples.DownloadFile.response;
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>>;
let result: Awaited<globalThis.ReturnType<typeof uriToLocalFile>>;
if (payload.base64) {
result = await uriToLocalFile(this.core.NapCatTempPath, `base64://${payload.base64}`, name);

View File

@ -5,18 +5,34 @@ import { MessageUnique } from 'napcat-common/src/message-unique';
import { Static, Type } from '@sinclair/typebox';
import { ChatType, ElementType, MsgSourceType, NTMsgType, RawMessage } from 'napcat-core';
import { isNumeric } from 'napcat-common/src/helper';
import { GoCQHTTPActionsExamples } from './examples';
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.Unknown(), { description: '消息列表' })),
}, { description: '合并转发消息' });
type ReturnType = Static<typeof ReturnSchema>;
function isForward (msg: OB11MessageData | string): msg is OB11MessageForward {
return typeof msg !== 'string' && msg.type === OB11MessageDataType.forward;
}
export class GoCQHTTPGetForwardMsgAction extends OneBotAction<PayloadType, ReturnType> {
override actionName = ActionName.GoCQHTTP_GetForwardMsg;
override payloadSchema = SchemaData;
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
override actionSummary = '获取合并转发消息';
override actionDescription = '获取合并转发消息的具体内容';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetForwardMsg.payload;
override returnExample = GoCQHTTPActionsExamples.GetForwardMsg.response;
private createTemplateNode (message: OB11Message): OB11MessageNode {
return {
@ -37,13 +53,18 @@ export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, {
const templateNode = this.createTemplateNode(message);
for (const msgdata of message.message) {
if ((msgdata as OB11MessageData).type === OB11MessageDataType.forward) {
if (isForward(msgdata)) {
const newNode = this.createTemplateNode(message);
newNode.data.message = await this.parseForward((msgdata as OB11MessageForward).data.content ?? []);
newNode.data.message = await this.parseForward(msgdata.data.content ?? []);
templateNode.data.message.push(newNode);
} else {
templateNode.data.message.push(msgdata as OB11MessageData);
if (typeof msgdata === 'string') {
const textMsg: OB11MessageData = { type: OB11MessageDataType.text, data: { text: msgdata } };
templateNode.data.message.push(textMsg);
} else {
templateNode.data.message.push(msgdata);
}
}
}
retMsg.push(templateNode);
@ -52,7 +73,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) {
@ -61,7 +82,7 @@ export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, {
// 2. 定义辅助函数 - 创建伪转发消息对象
const createFakeForwardMsg = (resId: string): RawMessage => {
return {
const fakeMsg: RawMessage = {
chatType: ChatType.KCHATTYPEGROUP,
elements: [{
elementType: ElementType.MULTIFORWARD,
@ -74,7 +95,7 @@ export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, {
}],
guildId: '',
isOnlineMsg: false,
msgId: '', // TODO: no necessary
msgId: '', // TODO: no necessary
msgRandom: '0',
msgSeq: '',
msgTime: '',
@ -95,15 +116,17 @@ export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, {
senderUin: '1094950020',
sourceType: MsgSourceType.K_DOWN_SOURCETYPE_UNKNOWN,
subMsgType: 1,
} as RawMessage;
};
return fakeMsg;
};
// 3. 定义协议回退逻辑函数
const protocolFallbackLogic = async (resId: string) => {
const ob = (await this.obContext.apis.MsgApi.parseMessageV2(createFakeForwardMsg(resId), true))?.arrayMsg;
if (ob) {
const firstMsg = ob?.message?.[0];
if (firstMsg && isForward(firstMsg)) {
return {
messages: (ob?.message?.[0] as OB11MessageForward)?.data?.content,
messages: firstMsg.data.content,
};
}
throw new Error('protocolFallbackLogic: 找不到相关的聊天记录');
@ -132,9 +155,12 @@ export class GoCQHTTPGetForwardMsgAction extends OneBotAction<Payload, {
// 6. 解析消息内容
const resMsg = (await this.obContext.apis.MsgApi.parseMessage(singleMsg, 'array', true));
const forwardContent = (resMsg?.message?.[0] as OB11MessageForward)?.data?.content;
if (forwardContent) {
return { messages: forwardContent };
const firstMsg = resMsg?.message?.[0];
if (firstMsg && isForward(firstMsg)) {
const forwardContent = firstMsg.data.content;
if (forwardContent) {
return { messages: forwardContent };
}
}
}
}

View File

@ -6,28 +6,38 @@ import { MessageUnique } from 'napcat-common/src/message-unique';
import { Static, Type } from '@sinclair/typebox';
import { NetworkAdapterConfig } from '@/napcat-onebot/config/config';
import { GoCQHTTPActionsExamples } from './examples';
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;
override actionSummary = '获取好友历史消息';
override actionDescription = '获取指定好友的历史聊天记录';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetFriendMsgHistory.payload;
override returnExample = GoCQHTTPActionsExamples.GetFriendMsgHistory.response;
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}不存在`);
@ -46,7 +56,7 @@ 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);
).filter((msg): msg is OB11Message => msg !== undefined);
return { messages: ob11MsgList };
}
}

View File

@ -1,22 +1,33 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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>;
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;
override actionSummary = '获取群艾特全体剩余次数';
override actionDescription = '获取指定群聊中艾特全体成员的剩余次数';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetGroupAtAllRemain.payload;
override returnExample = GoCQHTTPActionsExamples.GetGroupAtAllRemain.response;
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

@ -1,23 +1,34 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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 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;
override actionSummary = '获取群文件系统信息';
override actionDescription = '获取群聊文件系统的空间及状态信息';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetGroupFileSystemInfo.payload;
override returnExample = GoCQHTTPActionsExamples.GetGroupFileSystemInfo.response;
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

@ -2,35 +2,48 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { OB11Construct } from '@/napcat-onebot/helper/data';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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.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.Unknown(), { description: '文件列表' }),
folders: Type.Array(Type.Unknown(), { 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) {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
override payloadSchema = PayloadSchema;
override returnSchema = ReturnSchema;
override actionSummary = '获取群文件夹文件列表';
override actionDescription = '获取指定群文件夹下的文件及子文件夹列表';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetGroupFilesByFolder.payload;
override returnExample = GoCQHTTPActionsExamples.GetGroupFilesByFolder.response;
async _handle (payload: PayloadType): Promise<ReturnType> {
const retRaw = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: +payload.file_count,
startIndex: 0,
sortOrder: 2,
showOnlinedocFolder: 0,
folderId: payload.folder ?? payload.folder_id ?? '',
}).catch(() => []);
});
const ret = Array.isArray(retRaw) ? retRaw : [];
return {
files: ret.filter(item => item.fileInfo)
.map(item => OB11Construct.file(item.peerId, item.fileInfo!)),
folders: [] as [],
folders: [],
};
}
}

View File

@ -2,29 +2,38 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { WebHonorType } from 'napcat-core/types';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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.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;
override actionSummary = '获取群荣誉信息';
override actionDescription = '获取指定群聊的荣誉信息,如龙王等';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetGroupHonorInfo.payload;
override returnExample = GoCQHTTPActionsExamples.GetGroupHonorInfo.response;
async _handle (payload: Payload) {
async _handle (payload: PayloadType): Promise<ReturnType> {
if (!payload.type) {
payload.type = WebHonorType.ALL;
}

View File

@ -5,29 +5,38 @@ import { ChatType, Peer } from 'napcat-core/types';
import { MessageUnique } from 'napcat-common/src/message-unique';
import { Static, Type } from '@sinclair/typebox';
import { NetworkAdapterConfig } from '@/napcat-onebot/config/config';
import { GoCQHTTPActionsExamples } from './examples';
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;
override actionSummary = '获取群历史消息';
override actionDescription = '获取指定群聊的历史聊天记录';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetGroupMsgHistory.payload;
override returnExample = GoCQHTTPActionsExamples.GetGroupMsgHistory.response;
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');
// 拉取消息
@ -43,7 +52,7 @@ 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);
).filter((msg): msg is OB11Message => msg !== undefined);
return { messages: ob11MsgList };
}
}

View File

@ -1,23 +1,34 @@
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';
import { GoCQHTTPActionsExamples } from './examples';
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.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;
override actionSummary = '获取群根目录文件列表';
override actionDescription = '获取群文件根目录下的所有文件和文件夹';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetGroupRootFiles.payload;
override returnExample = GoCQHTTPActionsExamples.GetGroupRootFiles.response;
async _handle (payload: PayloadType) {
const ret = await this.core.apis.MsgApi.getGroupFileList(payload.group_id.toString(), {
sortType: 1,
fileCount: +payload.file_count,

View File

@ -1,9 +1,27 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { sleep } from 'napcat-common/src/helper';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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;
override actionSummary = '获取在线客户端';
override actionDescription = '获取当前登录账号的在线客户端列表';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetOnlineClient.payload;
override returnExample = GoCQHTTPActionsExamples.GetOnlineClient.response;
async _handle () {
// 注册监听
this.core.apis.SystemApi.getOnlineDev();

View File

@ -1,21 +1,49 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { OB11User, OB11UserSex } from '@/napcat-onebot/index';
import { OB11UserSex } from '@/napcat-onebot/index';
import { OB11Construct } from '@/napcat-onebot/helper/data';
import { ActionName } from '@/napcat-onebot/action/router';
import { calcQQLevel } from 'napcat-common/src/helper';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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.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;
override actionSummary = '获取陌生人信息';
override actionDescription = '获取指定非好友用户的信息';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GetStrangerInfo.payload;
override returnExample = GoCQHTTPActionsExamples.GetStrangerInfo.response;
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);
@ -37,11 +65,11 @@ export default class GoCQHTTPGetStrangerInfo extends OneBotAction<Payload, OB11U
sex: OB11Construct.sex(extendData.detail.simpleInfo.baseInfo.sex) ?? OB11UserSex.unknown,
long_nick: extendData.detail.simpleInfo.baseInfo.longNick ?? info.longNick,
reg_time: extendData.detail.commonExt?.regTime ?? info.regTime,
is_vip: extendData.detail.simpleInfo.vasInfo?.svipFlag,
is_years_vip: extendData.detail.simpleInfo.vasInfo?.yearVipFlag,
vip_level: extendData.detail.simpleInfo.vasInfo?.vipLevel,
remark: extendData.detail.simpleInfo.coreInfo.remark ?? info.remark,
status: extendData.detail.simpleInfo.status?.status ?? info.status,
is_vip: extendData.detail.simpleInfo.vasInfo?.svipFlag ?? false,
is_years_vip: extendData.detail.simpleInfo.vasInfo?.yearVipFlag ?? false,
vip_level: extendData.detail.simpleInfo.vasInfo?.vipLevel ?? 0,
remark: extendData.detail.simpleInfo.coreInfo.remark ?? info.remark ?? '',
status: extendData.detail.simpleInfo.status?.status ?? info.status ?? 0,
login_days: 0, // 失效
};
}

View File

@ -1,16 +1,29 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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;
override actionSummary = '检查URL安全性';
override actionDescription = '检查指定URL的安全等级';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GoCQHTTPCheckUrlSafely.payload;
override returnExample = GoCQHTTPActionsExamples.GoCQHTTPCheckUrlSafely.response;
async _handle () {
return { level: 1 };

View File

@ -1,21 +1,28 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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();
override actionSummary = '删除好友';
override actionDescription = '从好友列表中删除指定用户';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GoCQHTTPDeleteFriend.payload;
override returnExample = GoCQHTTPActionsExamples.GoCQHTTPDeleteFriend.response;
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

@ -1,23 +1,34 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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;
override actionSummary = '获取机型显示';
override actionDescription = '获取当前账号可用的设备机型显示名称列表';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GoCQHTTPGetModelShow.payload;
override returnExample = GoCQHTTPActionsExamples.GoCQHTTPGetModelShow.response;
async _handle (payload: Payload) {
async _handle (payload: GoCQHTTPGetModelShowPayload) {
if (!payload.model) {
payload.model = 'napcat';
}

View File

@ -1,8 +1,18 @@
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
// 兼容性代码
export class GoCQHTTPSetModelShow extends OneBotAction<void, void> {
override actionName = ActionName.GoCQHTTP_SetModelShow;
override payloadSchema = Type.Object({});
override returnSchema = Type.Null();
override actionSummary = '设置机型';
override actionDescription = '设置当前账号的设备机型名称';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.GoCQHTTPSetModelShow.payload;
override returnExample = GoCQHTTPActionsExamples.GoCQHTTPSetModelShow.response;
async _handle () {

View File

@ -1,19 +1,77 @@
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';
import { GoCQHTTPActionsExamples } from './examples';
interface Payload {
context: QuickActionEvent,
operation: QuickAction
}
const SenderSchema = Type.Object({
user_id: Type.String({ 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.String({ description: '发送者 QQ 号' }),
group_id: Type.Optional(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();
override actionSummary = '处理快速操作';
override actionDescription = '处理来自事件上报的快速操作请求';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.QuickAction.payload;
override returnExample = GoCQHTTPActionsExamples.QuickAction.response;
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,62 @@
import { ContextMode, normalize, ReturnDataType, SendMsgBase } from '@/napcat-onebot/action/msg/SendMsg';
import { OB11PostSendMsg } from '@/napcat-onebot/types';
import { OB11MessageMixType } from '@/napcat-onebot/types';
import { ContextMode, normalize, ReturnDataType, SendMsgBase, SendMsgPayload } from '@/napcat-onebot/action/msg/SendMsg';
import { ActionName } from '@/napcat-onebot/action/router';
// 未验证
type GoCQHTTPSendForwardMsgPayload = SendMsgPayload & { messages?: OB11MessageMixType; };
export class GoCQHTTPSendForwardMsgBase extends SendMsgBase {
protected override async check (payload: OB11PostSendMsg) {
protected override async check (payload: GoCQHTTPSendForwardMsgPayload) {
if (payload.messages) payload.message = normalize(payload.messages);
return super.check(payload);
}
}
export class GoCQHTTPSendForwardMsg extends GoCQHTTPSendForwardMsgBase {
override actionName = ActionName.GoCQHTTP_SendForwardMsg;
override actionSummary = '发送合并转发消息';
override actionDescription = '发送合并转发消息';
override actionTags = ['Go-CQHTTP'];
override payloadExample = {
group_id: '123456789',
messages: []
};
override returnExample = {
message_id: 123456
};
protected override async check (payload: OB11PostSendMsg) {
protected override async check (payload: GoCQHTTPSendForwardMsgPayload) {
if (payload.messages) payload.message = normalize(payload.messages);
return super.check(payload);
}
}
export class GoCQHTTPSendPrivateForwardMsg extends GoCQHTTPSendForwardMsgBase {
override actionName = ActionName.GoCQHTTP_SendPrivateForwardMsg;
override async _handle (payload: OB11PostSendMsg): Promise<ReturnDataType> {
override actionSummary = '发送私聊合并转发消息';
override actionTags = ['Go-CQHTTP'];
override payloadExample = {
user_id: '123456789',
messages: []
};
override returnExample = {
message_id: 123456
};
override async _handle (payload: GoCQHTTPSendForwardMsgPayload): 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 actionSummary = '发送群合并转发消息';
override actionTags = ['Go-CQHTTP'];
override payloadExample = {
group_id: '123456789',
messages: []
};
override returnExample = {
message_id: 123456
};
override async _handle (payload: GoCQHTTPSendForwardMsgPayload): Promise<ReturnDataType> {
return this.base_handle(payload, ContextMode.Group);
}
}

View File

@ -3,24 +3,32 @@ import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { unlink } from 'node:fs/promises';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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.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();
override actionSummary = '发送群公告';
override actionDescription = '在指定群聊中发布新的公告';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.SendGroupNotice.payload;
override returnExample = GoCQHTTPActionsExamples.SendGroupNotice.response;
async _handle (payload: SendGroupNoticePayload) {
let UploadImage: { id: string, width: number, height: number; } | undefined;
if (payload.image) {
// 公告图逻辑
@ -59,6 +67,5 @@ export class SendGroupNotice extends OneBotAction<Payload, null> {
if (!publishGroupBulletinResult || publishGroupBulletinResult.ec !== 0) {
throw new Error(`设置群公告失败,错误信息:${publishGroupBulletinResult?.em}`);
}
return null;
}
}

View File

@ -3,19 +3,33 @@ import { ActionName } from '@/napcat-onebot/action/router';
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()]),
import { GoCQHTTPActionsExamples } from './examples';
export const SetGroupPortraitPayloadSchema = Type.Object({
file: Type.String({ description: '头像文件路径或 URL' }),
group_id: Type.String({ description: '群号' }),
});
type Payload = Static<typeof SchemaData>;
export type SetGroupPortraitPayload = Static<typeof SetGroupPortraitPayloadSchema>;
export default class SetGroupPortrait extends OneBotAction<Payload, GeneralCallResult> {
const ReturnSchema = Type.Object({
result: Type.Number(),
errMsg: Type.String(),
}, { description: '设置结果' });
export type ReturnType = Static<typeof ReturnSchema>;
export default class SetGroupPortrait extends OneBotAction<SetGroupPortraitPayload, ReturnType> {
override actionName = ActionName.SetGroupPortrait;
override payloadSchema = SchemaData;
override payloadSchema = SetGroupPortraitPayloadSchema;
override returnSchema = ReturnSchema;
override actionSummary = '设置群头像';
override actionDescription = '修改指定群聊的头像';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.SetGroupPortrait.payload;
override returnExample = GoCQHTTPActionsExamples.SetGroupPortrait.response;
async _handle (payload: Payload): Promise<GeneralCallResult> {
async _handle (payload: SetGroupPortraitPayload): Promise<ReturnType> {
const { path, success } = (await uriToLocalFile(this.core.NapCatTempPath, payload.file));
if (!success) {
throw new Error(`头像${payload.file}设置失败,file字段可能格式不正确`);
@ -27,12 +41,15 @@ export default class SetGroupPortrait extends OneBotAction<Payload, GeneralCallR
if (!ret) {
throw new Error(`头像${payload.file}设置失败,api无返回`);
}
if (ret.result as number === 1004022) {
if (Number(ret.result) === 1004022) {
throw new Error(`头像${payload.file}设置失败,文件可能不是图片格式或权限不足`);
} else if (ret.result !== 0) {
} else if (Number(ret.result) !== 0) {
throw new Error(`头像${payload.file}设置失败,未知的错误,${ret.result}:${ret.errMsg}`);
}
return ret;
return {
result: Number(ret.result),
errMsg: ret.errMsg,
};
} else {
fs.unlink(path).catch(() => { });
throw new Error(`头像${payload.file}设置失败,无法获取头像,文件可能不存在`);

View File

@ -1,20 +1,26 @@
import { NTQQUserApi } from 'napcat-core/apis';
import { OneBotAction } from '@/napcat-onebot/action/OneBotAction';
import { ActionName } from '@/napcat-onebot/action/router';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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: '设置结果' });
override actionSummary = '设置QQ资料';
override actionDescription = '修改当前账号的昵称、个性签名等资料';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.SetQQProfile.payload;
override returnExample = GoCQHTTPActionsExamples.SetQQProfile.response;
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

@ -5,27 +5,36 @@ import fs from 'fs';
import { uriToLocalFile } from 'napcat-common/src/file';
import { SendMessageContext } from '@/napcat-onebot/api';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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.String({ description: '群号' }),
file: Type.String({ description: '资源路径或URL' }),
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;
override actionSummary = '上传群文件';
override actionDescription = '上传资源路径或URL指定的文件到指定群聊的文件系统中';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.UploadGroupFile.payload;
override returnExample = GoCQHTTPActionsExamples.UploadGroupFile.response;
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

@ -6,25 +6,34 @@ import { uriToLocalFile } from 'napcat-common/src/file';
import { SendMessageContext } from '@/napcat-onebot/api';
import { ContextMode, createContext } from '@/napcat-onebot/action/msg/SendMsg';
import { Static, Type } from '@sinclair/typebox';
import { GoCQHTTPActionsExamples } from './examples';
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.String({ description: '用户 QQ' }),
file: Type.String({ description: '资源路径或URL' }),
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;
override actionSummary = '上传私聊文件';
override actionDescription = '上传本地文件到指定私聊会话中';
override actionTags = ['Go-CQHTTP'];
override payloadExample = GoCQHTTPActionsExamples.UploadPrivateFile.payload;
override returnExample = GoCQHTTPActionsExamples.UploadPrivateFile.response;
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) {
@ -36,7 +45,7 @@ export default class GoCQHTTPUploadPrivateFile extends OneBotAction<Payload, Upl
throw new Error('缺少参数 user_id');
}
async _handle (payload: Payload): Promise<UploadPrivateFileResponse> {
async _handle (payload: GoCQHTTPUploadPrivateFilePayload): Promise<GoCQHTTPUploadPrivateFileResponse> {
let file = payload.file;
if (fs.existsSync(file)) {
file = `file://${file}`;

View File

@ -0,0 +1,102 @@
export const GoCQHTTPActionsExamples = {
GetStrangerInfo: {
payload: { user_id: '123456789' },
response: { user_id: 123456789, nickname: '昵称', sex: 'unknown' },
},
GetGroupHonorInfo: {
payload: { group_id: '123456', type: 'all' },
response: { group_id: 123456, current_talkative: {}, talkative_list: [] },
},
GetForwardMsg: {
payload: { message_id: '123456' },
response: { messages: [] },
},
SendForwardMsg: {
payload: { group_id: '123456', messages: [] },
response: { message_id: 123456 },
},
GetGroupAtAllRemain: {
payload: { group_id: '123456' },
response: { can_at_all: true, remain_at_all_count_for_group: 10, remain_at_all_count_for_self: 10 },
},
CreateGroupFileFolder: {
payload: { group_id: '123456', name: '测试目录' },
response: { result: {}, groupItem: {} },
},
DeleteGroupFile: {
payload: { group_id: '123456', file_id: 'file_uuid_123' },
response: {},
},
DeleteGroupFileFolder: {
payload: { group_id: '123456', folder_id: 'folder_uuid_123' },
response: {},
},
DownloadFile: {
payload: { url: 'https://example.com/file.png', thread_count: 1, headers: 'User-Agent: NapCat' },
response: { file: '/path/to/downloaded/file' },
},
GetFriendMsgHistory: {
payload: { user_id: '123456789', message_seq: 0, count: 20 },
response: { messages: [] },
},
GetGroupFilesByFolder: {
payload: { group_id: '123456', folder_id: 'folder_id' },
response: { files: [], folders: [] },
},
GetGroupFileSystemInfo: {
payload: { group_id: '123456' },
response: { file_count: 10, limit_count: 10000, used_space: 1024, total_space: 10737418240 },
},
GetGroupMsgHistory: {
payload: { group_id: '123456', message_seq: 0, count: 20 },
response: { messages: [] },
},
GetGroupRootFiles: {
payload: { group_id: '123456' },
response: { files: [], folders: [] },
},
GetOnlineClient: {
payload: { no_cache: false },
response: { clients: [] },
},
GoCQHTTPCheckUrlSafely: {
payload: { url: 'https://example.com' },
response: { level: 1 },
},
GoCQHTTPDeleteFriend: {
payload: { user_id: '123456789' },
response: {},
},
GoCQHTTPGetModelShow: {
payload: { model: 'iPhone 13' },
response: { variants: [] },
},
GoCQHTTPSetModelShow: {
payload: { model: 'iPhone 13', model_show: 'iPhone 13' },
response: {},
},
QuickAction: {
payload: { context: {}, operation: {} },
response: {},
},
SendGroupNotice: {
payload: { group_id: '123456', content: '公告内容', image: 'base64://...' },
response: {},
},
SetGroupPortrait: {
payload: { group_id: '123456', file: 'base64://...' },
response: {},
},
SetQQProfile: {
payload: { nickname: '新昵称', personal_note: '个性签名' },
response: {},
},
UploadGroupFile: {
payload: { group_id: '123456', file: '/path/to/file', name: 'test.txt' },
response: { file_id: 'file_uuid_123' },
},
UploadPrivateFile: {
payload: { user_id: '123456789', file: '/path/to/file', name: 'test.txt' },
response: { file_id: 'file_uuid_123' },
},
};

View File

@ -3,19 +3,32 @@ 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()),
import { GroupActionsExamples } from './examples';
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;
override actionSummary = '移出精华消息';
override actionDescription = '将一条消息从群精华消息列表中移出';
override actionTags = ['群组接口'];
override payloadExample = GroupActionsExamples.DelEssenceMsg.payload;
override returnExample = GroupActionsExamples.DelEssenceMsg.response;
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 +47,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,30 @@ 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(),
import { GroupActionsExamples } from './examples';
const PayloadSchema = Type.Object({
group_id: 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;
override actionSummary = '删除群公告';
override actionDescription = '删除群聊中的公告';
override actionTags = ['群组接口'];
override payloadExample = GroupActionsExamples.DelGroupNotice.payload;
override returnExample = GroupActionsExamples.DelGroupNotice.response;
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,33 @@ 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 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;
override actionSummary = '获取 AI 语音';
override actionDescription = '通过 AI 语音引擎获取指定文本的语音 URL';
override actionTags = ['AI 扩展'];
override payloadExample = {
character: 'ai_char_1',
group_id: '123456',
text: '你好'
};
override returnExample = 'http://example.com/ai_voice.silk';
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,36 @@ 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()]),
import { GroupActionsExamples } from './examples';
const PayloadSchema = Type.Object({
group_id: 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;
override actionSummary = '获取群详细信息';
override actionDescription = '获取群聊的详细信息,包括成员数、最大成员数等';
override actionTags = ['群组接口'];
override payloadExample = GroupActionsExamples.GetGroupDetailInfo.payload;
override returnExample = GroupActionsExamples.GetGroupDetailInfo.response;
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

@ -5,16 +5,39 @@ import { MessageUnique } from 'napcat-common/src/message-unique';
import crypto from 'crypto';
import { Static, Type } from '@sinclair/typebox';
import { NetworkAdapterConfig } from '@/napcat-onebot/config/config';
import { OB11MessageData, OB11MessageDataType } from '@/napcat-onebot/types';
const SchemaData = Type.Object({
group_id: Type.Union([Type.Number(), Type.String()]),
import { GroupActionsExamples } from './examples';
const PayloadSchema = Type.Object({
group_id: 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;
override actionSummary = '获取群精华消息';
override actionDescription = '获取指定群聊中的精华消息列表';
override actionTags = ['群组接口'];
override payloadExample = GroupActionsExamples.GetGroupEssence.payload;
override returnExample = GroupActionsExamples.GetGroupEssence.response;
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 +50,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('获取失败');
@ -42,6 +65,15 @@ export class GetGroupEssence extends OneBotAction<Payload, unknown> {
}, msg.msg_seq.toString(), msg.msg_random.toString());
if (msgOriginData) {
const { id: message_id, msg: rawMessage } = msgOriginData;
const parsed = await this.obContext.apis.MsgApi.parseMessage(rawMessage, config.messagePostFormat);
let content: OB11MessageData[] = [];
if (parsed) {
if (Array.isArray(parsed.message)) {
content = parsed.message;
} else {
content = [{ type: OB11MessageDataType.text, data: { text: parsed.message } }];
}
}
return {
msg_seq: msg.msg_seq,
msg_random: msg.msg_random,
@ -51,7 +83,7 @@ export class GetGroupEssence extends OneBotAction<Payload, unknown> {
operator_nick: msg.add_digest_nick,
message_id,
operator_time: msg.add_digest_time,
content: (await this.obContext.apis.MsgApi.parseMessage(rawMessage, config.messagePostFormat))?.message,
content,
};
}
const msgTempData = JSON.stringify({
@ -75,24 +107,25 @@ export class GetGroupEssence extends OneBotAction<Payload, unknown> {
operator_nick: msg.add_digest_nick,
message_id: shortId,
operator_time: msg.add_digest_time,
content: msg.msg_content.map((msg) => {
content: msg.msg_content.map((msg): OB11MessageData | undefined => {
if (msg.msg_type === 1) {
return {
type: 'text',
type: OB11MessageDataType.text,
data: {
text: msg?.text,
text: msg?.text ?? '',
},
};
} else if (msg.msg_type === 3) {
return {
type: 'image',
type: OB11MessageDataType.image,
data: {
file: '',
url: msg?.image_url,
},
};
}
return undefined;
}).filter(e => e !== undefined),
}).filter((e): e is OB11MessageData => e !== undefined),
};
}));
}

View File

@ -1,20 +1,37 @@
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 { Static, Type } from '@sinclair/typebox';
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;
override actionSummary = '获取群忽略通知';
override actionDescription = '获取被忽略的入群申请和邀请通知';
override actionTags = ['群组接口'];
override payloadExample = {};
override returnExample = {
invited_requests: [],
InvitedRequest: [],
join_requests: []
};
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,32 @@
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()]),
import { GroupActionsExamples } from './examples';
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;
override actionSummary = '获取群信息';
override actionDescription = '获取群聊的基本信息';
override actionTags = ['群组接口'];
override payloadExample = GroupActionsExamples.GetGroupInfo.payload;
override returnExample = GroupActionsExamples.GetGroupInfo.response;
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,32 @@
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()])),
import { ActionExamples } from '../examples';
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;
override actionSummary = '获取群列表';
override actionDescription = '获取当前帐号的群聊列表';
override actionTags = ['群组接口'];
override payloadExample = ActionExamples.GetGroupList.payload;
override returnExample = ActionExamples.GetGroupList.return;
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));

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