SnowCat 雪猫底层全源码:NapCat 4.18.28 底座 + SnowLuma 能力移植 + V8 通道适配 9.9.37
26 包 monorepo(TS 全源码): - snowcat-core: NT 内核 API 封装 + listener(含 9.9.37 六回调适配)+ Packet 发包 - snowcat-onebot: OneBot v11 全动作 + MCP Streamable HTTP 适配器 + 稳定线 - snowcat-webui-frontend/backend: 雪猫控制台(React+HeroUI) - snowcat-shell: 单文件 bundle 出口(vite inlineDynamicImports) - snowcat-native: napi2native / MoeHoo / ffmpeg / pty 运行时 - 56 项 SnowLuma 独门动作移植(qzone 全家桶/群相册/装扮/闪照/收藏) - 工具件: 解包器/启动器/便携制作器/doctor GitHub 关联已全量指向 DandanLLab/SnowCatQQ
This commit is contained in:
commit
b9655a5ab1
1048 files changed
+130851
No files matched your search
@@ -0,0 +1,32 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
host_uin: Type.String({ description: '说说主人的QQ号' }),
|
||||
tid: Type.String({ description: '说说tid' }),
|
||||
content: Type.String({ description: '评论正文' }),
|
||||
richval: Type.Optional(Type.String({ description: '图片评论时传图片直链(与发说说的richval串不同)' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class CommentQzoneMsg extends OneBotAction<PayloadType, unknown> {
|
||||
override actionName = ActionName.CommentQzoneMsg;
|
||||
override actionSummary = '评论说说';
|
||||
override actionDescription = '给一条说说发评论(emotion_cgi_re_feeds)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { host_uin: '123456789', tid: 'abc123', content: '说得好' };
|
||||
override returnExample = { comment_id: '999' };
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Object({ comment_id: Type.String() });
|
||||
|
||||
async _handle (payload: PayloadType) {
|
||||
return this.core.apis.WebApi.commentQzoneMsg(
|
||||
payload.host_uin,
|
||||
payload.tid,
|
||||
payload.content,
|
||||
payload.richval,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
page_num: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 1, description: '页码(无cursor时生效)' })),
|
||||
count: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 10, description: '每页条数(1-50)' })),
|
||||
cursor: Type.Optional(Type.String({ description: '上次返回的 next_cursor,续翻用' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class GetQzoneFeeds extends OneBotAction<PayloadType, unknown> {
|
||||
override actionName = ActionName.GetQzoneFeeds;
|
||||
override actionSummary = '获取空间好友动态流';
|
||||
override actionDescription = '读取QQ空间好友动态(HTML载荷数据级解析,不执行远程内容);cursor 续翻';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { page_num: 1, count: 10 };
|
||||
override returnExample = {
|
||||
feeds: [{ uin: 123456789, nickname: '张三', tid: 'abc', content: '动态正文', images: [], like_count: 5, comment_count: 2, appid: 311, key: 'k', time: 1760000000, html: '', content_complete: true }],
|
||||
has_more: true,
|
||||
next_cursor: 'eyJ...',
|
||||
};
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Object({
|
||||
feeds: Type.Array(Type.Any()),
|
||||
has_more: Type.Boolean(),
|
||||
next_cursor: Type.Union([Type.String(), Type.Null()]),
|
||||
});
|
||||
|
||||
async _handle (payload: PayloadType) {
|
||||
return this.core.apis.WebApi.getQzoneFeeds(
|
||||
payload.page_num !== undefined ? +payload.page_num : 1,
|
||||
payload.count !== undefined ? +payload.count : 10,
|
||||
payload.cursor,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
target_uin: Type.String({ description: '说说主人的QQ号' }),
|
||||
tid: Type.String({ description: '说说tid' }),
|
||||
pos: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 0, description: '评论起始偏移' })),
|
||||
num: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 20, description: '评论每页数量' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class GetQzoneMsgDetail extends OneBotAction<PayloadType, unknown> {
|
||||
override actionName = ActionName.GetQzoneMsgDetail;
|
||||
override actionSummary = '获取说说详情';
|
||||
override actionDescription = '读取一条说说正文与一页评论(含内联回复)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { target_uin: '123456789', tid: 'abc123' };
|
||||
override returnExample = {
|
||||
tid: 'abc123',
|
||||
content: '正文',
|
||||
comment_num: 2,
|
||||
comments: [],
|
||||
};
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Object({
|
||||
tid: Type.String(),
|
||||
content: Type.String(),
|
||||
comment_num: Type.Number(),
|
||||
comments: Type.Array(Type.Any()),
|
||||
});
|
||||
|
||||
async _handle (payload: PayloadType) {
|
||||
return this.core.apis.WebApi.getQzoneMsgDetail(
|
||||
payload.target_uin,
|
||||
payload.tid,
|
||||
payload.pos !== undefined ? +payload.pos : 0,
|
||||
payload.num !== undefined ? +payload.num : 20,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
// SnowCat · qzone Web 线动作组(SnowLuma 移植)
|
||||
// 全部走 core.apis.WebApi 的 cookie 管道(getQzoneAuth),无需本文件再做凭证处理。
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
target_uin: Type.Optional(Type.String({ description: '目标QQ号,省略=机器人自己' })),
|
||||
pos: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 0, description: '起始偏移' })),
|
||||
num: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 20, description: '每页数量' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class GetQzoneMsgList extends OneBotAction<PayloadType, unknown> {
|
||||
override actionName = ActionName.GetQzoneMsgList;
|
||||
override actionSummary = '获取说说列表';
|
||||
override actionDescription = '获取QQ空间说说列表(默认自己空间,可查有权限的他人空间);-10000限频自动切备路';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { target_uin: '123456789', pos: 0, num: 20 };
|
||||
override returnExample = {
|
||||
total: 100,
|
||||
msglist: [{
|
||||
tid: 'abc123',
|
||||
content: '今天天气不错',
|
||||
time: 1760000000,
|
||||
comment_num: 2,
|
||||
is_private: false,
|
||||
images: ['https://...'],
|
||||
}],
|
||||
};
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Object({
|
||||
total: Type.Number(),
|
||||
msglist: Type.Array(Type.Object({
|
||||
tid: Type.String(),
|
||||
content: Type.String(),
|
||||
time: Type.Number(),
|
||||
comment_num: Type.Number(),
|
||||
is_private: Type.Boolean(),
|
||||
images: Type.Array(Type.String()),
|
||||
})),
|
||||
});
|
||||
|
||||
async _handle (payload: PayloadType) {
|
||||
return this.core.apis.WebApi.getQzoneMsgList(
|
||||
payload.target_uin,
|
||||
payload.pos !== undefined ? +payload.pos : 0,
|
||||
payload.num !== undefined ? +payload.num : 20,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
target_uin: Type.Optional(Type.String({ description: '目标QQ号,省略=机器人自己' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class GetQzoneProfile extends OneBotAction<PayloadType, unknown> {
|
||||
override actionName = ActionName.GetQzoneProfile;
|
||||
override actionSummary = '获取空间名称和说明';
|
||||
override actionDescription = '获取QQ空间名称和说明(默认当前账号,可查有权限的他人空间)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { target_uin: '123456789' };
|
||||
override returnExample = { name: '我的空间', description: '记录日常' };
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Object({
|
||||
name: Type.String(),
|
||||
description: Type.String(),
|
||||
});
|
||||
|
||||
async _handle (payload: PayloadType) {
|
||||
return this.core.apis.WebApi.getQzoneProfile(payload.target_uin);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
host_uin: Type.String({ description: '说说主人的QQ号' }),
|
||||
tid: Type.String({ description: '说说tid' }),
|
||||
content: Type.String({ description: '回复正文' }),
|
||||
comment_id: Type.String({ description: '父评论id(顶层评论,回复楼中楼也传顶层)' }),
|
||||
comment_uin: Type.String({ description: '父评论作者QQ号' }),
|
||||
reply_to_uin: Type.Optional(Type.String({ description: '楼中楼点名作者的QQ号' })),
|
||||
reply_to_name: Type.Optional(Type.String({ description: '楼中楼点名作者的昵称' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class ReplyQzoneComment extends OneBotAction<PayloadType, unknown> {
|
||||
override actionName = ActionName.ReplyQzoneComment;
|
||||
override actionSummary = '回复说说评论';
|
||||
override actionDescription = '在说说的评论线程里回复(独立端点;点名作者自动转@提及)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { host_uin: '123456789', tid: 'abc123', content: '同意', comment_id: '999', comment_uin: '987654321' };
|
||||
override returnExample = { comment_id: '1001' };
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Object({ comment_id: Type.String() });
|
||||
|
||||
async _handle (payload: PayloadType) {
|
||||
const replyTo = payload.reply_to_uin && payload.reply_to_name
|
||||
? { uin: payload.reply_to_uin, name: payload.reply_to_name }
|
||||
: undefined;
|
||||
return this.core.apis.WebApi.replyQzoneComment(
|
||||
payload.host_uin,
|
||||
payload.tid,
|
||||
payload.content,
|
||||
{
|
||||
commentId: payload.comment_id,
|
||||
commentUin: payload.comment_uin,
|
||||
...(replyTo ? { replyTo } : {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
// SnowCat 富返回版发说说:与官方风格 send_qzone_msg 并存,多返回 time。
|
||||
|
||||
const ValidRights = [1, 4, 16, 64, 128] as const;
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
content: Type.String({ description: '说说正文' }),
|
||||
richvals: Type.Optional(Type.Array(Type.String(), { description: 'richval 数组(来自 uploadImageToQzone 或 get_qzone_msg_list 的图片机制),多图 \t 自动拼接' })),
|
||||
ugc_right: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 1, description: '查看权限: 1所有人 4好友 16部分好友 64仅自己 128部分好友不可见' })),
|
||||
target_uins: Type.Optional(Type.Array(Type.String(), { description: 'ugc_right为16/128时权限作用的QQ号数组' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class SendQzoneMsgFull extends OneBotAction<PayloadType, unknown> {
|
||||
override actionName = ActionName.SendQzoneMsgFull;
|
||||
override actionSummary = '发表说说(富返回)';
|
||||
override actionDescription = '发表QQ空间说说,返回 tid + 发布时间(send_qzone_msg 的富参版)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { content: '今天天气不错' };
|
||||
override returnExample = { tid: 'abc123', time: 1760000000 };
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Object({
|
||||
tid: Type.String(),
|
||||
time: Type.Number(),
|
||||
});
|
||||
|
||||
async _handle (payload: PayloadType) {
|
||||
const ugcRight = payload.ugc_right !== undefined ? +payload.ugc_right : 1;
|
||||
if (!ValidRights.includes(ugcRight as typeof ValidRights[number])) {
|
||||
throw new Error(`ugc_right 参数不合法, 允许的值为: ${ValidRights.join(', ')}`);
|
||||
}
|
||||
if ((ugcRight === 16 || ugcRight === 128) && (!payload.target_uins || payload.target_uins.length === 0)) {
|
||||
throw new Error('ugc_right 为 16 或 128 时, target_uins 不能为空');
|
||||
}
|
||||
return this.core.apis.WebApi.publishQzoneMsgFull(
|
||||
payload.content,
|
||||
payload.richvals ?? [],
|
||||
ugcRight,
|
||||
payload.target_uins,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
target_uin: Type.String({ description: '目标QQ号' }),
|
||||
ban: Type.Boolean({ default: true, description: 'true=拉黑 false=解拉黑' }),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class SetQzoneBlack extends OneBotAction<PayloadType, null> {
|
||||
override actionName = ActionName.SetQzoneBlack;
|
||||
override actionSummary = '空间拉黑/解拉黑';
|
||||
override actionDescription = '把一个用户加入/移出机器人QQ空间的黑名单';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { target_uin: '123456789', ban: true };
|
||||
override returnExample = null;
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Null();
|
||||
|
||||
async _handle (payload: PayloadType): Promise<null> {
|
||||
await this.core.apis.WebApi.setQzoneBlack(payload.target_uin, payload.ban);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
target_uin: Type.String({ description: '说说主人的QQ号' }),
|
||||
tid: Type.String({ description: '说说tid' }),
|
||||
like: Type.Boolean({ default: true, description: 'true=点赞 false=取消赞' }),
|
||||
abstime: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 0, description: '目标帖发帖时间(unix秒),传真实值更稳' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class SetQzoneLike extends OneBotAction<PayloadType, null> {
|
||||
override actionName = ActionName.SetQzoneLike;
|
||||
override actionSummary = '说说点赞/取消赞';
|
||||
override actionDescription = '对一条说说点赞或取消赞(appid 311 mood)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { target_uin: '123456789', tid: 'abc123', like: true };
|
||||
override returnExample = null;
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Null();
|
||||
|
||||
async _handle (payload: PayloadType): Promise<null> {
|
||||
await this.core.apis.WebApi.setQzoneLike(
|
||||
payload.target_uin,
|
||||
payload.tid,
|
||||
payload.like,
|
||||
payload.abstime !== undefined ? +payload.abstime : 0,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const ValidRights = [1, 4, 16, 64, 128] as const;
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
tid: Type.String({ description: '说说tid(自己的说说)' }),
|
||||
ugc_right: Type.Union([Type.Number(), Type.String()], { description: '查看权限: 1所有人 4好友 16部分好友 64仅自己 128部分好友不可见' }),
|
||||
target_uins: Type.Optional(Type.Array(Type.String(), { description: 'ugc_right为16/128时权限作用的QQ号数组' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class SetQzoneMsgRight extends OneBotAction<PayloadType, unknown> {
|
||||
override actionName = ActionName.SetQzoneMsgRight;
|
||||
override actionSummary = '修改说说查看权限';
|
||||
override actionDescription = '改一条已有说说的查看权限(内部走 msgdetail→update 两步全量重提)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { tid: 'abc123', ugc_right: 4 };
|
||||
override returnExample = { ugc_right: 4 };
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Object({ ugc_right: Type.Number() });
|
||||
|
||||
async _handle (payload: PayloadType) {
|
||||
const right = +payload.ugc_right;
|
||||
if (!ValidRights.includes(right as typeof ValidRights[number])) {
|
||||
throw new Error(`ugc_right 参数不合法, 允许的值为: ${ValidRights.join(', ')}`);
|
||||
}
|
||||
if ((right === 16 || right === 128) && (!payload.target_uins || payload.target_uins.length === 0)) {
|
||||
throw new Error('ugc_right 为 16 或 128 时, target_uins 不能为空');
|
||||
}
|
||||
return this.core.apis.WebApi.setQzoneMsgRight(payload.tid, right, payload.target_uins);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const PayloadSchema = Type.Object({
|
||||
name: Type.Optional(Type.String({ description: '空间名称,省略=不动' })),
|
||||
description: Type.Optional(Type.String({ description: '空间说明,省略=不动;空串=清空' })),
|
||||
});
|
||||
|
||||
type PayloadType = Static<typeof PayloadSchema>;
|
||||
|
||||
export class SetQzoneProfile extends OneBotAction<PayloadType, null> {
|
||||
override actionName = ActionName.SetQzoneProfile;
|
||||
override actionSummary = '修改空间名称和说明';
|
||||
override actionDescription = '修改当前账号的空间名称/说明,只动传了的字段,空串=清空';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { name: '我的空间', description: '记录日常' };
|
||||
override returnExample = null;
|
||||
override payloadSchema = PayloadSchema;
|
||||
override returnSchema = Type.Null();
|
||||
|
||||
async _handle (payload: PayloadType): Promise<null> {
|
||||
await this.core.apis.WebApi.setQzoneProfile({
|
||||
...(payload.name !== undefined ? { name: payload.name } : {}),
|
||||
...(payload.description !== undefined ? { description: payload.description } : {}),
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* SnowCat · 第三批动作组(SnowLuma 移植):群相册补/群管补/自定义表情/杂项
|
||||
*
|
||||
* 底层取舍(对账定谳 2026-11-11):
|
||||
* - 群相册 get_group_album_list:走 NapCat 现役 Web 线 getAlbumList(qun_list_album_v2,已实装)
|
||||
* - 群相册 Web 线媒体列表:getAlbumMediaListByNTQQ(NT AlbumService,已实装)
|
||||
* - get_msg_emoji_likes:NT getMsgEmojiLikesList(已实装,补 OB11 动作壳)
|
||||
* - get_friend_dress:NT getUserDetailInfo(已实装,补动作壳)
|
||||
* - fetch_sys_faces:NapCat 无目录表,返回空集占位(SnowLuma 侧是协议自编目录,待后续独立移植)
|
||||
* - get_group_todo_list/get_group_tags/set_group_reaction 等 OIDB 线:NapCat PacketApi 只透传裸包
|
||||
* (send_packet 动作已在),SDK 级 OIDB 编解码层为后续独立批次,此批不重复造。
|
||||
*/
|
||||
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
// ─────────────── 群相册补 ───────────────
|
||||
|
||||
const AlbumListPayload = Type.Object({
|
||||
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
|
||||
});
|
||||
export class GetGroupAlbumList extends OneBotAction<Static<typeof AlbumListPayload>, unknown> {
|
||||
override actionName = ActionName.GetGroupAlbumList;
|
||||
override actionSummary = '获取群相册列表';
|
||||
override actionDescription = '获取群相册列表(qzone Web 线 qun_list_album_v2)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { group_id: 123456789 };
|
||||
override returnExample = [{ id: '1', title: '相册一' }];
|
||||
override payloadSchema = AlbumListPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof AlbumListPayload>) {
|
||||
return this.core.apis.WebApi.getAlbumList(String(payload.group_id));
|
||||
}
|
||||
}
|
||||
|
||||
const AlbumWebMediaPayload = Type.Object({
|
||||
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
|
||||
album_id: Type.String({ description: '相册id(来自 get_group_album_list)' }),
|
||||
});
|
||||
export class GetGroupAlbumMediaListWeb extends OneBotAction<Static<typeof AlbumWebMediaPayload>, unknown> {
|
||||
override actionName = ActionName.GetGroupAlbumMediaListOnly;
|
||||
override actionSummary = '获取群相册媒体列表(Web线)';
|
||||
override actionDescription = '经 NT AlbumService 读取群相册媒体列表(与 get_group_album_media_list 分页线并存)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { group_id: 123456789, album_id: '1' };
|
||||
override returnExample = [];
|
||||
override payloadSchema = AlbumWebMediaPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof AlbumWebMediaPayload>) {
|
||||
return this.core.apis.WebApi.getAlbumMediaListByNTQQ(String(payload.group_id), payload.album_id);
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────── 群管补 ───────────────
|
||||
|
||||
const MsgEmojiLikesPayload = Type.Object({
|
||||
group_id: Type.Union([Type.Number(), Type.String()], { description: '群号' }),
|
||||
message_seq: Type.Union([Type.Number(), Type.String()], { description: '消息 seq' }),
|
||||
emoji_id: Type.String({ description: '表情id' }),
|
||||
emoji_type: Type.Optional(Type.String({ description: '表情类型(1-2,省略按 id 长度推断)' })),
|
||||
cookie: Type.Optional(Type.String({ description: '翻页 cookie,来自上一页返回' })),
|
||||
count: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 20, description: '每页数量' })),
|
||||
});
|
||||
export class GetMsgEmojiLikes extends OneBotAction<Static<typeof MsgEmojiLikesPayload>, unknown> {
|
||||
override actionName = ActionName.GetMsgEmojiLikes;
|
||||
override actionSummary = '查询消息表情回应列表';
|
||||
override actionDescription = '查询一条群消息的表情回应(谁点了什么表情),可翻页';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { group_id: 123456789, message_seq: 12345, emoji_id: '128077' };
|
||||
override returnExample = { cookie: '', likes: [] };
|
||||
override payloadSchema = MsgEmojiLikesPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof MsgEmojiLikesPayload>) {
|
||||
const peer = {
|
||||
chatType: 1,
|
||||
peerUin: String(payload.group_id),
|
||||
peerUid: '',
|
||||
guildId: '',
|
||||
};
|
||||
return this.core.apis.MsgApi.getMsgEmojiLikesList(
|
||||
peer,
|
||||
String(payload.message_seq),
|
||||
payload.emoji_id,
|
||||
payload.emoji_type ?? (payload.emoji_id.length > 3 ? '2' : '1'),
|
||||
payload.cookie ?? '',
|
||||
payload.count !== undefined ? +payload.count : 20,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────── 自定义表情/装扮 ───────────────
|
||||
|
||||
const FriendDressPayload = Type.Object({
|
||||
user_id: Type.Optional(Type.String({ description: '目标QQ号,省略=自己' })),
|
||||
});
|
||||
export class GetFriendDress extends OneBotAction<Static<typeof FriendDressPayload>, unknown> {
|
||||
override actionName = ActionName.GetFriendDress;
|
||||
override actionSummary = '获取用户装扮';
|
||||
override actionDescription = '获取好友/自己的装扮信息(挂件/气泡等,getUserDetailInfo)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { user_id: '123456789' };
|
||||
override returnExample = { dress: {} };
|
||||
override payloadSchema = FriendDressPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof FriendDressPayload>) {
|
||||
const uin = payload.user_id ?? this.core.selfInfo.uin;
|
||||
const uid = uin === this.core.selfInfo.uin
|
||||
? this.core.selfInfo.uid
|
||||
: await this.core.apis.UserApi.getUidByUinV2(uin);
|
||||
if (!uid) throw new Error('用户不存在');
|
||||
const info = await this.core.apis.UserApi.getUserDetailInfo(uid);
|
||||
return { dress: info as unknown as Record<string, unknown> };
|
||||
}
|
||||
}
|
||||
|
||||
const FetchSysFacesPayload = Type.Object({
|
||||
count: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 50, description: '取回数量' })),
|
||||
});
|
||||
export class FetchSysFaces extends OneBotAction<Static<typeof FetchSysFacesPayload>, unknown> {
|
||||
override actionName = ActionName.FetchSysFaces;
|
||||
override actionSummary = '获取系统表情目录';
|
||||
override actionDescription = '获取 QQ 系统表情目录(占位:协议自编目录待后续批次移植,当前返回空集)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { count: 50 };
|
||||
override returnExample = { items: [], note: 'sys face catalog 移植批次待排' };
|
||||
override payloadSchema = FetchSysFacesPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof FetchSysFacesPayload>) {
|
||||
void payload;
|
||||
return { items: [], note: 'sys face catalog 移植批次待排' };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
/**
|
||||
* SnowCat · QQ空间公共空间(空友推荐)13 动作
|
||||
*
|
||||
* 底层:snowcat-core/apis/qzone-public-web.ts(SnowLuma qzone-public.ts 移植)
|
||||
* 动作约定:feed/comment/reply 等复杂对象由调用方从 get_qzone_public_feeds /
|
||||
* get_qzone_public_feed_detail 的返回中原样回传(透明通道,不做二次建模)。
|
||||
*/
|
||||
|
||||
import { OneBotAction } from '@/snowcat-onebot/action/OneBotAction';
|
||||
import { ActionName } from '@/snowcat-onebot/action/router';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
|
||||
const FeedObject = Type.Any({ description: '完整动态对象(来自 get_qzone_public_feeds/feed_detail,原样回传)' });
|
||||
const CommentObject = Type.Any({ description: '评论对象(原样回传)' });
|
||||
const ReplyObject = Type.Optional(Type.Any({ description: '回复对象(原样回传)' }));
|
||||
const UserObject = Type.Any({ description: '用户身份对象(详情/列表响应里的 user 形态)' });
|
||||
|
||||
/** 公共动作共用的 WebApi 快捷取凭证。 */
|
||||
function publicApi (action: OneBotAction<unknown, unknown>) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return (action as any).core.apis.WebApi;
|
||||
}
|
||||
|
||||
// 1. get_qzone_public_capabilities —— 查询账号空友入口白名单
|
||||
const CapPayload = Type.Object({});
|
||||
export class GetQzonePublicCapabilities extends OneBotAction<Static<typeof CapPayload>, unknown> {
|
||||
override actionName = ActionName.GetQzonePublicCapabilities;
|
||||
override actionSummary = '查询空友入口能力';
|
||||
override actionDescription = '查询当前账号在 QQ 空间公共空间(空友)各入口的白名单能力';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = {};
|
||||
override returnExample = { entrance1: true, entrance15: false };
|
||||
override payloadSchema = CapPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle () {
|
||||
const api = publicApi(this);
|
||||
const { uin, g_tk, cookie } = await api.getQzoneAuth();
|
||||
return api.getQzonePublicCapabilities(cookie, g_tk, uin);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. get_qzone_public_feeds —— 空友推荐动态流
|
||||
const FeedsPayload = Type.Object({
|
||||
cursor: Type.Optional(Type.String({ description: '上次返回的 next_cursor,续翻用' })),
|
||||
});
|
||||
export class GetQzonePublicFeeds extends OneBotAction<Static<typeof FeedsPayload>, unknown> {
|
||||
override actionName = ActionName.GetQzonePublicFeeds;
|
||||
override actionSummary = '获取空友推荐动态';
|
||||
override actionDescription = '读取QQ空间公共空间(空友)推荐动态流,cursor 续翻';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = {};
|
||||
override returnExample = { feeds: [], has_more: false, next_cursor: null };
|
||||
override payloadSchema = FeedsPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof FeedsPayload>) {
|
||||
const { uin, g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).getQzonePublicFeeds(cookie, g_tk, uin, payload.cursor);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. get_qzone_public_feed_detail —— 空友单条动态详情
|
||||
const DetailPayload = Type.Object({ feed: FeedObject });
|
||||
export class GetQzonePublicFeedDetail extends OneBotAction<Static<typeof DetailPayload>, unknown> {
|
||||
override actionName = ActionName.GetQzonePublicFeedDetail;
|
||||
override actionSummary = '获取空友动态详情';
|
||||
override actionDescription = '获取一条空友推荐动态的完整详情(含评论首屏)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {} };
|
||||
override returnExample = {};
|
||||
override payloadSchema = DetailPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof DetailPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).getQzonePublicFeedDetail(cookie, g_tk, payload.feed);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. get_qzone_public_comments —— 空友评论分页
|
||||
const CommentsPayload = Type.Object({
|
||||
feed: FeedObject,
|
||||
cursor: Type.String({ description: '详情/上页返回的评论 attach_info' }),
|
||||
});
|
||||
export class GetQzonePublicComments extends OneBotAction<Static<typeof CommentsPayload>, unknown> {
|
||||
override actionName = ActionName.GetQzonePublicComments;
|
||||
override actionSummary = '获取空友评论分页';
|
||||
override actionDescription = '分页读取一条空友动态的评论';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, cursor: '' };
|
||||
override returnExample = {};
|
||||
override payloadSchema = CommentsPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof CommentsPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).getQzonePublicComments(cookie, g_tk, payload.feed, payload.cursor);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. get_qzone_public_replies —— 空友楼中楼分页
|
||||
const RepliesPayload = Type.Object({
|
||||
feed: FeedObject,
|
||||
comment: CommentObject,
|
||||
cursor: Type.Optional(Type.String({ description: '回复 attach_info,省略用 comment 自带' })),
|
||||
page_size: Type.Optional(Type.Union([Type.Number(), Type.String()], { default: 20, description: '每页条数' })),
|
||||
});
|
||||
export class GetQzonePublicReplies extends OneBotAction<Static<typeof RepliesPayload>, unknown> {
|
||||
override actionName = ActionName.GetQzonePublicReplies;
|
||||
override actionSummary = '获取空友楼中楼分页';
|
||||
override actionDescription = '分页读取一条空友评论的楼中楼回复';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, comment: {}, cursor: '', page_size: 20 };
|
||||
override returnExample = {};
|
||||
override payloadSchema = RepliesPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof RepliesPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).getQzonePublicReplies(
|
||||
cookie, g_tk, payload.feed, payload.comment,
|
||||
payload.cursor ?? '', payload.page_size !== undefined ? +payload.page_size : 20,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 6. set_qzone_public_upvote —— 空友动态点赞/取消(UFO Upvote)
|
||||
const UpvotePayload = Type.Object({ feed: FeedObject, enable: Type.Boolean({ default: true }) });
|
||||
export class SetQzonePublicUpvote extends OneBotAction<Static<typeof UpvotePayload>, unknown> {
|
||||
override actionName = ActionName.SetQzonePublicUpvote;
|
||||
override actionSummary = '空友动态点赞/取消';
|
||||
override actionDescription = '对一条空友推荐动态点赞或取消点赞(UFO Upvote/Downvote)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, enable: true };
|
||||
override returnExample = {};
|
||||
override payloadSchema = UpvotePayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof UpvotePayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).setQzonePublicUpvote(cookie, g_tk, payload.feed, payload.enable);
|
||||
}
|
||||
}
|
||||
|
||||
// 7. set_qzone_public_like —— 空友动态点赞(DoLike 系)
|
||||
const LikePayload = Type.Object({ feed: FeedObject, enable: Type.Boolean({ default: true }) });
|
||||
export class SetQzonePublicLike extends OneBotAction<Static<typeof LikePayload>, unknown> {
|
||||
override actionName = ActionName.SetQzonePublicLike;
|
||||
override actionSummary = '空友动态点赞(DoLike)';
|
||||
override actionDescription = '对一条空友动态点赞/取消赞(DoLike/UnLike,key 取 cur_like_key)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, enable: true };
|
||||
override returnExample = {};
|
||||
override payloadSchema = LikePayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof LikePayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).setQzonePublicLike(cookie, g_tk, payload.feed, payload.enable);
|
||||
}
|
||||
}
|
||||
|
||||
// 8. set_qzone_public_comment_like —— 空友评论/回复点赞
|
||||
const CommentLikePayload = Type.Object({
|
||||
feed: FeedObject,
|
||||
comment: CommentObject,
|
||||
reply: ReplyObject,
|
||||
enable: Type.Boolean({ default: true }),
|
||||
});
|
||||
export class SetQzonePublicCommentLike extends OneBotAction<Static<typeof CommentLikePayload>, unknown> {
|
||||
override actionName = ActionName.SetQzonePublicCommentLike;
|
||||
override actionSummary = '空友评论/回复点赞';
|
||||
override actionDescription = '给空友评论点赞(like_type=2)或给楼中楼回复点赞(like_type=3)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, comment: {}, enable: true };
|
||||
override returnExample = {};
|
||||
override payloadSchema = CommentLikePayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof CommentLikePayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).setQzonePublicCommentLike(
|
||||
cookie, g_tk, payload.feed, payload.comment, payload.enable,
|
||||
payload.reply as Record<string, unknown> | undefined,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 9. comment_qzone_public_feed —— 空友发评论
|
||||
const CommentPayload = Type.Object({
|
||||
feed: FeedObject,
|
||||
user: UserObject,
|
||||
content: Type.Union([Type.String(), Type.Array(Type.Any())], { description: '评论内容:纯文本或富内容数组' }),
|
||||
});
|
||||
export class CommentQzonePublicFeed extends OneBotAction<Static<typeof CommentPayload>, unknown> {
|
||||
override actionName = ActionName.CommentQzonePublicFeed;
|
||||
override actionSummary = '空友发评论';
|
||||
override actionDescription = '给一条空友推荐动态发评论';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, user: {}, content: '说得好' };
|
||||
override returnExample = {};
|
||||
override payloadSchema = CommentPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof CommentPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).commentQzonePublicFeed(
|
||||
cookie, g_tk, payload.feed,
|
||||
payload.user as Record<string, unknown>,
|
||||
payload.content as string | Record<string, unknown>[],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 10. reply_qzone_public_feed —— 空友回复评论/楼中楼
|
||||
const ReplyPayload = Type.Object({
|
||||
feed: FeedObject,
|
||||
user: UserObject,
|
||||
comment: CommentObject,
|
||||
content: Type.Union([Type.String(), Type.Array(Type.Any())], { description: '回复内容' }),
|
||||
reply: ReplyObject,
|
||||
});
|
||||
export class ReplyQzonePublicFeed extends OneBotAction<Static<typeof ReplyPayload>, unknown> {
|
||||
override actionName = ActionName.ReplyQzonePublicFeed;
|
||||
override actionSummary = '空友回复评论';
|
||||
override actionDescription = '在空友动态的评论线程里回复(可点名楼中楼目标)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, user: {}, comment: {}, content: '同意' };
|
||||
override returnExample = {};
|
||||
override payloadSchema = ReplyPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof ReplyPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).replyQzonePublicFeed(
|
||||
cookie, g_tk, payload.feed,
|
||||
payload.user as Record<string, unknown>,
|
||||
payload.comment as Record<string, unknown>,
|
||||
payload.content as string | Record<string, unknown>[],
|
||||
payload.reply as Record<string, unknown> | undefined,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 11. delete_qzone_public_comment —— 删空友评论
|
||||
const DelCommentPayload = Type.Object({ feed: FeedObject, comment: CommentObject });
|
||||
export class DeleteQzonePublicComment extends OneBotAction<Static<typeof DelCommentPayload>, unknown> {
|
||||
override actionName = ActionName.DeleteQzonePublicComment;
|
||||
override actionSummary = '删空友评论';
|
||||
override actionDescription = '删除一条空友动态的评论(自己的评论)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, comment: {} };
|
||||
override returnExample = {};
|
||||
override payloadSchema = DelCommentPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof DelCommentPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).deleteQzonePublicComment(
|
||||
cookie, g_tk, payload.feed, payload.comment as Record<string, unknown>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 12. delete_qzone_public_reply —— 删空友楼中楼
|
||||
const DelReplyPayload = Type.Object({ feed: FeedObject, comment: CommentObject, reply: Type.Any({ description: '回复对象(原样回传)' }) });
|
||||
export class DeleteQzonePublicReply extends OneBotAction<Static<typeof DelReplyPayload>, unknown> {
|
||||
override actionName = ActionName.DeleteQzonePublicReply;
|
||||
override actionSummary = '删空友楼中楼';
|
||||
override actionDescription = '删除一条空友评论的楼中楼回复(自己的回复)';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, comment: {}, reply: {} };
|
||||
override returnExample = {};
|
||||
override payloadSchema = DelReplyPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof DelReplyPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).deleteQzonePublicReply(
|
||||
cookie, g_tk, payload.feed,
|
||||
payload.comment as Record<string, unknown>,
|
||||
payload.reply as Record<string, unknown>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 13. set_qzone_public_follow —— 空友关注/取关
|
||||
const FollowPayload = Type.Object({ feed: FeedObject, enable: Type.Boolean({ default: true }) });
|
||||
export class SetQzonePublicFollow extends OneBotAction<Static<typeof FollowPayload>, unknown> {
|
||||
override actionName = ActionName.SetQzonePublicFollow;
|
||||
override actionSummary = '空友关注/取关';
|
||||
override actionDescription = '关注/取关一条空友动态的作者';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, enable: true };
|
||||
override returnExample = {};
|
||||
override payloadSchema = FollowPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof FollowPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).setQzonePublicFollow(cookie, g_tk, payload.feed, payload.enable);
|
||||
}
|
||||
}
|
||||
|
||||
// 14. forward_qzone_public_feed —— 转发空友动态
|
||||
const ForwardPayload = Type.Object({ feed: FeedObject, reason: Type.String({ description: '转发理由/附言' }) });
|
||||
export class ForwardQzonePublicFeed extends OneBotAction<Static<typeof ForwardPayload>, unknown> {
|
||||
override actionName = ActionName.ForwardQzonePublicFeed;
|
||||
override actionSummary = '转发空友动态';
|
||||
override actionDescription = '转发一条空友推荐动态到自己的空间';
|
||||
override actionTags = ['扩展接口'];
|
||||
override payloadExample = { feed: {}, reason: '转发' };
|
||||
override returnExample = {};
|
||||
override payloadSchema = ForwardPayload;
|
||||
override returnSchema = Type.Any();
|
||||
|
||||
async _handle (payload: Static<typeof ForwardPayload>) {
|
||||
const { g_tk, cookie } = await publicApi(this).getQzoneAuth();
|
||||
return publicApi(this).forwardQzonePublicFeed(cookie, g_tk, payload.feed, payload.reason);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user