From 7399f78092d0173f68e705e37a02d272523bb6c9 Mon Sep 17 00:00:00 2001 From: 3y Date: Fri, 24 Jun 2022 22:04:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=85=A5=20=E9=A3=9E=E4=B9=A6?= =?UTF-8?q?=E6=9C=BA=E5=99=A8=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/constant/SendAccountConstant.java | 6 + .../dto/account/FeiShuRobotAccount.java | 24 ++ .../dto/model/FeiShuRobotContentModel.java | 50 +++ .../austin/common/enums/ChannelType.java | 7 +- .../austin/common/enums/SendMessageType.java | 50 ++- .../domain/feishu/FeiShuRobotParam.java | 310 ++++++++++++++++++ .../domain/feishu/FeiShuRobotResult.java | 58 ++++ .../handler/impl/FeiShuRobotHandler.java | 106 ++++++ 8 files changed, 593 insertions(+), 18 deletions(-) create mode 100644 austin-common/src/main/java/com/java3y/austin/common/dto/account/FeiShuRobotAccount.java create mode 100644 austin-common/src/main/java/com/java3y/austin/common/dto/model/FeiShuRobotContentModel.java create mode 100644 austin-handler/src/main/java/com/java3y/austin/handler/domain/feishu/FeiShuRobotParam.java create mode 100644 austin-handler/src/main/java/com/java3y/austin/handler/domain/feishu/FeiShuRobotResult.java create mode 100644 austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/FeiShuRobotHandler.java diff --git a/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java b/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java index 58c2dba..baedd24 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java +++ b/austin-common/src/main/java/com/java3y/austin/common/constant/SendAccountConstant.java @@ -54,6 +54,12 @@ public class SendAccountConstant { public static final String ENTERPRISE_WECHAT_ROBOT_ACCOUNT_KEY = "enterpriseWechatAccountRobot"; public static final String ENTERPRISE_WECHAT_ROBOT_PREFIX = "enterprise_wechat_robot_"; + /** + * 飞书群机器人 账号 + */ + public static final String FEI_SHU_ROBOT_ACCOUNT_KEY = "feiShuAccountRobot"; + public static final String FEI_SHU_ROBOT_PREFIX = "fei_shu_robot_"; + /** * 企业微信 应用消息 账号 */ diff --git a/austin-common/src/main/java/com/java3y/austin/common/dto/account/FeiShuRobotAccount.java b/austin-common/src/main/java/com/java3y/austin/common/dto/account/FeiShuRobotAccount.java new file mode 100644 index 0000000..67f7907 --- /dev/null +++ b/austin-common/src/main/java/com/java3y/austin/common/dto/account/FeiShuRobotAccount.java @@ -0,0 +1,24 @@ +package com.java3y.austin.common.dto.account; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 飞书 机器人 账号信息 + * + * @author 3y + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class FeiShuRobotAccount { + /** + * 自定义群机器人中的 webhook + */ + private String webhook; + +} diff --git a/austin-common/src/main/java/com/java3y/austin/common/dto/model/FeiShuRobotContentModel.java b/austin-common/src/main/java/com/java3y/austin/common/dto/model/FeiShuRobotContentModel.java new file mode 100644 index 0000000..2a92869 --- /dev/null +++ b/austin-common/src/main/java/com/java3y/austin/common/dto/model/FeiShuRobotContentModel.java @@ -0,0 +1,50 @@ +package com.java3y.austin.common.dto.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author 3y + * 飞书群 机器人 + *

+ * https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN#756b882f + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class FeiShuRobotContentModel extends ContentModel { + + /** + * 发送类型 + */ + private String sendType; + + /** + * 发送内容 + */ + private String content; + + /** + * 发送标题 + */ + private String title; + + /** + * 媒体Id + */ + private String mediaId; + + + /** + * 富文本内容:[[{"tag":"text","text":"项目有更新: "},{"tag":"a","text":"请查看","href":"http://www.example.com/"},{"tag":"at","user_id":"ou_18eac8********17ad4f02e8bbbb"}]] + */ + private String postContent; + + /** + * 图片路径 + */ + private String imagePath; +} diff --git a/austin-common/src/main/java/com/java3y/austin/common/enums/ChannelType.java b/austin-common/src/main/java/com/java3y/austin/common/enums/ChannelType.java index 114eed4..965b857 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/enums/ChannelType.java +++ b/austin-common/src/main/java/com/java3y/austin/common/enums/ChannelType.java @@ -21,12 +21,13 @@ public enum ChannelType { PUSH(20, "push(通知栏)", PushContentModel.class, "push"), SMS(30, "sms(短信)", SmsContentModel.class, "sms"), EMAIL(40, "email(邮件)", EmailContentModel.class, "email"), - OFFICIAL_ACCOUNT(50, "OfficialAccounts(服务号)", OfficialAccountsContentModel.class, "official_accounts"), + OFFICIAL_ACCOUNT(50, "officialAccounts(服务号)", OfficialAccountsContentModel.class, "official_accounts"), MINI_PROGRAM(60, "miniProgram(小程序)", MiniProgramContentModel.class, "mini_program"), - ENTERPRISE_WE_CHAT(70, "EnterpriseWeChat(企业微信)", EnterpriseWeChatContentModel.class, "enterprise_we_chat"), + ENTERPRISE_WE_CHAT(70, "enterpriseWeChat(企业微信)", EnterpriseWeChatContentModel.class, "enterprise_we_chat"), DING_DING_ROBOT(80, "dingDingRobot(钉钉机器人)", DingDingRobotContentModel.class, "ding_ding_robot"), DING_DING_WORK_NOTICE(90, "dingDingWorkNotice(钉钉工作通知)", DingDingWorkContentModel.class, "ding_ding_work_notice"), - ENTERPRISE_WE_CHAT_ROBOT(100, "EnterpriseWeChat(企业微信机器人)", EnterpriseWeChatRobotContentModel.class, "enterprise_we_chat_robot"), + ENTERPRISE_WE_CHAT_ROBOT(100, "enterpriseWeChat(企业微信机器人)", EnterpriseWeChatRobotContentModel.class, "enterprise_we_chat_robot"), + FEI_SHU_ROBOT(110, "feiShuRoot(飞书机器人)", FeiShuRobotContentModel.class, "fei_shu_robot"), ; /** diff --git a/austin-common/src/main/java/com/java3y/austin/common/enums/SendMessageType.java b/austin-common/src/main/java/com/java3y/austin/common/enums/SendMessageType.java index 2dfeb1a..7301853 100644 --- a/austin-common/src/main/java/com/java3y/austin/common/enums/SendMessageType.java +++ b/austin-common/src/main/java/com/java3y/austin/common/enums/SendMessageType.java @@ -14,20 +14,22 @@ import lombok.ToString; @AllArgsConstructor public enum SendMessageType { - TEXT("10", "文本", "text", "text","text"), - VOICE("20", "语音", null, "voice",null), - VIDEO("30", "视频", null, null,null), - NEWS("40", "图文", "feedCard", null,"news"), - TEXT_CARD("50", "文本卡片", null, null,null), - FILE("60", "文件", null, "file","file"), - MINI_PROGRAM_NOTICE("70", "小程序通知", null, null,null), - MARKDOWN("80", "markdown", "markdown", "markdown","markdown"), - TEMPLATE_CARD("90", "模板卡片", null, null,"template_card"), - IMAGE("100", "图片", null, "image","image"), - LINK("110", "链接消息", "link", "link",null), - ACTION_CARD("120", "跳转卡片消息", "actionCard", "action_card",null), - OA("130", "OA消息", null, "oa",null), - MP_NEWS("140", "图文消息(mpnews)", null, null,null), + TEXT("10", "文本", "text", "text","text","text"), + VOICE("20", "语音", null, "voice",null,null), + VIDEO("30", "视频", null, null,null,null), + NEWS("40", "图文", "feedCard", null,"news",null), + TEXT_CARD("50", "文本卡片", null, null,null,null), + FILE("60", "文件", null, "file","file",null), + MINI_PROGRAM_NOTICE("70", "小程序通知", null, null,null,null), + MARKDOWN("80", "markdown", "markdown", "markdown","markdown",null), + TEMPLATE_CARD("90", "模板卡片", null, null,"template_card",null), + IMAGE("100", "图片", null, "image","image","image"), + LINK("110", "链接消息", "link", "link",null,null), + ACTION_CARD("120", "跳转卡片消息", "actionCard", "action_card",null,"interactive"), + OA("130", "OA消息", null, "oa",null,null), + MP_NEWS("140", "图文消息(mpNews)", null, null,null,null), + RICH_TEXT("150", "富文本", null, null,null,"post"), + SHARE_CHAT("160", "群名片", null, null,null,"share_chat") ; @@ -49,6 +51,11 @@ public enum SendMessageType { */ private String enterpriseWeChatRobotType; + /** + * 飞书机器人类型值 + */ + private String feiShuRobotType; + /** * 通过code获取钉钉机器人的Type值 @@ -94,5 +101,18 @@ public enum SendMessageType { } return null; } - + /** + * 通过code获取企业微信机器人的Type值 + * + * @param code + * @return + */ + public static String geFeiShuRobotTypeByCode(String code) { + for (SendMessageType value : SendMessageType.values()) { + if (value.getCode().equals(code)) { + return value.getFeiShuRobotType(); + } + } + return null; + } } diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/domain/feishu/FeiShuRobotParam.java b/austin-handler/src/main/java/com/java3y/austin/handler/domain/feishu/FeiShuRobotParam.java new file mode 100644 index 0000000..1bc67f2 --- /dev/null +++ b/austin-handler/src/main/java/com/java3y/austin/handler/domain/feishu/FeiShuRobotParam.java @@ -0,0 +1,310 @@ +package com.java3y.austin.handler.domain.feishu; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + + +/** + * @author 3y + * 飞书机器人 请求参数 + */ +@NoArgsConstructor +@Data +@AllArgsConstructor +@Builder +public class FeiShuRobotParam { + + /** + * msgType + */ + @JSONField(name = "msg_type") + private String msgType; + /** + * content + */ + @JSONField(name = "content") + private ContentDTO content; + /** + * card + */ + @JSONField(name = "card") + private CardDTO card; + + /** + * ContentDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class ContentDTO { + /** + * text + */ + @JSONField(name = "text") + private String text; + /** + * post + */ + @JSONField(name = "post") + private PostDTO post; + /** + * shareChatId + */ + @JSONField(name = "share_chat_id") + private String shareChatId; + /** + * imageKey + */ + @JSONField(name = "image_key") + private String imageKey; + + /** + * PostDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class PostDTO { + /** + * zhCn + */ + @JSONField(name = "zh_cn") + private ZhCnDTO zhCn; + + /** + * ZhCnDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class ZhCnDTO { + /** + * title + */ + @JSONField(name = "title") + private String title; + /** + * content + */ + @JSONField(name = "content") + private List> content; + + /** + * ContentDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class PostContentDTO { + /** + * tag + */ + @JSONField(name = "tag") + private String tag; + /** + * text + */ + @JSONField(name = "text") + private String text; + /** + * href + */ + @JSONField(name = "href") + private String href; + /** + * userId + */ + @JSONField(name = "user_id") + private String userId; + } + } + } + } + + /** + * CardDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class CardDTO { + /** + * config + */ + @JSONField(name = "config") + private ConfigDTO config; + /** + * elements + */ + @JSONField(name = "elements") + private List elements; + /** + * header + */ + @JSONField(name = "header") + private HeaderDTO header; + + /** + * ConfigDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class ConfigDTO { + /** + * wideScreenMode + */ + @JSONField(name = "wide_screen_mode") + private Boolean wideScreenMode; + /** + * enableForward + */ + @JSONField(name = "enable_forward") + private Boolean enableForward; + } + + /** + * HeaderDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class HeaderDTO { + /** + * title + */ + @JSONField(name = "title") + private TitleDTO title; + + /** + * TitleDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class TitleDTO { + /** + * content + */ + @JSONField(name = "content") + private String content; + /** + * tag + */ + @JSONField(name = "tag") + private String tag; + } + } + + /** + * ElementsDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class ElementsDTO { + /** + * tag + */ + @JSONField(name = "tag") + private String tag; + /** + * text + */ + @JSONField(name = "text") + private TextDTO text; + /** + * actions + */ + @JSONField(name = "actions") + private List actions; + + /** + * TextDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class TextDTO { + /** + * content + */ + @JSONField(name = "content") + private String content; + /** + * tag + */ + @JSONField(name = "tag") + private String tag; + } + + /** + * ActionsDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class ActionsDTO { + /** + * tag + */ + @JSONField(name = "tag") + private String tag; + /** + * text + */ + @JSONField(name = "text") + private TextDTO text; + /** + * url + */ + @JSONField(name = "url") + private String url; + /** + * type + */ + @JSONField(name = "type") + private String type; + /** + * value + */ + @JSONField(name = "value") + private ValueDTO value; + + /** + * TextDTO + */ + @NoArgsConstructor + @Data + public static class TextDTO { + } + + /** + * ValueDTO + */ + @NoArgsConstructor + @Data + @AllArgsConstructor + @Builder + public static class ValueDTO { + } + } + } + } +} diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/domain/feishu/FeiShuRobotResult.java b/austin-handler/src/main/java/com/java3y/austin/handler/domain/feishu/FeiShuRobotResult.java new file mode 100644 index 0000000..6b2a768 --- /dev/null +++ b/austin-handler/src/main/java/com/java3y/austin/handler/domain/feishu/FeiShuRobotResult.java @@ -0,0 +1,58 @@ +package com.java3y.austin.handler.domain.feishu; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +/** + * @author 3y + * 飞书机器人 返回值 + */ +@NoArgsConstructor +@Data +@AllArgsConstructor +@Builder +public class FeiShuRobotResult { + + /** + * extra + */ + @JSONField(name = "Extra") + private Object extra; + /** + * statusCode + */ + @JSONField(name = "StatusCode") + private Integer statusCode; + /** + * statusMessage + */ + @JSONField(name = "StatusMessage") + private String statusMessage; + /** + * code + */ + @JSONField(name = "code") + private Integer code; + /** + * msg + */ + @JSONField(name = "msg") + private String msg; + /** + * data + */ + @JSONField(name = "data") + private DataDTO data; + + /** + * DataDTO + */ + @NoArgsConstructor + @Data + public static class DataDTO { + } +} diff --git a/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/FeiShuRobotHandler.java b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/FeiShuRobotHandler.java new file mode 100644 index 0000000..dc80ae4 --- /dev/null +++ b/austin-handler/src/main/java/com/java3y/austin/handler/handler/impl/FeiShuRobotHandler.java @@ -0,0 +1,106 @@ +package com.java3y.austin.handler.handler.impl; + +import cn.hutool.core.codec.Base64; +import cn.hutool.core.io.file.FileReader; +import cn.hutool.crypto.digest.DigestUtil; +import cn.hutool.http.ContentType; +import cn.hutool.http.Header; +import cn.hutool.http.HttpRequest; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.google.common.base.Throwables; +import com.java3y.austin.common.constant.SendAccountConstant; +import com.java3y.austin.common.domain.TaskInfo; +import com.java3y.austin.common.dto.account.EnterpriseWeChatRobotAccount; +import com.java3y.austin.common.dto.account.FeiShuRobotAccount; +import com.java3y.austin.common.dto.model.EnterpriseWeChatRobotContentModel; +import com.java3y.austin.common.dto.model.FeiShuRobotContentModel; +import com.java3y.austin.common.enums.ChannelType; +import com.java3y.austin.common.enums.SendMessageType; +import com.java3y.austin.handler.domain.feishu.FeiShuRobotParam; +import com.java3y.austin.handler.domain.feishu.FeiShuRobotResult; +import com.java3y.austin.handler.domain.wechat.robot.EnterpriseWeChatRobotParam; +import com.java3y.austin.handler.handler.BaseHandler; +import com.java3y.austin.handler.handler.Handler; +import com.java3y.austin.support.domain.MessageTemplate; +import com.java3y.austin.support.utils.AccountUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * 企业微信群机器人 消息处理器 + * + * @author 3y + */ +@Slf4j +@Service +public class FeiShuRobotHandler extends BaseHandler implements Handler { + + @Autowired + private AccountUtils accountUtils; + + public FeiShuRobotHandler() { + channelCode = ChannelType.FEI_SHU_ROBOT.getCode(); + } + + @Override + public boolean handler(TaskInfo taskInfo) { + try { + FeiShuRobotAccount account = accountUtils.getAccount(taskInfo.getSendAccount(), SendAccountConstant.FEI_SHU_ROBOT_ACCOUNT_KEY, SendAccountConstant.FEI_SHU_ROBOT_PREFIX, FeiShuRobotAccount.class); + FeiShuRobotParam feiShuRobotParam = assembleParam(taskInfo); + String result = HttpRequest.post(account.getWebhook()) + .header(Header.CONTENT_TYPE.getValue(), ContentType.JSON.getValue()) + .body(JSON.toJSONString(feiShuRobotParam)) + .timeout(2000) + .execute().body(); + FeiShuRobotResult feiShuRobotResult = JSON.parseObject(result, FeiShuRobotResult.class); + if (feiShuRobotResult.getStatusCode() == 0) { + return true; + } + log.error("FeiShuRobotHandler#handler fail! result:{},params:{}", JSON.toJSONString(feiShuRobotResult), JSON.toJSONString(taskInfo)); + } catch (Exception e) { + log.error("FeiShuRobotHandler#handler fail!e:{},params:{}", Throwables.getStackTraceAsString(e), JSON.toJSONString(taskInfo)); + } + return false; + } + + private FeiShuRobotParam assembleParam(TaskInfo taskInfo) { + FeiShuRobotContentModel contentModel = (FeiShuRobotContentModel) taskInfo.getContentModel(); + + FeiShuRobotParam param = FeiShuRobotParam.builder() + .msgType(SendMessageType.geFeiShuRobotTypeByCode(contentModel.getSendType())).build(); + + if (SendMessageType.TEXT.getCode().equals(contentModel.getSendType())) { + param.setContent(FeiShuRobotParam.ContentDTO.builder().text(contentModel.getContent()).build()); + } + if (SendMessageType.RICH_TEXT.getCode().equals(contentModel.getSendType())) { + List postContentDTOS = JSON.parseArray(contentModel.getPostContent(), FeiShuRobotParam.ContentDTO.PostDTO.ZhCnDTO.PostContentDTO.class); + List> postContentList = new ArrayList<>(); + postContentList.add(postContentDTOS); + FeiShuRobotParam.ContentDTO.PostDTO postDTO = FeiShuRobotParam.ContentDTO.PostDTO.builder() + .zhCn(FeiShuRobotParam.ContentDTO.PostDTO.ZhCnDTO.builder().title(contentModel.getTitle()).content(postContentList).build()) + .build(); + param.setContent(FeiShuRobotParam.ContentDTO.builder().post(postDTO).build()); + } + if (SendMessageType.SHARE_CHAT.getCode().equals(contentModel.getSendType())) { + param.setContent(FeiShuRobotParam.ContentDTO.builder().shareChatId(contentModel.getMediaId()).build()); + } + if (SendMessageType.IMAGE.getCode().equals(contentModel.getSendType())) { + param.setContent(FeiShuRobotParam.ContentDTO.builder().imageKey(contentModel.getMediaId()).build()); + } + if (SendMessageType.ACTION_CARD.getCode().equals(contentModel.getSendType())) { + // + } + return param; + } + + @Override + public void recall(MessageTemplate messageTemplate) { + + } +} +