parent
f6c472f138
commit
35da14f32c
@ -27,9 +27,12 @@
|
||||
"ChakrounAnas.turbo-console-log",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"MS-CEINTL.vscode-language-pack-zh-hans",
|
||||
"Prisma.prisma"
|
||||
"Prisma.prisma",
|
||||
"humao.rest-client",
|
||||
"GitHub.copilot",
|
||||
"GitHub.copilot-chat"
|
||||
]
|
||||
}
|
||||
},
|
||||
"onCreateCommand": "curl -fsSL https://bun.sh/install | bash"
|
||||
"onCreateCommand": "curl -fsSL https://imoaix.cn/Soft/bun/install.sh | bash"
|
||||
}
|
||||
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
25
package.json
25
package.json
@ -17,18 +17,18 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.4.0",
|
||||
"@commitlint/config-conventional": "^19.2.2",
|
||||
"@eslint/js": "^9.9.0",
|
||||
"@commitlint/cli": "^19.5.0",
|
||||
"@commitlint/config-conventional": "^19.5.0",
|
||||
"@eslint/js": "^9.11.0",
|
||||
"@types/node-schedule": "^2.1.7",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"bun-types": "^1.1.25",
|
||||
"eslint": "^9.9.0",
|
||||
"bun-types": "^1.1.29",
|
||||
"eslint": "^9.11.0",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"husky": "^9.1.5",
|
||||
"lint-staged": "^15.2.9",
|
||||
"husky": "^9.1.6",
|
||||
"lint-staged": "^15.2.10",
|
||||
"prettier": "^3.3.3",
|
||||
"typescript-eslint": "^8.2.0"
|
||||
"typescript-eslint": "^8.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.5.4"
|
||||
@ -36,14 +36,15 @@
|
||||
"dependencies": {
|
||||
"@egg/hooks": "^1.2.0",
|
||||
"@egg/lark-msg-tool": "^1.2.0",
|
||||
"@egg/logger": "^1.3.0",
|
||||
"@egg/net-tool": "^1.6.0",
|
||||
"@egg/logger": "^1.4.2",
|
||||
"@egg/net-tool": "^1.6.3",
|
||||
"@egg/path-tool": "^1.3.0",
|
||||
"joi": "^17.13.3",
|
||||
"node-schedule": "^2.1.1",
|
||||
"p-limit": "^6.1.0",
|
||||
"pocketbase": "^0.21.4",
|
||||
"pocketbase": "^0.21.5",
|
||||
"uuid": "^10.0.0",
|
||||
"winston": "^3.14.2",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
|
||||
import { LarkService } from "../../services"
|
||||
import { Context } from "../../types"
|
||||
import createKVTemp from "../sheet/createKVTemp"
|
||||
|
||||
/**
|
||||
* 是否为P2P或者群聊并且艾特了小煎蛋
|
||||
@ -98,12 +99,8 @@ const manageIdMsg = (chatId: string, service: LarkService): void => {
|
||||
* @param {Context.Data} ctx - 上下文数据,包含body, logger, larkService和attachService
|
||||
* @returns {boolean} 是否处理了命令消息
|
||||
*/
|
||||
const manageCMDMsg = ({
|
||||
body,
|
||||
logger,
|
||||
larkService,
|
||||
attachService,
|
||||
}: Context.Data): boolean => {
|
||||
const manageCMDMsg = (ctx: Context.Data): boolean => {
|
||||
const { body, logger, larkService, attachService } = ctx
|
||||
const text = getMsgText(body)
|
||||
logger.debug(`bot req text: ${text}`)
|
||||
const chatId = getChatId(body)
|
||||
@ -133,6 +130,12 @@ const manageCMDMsg = ({
|
||||
attachService.reportCollector(body)
|
||||
return true
|
||||
}
|
||||
// 创建Sheet DB
|
||||
if (text.trim() === "/gen db") {
|
||||
logger.info(`bot command is /gen db, chatId: ${chatId}`)
|
||||
createKVTemp.createFromEvent(ctx)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
75
routes/sheet/createKVTemp.ts
Normal file
75
routes/sheet/createKVTemp.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { getChatId } from "@egg/lark-msg-tool"
|
||||
|
||||
import { Context, LarkServer } from "../../types"
|
||||
import { genSheetDbErrorMsg, genTempMsg } from "../../utils/genMsg"
|
||||
|
||||
/**
|
||||
* 创建键值多维表格
|
||||
* 实际上是从模版复制出来一个
|
||||
* @param {Context.Data} ctx - 上下文数据,包括larkService和logger
|
||||
* @returns {Promise<LarkServer.BaseRes>} - 返回包含链接和token的响应
|
||||
*/
|
||||
const create = async ({
|
||||
larkService,
|
||||
logger,
|
||||
}: Context.Data): Promise<LarkServer.BaseRes> => {
|
||||
const copyRes = await larkService.drive.copyFile(
|
||||
"D6ETfzaU9lN08adVDz3kjLey4Bx",
|
||||
"bask4drDOy7zc3nDVyZb5RYDzOe",
|
||||
"xxx 项目 KV管理",
|
||||
"bitable"
|
||||
)
|
||||
if (copyRes.code !== 0) return copyRes
|
||||
|
||||
const fileToken = copyRes.data.file.token
|
||||
|
||||
const tableRes = await larkService.sheet.getTables(fileToken)
|
||||
if (tableRes.code !== 0) return tableRes
|
||||
|
||||
const tableId = tableRes.data[0].table_id
|
||||
|
||||
const viewRes = await larkService.sheet.getViews(fileToken, tableId)
|
||||
if (viewRes.code !== 0) return viewRes
|
||||
const viewId = viewRes.data[0].view_id
|
||||
|
||||
const link = `https://xiaomi.f.mioffice.cn/base/${fileToken}?table=${tableId}&view=${viewId}`
|
||||
|
||||
const token = `${fileToken}|${tableId}|${viewId}`
|
||||
|
||||
logger.info(`create KV bitable successfully: ${{ link, token }}`)
|
||||
|
||||
return {
|
||||
code: 0,
|
||||
data: {
|
||||
link,
|
||||
token,
|
||||
},
|
||||
message: "success",
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从事件创建键值多维表格
|
||||
* @param {Context.Data} ctx - 上下文数据,包括larkService和logger
|
||||
*/
|
||||
const createFromEvent = async (ctx: Context.Data) => {
|
||||
const chatId = getChatId(ctx.body)
|
||||
if (!chatId) return
|
||||
const createRes = await create(ctx)
|
||||
// 错误处理,发送错误消息
|
||||
if (createRes.code !== 0) {
|
||||
const errorMsg = genSheetDbErrorMsg(createRes.message)
|
||||
ctx.larkService.message.send("chat_id", chatId, "interactive", errorMsg)
|
||||
return
|
||||
}
|
||||
// 成功了组织一下URL和Token,发送成功消息
|
||||
const successMsg = genTempMsg("ctp_AA00oqPWPXtG", createRes.data)
|
||||
ctx.larkService.message.send("chat_id", chatId, "interactive", successMsg)
|
||||
}
|
||||
|
||||
const createKVTemp = {
|
||||
create,
|
||||
createFromEvent,
|
||||
}
|
||||
|
||||
export default createKVTemp
|
@ -1,6 +1,9 @@
|
||||
import Joi from "joi"
|
||||
|
||||
import db from "../../db"
|
||||
import { Context } from "../../types"
|
||||
import { SheetProxy } from "../../types/sheetProxy"
|
||||
import insertSheet from "./insert"
|
||||
|
||||
/**
|
||||
* 校验表格请求的参数
|
||||
@ -11,22 +14,47 @@ const validateSheetReq = async (
|
||||
ctx: Context.Data
|
||||
): Promise<false | Response> => {
|
||||
const { body, genResp } = ctx
|
||||
if (!body.api_key) {
|
||||
return genResp.badRequest("api_key is required")
|
||||
}
|
||||
if (!body.sheet_token) {
|
||||
return genResp.badRequest("sheet_token is required")
|
||||
}
|
||||
if (!body.range) {
|
||||
return genResp.badRequest("range is required")
|
||||
}
|
||||
if (!body.values) {
|
||||
return genResp.badRequest("values is required")
|
||||
|
||||
// 定义基础的Schema
|
||||
let schema = Joi.object({
|
||||
api_key: Joi.string()
|
||||
.required()
|
||||
.messages({ "any.required": "api_key is required" }),
|
||||
sheet_token: Joi.string()
|
||||
.required()
|
||||
.messages({ "any.required": "sheet_token is required" }),
|
||||
range: Joi.string()
|
||||
.required()
|
||||
.messages({ "any.required": "range is required" }),
|
||||
type: Joi.string()
|
||||
.required()
|
||||
.custom((value, helpers) => {
|
||||
if (!SheetProxy.isType(value)) {
|
||||
return helpers.error("any.invalid")
|
||||
}
|
||||
return value
|
||||
})
|
||||
.messages({
|
||||
"any.required": "type is required",
|
||||
"any.invalid": "type is invalid",
|
||||
}),
|
||||
})
|
||||
|
||||
if (body.type === "insert") {
|
||||
schema = schema.keys({
|
||||
values: Joi.array()
|
||||
.items(Joi.array().items(Joi.string()))
|
||||
.required()
|
||||
.messages({ "any.required": "values is required" }),
|
||||
})
|
||||
}
|
||||
|
||||
if (!SheetProxy.isType(body.type)) {
|
||||
return genResp.badRequest("type is invalid")
|
||||
// 校验参数
|
||||
const { error } = schema.validate(body)
|
||||
if (error) {
|
||||
return genResp.badRequest(error.message)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -36,8 +64,8 @@ const validateSheetReq = async (
|
||||
* @returns {Promise<Response>} 返回响应对象
|
||||
*/
|
||||
export const manageSheetReq = async (ctx: Context.Data): Promise<Response> => {
|
||||
const { body: rawBody, genResp, larkService } = ctx
|
||||
const body = rawBody as SheetProxy.Body
|
||||
const { body: rawBody, genResp } = ctx
|
||||
const body = rawBody as SheetProxy.InsertData
|
||||
|
||||
// 校验参数
|
||||
const validateRes = await validateSheetReq(ctx)
|
||||
@ -55,17 +83,8 @@ export const manageSheetReq = async (ctx: Context.Data): Promise<Response> => {
|
||||
return genResp.notFound("app name not found")
|
||||
}
|
||||
|
||||
if (body.type === "insert") {
|
||||
// 插入行
|
||||
const insertRes = await larkService
|
||||
.child(appName)
|
||||
.sheet.insertRows(body.sheet_token, body.range, body.values)
|
||||
if (insertRes?.code !== 0) {
|
||||
return genResp.serverError(insertRes?.message)
|
||||
}
|
||||
// 返回插入结果
|
||||
return genResp.ok(insertRes?.data)
|
||||
}
|
||||
// 根据请求类型处理
|
||||
if (body.type === "insert") return await insertSheet(ctx, appName)
|
||||
|
||||
// 默认返回成功响应
|
||||
return genResp.ok()
|
||||
|
25
routes/sheet/insert.ts
Normal file
25
routes/sheet/insert.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Context } from "../../types"
|
||||
import { SheetProxy } from "../../types/sheetProxy"
|
||||
|
||||
/**
|
||||
* 插入表格数据
|
||||
* @param {Context.Data} ctx - 上下文数据,包含请求体和响应生成器
|
||||
* @param {string} appName - 应用名称
|
||||
* @returns {Promise<Response>} 返回响应对象
|
||||
*/
|
||||
const insertSheet = async (ctx: Context.Data, appName: string) => {
|
||||
const { genResp, larkService } = ctx
|
||||
const body = ctx.body as SheetProxy.InsertData
|
||||
|
||||
const insertRes = await larkService
|
||||
.child(appName)
|
||||
.sheet.insertRows(body.sheet_token, body.range, body.values)
|
||||
|
||||
if (insertRes?.code !== 0) {
|
||||
return genResp.serverError(insertRes?.message)
|
||||
}
|
||||
// 返回成功
|
||||
return genResp.ok(insertRes?.data)
|
||||
}
|
||||
|
||||
export default insertSheet
|
@ -53,6 +53,62 @@ class LarkDriveService extends LarkBaseService {
|
||||
message: "success",
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件列表。
|
||||
*
|
||||
* @param {string} folderToken - 文件夹令牌。
|
||||
* @returns {Promise<LarkServer.BaseRes>} 包含文件列表的响应对象。
|
||||
*/
|
||||
async listFiles(folderToken: string) {
|
||||
const path = "/drive/v1/files"
|
||||
return this.get<LarkServer.BaseRes>(path, {
|
||||
folder_token: folderToken,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件。
|
||||
*
|
||||
* @param {string} folderToken - 文件夹令牌。
|
||||
* @param {string} fileName - 文件名。
|
||||
* @param {"doc" | "sheet" | "bitable"} fileType - 文件类型。
|
||||
* @returns {Promise<LarkServer.BaseRes>} 包含响应数据的Promise。
|
||||
*/
|
||||
async createFile(
|
||||
folderToken: string,
|
||||
fileName: string,
|
||||
fileType: "doc" | "sheet" | "bitable"
|
||||
) {
|
||||
const path = `/drive/explorer/v2/file/${folderToken}`
|
||||
return this.post<LarkServer.BaseRes>(path, {
|
||||
title: fileName,
|
||||
type: fileType,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制文件。
|
||||
*
|
||||
* @param {string} folderToken - 文件夹令牌。
|
||||
* @param {string} fileToken - 文件令牌。
|
||||
* @param {string} fileName - 文件名。
|
||||
* @param {"doc" | "sheet" | "bitable"} fileType - 文件类型。
|
||||
* @returns {Promise<LarkServer.BaseRes<LarkServer.CopyFileData>} 包含响应数据的Promise。
|
||||
*/
|
||||
async copyFile(
|
||||
folderToken: string,
|
||||
fileToken: string,
|
||||
fileName: string,
|
||||
fileType: "doc" | "sheet" | "bitable"
|
||||
) {
|
||||
const path = `/drive/v1/files/${fileToken}/copy`
|
||||
return this.post<LarkServer.BaseRes<LarkServer.CopyFileData>>(path, {
|
||||
type: fileType,
|
||||
folder_token: folderToken,
|
||||
name: fileName,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default LarkDriveService
|
||||
|
@ -29,6 +29,70 @@ class LarkSheetService extends LarkBaseService {
|
||||
const path = `/sheets/v2/spreadsheets/${sheetToken}/values/${range}?valueRenderOption=ToString`
|
||||
return this.get<LarkServer.SpreadsheetRes>(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定表格的所有数据表(多维表格专用)
|
||||
* @param {string} appToken - 表格令牌。
|
||||
* @returns {Promise<LarkServer.BaseRes} 返回一个包含响应数据的Promise。
|
||||
*/
|
||||
async getTables(appToken: string) {
|
||||
const path = `/bitable/v1/apps/${appToken}/tables`
|
||||
let has_more = true
|
||||
const res = [] as LarkServer.TableData[]
|
||||
while (has_more) {
|
||||
const { data, code } = await this.get<
|
||||
LarkServer.BaseListRes<LarkServer.TableData>
|
||||
>(path, {
|
||||
page_size: 100,
|
||||
})
|
||||
if (code !== 0) break
|
||||
res.push(...data.items)
|
||||
has_more = data.has_more
|
||||
}
|
||||
return {
|
||||
code: 0,
|
||||
data: res,
|
||||
message: "ok",
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定数据表的所有视图(多维表格专用)
|
||||
* @param {string} appToken - 表格令牌。
|
||||
* @param {string} tableId - 表格ID。
|
||||
* @returns {Promise<LarkServer.BaseRes} 返回一个包含响应数据的Promise。
|
||||
*/
|
||||
async getViews(appToken: string, tableId: string) {
|
||||
const path = `/bitable/v1/apps/${appToken}/tables/${tableId}/views`
|
||||
let has_more = true
|
||||
const res = [] as LarkServer.ViewData[]
|
||||
while (has_more) {
|
||||
const { data, code } = await this.get<
|
||||
LarkServer.BaseListRes<LarkServer.ViewData>
|
||||
>(path, {
|
||||
page_size: 100,
|
||||
})
|
||||
if (code !== 0) break
|
||||
res.push(...data.items)
|
||||
has_more = data.has_more
|
||||
}
|
||||
return {
|
||||
code: 0,
|
||||
data: res,
|
||||
message: "ok",
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定数据表的记录。(多维表格专用)
|
||||
* @param {string} appToken - 表格令牌。
|
||||
* @param {string} tableId - 表格ID。
|
||||
* @returns {Promise<LarkServer.BaseRes>} 返回一个包含响应数据的Promise。
|
||||
*/
|
||||
async getRecords(appToken: string, tableId: string) {
|
||||
const path = `/bitable/v1/apps/${appToken}/tables/${tableId}/records`
|
||||
return this.get<LarkServer.BaseRes>(path)
|
||||
}
|
||||
}
|
||||
|
||||
export default LarkSheetService
|
||||
|
26
test/copyFile.ts
Normal file
26
test/copyFile.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { LarkService } from "../services"
|
||||
|
||||
const service = new LarkService("egg", "")
|
||||
|
||||
const {
|
||||
data: {
|
||||
file: { token: fileToken },
|
||||
},
|
||||
} = await service.drive.copyFile(
|
||||
"D6ETfzaU9lN08adVDz3kjLey4Bx",
|
||||
"bask4drDOy7zc3nDVyZb5RYDzOe",
|
||||
"xxx 项目 KV管理器",
|
||||
"bitable"
|
||||
)
|
||||
|
||||
const { data: tableList } = await service.sheet.getTables(fileToken)
|
||||
|
||||
const tableId = tableList[0].table_id
|
||||
|
||||
const { data: viewList } = await service.sheet.getViews(fileToken, tableId)
|
||||
|
||||
const viewId = viewList[0].view_id
|
||||
|
||||
console.log(fileToken, tableId, viewId)
|
||||
|
||||
// https://xiaomi.f.mioffice.cn/base/bask4IvKT61xCvTUxIkcMaWoiYf?table=tblghpLxu1pAdVOD&view=vewEpqn4oM
|
11
test/createFile.ts
Normal file
11
test/createFile.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import LarkDriveService from "../services/lark/drive"
|
||||
|
||||
const service = new LarkDriveService("egg", "")
|
||||
|
||||
const res = await service.createFile(
|
||||
"D6ETfzaU9lN08adVDz3kjLey4Bx",
|
||||
"xxx 项目 KV管理器",
|
||||
"bitable"
|
||||
)
|
||||
|
||||
console.log(JSON.stringify(res, null, 2))
|
10
test/sheet.insert.test.http
Normal file
10
test/sheet.insert.test.http
Normal file
@ -0,0 +1,10 @@
|
||||
POST http://localhost:3000/sheet
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"api_key": "uwnpzb9hvoft28h",
|
||||
"sheet_token": "shtk4VNSEksIDylbZjl2N77vERg",
|
||||
"range": "vtLQhI",
|
||||
"values": [["1", "2"]],
|
||||
"type": "insert"
|
||||
}
|
13
test/sheet.record.get.test.ts
Normal file
13
test/sheet.record.get.test.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { test } from "bun:test"
|
||||
|
||||
import LarkSheetService from "../services/lark/sheet"
|
||||
|
||||
const service = new LarkSheetService("egg", "")
|
||||
|
||||
test("getRecords", async () => {
|
||||
const res = await service.getRecords(
|
||||
"bask4BA989TBbnu5R7Onmdh1csb",
|
||||
"tblabYZk3AYtGLSe"
|
||||
)
|
||||
console.log(res)
|
||||
})
|
@ -71,13 +71,46 @@ export namespace LarkServer {
|
||||
valueRange: ValueRange // 值与范围
|
||||
}
|
||||
|
||||
export interface BaseRes {
|
||||
export interface CopyFileData {
|
||||
file: {
|
||||
name: string
|
||||
parent_token: string
|
||||
token: string
|
||||
type: "doc" | "sheet" | "bitable"
|
||||
url: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface TableData {
|
||||
table_id: string
|
||||
revision: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface ViewData {
|
||||
view_id: string
|
||||
view_name: string
|
||||
view_public_level: "Public" | "Locked" | "Private"
|
||||
view_type: string
|
||||
view_private_owner_id?: string
|
||||
}
|
||||
|
||||
export interface BaseRes<T = any> {
|
||||
code: number
|
||||
data: any
|
||||
data: T
|
||||
// 在错误处理中msg会被赋值为message
|
||||
message: string
|
||||
}
|
||||
|
||||
export interface BaseListRes<T = any> extends BaseRes {
|
||||
data: {
|
||||
has_more: boolean
|
||||
page_token: string
|
||||
total: number
|
||||
items: T[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface SpreadsheetRes extends BaseRes {
|
||||
data: SpreadsheetData
|
||||
}
|
||||
|
@ -3,12 +3,16 @@ export namespace SheetProxy {
|
||||
Insert = "insert",
|
||||
}
|
||||
|
||||
export interface Body {
|
||||
export interface BaseData {
|
||||
api_key: string
|
||||
sheet_token: string
|
||||
type: "insert"
|
||||
range: string
|
||||
values: string[][] // 二维数组
|
||||
type: Type
|
||||
}
|
||||
|
||||
export interface InsertData extends BaseData {
|
||||
type: Type.Insert
|
||||
values: string[][]
|
||||
}
|
||||
|
||||
// 判断一个值是否是枚举中的值
|
||||
|
79
utils/genMsg.ts
Normal file
79
utils/genMsg.ts
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 生成错误消息的 JSON 字符串
|
||||
* @param {string} title - 消息标题
|
||||
* @param {string} content - 消息内容
|
||||
* @returns {string} JSON 字符串
|
||||
*/
|
||||
const genErrorMsg = (title: string, content: string) =>
|
||||
JSON.stringify({
|
||||
elements: [
|
||||
{
|
||||
tag: "markdown",
|
||||
content,
|
||||
},
|
||||
],
|
||||
header: {
|
||||
title: {
|
||||
content: title,
|
||||
tag: "plain_text",
|
||||
},
|
||||
template: "red",
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* 生成成功消息的 JSON 字符串
|
||||
* @param {string} title - 消息标题
|
||||
* @param {string} content - 消息内容
|
||||
* @returns {string} JSON 字符串
|
||||
*/
|
||||
const genSuccessMsg = (title: string, content: string) =>
|
||||
JSON.stringify({
|
||||
elements: [
|
||||
{
|
||||
tag: "markdown",
|
||||
content,
|
||||
},
|
||||
],
|
||||
header: {
|
||||
title: {
|
||||
content: title,
|
||||
tag: "plain_text",
|
||||
},
|
||||
template: "green",
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* 生成模板消息的 JSON 字符串
|
||||
* @param {string} id - 模板 ID
|
||||
* @param {any} variable - 模板变量
|
||||
* @returns {string} JSON 字符串
|
||||
*/
|
||||
export const genTempMsg = (id: string, variable: any) =>
|
||||
JSON.stringify({
|
||||
type: "template",
|
||||
data: {
|
||||
config: {
|
||||
update_multi: true,
|
||||
},
|
||||
template_id: id,
|
||||
template_variable: variable,
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* 生成 Sheet DB 错误消息的 JSON 字符串
|
||||
* @param {string} content - 消息内容
|
||||
* @returns {string} JSON 字符串
|
||||
*/
|
||||
export const genSheetDbErrorMsg = (content: string) =>
|
||||
genErrorMsg("🍳 小煎蛋 Sheet DB 错误提醒", content)
|
||||
|
||||
/**
|
||||
* 生成 Sheet DB 成功消息的 JSON 字符串
|
||||
* @param {string} content - 消息内容
|
||||
* @returns {string} JSON 字符串
|
||||
*/
|
||||
export const genSheetDbSuccessMsg = (content: string) =>
|
||||
genSuccessMsg("🍳 感谢使用小煎蛋 Sheet DB", content)
|
Loading…
x
Reference in New Issue
Block a user