package com.codechecker.cache.notify; import com.fasterxml.jackson.databind.ObjectMapper; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * 企业微信群机器人通知(markdown 消息)。 */ public class WeComNotifier { private final ObjectMapper mapper = new ObjectMapper(); private final HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build(); /** * @return 是否发送成功 */ public boolean sendMarkdown(String webhookUrl, String markdown) { if (webhookUrl == null || webhookUrl.trim().isEmpty()) { System.err.println("[WeComNotifier] 未配置 webhook,跳过通知"); return false; } try { Map md = new LinkedHashMap<>(); md.put("content", markdown); Map payload = new LinkedHashMap<>(); payload.put("msgtype", "markdown"); payload.put("markdown", md); String body = mapper.writeValueAsString(payload); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(webhookUrl)) .timeout(Duration.ofSeconds(15)) .header("Content-Type", "application/json; charset=utf-8") .POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { // 企微成功时 body 一般为 {"errcode":0,...} if (response.body() != null && response.body().contains("\"errcode\":0")) { return true; } if (response.body() != null && response.body().contains("errcode") && !response.body().contains("\"errcode\":0")) { System.err.println("[WeComNotifier] 通知失败: " + response.body()); return false; } return true; } System.err.println("[WeComNotifier] 通知失败, HTTP " + response.statusCode() + ": " + response.body()); return false; } catch (Exception e) { System.err.println("[WeComNotifier] 通知异常: " + e.getMessage()); return false; } } /** * 按序发送多条 Markdown(用于超长按 key 拆分后的通知)。 * * @return 成功条数 */ public int sendMarkdownMessages(String webhookUrl, List markdownMessages) { if (markdownMessages == null || markdownMessages.isEmpty()) { return 0; } int ok = 0; for (int i = 0; i < markdownMessages.size(); i++) { String content = markdownMessages.get(i); boolean success = sendMarkdown(webhookUrl, content); if (success) { ok++; } System.out.println("[WeComNotifier] 第 " + (i + 1) + "/" + markdownMessages.size() + " 条发送" + (success ? "成功" : "失败") + " (" + content.getBytes(StandardCharsets.UTF_8).length + " bytes)"); // 避免触发机器人频率限制(约 20 条/分钟) if (i < markdownMessages.size() - 1) { try { Thread.sleep(200L); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } } return ok; } }