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
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:
commit
fa9c73363d
1367 files changed
+355735
No files matched your search
+579
@@ -0,0 +1,579 @@
|
||||
import type { ActionParams, ActionResult } from '@snowluma/sdk';
|
||||
|
||||
const album = { group_id: '10001', album_id: 'album' };
|
||||
const mediaLike = { ...album, batch_id: '9007199254740993', lloc: 'photo' };
|
||||
const mediaUpload = { ...album, album_name: 'Album', file: 'file:///fixture' };
|
||||
const download = { file: 'https://example.com/file', file_id: 'cached', chunk_size: '65536' };
|
||||
const fileset = { fileset_id: 'fileset' };
|
||||
const flashFile = { ...fileset, file_name: 'file.txt', file_index: '0' };
|
||||
const peer = { group_id: '10001', user_id: '10002', phone_number: '' };
|
||||
const qzoneLike = { tid: 'post', target_uin: '10002', abstime: '1700000000' };
|
||||
const qzonePublicFeed = {
|
||||
cell_common: {
|
||||
domain_type: 3,
|
||||
union_id: { uf_key: '9007199254740993', unknown_identity: 'preserved' },
|
||||
},
|
||||
cell_feed_transfer: { opaque: 'fixture' },
|
||||
unknown_cell: { decimal: '18446744073709551615' },
|
||||
};
|
||||
const qzonePublicComment = {
|
||||
id: '9007199254740993',
|
||||
user: { uid: 'public-reader' },
|
||||
like: { id: 'comment-like-key' },
|
||||
};
|
||||
const qzonePublicReply = {
|
||||
id: '18446744073709551615',
|
||||
user: { uid: 'public-author' },
|
||||
like: { id: 'reply-like-key' },
|
||||
};
|
||||
|
||||
// The same examples are compiled against the published declarations and parsed
|
||||
// by the real server action definitions. They never invoke QQ or perform I/O.
|
||||
export const actionParams = {
|
||||
get_friend_list: { with_profile: true },
|
||||
get_friends_with_category: { with_profile: false },
|
||||
get_group_admin_permissions: { group_id: '10001', user_id: '10002' },
|
||||
set_group_admin_permissions: {
|
||||
group_id: '10001',
|
||||
user_id: '10002',
|
||||
recall_member_message: false,
|
||||
kick_member: true,
|
||||
kick_member_per_day: '20',
|
||||
},
|
||||
set_group_admin_receive_verify: { group_id: '10001', user_id: '10002', enable: 'on' },
|
||||
_get_friend_dress: { user_id: '10002' },
|
||||
add_custom_face: { file: 'file:///fixture.png' },
|
||||
cancel_group_album_media_like: mediaLike,
|
||||
clean_stream_temp_file: {},
|
||||
comment_qzone: {
|
||||
tid: 'post',
|
||||
content: 'Comment',
|
||||
target_uin: '10002',
|
||||
images: [],
|
||||
comment_id: '0',
|
||||
comment_uin: '10003',
|
||||
reply_uin: '10004',
|
||||
reply_name: 'Reader',
|
||||
},
|
||||
comment_qzone_public_feed: {
|
||||
feed: qzonePublicFeed,
|
||||
content: [{ type: 0, content: 'Comment', upstream_option: true }],
|
||||
},
|
||||
create_flash_task: {
|
||||
files: ['file:///one', { file: 'file:///two', name: 'two.txt' }],
|
||||
name: 'Files',
|
||||
thumb_path: '',
|
||||
},
|
||||
del_group_album_media: { ...album, lloc: 'photo' },
|
||||
delete_custom_face: { emoji_id: 'face' },
|
||||
delete_flash_file: fileset,
|
||||
delete_qzone_msg: { tid: 'post' },
|
||||
delete_qzone_public_comment: { feed: qzonePublicFeed, comment: qzonePublicComment },
|
||||
delete_qzone_public_reply: {
|
||||
feed: qzonePublicFeed,
|
||||
comment: qzonePublicComment,
|
||||
reply: qzonePublicReply,
|
||||
},
|
||||
do_group_album_comment: { ...album, lloc: 'photo', content: 'Comment' },
|
||||
download_file_image_stream: download,
|
||||
download_file_record_stream: download,
|
||||
download_file_stream: download,
|
||||
download_fileset: flashFile,
|
||||
fetch_custom_face_detail: { count: '48' },
|
||||
fetch_ptt_text: { message_id: -42 },
|
||||
forward_qzone_public_feed: { feed: qzonePublicFeed, reason: '' },
|
||||
get_ptt_text: { message_id: '-42' },
|
||||
get_record_text: { message_id: -42 },
|
||||
get_doubt_friends_add_request: { count: '50' },
|
||||
get_fileset_id: { share_code: 'share' },
|
||||
get_fileset_info: fileset,
|
||||
get_flash_file_list: fileset,
|
||||
get_flash_file_url: flashFile,
|
||||
get_group_album_list: { group_id: '10001' },
|
||||
get_group_album_media_list: { ...album, attach_info: '' },
|
||||
get_group_signed_list: { group_id: '10001' },
|
||||
get_msg_emoji_likes: { message_id: '-42' },
|
||||
get_qun_album_list: { group_id: '10001', attach_info: '' },
|
||||
get_qzone_feeds: { page_num: '1', count: '10', cursor: 'cursor-from-previous-response' },
|
||||
get_qzone_msg_list: { target_uin: '10002', pos: '0', num: '20' },
|
||||
get_qzone_profile: { target_uin: '10002' },
|
||||
get_qzone_public_capabilities: {},
|
||||
get_qzone_home_feeds: { target_uin: '10001', cursor: 'home-feed-cursor' },
|
||||
get_qzone_feed_detail: { tid: '1127000000f1536501000000' },
|
||||
get_qzone_share_ark: { feed: qzonePublicFeed },
|
||||
get_qzone_public_comments: { feed: qzonePublicFeed, cursor: 'comments-from-detail' },
|
||||
get_qzone_public_feed_detail: { feed: qzonePublicFeed },
|
||||
get_qzone_public_feeds: { cursor: 'public-feed-cursor' },
|
||||
get_qzone_public_replies: {
|
||||
feed: qzonePublicFeed,
|
||||
comment: qzonePublicComment,
|
||||
cursor: '',
|
||||
page_size: '20',
|
||||
},
|
||||
get_rkey_server: {},
|
||||
get_share_link: fileset,
|
||||
like_qzone: qzoneLike,
|
||||
list_filesets: {},
|
||||
modify_custom_face: { emoji_id: 'face', desc: 'Description' },
|
||||
move_custom_face_to_front: { emoji_id: 'face' },
|
||||
rename_flash_file: { ...fileset, new_name: 'new.txt' },
|
||||
reply_qzone_public_feed: {
|
||||
feed: qzonePublicFeed,
|
||||
comment: qzonePublicComment,
|
||||
content: 'Reply',
|
||||
reply: qzonePublicReply,
|
||||
},
|
||||
request_decrypt_key: { db_path: '/fixture.db' },
|
||||
send_ark_share: peer,
|
||||
send_flash_msg: { ...fileset, group_id: '10001', user_id: '10002' },
|
||||
send_group_ark_share: { group_id: '10001' },
|
||||
send_qzone_msg: {
|
||||
content: 'Post',
|
||||
images: [],
|
||||
ugc_right: '16',
|
||||
target_uins: ['10002'],
|
||||
},
|
||||
send_tuwen_ark: {
|
||||
group_id: '10001',
|
||||
user_id: '10002',
|
||||
title: 'Title',
|
||||
desc: 'Description',
|
||||
summary: 'Summary',
|
||||
preview_url: '',
|
||||
jump_url: 'https://example.com/',
|
||||
},
|
||||
set_doubt_friends_add_request: { flag: 'u_fixture', approve: 'yes' },
|
||||
set_group_album_media_like: mediaLike,
|
||||
set_group_member_invite_policy: { group_id: '10001', policy: 'require_approval' },
|
||||
set_group_member_permissions: {
|
||||
group_id: '10001',
|
||||
allow_member_upload_album: false,
|
||||
allow_member_temporary_session: 'off',
|
||||
allow_member_create_group: 1,
|
||||
},
|
||||
set_group_new_member_history_visibility: { group_id: '10001', visible: 'on' },
|
||||
set_group_robot_add_option: {
|
||||
group_id: '10001',
|
||||
robot_member_switch: '1',
|
||||
robot_member_examine: '0',
|
||||
},
|
||||
set_qzone_ban: { user_id: '10002', enable: false },
|
||||
set_qzone_msg_right: { tid: 'post', ugc_right: '128', target_uins: ['10002'] },
|
||||
set_qzone_profile: { name: 'Space', description: '' },
|
||||
set_qzone_public_follow: { feed: qzonePublicFeed, enable: 'off' },
|
||||
set_qzone_public_comment_like: {
|
||||
feed: qzonePublicFeed,
|
||||
comment: qzonePublicComment,
|
||||
reply: qzonePublicReply,
|
||||
enable: 'on',
|
||||
},
|
||||
set_qzone_public_like: { feed: qzonePublicFeed, enable: 0 },
|
||||
set_qzone_public_upvote: { feed: qzonePublicFeed, enable: true },
|
||||
share_group_ex: { group_id: '10001' },
|
||||
share_peer: peer,
|
||||
test_download_stream: { error: false },
|
||||
unlike_qzone: qzoneLike,
|
||||
upload_file_stream: {
|
||||
stream_id: 'fixture',
|
||||
chunk_data: 'YQ==',
|
||||
chunk_index: '0',
|
||||
total_chunks: '1',
|
||||
file_size: '1',
|
||||
expected_sha256: '',
|
||||
is_complete: 'false',
|
||||
filename: 'file.txt',
|
||||
reset: false,
|
||||
verify_only: 0,
|
||||
file_retention: '0',
|
||||
},
|
||||
upload_image_to_qun_album: mediaUpload,
|
||||
upload_video_to_qun_album: mediaUpload,
|
||||
'.handle_quick_operation_async': { context: {}, operation: {} },
|
||||
} satisfies { [K in CoveredAction]: ActionParams<K> };
|
||||
|
||||
// Keep this independent of SnowLumaActionMap: a missing map entry must fail the
|
||||
// consumer's coverage check rather than silently remove that example.
|
||||
export type CoveredAction =
|
||||
| 'get_friend_list'
|
||||
| 'get_friends_with_category'
|
||||
| 'get_group_admin_permissions'
|
||||
| 'set_group_admin_permissions'
|
||||
| 'set_group_admin_receive_verify'
|
||||
| '_get_friend_dress'
|
||||
| 'add_custom_face'
|
||||
| 'cancel_group_album_media_like'
|
||||
| 'clean_stream_temp_file'
|
||||
| 'comment_qzone'
|
||||
| 'comment_qzone_public_feed'
|
||||
| 'create_flash_task'
|
||||
| 'del_group_album_media'
|
||||
| 'delete_custom_face'
|
||||
| 'delete_flash_file'
|
||||
| 'delete_qzone_msg'
|
||||
| 'delete_qzone_public_comment'
|
||||
| 'delete_qzone_public_reply'
|
||||
| 'do_group_album_comment'
|
||||
| 'download_file_image_stream'
|
||||
| 'download_file_record_stream'
|
||||
| 'download_file_stream'
|
||||
| 'download_fileset'
|
||||
| 'fetch_custom_face_detail'
|
||||
| 'fetch_ptt_text'
|
||||
| 'forward_qzone_public_feed'
|
||||
| 'get_ptt_text'
|
||||
| 'get_record_text'
|
||||
| 'get_doubt_friends_add_request'
|
||||
| 'get_fileset_id'
|
||||
| 'get_fileset_info'
|
||||
| 'get_flash_file_list'
|
||||
| 'get_flash_file_url'
|
||||
| 'get_group_album_list'
|
||||
| 'get_group_album_media_list'
|
||||
| 'get_group_signed_list'
|
||||
| 'get_msg_emoji_likes'
|
||||
| 'get_qun_album_list'
|
||||
| 'get_qzone_feeds'
|
||||
| 'get_qzone_msg_list'
|
||||
| 'get_qzone_profile'
|
||||
| 'get_qzone_public_capabilities'
|
||||
| 'get_qzone_home_feeds'
|
||||
| 'get_qzone_feed_detail'
|
||||
| 'get_qzone_share_ark'
|
||||
| 'get_qzone_public_comments'
|
||||
| 'get_qzone_public_feed_detail'
|
||||
| 'get_qzone_public_feeds'
|
||||
| 'get_qzone_public_replies'
|
||||
| 'get_rkey_server'
|
||||
| 'get_share_link'
|
||||
| 'like_qzone'
|
||||
| 'list_filesets'
|
||||
| 'modify_custom_face'
|
||||
| 'move_custom_face_to_front'
|
||||
| 'rename_flash_file'
|
||||
| 'reply_qzone_public_feed'
|
||||
| 'request_decrypt_key'
|
||||
| 'send_ark_share'
|
||||
| 'send_flash_msg'
|
||||
| 'send_group_ark_share'
|
||||
| 'send_qzone_msg'
|
||||
| 'send_tuwen_ark'
|
||||
| 'set_doubt_friends_add_request'
|
||||
| 'set_group_album_media_like'
|
||||
| 'set_group_member_invite_policy'
|
||||
| 'set_group_member_permissions'
|
||||
| 'set_group_new_member_history_visibility'
|
||||
| 'set_group_robot_add_option'
|
||||
| 'set_qzone_ban'
|
||||
| 'set_qzone_msg_right'
|
||||
| 'set_qzone_profile'
|
||||
| 'set_qzone_public_follow'
|
||||
| 'set_qzone_public_comment_like'
|
||||
| 'set_qzone_public_like'
|
||||
| 'set_qzone_public_upvote'
|
||||
| 'share_group_ex'
|
||||
| 'share_peer'
|
||||
| 'test_download_stream'
|
||||
| 'unlike_qzone'
|
||||
| 'upload_file_stream'
|
||||
| 'upload_image_to_qun_album'
|
||||
| 'upload_video_to_qun_album'
|
||||
| '.handle_quick_operation_async';
|
||||
|
||||
const flashInfo = {
|
||||
fileset_id: 'fileset',
|
||||
file_name: 'file.txt',
|
||||
orig_name: 'original.txt',
|
||||
size: 42,
|
||||
share_url: 'https://example.com/share',
|
||||
file_id: 'file',
|
||||
download_url: '',
|
||||
};
|
||||
|
||||
export const actionResults = {
|
||||
get_friend_list: [
|
||||
{
|
||||
user_id: 10001,
|
||||
nickname: 'Friend',
|
||||
remark: '',
|
||||
category_id: 0,
|
||||
long_nick: '',
|
||||
age: 0,
|
||||
is_qq_vip: false,
|
||||
privilege_icons: {
|
||||
open: [{ type: 1, icon_url: 'normal', deluxe_icon_url: 'deluxe' }],
|
||||
closed: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
get_friends_with_category: [
|
||||
{
|
||||
categoryId: 0,
|
||||
categoryName: 'Friends',
|
||||
categoryMbCount: 1,
|
||||
buddyList: [{ user_id: 10001, nickname: 'Friend', remark: '', city: 'City' }],
|
||||
},
|
||||
],
|
||||
get_group_admin_permissions: {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
recall_member_message: null,
|
||||
kick_member: true,
|
||||
kick_member_per_day: 20,
|
||||
receive_verify: false,
|
||||
},
|
||||
set_group_admin_permissions: null,
|
||||
set_group_admin_receive_verify: null,
|
||||
_get_friend_dress: {
|
||||
target_uin: '10002',
|
||||
is_svip: true,
|
||||
avatar_url: '',
|
||||
items: [
|
||||
{
|
||||
app_id: 15,
|
||||
kind: 'card',
|
||||
item_id: 1,
|
||||
name: 'Card',
|
||||
preview_url: '',
|
||||
video_url: '',
|
||||
price: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
add_custom_face: { emoji_id: 'face' },
|
||||
cancel_group_album_media_like: {},
|
||||
clean_stream_temp_file: { message: 'success', removed: 1, freed_bytes: 42, skipped_active: 1 },
|
||||
comment_qzone: { comment_id: 'comment' },
|
||||
comment_qzone_public_feed: { comment: qzonePublicComment },
|
||||
create_flash_task: { fileset_id: 'fileset', task_id: 'fileset' },
|
||||
del_group_album_media: { success: true },
|
||||
delete_custom_face: null,
|
||||
delete_flash_file: null,
|
||||
delete_qzone_msg: null,
|
||||
delete_qzone_public_comment: {},
|
||||
delete_qzone_public_reply: {},
|
||||
do_group_album_comment: {
|
||||
id: 'comment',
|
||||
user: { uin: '10002' },
|
||||
content: [{ type: 0, content: 'Comment' }],
|
||||
time: '1700000000',
|
||||
clientKey: 'fixture',
|
||||
},
|
||||
download_file_image_stream: {
|
||||
type: 'stream',
|
||||
data_type: 'file_info',
|
||||
file_name: 'image',
|
||||
file_size: 1,
|
||||
chunk_size: 1,
|
||||
},
|
||||
download_file_record_stream: {
|
||||
type: 'stream',
|
||||
data_type: 'file_chunk',
|
||||
index: 0,
|
||||
data: 'YQ==',
|
||||
size: 1,
|
||||
progress: 100,
|
||||
base64_size: 4,
|
||||
},
|
||||
download_file_stream: {
|
||||
type: 'response',
|
||||
data_type: 'file_complete',
|
||||
file_name: 'file',
|
||||
total_chunks: 1,
|
||||
total_bytes: 1,
|
||||
message: 'Download completed',
|
||||
},
|
||||
download_fileset: { url: '', file_name: 'file.txt', file_size: 42 },
|
||||
fetch_custom_face_detail: [{ emoji_id: 'face', resId: 'face', url: '', md5: '', desc: '' }],
|
||||
fetch_ptt_text: { text: 'Speech' },
|
||||
forward_qzone_public_feed: {},
|
||||
get_ptt_text: { text: 'Speech' },
|
||||
get_record_text: { text: 'Speech' },
|
||||
get_doubt_friends_add_request: [
|
||||
{
|
||||
uid: 'u_fixture',
|
||||
user_id: 10002,
|
||||
nick: 'User',
|
||||
source: '',
|
||||
reason: '',
|
||||
msg: '',
|
||||
group_code: '',
|
||||
reqTime: 0,
|
||||
},
|
||||
],
|
||||
get_fileset_id: { fileset_id: 'fileset' },
|
||||
get_fileset_info: { fileset_id: 'fileset', file_list: [flashInfo] },
|
||||
get_flash_file_list: [flashInfo],
|
||||
get_flash_file_url: { url: '' },
|
||||
get_group_album_list: [
|
||||
{
|
||||
id: 'album',
|
||||
name: 'Album',
|
||||
picNum: 1,
|
||||
createTime: 1,
|
||||
desc: '',
|
||||
owner: '10002',
|
||||
createuin: '10002',
|
||||
createnickname: 'User',
|
||||
last_upload_time: 1,
|
||||
cover: null,
|
||||
},
|
||||
],
|
||||
get_group_album_media_list: {
|
||||
mediaList: [
|
||||
{
|
||||
type: 2,
|
||||
video: { id: 'video', videoTime: '1000' },
|
||||
batchId: '9007199254740993',
|
||||
uploadTime: '1',
|
||||
},
|
||||
],
|
||||
nextAttachInfo: '',
|
||||
},
|
||||
get_group_signed_list: [{ user_id: 10002, nick: 'User', time: 1, rank: 1 }],
|
||||
get_msg_emoji_likes: [
|
||||
{
|
||||
emoji_id: '1',
|
||||
emoji_type: 1,
|
||||
count: 1,
|
||||
last_reaction_time: 1,
|
||||
users: [{ user_id: 10002 }],
|
||||
},
|
||||
],
|
||||
get_qun_album_list: {
|
||||
album_list: [
|
||||
{
|
||||
album_id: 'album',
|
||||
owner: '10002',
|
||||
name: 'Album',
|
||||
desc: '',
|
||||
create_time: '1',
|
||||
modify_time: '1',
|
||||
last_upload_time: '1',
|
||||
upload_number: '9007199254740993',
|
||||
cover: {
|
||||
type: 1,
|
||||
image: {
|
||||
name: '',
|
||||
sloc: '',
|
||||
lloc: '',
|
||||
photoUrls: [],
|
||||
defaultUrl: null,
|
||||
isGif: false,
|
||||
hasRaw: false,
|
||||
},
|
||||
},
|
||||
top_flag: '0',
|
||||
busi_type: 0,
|
||||
status: 0,
|
||||
allow_share: true,
|
||||
is_subscribe: false,
|
||||
bitmap: '',
|
||||
is_share_album: false,
|
||||
qz_album_type: 0,
|
||||
cover_type: 0,
|
||||
default_desc: '',
|
||||
sort_type: 0,
|
||||
},
|
||||
],
|
||||
attach_info: '',
|
||||
has_more: false,
|
||||
},
|
||||
get_qzone_feeds: {
|
||||
feeds: [{ uin: 10002, nickname: 'User', time: 1, appid: 311, key: 'post', html: '' }],
|
||||
has_more: false,
|
||||
},
|
||||
get_qzone_msg_list: {
|
||||
total: 1,
|
||||
msglist: [
|
||||
{
|
||||
tid: 'post',
|
||||
content: 'Post',
|
||||
time: 1,
|
||||
comment_num: 0,
|
||||
is_private: false,
|
||||
images: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
get_qzone_profile: { name: 'Space', description: 'Description' },
|
||||
get_qzone_public_capabilities: { public_qzone_entrance_switch: true, can_upvote: true },
|
||||
get_qzone_home_feeds: { feeds: [qzonePublicFeed], has_more: false, next_cursor: null },
|
||||
get_qzone_feed_detail: {
|
||||
feed: {
|
||||
cell_common: { domain_type: 1, union_id: { feed_id: '1127000000f1536501000000' } },
|
||||
cell_pic: { future_image_field: true },
|
||||
},
|
||||
attach_info: 'comments-from-detail',
|
||||
},
|
||||
get_qzone_share_ark: {
|
||||
ark: '{"app":"com.tencent.tuwen.lua"}',
|
||||
requires_confirmation: false,
|
||||
notice: null,
|
||||
},
|
||||
get_qzone_public_comments: {
|
||||
cell_comment: { comments: [qzonePublicComment] },
|
||||
attach_info: 'next-comments',
|
||||
has_more: true,
|
||||
},
|
||||
get_qzone_public_feed_detail: {
|
||||
feed: { feed: qzonePublicFeed },
|
||||
attach_info: 'comments-from-detail',
|
||||
has_more: true,
|
||||
},
|
||||
get_qzone_public_feeds: {
|
||||
feeds: [qzonePublicFeed],
|
||||
has_more: true,
|
||||
next_cursor: 'public-feed-cursor',
|
||||
unknown_page: { preserved: true },
|
||||
},
|
||||
get_qzone_public_replies: {
|
||||
replys: [qzonePublicReply],
|
||||
reply_attach_info: '',
|
||||
has_more: false,
|
||||
},
|
||||
get_rkey_server: { expired_time: 1, name: 'SnowLuma', private_rkey: 'fixture' },
|
||||
get_share_link: 'https://example.com/share',
|
||||
like_qzone: null,
|
||||
list_filesets: [flashInfo],
|
||||
modify_custom_face: null,
|
||||
move_custom_face_to_front: null,
|
||||
rename_flash_file: null,
|
||||
reply_qzone_public_feed: { reply: qzonePublicReply },
|
||||
request_decrypt_key: { db_key: 'fixture' },
|
||||
send_ark_share: { arkMsg: '{}' },
|
||||
send_flash_msg: { message_id: 0 },
|
||||
send_group_ark_share: '{}',
|
||||
send_qzone_msg: { tid: 'post', time: 1 },
|
||||
send_tuwen_ark: null,
|
||||
set_doubt_friends_add_request: null,
|
||||
set_group_album_media_like: { id: 'like', status: 1 },
|
||||
set_group_member_invite_policy: null,
|
||||
set_group_member_permissions: null,
|
||||
set_group_new_member_history_visibility: null,
|
||||
set_group_robot_add_option: null,
|
||||
set_qzone_ban: null,
|
||||
set_qzone_msg_right: { ugc_right: 128 },
|
||||
set_qzone_profile: null,
|
||||
set_qzone_public_follow: { ret_code: 0 },
|
||||
set_qzone_public_comment_like: { like: { status: 1 } },
|
||||
set_qzone_public_like: { like: { liked: true } },
|
||||
set_qzone_public_upvote: { upvote: { upvoted: true } },
|
||||
share_group_ex: '{}',
|
||||
share_peer: { arkMsg: '{}' },
|
||||
test_download_stream: {
|
||||
type: 'response',
|
||||
data_type: 'data_complete',
|
||||
data: 'Stream transmission complete',
|
||||
},
|
||||
unlike_qzone: null,
|
||||
upload_file_stream: {
|
||||
type: 'stream',
|
||||
stream_id: 'fixture',
|
||||
status: 'chunk_received',
|
||||
received_chunks: 1,
|
||||
total_chunks: 1,
|
||||
},
|
||||
upload_image_to_qun_album: null,
|
||||
upload_video_to_qun_album: { id: 'video' },
|
||||
'.handle_quick_operation_async': null,
|
||||
} satisfies { [K in CoveredAction]: ActionResult<K> };
|
||||
+324
@@ -0,0 +1,324 @@
|
||||
import type {
|
||||
ActionParams,
|
||||
ActionResult,
|
||||
DownloadFileStreamComplete,
|
||||
JsonObject,
|
||||
JsonValue,
|
||||
SnowLumaActionMap,
|
||||
SnowLumaHttpClient,
|
||||
SnowLumaKnownAction,
|
||||
SnowLumaWebSocketClient,
|
||||
StreamApiResponse,
|
||||
UploadFileStreamComplete,
|
||||
} from '@snowluma/sdk';
|
||||
import { actionParams, actionResults, type CoveredAction } from './action-contracts.js';
|
||||
|
||||
type AssertNever<T extends never> = T;
|
||||
export type MissingActionTypes = AssertNever<Exclude<SnowLumaKnownAction, keyof SnowLumaActionMap>>;
|
||||
export type UnregisteredActionTypes = AssertNever<
|
||||
Exclude<keyof SnowLumaActionMap, SnowLumaKnownAction>
|
||||
>;
|
||||
export type UnspecifiedResults = AssertNever<
|
||||
{
|
||||
[K in CoveredAction]: JsonValue extends ActionResult<K> ? K : never;
|
||||
}[CoveredAction]
|
||||
>;
|
||||
|
||||
type AssertTrue<T extends true> = T;
|
||||
type Equal<A, B> =
|
||||
(<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
||||
export type PttAliasParams = AssertTrue<
|
||||
Equal<ActionParams<'get_ptt_text'>, ActionParams<'fetch_ptt_text'>>
|
||||
>;
|
||||
export type PttAliasResult = AssertTrue<
|
||||
Equal<ActionResult<'get_record_text'>, ActionResult<'fetch_ptt_text'>>
|
||||
>;
|
||||
export type QuickAlias = AssertTrue<
|
||||
Equal<
|
||||
SnowLumaActionMap['.handle_quick_operation_async'],
|
||||
SnowLumaActionMap['.handle_quick_operation']
|
||||
>
|
||||
>;
|
||||
|
||||
declare const http: SnowLumaHttpClient;
|
||||
declare const ws: SnowLumaWebSocketClient;
|
||||
|
||||
const groupSystemMessages = await http.getGroupSystemMessages({ groupId: 10001 });
|
||||
export const invitationTarget: number | undefined = groupSystemMessages[0]?.target_uin;
|
||||
export const invitationOperator: number | undefined = groupSystemMessages[0]?.operator_uin;
|
||||
export const invitationIdentityStatus: 'known' | 'unknown' | undefined =
|
||||
groupSystemMessages[0]?.invitor_status;
|
||||
|
||||
const adminPermissions = await http.raw('get_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
});
|
||||
export const adminRecall: boolean | null = adminPermissions.recall_member_message;
|
||||
export const adminKickLimit: number | null = adminPermissions.kick_member_per_day;
|
||||
export const adminReceiveVerify: boolean | null = adminPermissions.receive_verify;
|
||||
await http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
recall_member_message: false,
|
||||
});
|
||||
await http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
kick_member: false,
|
||||
});
|
||||
await http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
kick_member: true,
|
||||
kick_member_per_day: 0,
|
||||
});
|
||||
await http.raw('set_group_admin_receive_verify', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
enable: false,
|
||||
});
|
||||
// @ts-expect-error a patch must change a permission
|
||||
http.raw('set_group_admin_permissions', { group_id: 10001, user_id: 10002 });
|
||||
// @ts-expect-error enabling removal requires an explicit limit
|
||||
http.raw('set_group_admin_permissions', { group_id: 10001, user_id: 10002, kick_member: true });
|
||||
http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
kick_member: false,
|
||||
// @ts-expect-error a limit without enabling removal is invalid
|
||||
kick_member_per_day: 20,
|
||||
});
|
||||
http.raw('set_group_admin_permissions', {
|
||||
group_id: 10001,
|
||||
user_id: 10002,
|
||||
kick_member: true,
|
||||
// @ts-expect-error only supported limits may be written
|
||||
kick_member_per_day: 1,
|
||||
});
|
||||
// @ts-expect-error receive-verification enable is required
|
||||
http.raw('set_group_admin_receive_verify', { group_id: 10001, user_id: 10002 });
|
||||
|
||||
export const uploadedFile: Promise<UploadFileStreamComplete> = http.uploadFileStream(
|
||||
new Blob(['file']),
|
||||
);
|
||||
export const download: AsyncGenerator<Uint8Array, DownloadFileStreamComplete, void> =
|
||||
ws.downloadFileStream({ file_id: 'media' }, { action: 'download_file_image_stream' });
|
||||
export const rawFrames: AsyncIterableIterator<
|
||||
StreamApiResponse<ActionResult<'test_download_stream'>>
|
||||
> = http.requestStream('test_download_stream', {});
|
||||
|
||||
for await (const item of ws.stream('download_file_stream', { file: '/remote/file' })) {
|
||||
if (item.type === 'stream' && item.data_type === 'file_chunk') {
|
||||
const encoded: string = item.data;
|
||||
void encoded;
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error single-response actions use request()/call()
|
||||
http.stream('get_status', {});
|
||||
// @ts-expect-error uploads accept bytes rather than text chunks
|
||||
http.uploadFileStream('text');
|
||||
// @ts-expect-error downloads require a file or file ID
|
||||
ws.downloadFileStream({});
|
||||
|
||||
const feeds = await http.raw('get_qzone_feeds', { page_num: '2', count: 10 });
|
||||
const more: boolean = feeds.has_more;
|
||||
const author: number = feeds.feeds[0].uin;
|
||||
export const legacyFeedHtml: string = feeds.feeds[0].html;
|
||||
export const feedContent: string | null | undefined = feeds.feeds[0].content;
|
||||
export const feedPhotos: string[] | null | undefined = feeds.feeds[0].images;
|
||||
export const feedLikeCount: number | null | undefined = feeds.feeds[0].like_count;
|
||||
export const feedCursor: string | null | undefined = feeds.next_cursor;
|
||||
|
||||
if (feedCursor) {
|
||||
await http.raw('get_qzone_feeds', { cursor: feedCursor, count: 10 });
|
||||
}
|
||||
|
||||
export const legacyFeedsResult: ActionResult<'get_qzone_feeds'> = {
|
||||
feeds: [{ uin: 10002, nickname: 'User', time: 1, appid: 311, key: 'post', html: '' }],
|
||||
has_more: false,
|
||||
};
|
||||
// @ts-expect-error continuation tokens must be strings
|
||||
http.raw('get_qzone_feeds', { cursor: 123 });
|
||||
const qzoneReply = await http.raw('comment_qzone', actionParams.comment_qzone);
|
||||
export const qzoneReplyId: string = qzoneReply.comment_id;
|
||||
export const qzoneParentId: string | undefined = qzoneReply.parent_comment_id;
|
||||
export const qzoneParentUin: number | undefined = qzoneReply.parent_comment_uin;
|
||||
export const legacyQzoneComment: ActionParams<'comment_qzone'> = {
|
||||
tid: 'post',
|
||||
content: 'Comment',
|
||||
images: ['https://example.com/image.png'],
|
||||
};
|
||||
export const legacyQzoneResult: ActionResult<'comment_qzone'> = { comment_id: '' };
|
||||
const qzoneProfile = await http.raw('get_qzone_profile', actionParams.get_qzone_profile);
|
||||
export const qzoneName: string = qzoneProfile.name;
|
||||
export const qzoneDescription: string = qzoneProfile.description;
|
||||
export const ownQzoneProfile = http.raw('get_qzone_profile', {});
|
||||
export const qzoneProfileUpdate: Promise<null> = ws.raw('set_qzone_profile', {
|
||||
name: 'Space',
|
||||
description: '',
|
||||
});
|
||||
export const qzoneNameOnly: ActionParams<'set_qzone_profile'> = { name: 'Space' };
|
||||
export const qzoneDescriptionOnly: ActionParams<'set_qzone_profile'> = { description: '' };
|
||||
export const qzoneScalarFields: ActionParams<'set_qzone_profile'> = {
|
||||
name: 123,
|
||||
description: false,
|
||||
};
|
||||
// @ts-expect-error a space profile patch requires at least one field
|
||||
export const emptyQzoneProfilePatch: ActionParams<'set_qzone_profile'> = {};
|
||||
export const invalidQzoneProfilePatch: ActionParams<'set_qzone_profile'> = {
|
||||
// @ts-expect-error profile fields accept string, number or boolean primitives
|
||||
description: [],
|
||||
};
|
||||
const feedDetail = await http.raw('get_qzone_feed_detail', actionParams.get_qzone_feed_detail);
|
||||
export const fullQzoneFeed: JsonObject = feedDetail.feed;
|
||||
export const feedDetailCursor: string | null = feedDetail.attach_info;
|
||||
export const feedDetailCard = await http.raw('get_qzone_share_ark', { feed: feedDetail.feed });
|
||||
// @ts-expect-error querying a feed requires a post ID
|
||||
http.raw('get_qzone_feed_detail', {});
|
||||
// @ts-expect-error the post ID is hexadecimal text, not an array
|
||||
http.raw('get_qzone_feed_detail', { tid: [] });
|
||||
|
||||
const publicPage = await http.raw('get_qzone_public_feeds', {});
|
||||
export const publicCells: JsonObject[] = publicPage.feeds;
|
||||
export const publicHasMore: boolean = publicPage.has_more;
|
||||
export const publicCursor: string | null = publicPage.next_cursor;
|
||||
|
||||
if (publicPage.has_more && publicPage.next_cursor) {
|
||||
await http.raw('get_qzone_public_feeds', { cursor: publicPage.next_cursor });
|
||||
}
|
||||
|
||||
declare const publicFeed: JsonObject;
|
||||
declare const publicComment: JsonObject;
|
||||
export const publicReplyDefaults: ActionParams<'get_qzone_public_replies'> = {
|
||||
feed: publicFeed,
|
||||
comment: publicComment,
|
||||
};
|
||||
export const publicUpvoteDefault: ActionParams<'set_qzone_public_upvote'> = { feed: publicFeed };
|
||||
export const publicLikeDefault: ActionParams<'set_qzone_public_like'> = { feed: publicFeed };
|
||||
export const publicFollowDefault: ActionParams<'set_qzone_public_follow'> = { feed: publicFeed };
|
||||
export const publicCommentLikeDefault: ActionParams<'set_qzone_public_comment_like'> = {
|
||||
feed: publicFeed,
|
||||
comment: publicComment,
|
||||
};
|
||||
export const publicReplyLike: ActionParams<'set_qzone_public_comment_like'> = {
|
||||
feed: publicFeed,
|
||||
comment: publicComment,
|
||||
reply: { id: '18446744073709551615', like: { id: 'reply-like-key' } },
|
||||
enable: false,
|
||||
};
|
||||
export const publicReplyToComment: ActionParams<'reply_qzone_public_feed'> = {
|
||||
feed: publicFeed,
|
||||
comment: publicComment,
|
||||
content: 'Reply',
|
||||
};
|
||||
export const publicForwardDefault: ActionParams<'forward_qzone_public_feed'> = { feed: publicFeed };
|
||||
export const publicReplyResult: JsonObject = await ws.raw(
|
||||
'reply_qzone_public_feed',
|
||||
actionParams.reply_qzone_public_feed,
|
||||
);
|
||||
// @ts-expect-error follow-up comments require attach_info as the cursor
|
||||
export const publicCommentsWithoutCursor: ActionParams<'get_qzone_public_comments'> = {
|
||||
feed: publicFeed,
|
||||
};
|
||||
export const invalidPublicContent: ActionParams<'comment_qzone_public_feed'> = {
|
||||
feed: publicFeed,
|
||||
// @ts-expect-error public content does not coerce numeric primitives
|
||||
content: 123,
|
||||
};
|
||||
export const invalidPublicRichItems: ActionParams<'comment_qzone_public_feed'> = {
|
||||
feed: publicFeed,
|
||||
// @ts-expect-error rich-text arrays contain JSON objects, not strings
|
||||
content: ['text'],
|
||||
};
|
||||
const speech = await ws.raw('get_record_text', { message_id: -42 });
|
||||
const transcription: string = speech.text;
|
||||
const flash = await http.raw('get_fileset_info', { fileset_id: 'files' });
|
||||
const bytes: number = flash.file_list[0].size;
|
||||
const envelope = await ws.rawResponse('get_fileset_info', actionParams.get_fileset_info);
|
||||
const filesetId: string = envelope.data.fileset_id;
|
||||
const album = await http.raw('get_qun_album_list', actionParams.get_qun_album_list);
|
||||
const count: string = album.album_list[0].upload_number;
|
||||
const cover: string | null | undefined = album.album_list[0].cover?.image?.defaultUrl?.url;
|
||||
const upload = await ws.raw('upload_file_stream', { stream_id: 'fixture', verify_only: true });
|
||||
|
||||
if (upload.type === 'response') {
|
||||
const checksum: string = upload.sha256;
|
||||
const received: number = upload.received_chunks;
|
||||
void [checksum, received];
|
||||
} else if (upload.type === 'stream') {
|
||||
const status: 'file_created' | 'chunk_received' = upload.status;
|
||||
void status;
|
||||
}
|
||||
|
||||
declare const frame: ActionResult<'download_file_stream'>;
|
||||
|
||||
if (frame.data_type === 'file_chunk') {
|
||||
const chunk: string = frame.data;
|
||||
const index: number = frame.index;
|
||||
void [chunk, index];
|
||||
}
|
||||
|
||||
// Extra JSON fields and all accepted flash-task forms remain available.
|
||||
export const extra: ActionParams<'send_qzone_msg'> = { content: 'Post', vendor_option: true };
|
||||
export const singlePath: ActionParams<'create_flash_task'> = { files: '/fixture' };
|
||||
export const namedFile: ActionParams<'create_flash_task'> = {
|
||||
files: { file: '/fixture', name: 'file' },
|
||||
};
|
||||
export const legacyScalars: ActionParams<'modify_custom_face'> = { emoji_id: 123, desc: false };
|
||||
export const onePermission: ActionParams<'set_group_member_permissions'> = {
|
||||
group_id: 10001,
|
||||
allow_member_upload_album: false,
|
||||
};
|
||||
export const completed: ActionResult<'upload_file_stream'> = {
|
||||
type: 'response',
|
||||
stream_id: 'fixture',
|
||||
status: 'file_complete',
|
||||
received_chunks: 1,
|
||||
total_chunks: 1,
|
||||
file_path: '/fixture',
|
||||
file_name: 'file',
|
||||
file_size: 1,
|
||||
sha256: 'fixture',
|
||||
};
|
||||
export const streamError: ActionResult<'download_file_stream'> = {
|
||||
type: 'error',
|
||||
data_type: 'error',
|
||||
};
|
||||
|
||||
// @ts-expect-error publishing requires content
|
||||
export const missingContent: ActionParams<'send_qzone_msg'> = {};
|
||||
// @ts-expect-error flash files must be paths or named file objects
|
||||
export const invalidFlashFile: ActionParams<'create_flash_task'> = { files: [123] };
|
||||
// @ts-expect-error a permission patch needs at least one flag
|
||||
export const missingPermission: ActionParams<'set_group_member_permissions'> = { group_id: 10001 };
|
||||
export const invalidPolicy: ActionParams<'set_group_member_invite_policy'> = {
|
||||
group_id: 10001,
|
||||
// @ts-expect-error the policy is a closed server enum
|
||||
policy: 'admin_only',
|
||||
};
|
||||
// @ts-expect-error uint64 album counters are returned as strings
|
||||
export const invalidCount: ActionResult<'get_qun_album_list'>['album_list'][number]['upload_number'] = 1;
|
||||
// @ts-expect-error voice transcription is an object with a text field
|
||||
export const invalidSpeech: ActionResult<'fetch_ptt_text'> = 'Speech';
|
||||
|
||||
// The open action namespace and JSON escape hatch remain available.
|
||||
declare const dynamicAction: string;
|
||||
declare const dynamicParams: JsonObject;
|
||||
const custom: Promise<JsonValue> = http.raw('consumer_extension', { custom: true });
|
||||
const dynamic: Promise<JsonValue> = ws.raw(dynamicAction, dynamicParams);
|
||||
|
||||
export {
|
||||
more,
|
||||
author,
|
||||
transcription,
|
||||
bytes,
|
||||
filesetId,
|
||||
count,
|
||||
cover,
|
||||
custom,
|
||||
dynamic,
|
||||
actionResults,
|
||||
};
|
||||
export type NewParams = ActionParams<'send_qzone_msg'>;
|
||||
export type NewResult = ActionResult<'send_qzone_msg'>;
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
import {
|
||||
createEventContext,
|
||||
isGroupMessageEvent,
|
||||
quoteMessage,
|
||||
text,
|
||||
type EventHandler,
|
||||
type EventMiddleware,
|
||||
type EventWaitOptions,
|
||||
type MediaSource,
|
||||
type OneBotGroupMessageEvent,
|
||||
type OneBotMessageEvent,
|
||||
type SendMessageResult,
|
||||
type SnowLumaEvent,
|
||||
type SnowLumaEventContext,
|
||||
type SnowLumaEventContextWithQuote,
|
||||
type SnowLumaHttpClient,
|
||||
type SnowLumaWebSocketClient,
|
||||
} from '@snowluma/sdk';
|
||||
import { localFile } from '@snowluma/sdk/node';
|
||||
import type { EventWaitOptions as ClientWaitOptions } from '@snowluma/sdk/client';
|
||||
import type { SendImageOptions } from '@snowluma/sdk/types';
|
||||
import { quoteMessage as messageQuote } from '@snowluma/sdk/messages';
|
||||
|
||||
declare const http: SnowLumaHttpClient;
|
||||
declare const ws: SnowLumaWebSocketClient;
|
||||
declare const event: OneBotMessageEvent;
|
||||
const source: MediaSource = await localFile('./picture.png');
|
||||
const options: SendImageOptions = { image: { summary: 'picture' }, chunkSize: 16384 };
|
||||
const sent: Promise<SendMessageResult> = http.sendGroupImage(123, source, options);
|
||||
const sentPrivate: Promise<SendMessageResult> = ws.sendPrivateVideo(456, new Blob(['bytes']));
|
||||
const file: Promise<{ file_id: string | null }> = ws.sendPrivateFile(456, new Uint8Array([1]));
|
||||
ws.sendGroupFile(
|
||||
123,
|
||||
{ source: new Blob(['bytes']), filename: 'notes.txt' },
|
||||
{ folderId: '/docs' },
|
||||
);
|
||||
// @ts-expect-error Strings remain server paths; opening a local file must be explicit.
|
||||
http.sendPrivateImage(456, './picture.png');
|
||||
// @ts-expect-error Media attributes remain checked.
|
||||
http.sendGroupImage(123, source, { image: { subType: 'invalid' } });
|
||||
|
||||
const oldContext: SnowLumaEventContext<OneBotMessageEvent> = {
|
||||
event,
|
||||
client: http,
|
||||
stopped: false,
|
||||
stopPropagation() {},
|
||||
async reply() {},
|
||||
async approve() {},
|
||||
async reject() {},
|
||||
async quickOperation() {},
|
||||
};
|
||||
|
||||
const oldHandler: EventHandler<OneBotMessageEvent> = async (_event, context) => {
|
||||
await context.reply('unchanged');
|
||||
};
|
||||
|
||||
oldHandler(event, oldContext);
|
||||
ws.onMessage(oldHandler);
|
||||
|
||||
const oldMiddleware: EventMiddleware = async (_event, context, next) => {
|
||||
await context.reply('unchanged');
|
||||
await next();
|
||||
};
|
||||
|
||||
oldMiddleware(event, oldContext, async () => {});
|
||||
ws.use(oldMiddleware);
|
||||
|
||||
const context: SnowLumaEventContextWithQuote<OneBotMessageEvent> = createEventContext(event, http);
|
||||
const quoted: Promise<SendMessageResult> = context.quote(text('hello'));
|
||||
ws.onMessage(async (_event, ctx) => {
|
||||
await ctx.quote('hello');
|
||||
});
|
||||
ws.onGroupMessage(async (_event, ctx) => {
|
||||
await ctx.quote('hello');
|
||||
});
|
||||
ws.use(async (_event, ctx, next) => {
|
||||
await ctx.quote('hello');
|
||||
await next();
|
||||
});
|
||||
ws.command('ping', async (_event, ctx) => {
|
||||
await ctx.quote('pong');
|
||||
});
|
||||
http.sendGroupMessage(123, quoteMessage(-42, 'body'));
|
||||
http.sendPrivateMessage(456, messageQuote(-42, text('body')));
|
||||
|
||||
const waitOptions: EventWaitOptions & ClientWaitOptions = {
|
||||
timeoutMs: 100,
|
||||
signal: new AbortController().signal,
|
||||
};
|
||||
const group: Promise<OneBotGroupMessageEvent> = ws.waitForEvent(isGroupMessageEvent, waitOptions);
|
||||
const groupMessage: Promise<OneBotGroupMessageEvent> = ws.waitForMessage(isGroupMessageEvent);
|
||||
const message: Promise<OneBotMessageEvent> = ws.waitForMessage(
|
||||
(e) => e.user_id === 456,
|
||||
waitOptions,
|
||||
);
|
||||
const anyEvent: Promise<SnowLumaEvent> = ws.waitForEvent(waitOptions);
|
||||
ws.waitForEvent(undefined, waitOptions);
|
||||
ws.waitForMessage(waitOptions);
|
||||
// @ts-expect-error A filter without a type guard does not promise group fields.
|
||||
const wrong: Promise<OneBotGroupMessageEvent> = ws.waitForEvent(() => true);
|
||||
// @ts-expect-error Wait predicates are synchronous.
|
||||
ws.waitForMessage(async () => true);
|
||||
export { sent, sentPrivate, file, quoted, group, groupMessage, message, anyEvent, wrong };
|
||||
Reference in new issue
Block a user