UNPKG

kitten-cloud-function

Version:

用于编程猫源码云功能(云变量、云列表等)的客户端工具

606 lines (605 loc) 26.9 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CodemaoWorkInfo = void 0; const promise_any_1 = __importDefault(require("@ungap/promise-any")); const other_1 = require("../../utils/other"); const codemao_community_api_1 = require("../codemao-community-api"); const codemao_user_1 = require("../user/codemao-user"); const codemao_user_sex_1 = require("../user/codemao-user-sex"); const codemao_work_editor_1 = require("./codemao-work-editor"); const codemao_environment_1 = require("../codemao-environment"); const codemao_user_badge_1 = require("../user/codemao-user-badge"); async function testWorkEditorByKittenCloud(info, editor) { const KITTEN_WEB_SOCKET_URL_PARAMS = { [codemao_work_editor_1.CodemaoWorkEditor.NEMO.symbol]: { authorization_type: 5, stag: 2, EIO: 3, transport: "websocket" }, [codemao_work_editor_1.CodemaoWorkEditor.KITTEN.symbol]: { authorization_type: 1, stag: 1, EIO: 3, transport: "websocket" }, [codemao_work_editor_1.CodemaoWorkEditor.KITTEN_N.symbol]: { authorization_type: 5, stag: 3, token: "", EIO: 3, transport: "websocket" }, }; const url = await (async () => { const scheme = typeof global == "object" || window.location.protocol != "http:" ? "wss" : "ws"; const host = ["socketcv", "codemao", "cn"].join("."); const port = 9096; const path = "/cloudstorage/"; const particularParams = KITTEN_WEB_SOCKET_URL_PARAMS[editor.symbol]; if (particularParams == null) { throw new Error(`不支持的作品类型: ${editor.name}`); } const params = `session_id=${await info.id}&${Object.entries(particularParams) .map(([key, value]) => `${key}=${value}`) .join("&")}`; return `${scheme}://${host}:${port}${path}?${params}`; })(); const socket = await (0, codemao_environment_1.CodemaoWebSocket)(url); return new Promise((resolve, reject) => { socket.onopen = () => { try { // @ts-ignore socket.close(); } catch (error) { console.error(error); } resolve({ editor }); }; socket.onerror = async () => { reject(new Error(`通过云功能连接试探作品 ${await info.id} 编辑器类型为 ${editor.name} 失败:WebSocket 出错`)); }; }); } /** * ## 编程猫作品信息类 * * - 用于获取编程猫作品信息。 * - 所有属性均为`Promise`对象,当属性获取失败时访问该属性的值会被拒绝。 * * 提供的作品信息详见类属性 * * ### 具有以下特性: * - 集成多个API接口,以确保在部分API接口信息获取失败时仍能提供尽可能完整的作品信息。 * - 内置懒加载和缓存机制,以减少不必要的请求。 * * ### 集成API接口 * * #### 已经集成的API接口 * - {@link getWorkInfo} * - {@link getWorkDetail} * - {@link getNemoWorkPublicResource} * - {@link getKittenWorkPublicResource} * - {@link getKitten_NWorkPublicResource} * * #### 将来可能集成的API接口: * - {@link searchWorkByName} * * #### API优先级: * - 优先使用 {@link getWorkInfo} 接口获取作品信息,该接口包含了作品的全部信息,但是容易出错。 * - 如果 {@link getWorkInfo} 接口获取失败,则使用 {@link getWorkDetail} 接口获取作品的大部分信息。 * - 如果 {@link getWorkDetail} 接口获取失败,则使用 {@link getNemoWorkPublicResource}、{@link getKittenWorkPublicResource} 和 {@link getKitten_NWorkPublicResource} 接口获取作品的少部分信息。 * - 对于作品编辑器类型而言,如果所有接口都获取失败,还会利用 {@link testWorkEditorByKittenCloud} 试探作品类型。 * - 如果所有接口都获取失败,则抛出异常,对应属性的值会被拒绝。 */ class CodemaoWorkInfo { get workInfo() { return (async () => { if (this.__workInfo == null) { Object.defineProperty(this, "__workInfo", { value: (async () => { const workInfo = await (0, codemao_community_api_1.getWorkInfo)(await this.id); return { id: workInfo.id, name: workInfo.work_name, author: new codemao_user_1.CodemaoUser({ id: workInfo.user_info.id, nickname: workInfo.user_info.nickname, avatarURL: workInfo.user_info.avatar, description: workInfo.user_info.description, badge: codemao_user_badge_1.CodemaoUserBadge.parse(workInfo.user_info.author_level) }), editor: codemao_work_editor_1.CodemaoWorkEditor.parse(workInfo.type), description: workInfo.description, operationInstruction: workInfo.operation, publishTime: new Date(workInfo.publish_time * 1000), playerURL: workInfo.player_url, shareURL: workInfo.share_url, coverURL: workInfo.preview, previewURL: workInfo.screenshot_cover_url, viewTimes: workInfo.view_times, likeTimes: workInfo.praise_times, collectTimes: workInfo.collect_times, shareTimes: workInfo.share_times, commentTimes: workInfo.comment_times, openResource: workInfo.fork_enable }; })(), enumerable: false, configurable: true }); this.setCache(await this.__workInfo); } return await this.__workInfo; })(); } get workDetail() { return (async () => { if (this.__workDetail == null) { Object.defineProperty(this, "__workDetail", { value: (async () => { const { workInfo, userInfo, qrcodeUrl, allowFork } = await (0, codemao_community_api_1.getWorkDetail)(await this.id); return { id: workInfo.id, name: workInfo.name, author: new codemao_user_1.CodemaoUser({ id: userInfo.id, nickname: userInfo.nickname, avatarURL: userInfo.avatar, description: userInfo.description, sex: codemao_user_sex_1.CodemaoUserSex.parse(userInfo.sex) }), description: workInfo.description, publishTime: new Date(workInfo.publish_time * 1000), shareURL: qrcodeUrl, previewURL: workInfo.preview, viewTimes: workInfo.view_times, likeTimes: workInfo.praise_times, collectTimes: workInfo.collection_times, openResource: Boolean(allowFork) }; })(), enumerable: false, configurable: true }); this.setCache(await this.__workDetail); } return await this.__workDetail; })(); } get nemoWorkPublicResource() { return (async () => { if (this.__nemoPublicResource == null) { Object.defineProperty(this, "__nemoPublicResource", { value: (async () => { const source = await (0, codemao_community_api_1.getNemoWorkPublicResource)(await this.id); return { id: source.work_id, name: source.name, author: new codemao_user_1.CodemaoUser({ id: source.user.id, nickname: source.user.nickname, avatarURL: source.user.avatar_url }), editor: codemao_work_editor_1.CodemaoWorkEditor.NEMO, coverURL: source.preview, previewURL: source.preview, viewTimes: source.view_times, likeTimes: source.n_likes }; })(), enumerable: false, configurable: true }); this.setCache(await this.__nemoPublicResource); } return await this.__nemoPublicResource; })(); } get kittenWorkPublicResource() { return (async () => { if (this.__kittenPublicResource == null) { Object.defineProperty(this, "__kittenPublicResource", { value: (async () => { const source = await (0, codemao_community_api_1.getKittenWorkPublicResource)(await this.id); return { name: source.name, editor: codemao_work_editor_1.CodemaoWorkEditor.KITTEN, publishTime: new Date(source.updated_time * 1000) }; })(), enumerable: false, configurable: true }); this.setCache(await this.__kittenPublicResource); } return await this.__kittenPublicResource; })(); } get kitten_NWorkPublicResource() { return (async () => { if (this.__kittenNPublicResource == null) { Object.defineProperty(this, "__kittenNPublicResource", { value: (async () => { const source = await (0, codemao_community_api_1.getKittenNWorkPublicResource)(await this.id); return { name: source.name, author: new codemao_user_1.CodemaoUser({ id: parseInt(source.author_id) }), editor: codemao_work_editor_1.CodemaoWorkEditor.KITTEN_N, publishTime: new Date(source.update_time * 1000), previewURL: source.preview_url }; })(), enumerable: false, configurable: true }); this.setCache(await this.__kittenNPublicResource); } return await this.__kittenNPublicResource; })(); } /** * 作品 ID。 */ get id() { if (this.__id == null) { this.__id = Promise.reject(["获取作品ID失败", new Error("没有提供作品ID")]); } return this.__id; } /** * 作品名称。 */ get name() { if (this.__name == null) { this.__name = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品名称")), this.workInfo .catch((getWorkInfoError) => this.workDetail.catch((getWorkDetailError) => Promise.reject([getWorkInfoError, getWorkDetailError]))).catch((error0) => (0, promise_any_1.default)([ this.nemoWorkPublicResource, this.kittenWorkPublicResource, this.kitten_NWorkPublicResource ]).catch((error1) => Promise.reject([...error0, ...error1.errors]))).then((info) => info.name) ]).catch(({ errors }) => Promise.reject(["获取作品名称失败", errors[0], ...errors[1]])); } return this.__name; } /** * 作品作者。 */ get author() { if (this.__author == null) { this.__author = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品作者")), this.workInfo .catch((error0) => this.workDetail.catch((error1) => (0, promise_any_1.default)([ this.nemoWorkPublicResource, this.kitten_NWorkPublicResource ]).catch((error2) => Promise.reject([error0, error1, ...error2.errors])))).then((info) => info.author) ]).catch(({ errors }) => Promise.reject(["获取作品作者失败", errors[0], ...errors[1]])); } return this.__author; } /** * 作品使用的编辑器类型,详见 {@link CodemaoWorkEditor}。 */ get editor() { if (this.__editor == null) { this.__editor = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品类型")), this.workInfo .catch((error0) => (0, promise_any_1.default)([ this.nemoWorkPublicResource, this.kittenWorkPublicResource, this.kitten_NWorkPublicResource ]).catch((error1) => (0, promise_any_1.default)([ testWorkEditorByKittenCloud(this, codemao_work_editor_1.CodemaoWorkEditor.NEMO), testWorkEditorByKittenCloud(this, codemao_work_editor_1.CodemaoWorkEditor.KITTEN), testWorkEditorByKittenCloud(this, codemao_work_editor_1.CodemaoWorkEditor.KITTENN) ]).catch(error2 => Promise.reject([error0, ...error1.errors, ...error2.errors])))).then((info) => info.editor) ]).catch(({ errors }) => Promise.reject(["获取作品类型失败", errors[0], ...errors[1]])); } return this.__editor; } /** * 作品描述。 */ get description() { if (this.__description == null) { this.__description = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品描述")), this.workInfo .catch((error0) => this.workDetail.catch((error1) => Promise.reject([error0, error1]))).then((info) => info.description) ]).catch(({ errors }) => Promise.reject(["获取作品描述失败", errors[0], ...errors[1]])); } return this.__description; } /** * 作品操作说明。 */ get operationInstruction() { if (this.__operationInstruction == null) { this.__operationInstruction = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品操作说明")), this.workInfo.then((info) => info.operationInstruction) ]).catch(({ errors }) => Promise.reject(["获取作品操作说明失败", ...errors])); } return this.__operationInstruction; } /** * 作品发布时间。 */ get publishTime() { if (this.__publishTime == null) { this.__publishTime = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品发布时间")), this.workInfo .catch((error0) => (0, promise_any_1.default)([ this.kittenWorkPublicResource, this.kitten_NWorkPublicResource ]).catch((error1) => Promise.reject([error0, ...error1.errors]))).then((info) => info.publishTime) ]).catch(({ errors }) => Promise.reject(["获取作品发布时间失败", errors[0], ...errors[1]])); } return this.__publishTime; } /** * 作品运行器(即 Player)地址。 */ get playerURL() { if (this.__playerURL == null) { this.__playerURL = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品运行器地址")), this.workInfo.then((info) => info.playerURL) ]).catch(({ errors }) => Promise.reject(["获取作品运行器地址失败", ...errors])); } return this.__playerURL; } /** * 作品分享地址。 */ get shareURL() { if (this.__shareURL == null) { this.__shareURL = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品分享地址")), this.workInfo .catch((error0) => this.workDetail.catch((error1) => Promise.reject([error0, error1]))).then((info) => info.shareURL) ]).catch(({ errors }) => Promise.reject(["获取作品分享地址失败", errors[0], ...errors[1]])); } return this.__shareURL; } /** * 作品封面地址。 */ get coverURL() { if (this.__coverURL == null) { this.__coverURL = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品封面地址")), this.workInfo .catch((error0) => this.nemoWorkPublicResource .catch((error1) => Promise.reject([error0, error1]))).then((info) => info.coverURL) ]).catch(({ errors }) => Promise.reject(["获取作品封面地址失败", errors[0], ...errors[1]])); } return this.__coverURL; } /** * 作品预览地址。 */ get previewURL() { if (this.__previewURL == null) { this.__previewURL = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品预览地址")), this.workInfo .catch((error0) => this.workDetail.catch((error1) => Promise.reject([error0, error1]))).catch((error0) => (0, promise_any_1.default)([ this.nemoWorkPublicResource, this.kitten_NWorkPublicResource ]).catch((error1) => Promise.reject([...error0, ...error1.errors]))).then((info) => info.previewURL) ]).catch(({ errors }) => Promise.reject(["获取作品预览地址失败", errors[0], ...errors[1]])); } return this.__previewURL; } /** * 作品被浏览的次数。 */ get viewTimes() { if (this.__viewTimes == null) { this.__viewTimes = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品浏览次数")), this.workInfo .catch((error0) => this.workDetail.catch((error1) => Promise.reject([error0, error1]))).catch((error0) => this.nemoWorkPublicResource .catch((error1) => Promise.reject([...error0, error1]))).then((info) => info.viewTimes) ]).catch(({ errors }) => Promise.reject(["获取作品浏览次数失败", errors[0], ...errors[1]])); } return this.__viewTimes; } /** * 点赞该作品的人数。 */ get likeTimes() { if (this.__likeTimes == null) { this.__likeTimes = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品点赞次数")), this.workInfo .catch((error0) => this.workDetail.catch((error1) => Promise.reject([error0, error1]))).catch((error0) => this.nemoWorkPublicResource .catch((error1) => Promise.reject([...error0, error1]))).then((info) => info.likeTimes) ]).catch(({ errors }) => Promise.reject(["获取作品点赞次数失败", errors[0], ...errors[1]])); } return this.__likeTimes; } /** * 收藏该作品的人数。 */ get collectTimes() { if (this.__collectTimes == null) { this.__collectTimes = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品收藏次数")), this.workInfo .catch((error0) => this.workDetail.catch((error1) => Promise.reject([error0, error1]))).then((info) => info.collectTimes) ]).catch(({ errors }) => Promise.reject(["获取作品收藏次数失败", errors[0], ...errors[1]])); } return this.__collectTimes; } /** * 作品被分享的次数。 */ get shareTimes() { if (this.__shareTimes == null) { this.__shareTimes = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品分享次数")), this.workInfo.then((info) => info.shareTimes) ]).catch(({ errors }) => Promise.reject(["获取作品分享次数失败", ...errors])); } return this.__shareTimes; } /** * 作品的评论区中评论的数量,包括二级评论。 */ get commentTimes() { if (this.__commentTimes == null) { this.__commentTimes = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品评论次数")), this.workInfo.then((info) => info.commentTimes) ]).catch(({ errors }) => Promise.reject(["获取作品分享次数失败", ...errors])); } return this.__commentTimes; } /** * 作品是否是否开源。 */ get openResource() { if (this.__openResource == null) { this.__openResource = (0, promise_any_1.default)([ Promise.reject(new Error("没有提供作品开源状态")), this.workInfo .catch((error0) => this.workDetail.catch((error1) => Promise.reject([error0, error1]))).then((info) => info.openResource) ]).catch(({ errors }) => Promise.reject(["获取作品分享次数失败", errors[0], ...errors[1]])); } return this.__openResource; } /** * @param info 已知的作品信息。 */ constructor(info) { for (const key in this) { if (key.startsWith("__") && this[key] == Node) { Object.defineProperty(this, key, { value: undefined, enumerable: false, configurable: true }); } } this.setCache(info); } async setCache(info) { for (let key in info) { let value = info[key]; if (value != null) { if (value instanceof codemao_user_1.CodemaoUser) { if (this.__author == null) { this.__author = Promise.resolve(new codemao_user_1.CodemaoUser()); } const userInfoObject = {}; for (const key in value.info) { if (`__${key}` in value.info) { try { // @ts-ignore userInfoObject[key] = await value.info[`__${key}`]; } catch (error) { console.error(error); } } } ; (await this.__author).info.setCache(userInfoObject); } else { Object.defineProperty(this, `__${key}`, { value: Promise.resolve(value), enumerable: false, configurable: true }); } } } } } exports.CodemaoWorkInfo = CodemaoWorkInfo; __decorate([ (0, other_1.enumerable)(false) ], CodemaoWorkInfo.prototype, "workInfo", null); __decorate([ (0, other_1.enumerable)(false) ], CodemaoWorkInfo.prototype, "workDetail", null); __decorate([ (0, other_1.enumerable)(false) ], CodemaoWorkInfo.prototype, "nemoWorkPublicResource", null); __decorate([ (0, other_1.enumerable)(false) ], CodemaoWorkInfo.prototype, "kittenWorkPublicResource", null); __decorate([ (0, other_1.enumerable)(false) ], CodemaoWorkInfo.prototype, "kitten_NWorkPublicResource", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "id", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "name", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "author", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "editor", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "description", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "operationInstruction", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "publishTime", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "playerURL", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "shareURL", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "coverURL", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "previewURL", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "viewTimes", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "likeTimes", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "collectTimes", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "shareTimes", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "commentTimes", null); __decorate([ (0, other_1.enumerable)(true) ], CodemaoWorkInfo.prototype, "openResource", null);