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
@@ -0,0 +1,324 @@
|
||||
import type { JsonObject } from '@snowluma/common/json';
|
||||
import {
|
||||
commentQzoneMsg,
|
||||
deleteQzoneMsg,
|
||||
getQzoneFeeds,
|
||||
getQzoneMsgDetail,
|
||||
getQzoneMsgList,
|
||||
getQzoneProfile,
|
||||
publishQzoneMsg,
|
||||
replyQzoneComment,
|
||||
setQzoneBlack,
|
||||
setQzoneLike,
|
||||
setQzoneProfile,
|
||||
updateQzoneMsgRight,
|
||||
uploadQzoneImageFromSource,
|
||||
type QzoneCommentResult,
|
||||
type QzoneFeedsPage,
|
||||
type QzoneMsgDetailResult,
|
||||
type QzoneMsgListResult,
|
||||
type QzoneProfile,
|
||||
type QzoneProfileUpdate,
|
||||
type QzonePublishResult,
|
||||
type QzoneReplyTarget,
|
||||
type QzoneUpdateRightResult,
|
||||
type QzoneUploadImageResult,
|
||||
} from '@snowluma/protocol/web/qzone';
|
||||
import {
|
||||
getQzonePublicCapabilities,
|
||||
getQzoneHomeFeeds,
|
||||
getQzoneFeedDetail,
|
||||
type QzoneFeedDetail,
|
||||
getQzoneShareArk,
|
||||
type QzoneShareArk,
|
||||
getQzonePublicFeeds,
|
||||
getQzonePublicFeedDetail,
|
||||
getQzonePublicComments,
|
||||
getQzonePublicReplies,
|
||||
setQzonePublicUpvote,
|
||||
setQzonePublicLike,
|
||||
setQzonePublicCommentLike,
|
||||
commentQzonePublicFeed,
|
||||
replyQzonePublicFeed,
|
||||
deleteQzonePublicComment,
|
||||
deleteQzonePublicReply,
|
||||
setQzonePublicFollow,
|
||||
forwardQzonePublicFeed,
|
||||
type QzonePublicContent,
|
||||
type QzonePublicFeedsPage,
|
||||
} from '@snowluma/protocol/web/qzone-public';
|
||||
import type { BridgeContext } from '../bridge-context';
|
||||
|
||||
/**
|
||||
* Personal QQ-Zone (个人空间) web API: 说说, public recommendations, likes,
|
||||
* comments and image upload over the cookie-backed Qzone web interfaces,
|
||||
* reusing the same `getCookies('qzone.qq.com')` plumbing as GroupAlbumApi.
|
||||
* Distinct from the group-album surface, which lives on GroupAlbumApi.
|
||||
*/
|
||||
export class QzoneApi {
|
||||
constructor(private readonly ctx: BridgeContext) {}
|
||||
|
||||
async getProfile(targetUin?: number): Promise<QzoneProfile> {
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzoneProfile(cookieObject, this.ctx.identity.uin, targetUin?.toString());
|
||||
}
|
||||
|
||||
async setProfile(profile: QzoneProfileUpdate): Promise<void> {
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
await setQzoneProfile(cookieObject, this.ctx.identity.uin, profile);
|
||||
}
|
||||
|
||||
async getPublicCapabilities(): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzonePublicCapabilities(cookies, this.ctx.identity.uin);
|
||||
}
|
||||
|
||||
async getPublicFeeds(cursor?: string): Promise<QzonePublicFeedsPage> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzonePublicFeeds(cookies, this.ctx.identity.uin, cursor);
|
||||
}
|
||||
|
||||
async getHomeFeeds(targetUin?: number, cursor?: string): Promise<QzonePublicFeedsPage> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzoneHomeFeeds(cookies, this.ctx.identity.uin, targetUin?.toString(), cursor);
|
||||
}
|
||||
|
||||
async getFeedDetail(tid: string): Promise<QzoneFeedDetail> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzoneFeedDetail(cookies, tid);
|
||||
}
|
||||
|
||||
async getShareArk(feed: JsonObject): Promise<QzoneShareArk> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzoneShareArk(cookies, feed);
|
||||
}
|
||||
|
||||
async getPublicFeedDetail(feed: JsonObject): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzonePublicFeedDetail(cookies, feed);
|
||||
}
|
||||
|
||||
async getPublicComments(feed: JsonObject, cursor: string): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzonePublicComments(cookies, feed, cursor);
|
||||
}
|
||||
|
||||
async getPublicReplies(
|
||||
feed: JsonObject,
|
||||
comment: JsonObject,
|
||||
cursor = '',
|
||||
pageSize = 20,
|
||||
): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzonePublicReplies(cookies, feed, comment, cursor, pageSize);
|
||||
}
|
||||
|
||||
async setPublicUpvote(feed: JsonObject, enable = true): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return setQzonePublicUpvote(cookies, feed, enable);
|
||||
}
|
||||
|
||||
async setPublicLike(feed: JsonObject, enable = true): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return setQzonePublicLike(cookies, feed, enable);
|
||||
}
|
||||
|
||||
async setPublicCommentLike(
|
||||
feed: JsonObject,
|
||||
comment: JsonObject,
|
||||
enable = true,
|
||||
reply?: JsonObject,
|
||||
): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return setQzonePublicCommentLike(cookies, feed, comment, enable, reply);
|
||||
}
|
||||
|
||||
async commentPublicFeed(feed: JsonObject, content: QzonePublicContent): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
const user = {
|
||||
uin: this.ctx.identity.uin,
|
||||
uid: this.ctx.identity.selfUid ?? '',
|
||||
nick: this.ctx.identity.nickname,
|
||||
};
|
||||
return commentQzonePublicFeed(cookies, feed, user, content);
|
||||
}
|
||||
|
||||
async replyPublicFeed(
|
||||
feed: JsonObject,
|
||||
comment: JsonObject,
|
||||
content: QzonePublicContent,
|
||||
reply?: JsonObject,
|
||||
): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
const user = {
|
||||
uin: this.ctx.identity.uin,
|
||||
uid: this.ctx.identity.selfUid ?? '',
|
||||
nick: this.ctx.identity.nickname,
|
||||
};
|
||||
return replyQzonePublicFeed(cookies, feed, user, comment, content, reply);
|
||||
}
|
||||
|
||||
async deletePublicComment(feed: JsonObject, comment: JsonObject): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return deleteQzonePublicComment(cookies, feed, comment);
|
||||
}
|
||||
|
||||
async deletePublicReply(
|
||||
feed: JsonObject,
|
||||
comment: JsonObject,
|
||||
reply: JsonObject,
|
||||
): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return deleteQzonePublicReply(cookies, feed, comment, reply);
|
||||
}
|
||||
|
||||
async setPublicFollow(feed: JsonObject, enable = true): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return setQzonePublicFollow(cookies, feed, enable);
|
||||
}
|
||||
|
||||
async forwardPublicFeed(feed: JsonObject, reason = ''): Promise<JsonObject> {
|
||||
const cookies = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return forwardQzonePublicFeed(cookies, feed, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取说说列表。`targetUin` 省略时取机器人自己的空间。
|
||||
* `pos` 为起始偏移,`num` 为本页数量(服务端上限约 20/页)。
|
||||
*/
|
||||
async getMsgList(targetUin?: number, pos = 0, num = 20): Promise<QzoneMsgListResult> {
|
||||
const uin = targetUin && targetUin > 0 ? targetUin.toString() : this.ctx.identity.uin;
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzoneMsgList(cookieObject, uin, pos, num);
|
||||
}
|
||||
|
||||
/** 获取说说详情和一页评论。省略 targetUin 时使用当前账号。 */
|
||||
async getMsgDetail(
|
||||
tid: string,
|
||||
targetUin?: number,
|
||||
pos = 0,
|
||||
num = 20,
|
||||
): Promise<QzoneMsgDetailResult> {
|
||||
const uin = targetUin === undefined ? this.ctx.identity.uin : String(targetUin);
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzoneMsgDetail(cookieObject, uin, tid, pos, num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取好友动态。页码调用从首页顺序定位;续页优先传上一页的 cursor。
|
||||
* 始终以机器人自己的身份拉取好友动态。
|
||||
*/
|
||||
async getFeeds(pageNum = 1, count = 10, cursor?: string): Promise<QzoneFeedsPage> {
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return getQzoneFeeds(cookieObject, this.ctx.identity.uin, pageNum, count, cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从来源上传图片到 QQ 空间。
|
||||
* `source` 支持: file:// 本地路径 | http(s):// URL | base64:// base64数据
|
||||
*/
|
||||
async uploadImageFromSource(source: string): Promise<QzoneUploadImageResult> {
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return uploadQzoneImageFromSource(cookieObject, this.ctx.identity.uin, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发表说说,返回新说说的 tid。始终发到机器人自己的空间。
|
||||
* `richType` / `richval`: 带图说说时传 richType=1 和 richval 字符串
|
||||
* (多图用 `\t` 连接多个 richval)。纯文字说说省略这两个参数。
|
||||
* `ugcRight` / `targetUins`: 查看权限及其作用名单(ugcRight=16/128 时必填)。
|
||||
*/
|
||||
async publish(
|
||||
content: string,
|
||||
richType?: number,
|
||||
richval?: string,
|
||||
ugcRight = 1,
|
||||
targetUins?: string,
|
||||
): Promise<QzonePublishResult> {
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return publishQzoneMsg(
|
||||
cookieObject,
|
||||
this.ctx.identity.uin,
|
||||
content,
|
||||
richType,
|
||||
richval,
|
||||
ugcRight,
|
||||
targetUins,
|
||||
);
|
||||
}
|
||||
|
||||
/** 删除机器人自己空间的一条说说(按 tid)。 */
|
||||
async delete(tid: string): Promise<void> {
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
await deleteQzoneMsg(cookieObject, this.ctx.identity.uin, tid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改机器人自己空间一条已发说说的查看权限(按 tid)。
|
||||
* `ugcRight` / `targetUins` 含义同 publish(16/128 时 targetUins 必填)。
|
||||
*/
|
||||
async updateRight(
|
||||
tid: string,
|
||||
ugcRight: number,
|
||||
targetUins?: string,
|
||||
): Promise<QzoneUpdateRightResult> {
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
return updateQzoneMsgRight(cookieObject, this.ctx.identity.uin, tid, ugcRight, targetUins);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给一条说说点赞/取消赞。`targetUin` 省略时点赞机器人自己空间的说说;
|
||||
* 点赞好友说说时传好友 uin(tid 来自 get_qzone_feeds / get_qzone_msg_list)。
|
||||
*/
|
||||
async like(
|
||||
tid: string,
|
||||
targetUin: number | undefined,
|
||||
like: boolean,
|
||||
abstime = 0,
|
||||
): Promise<void> {
|
||||
const selfUin = this.ctx.identity.uin;
|
||||
const owner = targetUin && targetUin > 0 ? targetUin.toString() : selfUin;
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
await setQzoneLike(cookieObject, selfUin, owner, tid, like, abstime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 评论一条说说。`targetUin` 为说说所属 QQ 号(省略=机器人自己空间);
|
||||
* 始终以机器人身份发表评论。返回新评论 id(尽力而为)。
|
||||
* `richType` / `richval`: 带图评论时传 richType=1 和图片直链 URL
|
||||
* (从 uploadImageFromSource 的 url 字段获取)。
|
||||
* `reply` 指定父评论及可选回复对象;楼中楼回复仅支持文字。
|
||||
*/
|
||||
async comment(
|
||||
tid: string,
|
||||
content: string,
|
||||
targetUin: number | undefined,
|
||||
richType?: number,
|
||||
richval?: string,
|
||||
reply?: QzoneReplyTarget,
|
||||
): Promise<QzoneCommentResult> {
|
||||
if (reply !== undefined && (richType !== undefined || richval !== undefined)) {
|
||||
throw new Error('images are not supported for Qzone comment replies');
|
||||
}
|
||||
|
||||
const selfUin = this.ctx.identity.uin;
|
||||
const owner = targetUin && targetUin > 0 ? targetUin.toString() : selfUin;
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
|
||||
if (reply !== undefined) {
|
||||
return replyQzoneComment(cookieObject, selfUin, owner, tid, content, reply);
|
||||
}
|
||||
|
||||
return commentQzoneMsg(cookieObject, selfUin, owner, tid, content, richType, richval);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉黑或解除拉黑某人(修改机器人自身 QQ 空间黑名单)。
|
||||
* `ban=true` 拉黑,`ban=false` 解除拉黑。
|
||||
*/
|
||||
async setBlack(targetUin: number, ban: boolean): Promise<void> {
|
||||
const selfUin = this.ctx.identity.uin;
|
||||
const cookieObject = await this.ctx.apis.web.getCookies('qzone.qq.com');
|
||||
await setQzoneBlack(cookieObject, selfUin, targetUin.toString(), ban);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user