This commit is contained in:
2025-06-18 18:30:01 +08:00
parent 98bb3529ea
commit 3d072958d6
12 changed files with 456 additions and 510 deletions

View File

@@ -9,7 +9,6 @@ import java.text.SimpleDateFormat;
import java.util.*;
import com.tashow.cloud.sdk.feishu.config.LarkConfig;
import com.tashow.cloud.sdk.feishu.util.LarkClientUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,32 +24,15 @@ public class FeiShuAlertClient {
private final Client client;
private final LarkConfig larkConfig;
private final ChartImageGenerator chartImageGenerator;
public interface CardDataHandler {
/**
* 保存卡片数据
* @param messageId 消息ID
* @param data 卡片数据
*/
void saveCardData(String messageId, Map<String, Object> data);
/**
* 获取卡片数据
* @param messageId 消息ID
* @return 卡片数据
*/
Map<String, Object> getCardData(String messageId);
}
private CardDataHandler cardDataHandler;
@Autowired
public FeiShuAlertClient(LarkClientUtil larkClientUtil, LarkConfig larkConfig,
ChartImageGenerator chartImageGenerator, ObjectMapper objectMapper) {
ChartImageGenerator chartImageGenerator) {
this.client = larkClientUtil.getLarkClient();
this.larkConfig = larkConfig;
this.chartImageGenerator = chartImageGenerator;
}
/**
* 创建报警群并拉人入群
*
@@ -74,18 +56,6 @@ public class FeiShuAlertClient {
return resp.getData().getChatId();
}
/**
* 发送埋点报警消息
*
* @param chatId 会话ID
* @param buriedPointData 埋点数据
* @param failCount 失败数量
* @throws Exception 异常信息
*/
public void sendBuriedPointAlertMessage(String chatId, List<ChartImageGenerator.MonitoringDataPoint> buriedPointData, int failCount) throws Exception {
sendBuriedPointAlertMessage(chatId, buriedPointData, failCount, null);
}
/**
* 发送带错误信息的埋点报警消息
*
@@ -93,9 +63,10 @@ public class FeiShuAlertClient {
* @param buriedPointData 埋点数据
* @param failCount 失败数量
* @param errorMessage 错误信息
* @return 发送的消息ID
* @throws Exception 异常信息
*/
public void sendBuriedPointAlertMessage(String chatId, List<ChartImageGenerator.MonitoringDataPoint> buriedPointData, int failCount, String errorMessage) throws Exception {
public String sendBuriedPointAlertMessage(String chatId, List<ChartImageGenerator.MonitoringDataPoint> buriedPointData, int failCount, String errorMessage) throws Exception {
HashMap<String, Object> templateData = new HashMap<>();
String imageKey = uploadImage(buriedPointData, errorMessage);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@@ -104,7 +75,7 @@ public class FeiShuAlertClient {
templateData.put("image_key", imageKey);
templateData.put("current_time", currentTime);
templateData.put("fail_count", failCount);
sendCardMessage(chatId, "AAqdpjayeOVp2", templateData);
return sendCardMessage(chatId, "AAqdpjayeOVp2", templateData);
}
/**
@@ -113,11 +84,13 @@ public class FeiShuAlertClient {
* @param buriedPointData 埋点数据
* @param failCount 失败数量
* @param errorMessage 错误信息
* @return 创建的群ID和消息ID格式为 "chatId:messageId"
* @throws Exception 异常信息
*/
public void sendBuriedPointAlertMessage(List<ChartImageGenerator.MonitoringDataPoint> buriedPointData, int failCount, String errorMessage) throws Exception {
public String sendBuriedPointAlertMessage(List<ChartImageGenerator.MonitoringDataPoint> buriedPointData, int failCount, String errorMessage) throws Exception {
String chatId = createAlertChat();
sendBuriedPointAlertMessage(chatId, buriedPointData, failCount, errorMessage);
String messageId = sendBuriedPointAlertMessage(chatId, buriedPointData, failCount, errorMessage);
return chatId + ":" + messageId;
}
/**
@@ -214,47 +187,10 @@ public class FeiShuAlertClient {
.build();
}
/**
* 构建埋点异常卡片
*
* @param buttonName 按钮名称
* @param buriedPointData 埋点数据
* @param failCount 失败数量
* @return 卡片JSON
* @throws Exception 异常信息
*/
private String buildBuriedPointCard(String buttonName, List<ChartImageGenerator.MonitoringDataPoint> buriedPointData, int failCount) throws Exception {
return buildBuriedPointCard(buttonName, buriedPointData, failCount, null);
}
/**
* 构建埋点异常卡片(带错误信息)
*
* @param buttonName 按钮名称
* @param buriedPointData 埋点数据
* @param failCount 失败数量
* @param errorMessage 错误信息
* @return 卡片JSON
* @throws Exception 异常信息
*/
private String buildBuriedPointCard(String buttonName, List<ChartImageGenerator.MonitoringDataPoint> buriedPointData, int failCount, String errorMessage) throws Exception {
String imageKey = uploadImage(buriedPointData, errorMessage);
// 获取当前时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTime = sdf.format(new Date());
HashMap<String, Object> templateData = new HashMap<>();
templateData.put("alert_title", "埋点数据异常告警");
templateData.put("image_key", imageKey);
templateData.put("current_time", currentTime);
templateData.put("fail_count", failCount);
templateData.put("button_name", buttonName);
return buildCardWithData("AAqdpjayeOVp2", templateData);
}
/**
* 发送卡片消息并保存数据
* 发送卡片消息
*
* @param chatId 会话ID
* @param templateId 卡片模板ID
@@ -264,11 +200,6 @@ public class FeiShuAlertClient {
*/
public String sendCardMessage(String chatId, String templateId, Map<String, Object> templateData) throws Exception {
String cardContent = buildCardWithData(templateId, templateData);
String messageId = sendMessage(chatId, "interactive", cardContent);
if (cardDataHandler != null && messageId != null) {
cardDataHandler.saveCardData(messageId, templateData);
}
return messageId;
return sendMessage(chatId, "interactive", cardContent);
}
}

View File

@@ -1,16 +1,13 @@
package com.tashow.cloud.sdk.feishu.client;
import com.lark.oapi.Client;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.im.v1.model.*;
import com.tashow.cloud.sdk.feishu.config.LarkConfig;
import com.tashow.cloud.sdk.feishu.util.LarkClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Arrays;
/**
* 飞书普通消息客户端
@@ -18,92 +15,73 @@ import java.util.*;
*/
@Service
public class FeiShuMessageClient {
private final Logger log = LoggerFactory.getLogger(FeiShuMessageClient.class);
private final Client client;
private final LarkConfig larkConfig;
@Autowired
public FeiShuMessageClient(LarkClientUtil larkClientUtil, LarkConfig larkConfig) {
public FeiShuMessageClient(LarkClientUtil larkClientUtil) {
this.client = larkClientUtil.getLarkClient();
this.larkConfig = larkConfig;
}
/**
* 发送文本消息
* 发送通用消息
* @param chatId 会话ID
* @param text 消息文本
* @return 发送结果
* @param msgType 消息类型
* @param content 消息内容(不同消息类型有不同的格式要求)
* @return 发送结果包含消息ID和是否成功
* @throws Exception 异常信息
*/
public boolean sendTextMessage(String chatId, String text) throws Exception {
Map<String, String> content = new HashMap<>();
content.put("text", text);
public Map<String, Object> sendMessage(String chatId, String msgType, String content) throws Exception {
CreateMessageReq req = CreateMessageReq.newBuilder()
.receiveIdType("chat_id")
.createMessageReqBody(CreateMessageReqBody.newBuilder()
.receiveId(chatId)
.msgType("text")
.content(Jsons.DEFAULT.toJson(content))
.msgType(msgType)
.content(content)
.build())
.build();
CreateMessageResp resp = client.im().message().create(req);
if (!resp.success()) {
System.out.println("发送失败原因: " + resp.getMsg() + ", 错误码: " + resp.getCode());
Map<String, Object> result = new HashMap<>();
result.put("success", resp.success());
if (resp.success()) {
result.put("messageId", resp.getData().getMessageId());
} else {
result.put("errorCode", resp.getCode());
result.put("errorMessage", resp.getMsg());
result.put("requestId", resp.getRequestId());
log.error("发送消息失败: 类型={}, 错误码={}, 错误信息={}", msgType, resp.getCode(), resp.getMsg());
}
return resp.success();
return result;
}
/**
* 发送富文本消息
* @param chatId 会话ID()
* @param title 标题
* @param content 内容
* @return 发送结果
* @throws Exception 异常信息
*/
public boolean sendPostMessage(String chatId, String title, String content) throws Exception {
// 正确的富文本消息格式
String postJson = String.format("{\"zh_cn\":{\"title\":\"%s\",\"content\":[[{\"tag\":\"text\",\"text\":\"%s\"}]]}}",
title, content);
CreateMessageReq req = CreateMessageReq.newBuilder()
.receiveIdType("chat_id")
.createMessageReqBody(CreateMessageReqBody.newBuilder()
.receiveId(chatId)
.msgType("post")
.content(postJson)
.build())
.build();
CreateMessageResp resp = client.im().message().create(req);
if (!resp.success()) {
System.out.println("发送失败原因: " + resp.getMsg() + ", 错误码: " + resp.getCode());
}
return resp.success();
}
/**
* 获取会话历史消息
* @param chatId 会话ID
* @return 消息列表
* @throws Exception 异常信息
*/
public void listChatHistory(String chatId) throws Exception {
ListMessageReq req = ListMessageReq.newBuilder().containerIdType("chat").containerId(chatId).build();
public List<Message> listChatHistory(String chatId) throws Exception {
ListMessageReq req = ListMessageReq.newBuilder()
.containerIdType("chat")
.containerId(chatId)
.build();
ListMessageResp resp = client.im().message().list(req);
if (!resp.success()) {
throw new Exception(String.format("client.im.message.list failed, code: %d, msg: %s, logId: %s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
throw new Exception(String.format("获取消息历史失败,错误码: %d, 错误信息: %s, 请求ID: %s",
resp.getCode(), resp.getMsg(), resp.getRequestId()));
}
File file = new File("./src/main/java/com/larksuite/oapi/quick_start/robot/chat_history.txt");
FileWriter writer = new FileWriter(file);
for (Message item : resp.getData().getItems()) {
String senderId = item.getSender().getId();
String content = item.getBody().getContent();
String createTime = item.getCreateTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
createTime = sdf.format(new Date(Long.parseLong(createTime)));
writer.write(String.format("chatter(%s) at (%s) send: %s\n", senderId, createTime, content));
}
writer.close();
return Arrays.asList(resp.getData().getItems());
}
}

View File

@@ -31,5 +31,9 @@ public class LarkConfig {
@Value("${lark.alert.user-open-ids}")
private String[] alertUserOpenIds;
@Value("${lark.alert.exception-card}")
private String exceptionCards;
@Value("${lark.alert.success-card}")
private String successCards;
}