191 lines
5.6 KiB
TypeScript
191 lines
5.6 KiB
TypeScript
import { Lark } from "../types"
|
||
import LarkBaseService from "./base"
|
||
|
||
class LarkMessageService extends LarkBaseService {
|
||
/**
|
||
* 发送卡片
|
||
* @param receiveIdType 消息接收者id类型 open_id/user_id/union_id/email/chat_id
|
||
* @param receiveId 消息接收者的ID,ID类型应与查询参数receiveIdType 对应
|
||
* @param msgType 消息类型 包括:text、post、image、file、audio、media、sticker、interactive、share_chat、share_user
|
||
* @param content 消息内容,JSON结构序列化后的字符串。不同msgType对应不同内容
|
||
*/
|
||
async send(
|
||
receiveIdType: Lark.ReceiveIDType,
|
||
receiveId: string,
|
||
msgType: Lark.MsgType,
|
||
content: string | Record<string, any>
|
||
) {
|
||
if (!content) return { code: 1, message: "content is required" }
|
||
const path = `/im/v1/messages?receive_id_type=${receiveIdType}`
|
||
if (typeof content === "object") {
|
||
content = JSON.stringify(content)
|
||
}
|
||
if (msgType === "text" && !content.includes('"text"')) {
|
||
content = JSON.stringify({ text: content })
|
||
}
|
||
return this.post<Lark.BaseRes<{ message_id: string }>>(path, {
|
||
receive_id: receiveId,
|
||
msg_type: msgType,
|
||
content,
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 发送卡片信息
|
||
* @param receiveId 消息接收者的ID,ID类型应与查询参数receiveIdType 对应
|
||
* @param content 消息内容
|
||
*/
|
||
async sendCard2Chat(
|
||
receiveId: string,
|
||
content: string | Record<string, any>
|
||
) {
|
||
return this.send("chat_id", receiveId, "interactive", content)
|
||
}
|
||
|
||
/**
|
||
* 发送文本信息
|
||
* @param receiveId 消息接收者的ID,ID类型应与查询参数receiveIdType 对应
|
||
* @param content 消息内容
|
||
* @param title 消息标题
|
||
*/
|
||
async sendText2Chat(receiveId: string, content: string, title?: string) {
|
||
const messageContent = title ? `<b>${title}</b>\n${content}` : content
|
||
return this.send("chat_id", receiveId, "text", messageContent)
|
||
}
|
||
|
||
/**
|
||
* 更新卡片
|
||
* @param messageId 消息id
|
||
* @param content 消息内容,JSON结构序列化后的字符串。不同msgType对应不同内容
|
||
*/
|
||
async update(
|
||
messageId: string,
|
||
content: string | Record<string, any>,
|
||
isText: boolean = false
|
||
) {
|
||
if (!content) return { code: 1, message: "content is required" }
|
||
const path = `/im/v1/messages/${messageId}`
|
||
if (typeof content === "object") {
|
||
content = JSON.stringify(content)
|
||
}
|
||
if (isText && !content.includes('"text"')) {
|
||
content = JSON.stringify({ text: content })
|
||
}
|
||
if (!isText) return this.patch<Lark.BaseRes>(path, { content })
|
||
return this.put<Lark.BaseRes>(path, { content, msg_type: "text" })
|
||
}
|
||
|
||
/**
|
||
* 获取消息历史记录
|
||
* @param chatId 会话ID
|
||
* @param startTime 开始时间 秒级时间戳
|
||
* @param endTime 结束时间 秒级时间戳
|
||
*/
|
||
async getHistory(chatId: string, startTime: string, endTime: string) {
|
||
const path = `/im/v1/messages`
|
||
const messageList = [] as Lark.MessageData[]
|
||
let hasMore = true
|
||
let pageToken = ""
|
||
while (hasMore) {
|
||
const { code, data } = await this.get<Lark.BaseListRes<Lark.MessageData>>(
|
||
path,
|
||
{
|
||
container_id_type: "chat",
|
||
container_id: chatId,
|
||
start_time: startTime,
|
||
end_time: endTime,
|
||
page_size: 50,
|
||
page_token: pageToken,
|
||
}
|
||
)
|
||
if (code !== 0) break
|
||
messageList.push(...data.items)
|
||
hasMore = data.has_more
|
||
pageToken = data.page_token
|
||
}
|
||
return {
|
||
code: 0,
|
||
data: messageList,
|
||
message: "ok",
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 回复消息
|
||
* @param messageId 消息ID
|
||
* @param msgType 消息类型 包括:text、post、image、file、audio、media、sticker、interactive、share_chat、share_user
|
||
* @param content 消息内容
|
||
*/
|
||
async reply(
|
||
messageId: string,
|
||
msgType: Lark.MsgType,
|
||
content: string | Record<string, any>
|
||
) {
|
||
if (!content) return { code: 1, message: "content is required" }
|
||
const path = `/im/v1/messages/${messageId}/reply`
|
||
if (typeof content === "object") {
|
||
content = JSON.stringify(content)
|
||
}
|
||
if (msgType === "text" && !content.includes('"text"')) {
|
||
content = JSON.stringify({ text: content })
|
||
}
|
||
return this.post<Lark.BaseRes<{ message_id: string }>>(path, {
|
||
msg_type: msgType,
|
||
content,
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 回复卡片消息
|
||
* @param messageId 消息ID
|
||
* @param content 消息内容
|
||
*/
|
||
async replyCard(messageId: string, content: string | Record<string, any>) {
|
||
return this.reply(messageId, "interactive", content)
|
||
}
|
||
|
||
private repliedMessageId: string = ""
|
||
private replyMessageId: string = ""
|
||
private replyMsgType: "text" | "interactive" = "interactive"
|
||
|
||
/**
|
||
* 设置回复消息的ID和类型
|
||
* @param messageId 消息ID
|
||
* @param msgType 消息类型 包括:text、interactive
|
||
*/
|
||
setReplyMessage(
|
||
messageId: string,
|
||
msgType: "text" | "interactive" = "interactive"
|
||
) {
|
||
this.replyMessageId = messageId
|
||
this.replyMsgType = msgType
|
||
}
|
||
|
||
/**
|
||
* 更新或回复消息
|
||
* @param content 消息内容
|
||
* @returns 更新或回复的消息ID
|
||
*/
|
||
async updateOrReply(content: string) {
|
||
if (this.repliedMessageId) {
|
||
await this.update(
|
||
this.repliedMessageId,
|
||
content,
|
||
this.replyMsgType === "text"
|
||
)
|
||
return this.repliedMessageId
|
||
}
|
||
const res = await this.reply(
|
||
this.replyMessageId,
|
||
this.replyMsgType,
|
||
content
|
||
)
|
||
if ("data" in res) {
|
||
this.repliedMessageId = res.data.message_id
|
||
}
|
||
return this.repliedMessageId
|
||
}
|
||
}
|
||
|
||
export default LarkMessageService
|