UNPKG

feishu-bot-notify

Version:

基于 tsdown 打包的飞书机器人通知工具

198 lines (193 loc) 5.56 kB
//#region rolldown:runtime var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { key = keys[i]; if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ((k) => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); //#endregion let ofetch = require("ofetch"); ofetch = __toESM(ofetch); //#region src/card.ts const DEFAULT_TITLE = "组件更新啦!!!"; const DEFAULT_BUTTON_TEXT = "去看看"; /** * 构造飞书交互式卡片 */ function buildComponentUpdateCard(options) { const { componentName, version, changes, buttonUrl, title, buttonText } = options; const markdownUpdates = formatChanges(changes); return { schema: "2.0", config: { update_multi: true, style: { text_size: { normal_v2: { default: "normal", pc: "normal", mobile: "heading" } } } }, header: { title: { tag: "plain_text", content: title ?? DEFAULT_TITLE }, template: "blue", icon: { tag: "standard_icon", token: "speaker_filled" }, padding: "12px 12px 12px 12px" }, body: { direction: "vertical", padding: "12px 12px 12px 12px", elements: [ { tag: "hr", margin: "0px 0px 0px 0px" }, buildMetaColumn(componentName, version), { tag: "div", text: { tag: "lark_md", content: `**📝更新说明:**\n${markdownUpdates}`, text_size: "normal_v2", text_align: "left", text_color: "default", lines: 5 }, margin: "0px 0px 0px 0px" }, { tag: "hr", margin: "0px 0px 0px 0px" }, { tag: "button", text: { tag: "plain_text", content: buttonText ?? DEFAULT_BUTTON_TEXT }, type: "primary_filled", width: "default", size: "medium", behaviors: [{ type: "open_url", default_url: buttonUrl }], margin: "0px 0px 0px 0px", element_id: "go_component_url" } ] } }; } function buildMetaColumn(componentName, version) { return { tag: "column_set", columns: [{ tag: "column", width: "weighted", elements: [{ tag: "markdown", content: `**📦组件名称:**${componentName}`, text_align: "left", text_size: "normal_v2" }], vertical_align: "top", weight: 1 }, { tag: "column", width: "weighted", elements: [{ tag: "markdown", content: `**💥版本:** ${version}`, text_align: "left", text_size: "normal_v2" }], vertical_align: "top", weight: 1 }] }; } function formatChanges(changes) { if (!Array.isArray(changes)) return changes; if (!changes.length) return "- 暂无更新内容"; return changes.map((item) => item.startsWith("-") ? item : `- ${item}`).join("\n"); } //#endregion //#region src/sender.ts const client = ofetch.ofetch.create({ headers: { "Content-Type": "application/json" }, retry: 0 }); /** * 负责向飞书 webhook 推送交互式卡片,默认使用 ofetch 并保留详细错误信息 */ async function sendCardToWebhook(options) { const { webhookUrl, card, timeoutMs } = options; const payload = { msg_type: "interactive", card }; try { const { status, _data } = await client.raw(webhookUrl, { method: "POST", body: payload, timeout: timeoutMs }); if (status < 200 || status >= 300) throw new Error(`飞书接口返回 HTTP ${status}`); if (!_data || typeof _data.code !== "number") throw new Error("飞书接口返回内容为空或结构异常"); if (_data.code !== 0) throw new Error(`飞书接口响应异常:${JSON.stringify(_data)}`); return _data; } catch (error) { if (error instanceof ofetch.FetchError) { var _error$cause; if (error.status === 408 || ((_error$cause = error.cause) === null || _error$cause === void 0 ? void 0 : _error$cause.name) === "AbortError") throw new Error("请求飞书接口超时"); if (typeof error.status === "number" && error.status >= 400) { const bodyText = typeof error.data === "string" ? error.data : JSON.stringify(error.data ?? {}); throw new Error(`飞书接口返回 HTTP ${error.status}${bodyText}`); } } throw error instanceof Error ? error : /* @__PURE__ */ new Error("请求飞书接口失败"); } } //#endregion //#region src/index.ts /** * 基于组件更新信息构建卡片并推送至飞书机器人 */ async function sendComponentUpdateNotification(options) { const { webhookUrl, timeoutMs,...cardOptions } = options; const card = buildComponentUpdateCard(cardOptions); return sendCardToWebhook({ webhookUrl, card, timeoutMs }); } /** * 仅构建飞书交互式卡片,便于在外部服务中复用 */ function createComponentUpdateCard(options) { return buildComponentUpdateCard(options); } //#endregion exports.createComponentUpdateCard = createComponentUpdateCard; exports.sendComponentUpdateNotification = sendComponentUpdateNotification;