SnowLuma v2.4.2 source snapshot
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run

This commit is contained in:
TanTan committed 2026-11-13 09:02:00 +08:00
commit fa9c73363d
1367 files changed
+355735

No files matched your search

+520
View File
@@ -0,0 +1,520 @@
import { groupAction, f } from '../action-kit';
import type { JsonValue } from '../types';
import { okResponse } from '../types';
const albumCoverUrlSchema = {
type: ['object', 'null'],
properties: {
url: { type: 'string', description: '封面地址' },
width: { type: 'integer', description: '封面宽度' },
height: { type: 'integer', description: '封面高度' },
},
required: ['url', 'width', 'height'],
};
const albumCoverSchema = {
type: ['object', 'null'],
description: '相册封面;没有封面时为 null',
properties: {
type: { type: 'integer', description: '封面媒体类型' },
image: {
type: ['object', 'null'],
description: '封面图片信息',
properties: {
name: { type: 'string', description: '图片名称' },
sloc: { type: 'string', description: '图片短定位标识' },
lloc: { type: 'string', description: '图片长定位标识' },
photoUrls: {
type: 'array',
description: '不同规格的封面地址',
items: {
type: 'object',
properties: {
spec: { type: 'integer', description: '图片规格' },
url: albumCoverUrlSchema,
},
required: ['spec', 'url'],
},
},
defaultUrl: albumCoverUrlSchema,
isGif: { type: 'boolean', description: '是否为动图' },
hasRaw: { type: 'boolean', description: '是否有原图' },
},
required: ['name', 'sloc', 'lloc', 'photoUrls', 'defaultUrl', 'isGif', 'hasRaw'],
},
},
required: ['type', 'image'],
};
// Media-list entries are passed through rather than normalized like covers.
// Missing fields can be absent; decoded undefined values become null.
const mediaUrlSchema = {
type: ['object', 'null'],
properties: {
url: { type: ['string', 'null'] },
width: { type: ['integer', 'null'] },
height: { type: ['integer', 'null'] },
},
};
const mediaPhotoUrlsSchema = {
type: ['array', 'null'],
items: {
type: 'object',
properties: { spec: { type: ['integer', 'null'] }, url: mediaUrlSchema },
},
};
const mediaImageSchema = {
type: ['object', 'null'],
properties: {
name: { type: ['string', 'null'] },
sloc: { type: ['string', 'null'] },
lloc: { type: ['string', 'null'], description: '图片长定位标识,供评论、删除等操作使用' },
photoUrls: mediaPhotoUrlsSchema,
defaultUrl: mediaUrlSchema,
isGif: { type: ['boolean', 'null'] },
hasRaw: { type: ['boolean', 'null'] },
},
};
const albumMediaSchema = {
type: 'object',
properties: {
type: { type: ['integer', 'null'] },
image: mediaImageSchema,
video: {
type: ['object', 'null'],
properties: {
id: { type: ['string', 'null'], description: '视频标识,供评论、删除等操作使用' },
url: { type: ['string', 'null'] },
cover: mediaImageSchema,
width: { type: ['integer', 'null'] },
height: { type: ['integer', 'null'] },
videoTime: { type: ['string', 'null'], description: '时长,十进制字符串' },
videoUrl: mediaPhotoUrlsSchema,
},
},
uploader: { type: ['string', 'null'] },
batchId: { type: ['string', 'null'], description: '上传批次,十进制字符串' },
uploadTime: { type: ['string', 'null'], description: '上传时间,十进制字符串' },
},
};
export const actions = [
groupAction({
name: 'get_group_album_list',
examples: [
{
summary: '基本调用',
params: {
group_id: 20001,
},
notes: '将 group_id 替换为当前账号可访问的群号。',
},
],
readOnly: true,
returns: '群相册列表数组,每项为一个相册的基本信息。',
returnsSchema: {
type: 'array',
description: '群相册列表',
items: {
type: 'object',
properties: {
id: { type: 'string', description: '相册 id' },
name: { type: 'string', description: '相册名称' },
picNum: { type: 'integer', description: '相册内照片数量' },
createTime: { type: 'integer', description: '相册创建时间(unix 秒)' },
last_upload_time: { type: 'integer', description: '最后上传时间(unix 秒)' },
cover: albumCoverSchema,
createuin: { type: 'string', description: '相册创建者 QQ 号' },
createnickname: {
type: 'string',
description: '相册创建者昵称(原始 Unicode)',
},
},
required: [
'id',
'name',
'picNum',
'createTime',
'last_upload_time',
'cover',
'createuin',
'createnickname',
],
},
},
run: async (p, ctx) => {
const albumList = await ctx.bridge.apis.groupAlbum.list(p.group_id);
return okResponse(albumList);
},
}),
// get_qun_album_list — NapCat-compatible view of QQ NT's AlbumService.
groupAction({
name: 'get_qun_album_list',
examples: [
{
summary: '基本调用',
params: {
group_id: 20001,
attach_info: '',
},
notes: '后续页原样传回上一页的 attach_info;has_more=false 表示结束。',
},
],
readOnly: true,
returns: 'NapCat 风格的相册列表封套:{album_list, attach_info, has_more}。',
returnsSchema: {
type: 'object',
properties: {
album_list: {
type: 'array',
description: '相册列表',
items: {
type: 'object',
properties: {
album_id: { type: 'string', description: '相册 id' },
name: { type: 'string', description: '相册名称' },
create_time: { type: 'string', description: '相册创建时间(unix 秒)' },
last_upload_time: {
type: 'string',
description: '最后上传时间(unix 秒)',
},
upload_number: { type: 'string', description: '相册内媒体数量' },
cover: albumCoverSchema,
creator: {
type: 'object',
description: '相册创建者信息',
properties: {
uin: { type: 'string', description: '创建者 QQ 号' },
uid: { type: 'string', description: '创建者 UID' },
nick: {
type: 'string',
description: '创建者原始 Unicode 昵称',
},
},
},
},
required: [
'album_id',
'name',
'create_time',
'last_upload_time',
'upload_number',
'cover',
],
},
},
attach_info: { type: 'string', description: '下一页分页游标' },
has_more: { type: 'boolean', description: '是否还有更多' },
},
required: ['album_list', 'attach_info', 'has_more'],
},
params: {
attach_info: f.string().default(''),
},
run: async (p, ctx) => {
const result = await ctx.bridge.apis.groupAlbum.listQun(p.group_id, p.attach_info);
return okResponse({
album_list: result.albumList,
attach_info: result.attachInfo,
has_more: result.hasMore,
} as unknown as JsonValue);
},
}),
groupAction({
name: 'upload_image_to_qun_album',
examples: [
{
summary: '基本调用',
params: {
group_id: 20001,
album_id: '<album-id>',
album_name: '活动照片',
file: 'file:///path/to/photo.png',
},
notes: 'album_id 来自 get_group_album_list;lloc 或视频 id、batch_id 来自 get_group_album_media_list。替换群号及对应资源标识。 示例路径位于 SnowLuma 服务端,须替换为该服务可读取的实际文件。',
},
],
returnsSchema: {
type: 'null',
description: '成功时 data 为 null;失败另见响应的 status、retcode 和 wording',
},
params: {
album_id: f.string({ allowEmpty: false }),
album_name: f.string({ allowEmpty: false }),
file: f.image(),
},
run: async (p, ctx) => {
await ctx.bridge.apis.groupAlbum.upload(p.group_id, p.album_id, p.album_name, p.file);
return okResponse(null);
},
}),
groupAction({
name: 'upload_video_to_qun_album',
examples: [
{
summary: '上传视频到群相册',
params: {
group_id: 20001,
album_id: '<album-id>',
album_name: '活动视频',
file: 'file:///path/to/video.mp4',
},
notes: 'album_id 来自 get_group_album_list;lloc 或视频 id、batch_id 来自 get_group_album_media_list。替换群号及对应资源标识。 示例路径位于 SnowLuma 服务端,须替换为该服务可读取的实际文件。',
},
],
summary: '上传视频到群相册',
returns: '{ id: string }',
returnsSchema: {
type: 'object',
properties: {
id: { type: 'string', description: '视频 id' },
},
required: ['id'],
},
params: {
album_id: f.string({ allowEmpty: false }).describe('相册 id'),
album_name: f.string({ allowEmpty: false }).describe('相册名称'),
file: f.video().describe('视频文件'),
},
run: async (p, ctx) => {
const result = await ctx.bridge.apis.groupAlbum.uploadVideo(
p.group_id,
p.album_id,
p.album_name,
p.file,
);
return okResponse(result);
},
}),
groupAction({
name: 'get_group_album_media_list',
examples: [
{
summary: '基本调用',
params: {
group_id: 20001,
album_id: '<album-id>',
attach_info: '',
},
notes: 'album_id 来自 get_group_album_list;lloc 或视频 id、batch_id 来自 get_group_album_media_list。替换群号及对应资源标识。 下一页传回 nextAttachInfo。',
},
],
readOnly: true,
returns:
'相册图片/视频列表及下一页分页游标;视频项包含 id、url、cover、尺寸、时长和多规格地址。',
returnsSchema: {
type: 'object',
properties: {
mediaList: {
type: 'array',
description: '相册图片或视频,未返回的字段可省略或为 null',
items: albumMediaSchema,
},
nextAttachInfo: { type: 'string', description: '下一页分页游标(空串表示无更多)' },
},
required: ['mediaList', 'nextAttachInfo'],
},
params: {
album_id: f.string({ allowEmpty: false }),
attach_info: f.string().default(''),
},
run: async (p, ctx) => {
const mediaList = await ctx.bridge.apis.groupAlbum.getMediaList(
p.group_id,
p.album_id,
p.attach_info,
);
return okResponse(mediaList as unknown as JsonValue);
},
}),
groupAction({
name: 'do_group_album_comment',
examples: [
{
summary: '基本调用',
params: {
group_id: 20001,
album_id: '<album-id>',
lloc: '<media-lloc-or-video-id>',
content: '拍得很好',
},
notes: 'album_id 来自 get_group_album_list;lloc 或视频 id、batch_id 来自 get_group_album_media_list。替换群号及对应资源标识。',
},
],
returnsSchema: {
type: 'object',
properties: {
id: {
type: 'string',
},
user: {
type: 'object',
properties: {
uin: {
type: 'string',
},
},
required: ['uin'],
},
content: {
type: 'array',
items: {
type: 'object',
properties: {
type: {
type: 'integer',
},
content: {
type: 'string',
},
},
required: ['type', 'content'],
},
},
time: {
type: 'string',
description: '十进制时间字符串',
},
clientKey: {
type: 'string',
},
},
required: ['id', 'user', 'content', 'time', 'clientKey'],
},
params: {
album_id: f.string({ allowEmpty: false }),
lloc: f.string({ allowEmpty: false }),
content: f.string({ allowEmpty: false }),
},
run: async (p, ctx) => {
const comment = await ctx.bridge.apis.groupAlbum.comment(
p.group_id,
p.album_id,
p.lloc,
p.content,
);
return okResponse(comment as unknown as JsonValue);
},
}),
groupAction({
name: 'set_group_album_media_like',
examples: [
{
summary: '基本调用',
params: {
group_id: 20001,
album_id: '<album-id>',
batch_id: '1700000000',
},
notes: 'album_id 来自 get_group_album_list;lloc 或视频 id、batch_id 来自 get_group_album_media_list。替换群号及对应资源标识。 batch_id 必须是实际批次的十进制字符串。',
},
],
returnsSchema: {
type: 'object',
properties: {
id: {
type: ['string', 'null'],
},
status: {
type: ['integer', 'null'],
},
},
},
params: {
album_id: f.string({ allowEmpty: false }),
batch_id: f.string({ allowEmpty: false }),
lloc: f.string().optional(), // 可选参数(空串按未传处理)
},
run: async (p, ctx) => {
const res = await ctx.bridge.apis.groupAlbum.like(
p.group_id,
p.album_id,
p.batch_id,
p.lloc || undefined,
true,
);
return okResponse(res);
},
}),
// 取消点赞群相册媒体
groupAction({
name: 'cancel_group_album_media_like',
examples: [
{
summary: '基本调用',
params: {
group_id: 20001,
album_id: '<album-id>',
batch_id: '1700000000',
},
notes: 'album_id 来自 get_group_album_list;lloc 或视频 id、batch_id 来自 get_group_album_media_list。替换群号及对应资源标识。 batch_id 必须是实际批次的十进制字符串。',
},
],
returnsSchema: {
type: 'object',
properties: {
id: {
type: ['string', 'null'],
},
status: {
type: ['integer', 'null'],
},
},
},
params: {
album_id: f.string({ allowEmpty: false }),
batch_id: f.string({ allowEmpty: false }),
lloc: f.string().optional(), // 可选参数(空串按未传处理)
},
run: async (p, ctx) => {
const res = await ctx.bridge.apis.groupAlbum.like(
p.group_id,
p.album_id,
p.batch_id,
p.lloc || undefined,
false,
);
return okResponse(res);
},
}),
groupAction({
name: 'del_group_album_media',
examples: [
{
summary: '删除群相册图片或视频',
params: {
group_id: 20001,
album_id: '<album-id>',
lloc: '<media-lloc-or-video-id>',
},
notes: 'album_id 来自 get_group_album_list;lloc 或视频 id、batch_id 来自 get_group_album_media_list。替换群号及对应资源标识。',
},
],
returnsSchema: {
type: 'object',
properties: {
success: {
const: true,
},
},
required: ['success'],
},
summary: '删除群相册图片或视频',
params: {
album_id: f.string({ allowEmpty: false }),
lloc: f.string({ allowEmpty: false }).describe('图片长定位标识,或视频 id'),
},
run: async (p, ctx) => {
const res = await ctx.bridge.apis.groupAlbum.delete(p.group_id, p.album_id, p.lloc);
return okResponse(res);
},
}),
];