feat:2.6.0 企业微信通知

This commit is contained in:
lizhongyuan3 2023-12-14 21:30:11 +08:00 committed by byteblogs168
parent c163986a82
commit 1b5b131a0c
8 changed files with 186 additions and 32 deletions

View File

@ -0,0 +1,19 @@
package com.aizuda.easy.retry.common.core.alarm;
import lombok.Data;
import java.util.List;
/**
* 企业微信
*
* @author lizhongyuan
*/
@Data
public class QiYeWechatAttribute {
private String webhookUrl;
private List<String> ats;
}

View File

@ -36,7 +36,7 @@ import java.util.Map;
public class LarkAlarm extends AbstractAlarm<AlarmContext> {
public static final String atLabel = "<at id={0}></at>";
public static final String AT_LABEL = "<at id={0}></at>";
@Override
public Integer getAlarmType() {
@ -45,9 +45,7 @@ public class LarkAlarm extends AbstractAlarm<AlarmContext> {
@Override
public boolean asyncSendMessage(AlarmContext context) {
threadPoolExecutor.execute(() -> {
syncSendMessage(context);
});
threadPoolExecutor.execute(() -> syncSendMessage(context));
return true;
}
@ -69,12 +67,15 @@ public class LarkAlarm extends AbstractAlarm<AlarmContext> {
HttpRequest request = post.body(JsonUtil.toJsonString(builder), ContentType.JSON.toString());
HttpResponse execute = request.execute();
LogUtils.debug(log, JsonUtil.toJsonString(execute));
if (execute.isOk()) {
return true;
}
LogUtils.error(log, "发送lark消息失败:{}", execute.body());
return false;
} catch (Exception e) {
log.error("发送lark消息失败", e);
return false;
}
return true;
}
private List buildElements(String text, List<String> ats) {
@ -123,10 +124,10 @@ public class LarkAlarm extends AbstractAlarm<AlarmContext> {
StringBuilder sb = new StringBuilder(text);
if (ats.stream().map(String::toLowerCase).anyMatch(SystemConstants.AT_ALL::equals)) {
sb.append(MessageFormat.format(atLabel, SystemConstants.AT_ALL));
sb.append(MessageFormat.format(AT_LABEL, SystemConstants.AT_ALL));
} else {
ats.stream().filter(StrUtil::isNotBlank)
.forEach(at -> sb.append(MessageFormat.format(atLabel, at)));
.forEach(at -> sb.append(MessageFormat.format(AT_LABEL, at)));
}
return sb.toString();
}

View File

@ -0,0 +1,91 @@
package com.aizuda.easy.retry.common.core.alarm.strategy;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.*;
import com.aizuda.easy.retry.common.core.alarm.AlarmContext;
import com.aizuda.easy.retry.common.core.alarm.QiYeWechatAttribute;
import com.aizuda.easy.retry.common.core.enums.AlarmTypeEnum;
import com.aizuda.easy.retry.common.core.log.LogUtils;
import com.aizuda.easy.retry.common.core.util.DingDingUtils;
import com.aizuda.easy.retry.common.core.util.JsonUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* 企业微信通知
*
* @author lizhongyuan
*/
@Slf4j
@Component
public class QiYeWechatAlarm extends AbstractAlarm<AlarmContext> {
public static final String AT_LABEL = "<@{0}>";
@Override
public Integer getAlarmType() {
return AlarmTypeEnum.QI_YE_WECHAT.getValue();
}
@Override
public boolean asyncSendMessage(AlarmContext context) {
threadPoolExecutor.execute(() -> syncSendMessage(context));
return true;
}
@Override
public boolean syncSendMessage(AlarmContext context) {
try {
QiYeWechatAttribute qiYeWechatAttribute = JsonUtil.parseObject(context.getNotifyAttribute(), QiYeWechatAttribute.class);
String webhookUrl = qiYeWechatAttribute.getWebhookUrl();
if (StrUtil.isBlank(webhookUrl)) {
log.error("请先配置微信机器人 webhookUrl");
return false;
}
Map<String, Object> map = MapUtil.newHashMap();
QiYeWechatMessageContent messageContent = new QiYeWechatMessageContent();
messageContent.setContent(StrUtil.sub(DingDingUtils.getAtText(qiYeWechatAttribute.getAts(), context.getText(), AT_LABEL), 0, 4096));
map.put("msgtype", "markdown");
map.put("markdown", messageContent);
HttpRequest post = HttpUtil.createPost(webhookUrl);
HttpRequest request = post.body(JsonUtil.toJsonString(map), ContentType.JSON.toString());
HttpResponse execute = request.execute();
LogUtils.debug(log, JsonUtil.toJsonString(execute));
if (execute.isOk()) {
return true;
}
LogUtils.error(log, "发送企业微信消息失败:{}", execute.body());
return false;
} catch (Exception e) {
log.error("发送企业微信消息失败", e);
return false;
}
}
@Override
public boolean asyncSendMessage(List<AlarmContext> alarmContexts) {
for (AlarmContext alarmContext : alarmContexts) {
asyncSendMessage(alarmContext);
}
return Boolean.TRUE;
}
@Data
private static class QiYeWechatMessageContent {
/**
* markdown内容最长不超过4096个字节必须是utf8编码
*/
private String content;
}
}

View File

@ -8,13 +8,9 @@ import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author: www.byteblogs.com
@ -25,22 +21,6 @@ public class DingDingUtils {
public static final String atLabel = "@{0}";
/**
* 防止文本过长钉钉限流目前最大为4000
*
* @param text
* @return
*/
private static String subTextLength(String text) {
int length = text.length();
if (length > 4000) {
return text.substring(0, 4000);
} else {
return text;
}
}
/**
* 组装OapiRobotSendRequest
*
@ -53,7 +33,8 @@ public class DingDingUtils {
request.setMsgtype("markdown");
OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
markdown.setTitle(title);
markdown.setText(subTextLength(getAtText(ats, text)));
// 防止文本过长钉钉限流目前最大为4000
markdown.setText(StrUtil.sub(getAtText(ats, text, atLabel), 0, 4000));
request.setMarkdown(markdown);
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
@ -65,7 +46,7 @@ public class DingDingUtils {
return request;
}
public static String getAtText(List<String> ats, String text) {
public static String getAtText(List<String> ats, String text, String atLabel) {
if (CollectionUtils.isEmpty(ats)) {
return text;
}

View File

@ -171,6 +171,10 @@ const enums = {
'name': '邮箱通知',
'color': '#1b7ee5'
},
'3': {
'name': '企业微信',
'color': '#0082EF'
},
'4': {
'name': '飞书',
'color': '#087da1'

View File

@ -90,6 +90,10 @@ const enums = {
'name': '邮箱通知',
'color': '#1b7ee5'
},
'3': {
'name': '企业微信',
'color': '#0082EF'
},
'4': {
'name': '飞书',
'color': '#087da1'

View File

@ -164,7 +164,8 @@
{rules: [{ required: true, message: '请输入钉钉URL', whitespace: true}]}
]" />
</a-form-item>
<a-form-item v-if="this.tempNotifyTypeValue === '1'">
<a-form-item
v-if="this.tempNotifyTypeValue === '1'">
<span slot="label">@人手机号或钉钉号&nbsp</span>
<a-input
placeholder="请输入被@人手机号或钉钉号"
@ -175,6 +176,28 @@
{rules: [{ required: false, message: '请输入被@人手机号或钉钉号', whitespace: true}]}
]" />
</a-form-item>
<a-form-item
v-if="this.tempNotifyTypeValue === '3'"
label="企业微信URL">
<a-input
placeholder="请输入企业微信URL"
v-decorator="[
'webhookUrl',
{rules: [{ required: true, message: '请输入企业微信URL', whitespace: true}]}
]" />
</a-form-item>
<a-form-item
v-if="this.tempNotifyTypeValue === '3'">
<span slot="label">@人企业微信用户id&nbsp</span>
<a-input
placeholder="请输入被@人企业微信用户id"
type="textarea"
v-if="this.tempNotifyTypeValue === '3'"
v-decorator="[
'ats',
{rules: [{ required: false, message: '请输入被@人企业微信用户id', whitespace: true}]}
]" />
</a-form-item>
<a-form-item
v-if="this.tempNotifyTypeValue === '4'"
label="飞书URL">
@ -493,6 +516,10 @@ export default {
s =
'钉钉Url:' + json['webhookUrl'] + ';' +
'被@人手机号:' + json['ats'] + ';'
} else if (this.notifyTypeValue === '3') {
s =
'企业微信Url:' + json['webhookUrl'] + ';' +
'被@人企业微信用户id:' + json['ats'] + ';'
} else if (this.notifyTypeValue === '4') {
s =
'飞书Url:' + json['webhookUrl'] + ';' +

View File

@ -165,7 +165,8 @@
{rules: [{ required: true, message: '请输入钉钉URL', whitespace: true}]}
]" />
</a-form-item>
<a-form-item v-if="this.tempNotifyTypeValue === '1'">
<a-form-item
v-if="this.tempNotifyTypeValue === '1'">
<span slot="label">@人手机号或钉钉号&nbsp;</span>
<a-input
placeholder="请输入被@人手机号或钉钉号"
@ -176,6 +177,28 @@
{rules: [{ required: false, message: '请输入被@人手机号或钉钉号', whitespace: true}]}
]" />
</a-form-item>
<a-form-item
v-if="this.tempNotifyTypeValue === '3'"
label="企业微信URL">
<a-input
placeholder="请输入企业微信URL"
v-decorator="[
'webhookUrl',
{rules: [{ required: true, message: '请输入企业微信URL', whitespace: true}]}
]" />
</a-form-item>
<a-form-item
v-if="this.tempNotifyTypeValue === '3'">
<span slot="label">@人企业微信用户id&nbsp;</span>
<a-input
placeholder="请输入被@人企业微信用户id"
type="textarea"
v-if="this.tempNotifyTypeValue === '3'"
v-decorator="[
'ats',
{rules: [{ required: false, message: '请输入被@人企业微信用户id', whitespace: true}]}
]" />
</a-form-item>
<a-form-item
v-if="this.tempNotifyTypeValue === '4'"
label="飞书URL">
@ -493,6 +516,10 @@ export default {
s =
'钉钉Url:' + json['webhookUrl'] + ';' +
'被@人手机号或钉钉号:' + json['ats'] + ';'
} else if (this.notifyTypeValue === '3') {
s =
'企业微信Url:' + json['webhookUrl'] + ';' +
'被@人企业微信用户id:' + json['ats'] + ';'
} else if (this.notifyTypeValue === '4') {
s =
'飞书Url:' + json['webhookUrl'] + ';' +