diff --git a/dinky-admin/src/main/java/org/dinky/data/dto/AlertInstanceDTO.java b/dinky-admin/src/main/java/org/dinky/data/dto/AlertInstanceDTO.java index cb3865714a..fd5c424930 100644 --- a/dinky-admin/src/main/java/org/dinky/data/dto/AlertInstanceDTO.java +++ b/dinky-admin/src/main/java/org/dinky/data/dto/AlertInstanceDTO.java @@ -21,6 +21,8 @@ import org.dinky.mybatis.annotation.Save; +import java.util.Map; + import javax.validation.constraints.NotNull; import io.swagger.annotations.ApiModel; @@ -68,5 +70,5 @@ public class AlertInstanceDTO { required = true, dataType = "String", example = "{\"webhook\":\"https://oapi.dingtalk.com/robot/send?access_token=xxxxxx\"}") - private String params; + private Map params; } diff --git a/dinky-admin/src/main/java/org/dinky/data/model/alert/AlertInstance.java b/dinky-admin/src/main/java/org/dinky/data/model/alert/AlertInstance.java index f40b80db8d..84120da4fd 100644 --- a/dinky-admin/src/main/java/org/dinky/data/model/alert/AlertInstance.java +++ b/dinky-admin/src/main/java/org/dinky/data/model/alert/AlertInstance.java @@ -19,8 +19,14 @@ package org.dinky.data.model.alert; +import org.dinky.data.typehandler.JSONObjectHandler; import org.dinky.mybatis.model.SuperEntity; +import org.apache.ibatis.type.JdbcType; + +import java.util.Map; + +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModelProperty; @@ -61,5 +67,6 @@ public class AlertInstance extends SuperEntity { required = true, dataType = "String", example = "{\"webhook\":\"https://oapi.dingtalk.com/robot/send?access_token=xxxxxx\"}") - private String params; + @TableField(jdbcType = JdbcType.VARCHAR, typeHandler = JSONObjectHandler.class) + private Map params; } diff --git a/dinky-admin/src/main/java/org/dinky/job/handler/JobAlertHandler.java b/dinky-admin/src/main/java/org/dinky/job/handler/JobAlertHandler.java index 84a4cde153..c37d9063b7 100644 --- a/dinky-admin/src/main/java/org/dinky/job/handler/JobAlertHandler.java +++ b/dinky-admin/src/main/java/org/dinky/job/handler/JobAlertHandler.java @@ -210,8 +210,8 @@ private void executeAlertAction(Facts facts, AlertRuleDTO alertRuleDTO) { */ private void sendAlert( AlertInstance alertInstance, int jobInstanceId, int alertGid, String title, String alertMsg) { - Map params = JsonUtils.toMap(alertInstance.getParams()); - AlertConfig alertConfig = AlertConfig.build(alertInstance.getName(), alertInstance.getType(), params); + AlertConfig alertConfig = + AlertConfig.build(alertInstance.getName(), alertInstance.getType(), alertInstance.getParams()); Alert alert = Alert.build(alertConfig); AlertResult alertResult = alert.send(title, alertMsg); diff --git a/dinky-admin/src/main/java/org/dinky/service/impl/AlertInstanceServiceImpl.java b/dinky-admin/src/main/java/org/dinky/service/impl/AlertInstanceServiceImpl.java index ff97eddd15..e505079c25 100644 --- a/dinky-admin/src/main/java/org/dinky/service/impl/AlertInstanceServiceImpl.java +++ b/dinky-admin/src/main/java/org/dinky/service/impl/AlertInstanceServiceImpl.java @@ -20,6 +20,7 @@ package org.dinky.service.impl; import org.dinky.alert.Alert; +import org.dinky.alert.AlertBaseConstant; import org.dinky.alert.AlertConfig; import org.dinky.alert.AlertResult; import org.dinky.data.dto.AlertInstanceDTO; @@ -30,7 +31,6 @@ import org.dinky.mybatis.service.impl.SuperServiceImpl; import org.dinky.service.AlertGroupService; import org.dinky.service.AlertInstanceService; -import org.dinky.utils.JsonUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; @@ -68,19 +68,10 @@ public List listEnabledAll() { @Override public AlertResult testAlert(AlertInstanceDTO alertInstanceDTO) { - AlertConfig alertConfig = AlertConfig.build( - alertInstanceDTO.getName(), alertInstanceDTO.getType(), JsonUtils.toMap(alertInstanceDTO.getParams())); + AlertConfig alertConfig = + AlertConfig.build(alertInstanceDTO.getName(), alertInstanceDTO.getType(), alertInstanceDTO.getParams()); Alert alert = Alert.buildTest(alertConfig); - - String msg = "\n- **Job Name :** Test Job\n" - + "- **Job Status :** FAILED\n" - + "- **Alert Time :** 2023-01-01 12:00:00\n" - + "- **Start Time :** 2023-01-01 12:00:00\n" - + "- **End Time :** 2023-01-01 12:00:00\n" - + "- **The test exception, your job exception will pass here**\n" - + "[Go to Task Web](https://github.com/DataLinkDC/dinky)"; - - return alert.send("Fei Shu Alert Test", msg); + return alert.send(AlertBaseConstant.ALERT_TEMPLATE_TITLE, AlertBaseConstant.ALERT_TEMPLATE_MSG); } /** diff --git a/dinky-admin/src/main/resources/db/db-h2-ddl.sql b/dinky-admin/src/main/resources/db/db-h2-ddl.sql index 484663bbad..132090072a 100644 --- a/dinky-admin/src/main/resources/db/db-h2-ddl.sql +++ b/dinky-admin/src/main/resources/db/db-h2-ddl.sql @@ -34,7 +34,7 @@ CREATE TABLE `dinky_alert_instance` ( `name` varchar(50) NOT null COMMENT 'alert instance name', `tenant_id` int(11) NOT null DEFAULT 1 COMMENT 'tenant id', `type` varchar(50) null DEFAULT null COMMENT 'alert instance type such as: DingTalk,Wechat(Webhook,app) Feishu ,email', - `params` text null COMMENT 'configuration', + `params` json null COMMENT 'configuration', `enabled` tinyint(4) null DEFAULT 1 COMMENT 'is enable', `create_time` datetime(0) null DEFAULT null COMMENT 'create time', `update_time` datetime(0) null DEFAULT null COMMENT 'update time', diff --git a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertBaseConstant.java b/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertBaseConstant.java index 09e760c8f1..48dbce880b 100644 --- a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertBaseConstant.java +++ b/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertBaseConstant.java @@ -32,14 +32,22 @@ public class AlertBaseConstant { public static final String SECRET = "secret"; public static final String MSG_TYPE = "msgtype"; public static final String AT_MOBILES = "atMobiles"; - public static final String AT_USERIDS = "atUserIds"; public static final String AT_ALL = "isAtAll"; public static final String PROXY = "proxy"; public static final String PORT = "port"; public static final String USER = "user"; - public static final String AT_USERS = "users"; + public static final String AT_USERS = "atUsers"; public static final String PASSWORD = "password"; + public static final String ALERT_TEMPLATE_TITLE = "Job Alert Test Title"; + public static final String ALERT_TEMPLATE_MSG = "\n- **Job Name:** Test Job\n" + + "- **Job Status:** FAILED\n" + + "- **Alert Time:** 2023-01-01 12:00:00\n" + + "- **Start Time:** 2023-01-01 12:00:00\n" + + "- **End Time:** 2023-01-01 12:00:00\n" + + "- **The test exception, your job exception will pass here**\n" + + "[Go to Task Web](https://github.com/DataLinkDC/dinky)"; + public AlertBaseConstant() { throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } diff --git a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertConfig.java b/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertConfig.java index 83598d5daa..f901feacaf 100644 --- a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertConfig.java +++ b/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertConfig.java @@ -30,17 +30,17 @@ public class AlertConfig { private String name; private String type; - private Map param; + private Map param; public AlertConfig() {} - public AlertConfig(String name, String type, Map param) { + public AlertConfig(String name, String type, Map param) { this.name = name; this.type = type; this.param = param; } - public static AlertConfig build(String name, String type, Map param) { + public static AlertConfig build(String name, String type, Map param) { return new AlertConfig(name, type, param); } @@ -60,11 +60,11 @@ public void setType(String type) { this.type = type; } - public Map getParam() { + public Map getParam() { return param; } - public void setParam(Map param) { + public void setParam(Map param) { this.param = param; } } diff --git a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertMsg.java b/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertMsg.java deleted file mode 100644 index d8d563e568..0000000000 --- a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/alert/AlertMsg.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.dinky.alert; - -import lombok.Builder; -import lombok.Data; - -/** - * AlertMsg - * - * @since 2022/3/7 18:30 - */ -@Data -@Builder -public class AlertMsg { - - private String alertType; - private String alertTime; - private String jobID; - private String jobName; - private String jobType; - private String jobStatus; - private String jobStartTime; - private String jobEndTime; - private String jobDuration; - - /** Flink WebUI link url */ - private String linkUrl; - - /** Flink job Root Exception url */ - private String exceptionUrl; - - public AlertMsg() {} - - public AlertMsg( - String alertType, - String alertTime, - String jobID, - String jobName, - String jobType, - String jobStatus, - String jobStartTime, - String jobEndTime, - String jobDuration, - String linkUrl, - String exceptionUrl) { - - this.alertType = alertType; - this.alertTime = alertTime; - this.jobID = jobID; - this.jobName = jobName; - this.jobType = jobType; - this.jobStatus = jobStatus; - this.jobStartTime = jobStartTime; - this.jobEndTime = jobEndTime; - this.jobDuration = jobDuration; - this.linkUrl = linkUrl; - this.exceptionUrl = exceptionUrl; - } - - public String toString() { - return "[{ \"Alert Type\":\"" - + alertType - + "\"," - + "\"Alert Time\":\"" - + alertTime - + "\"," - + "\"Job ID\":\"" - + jobID - + "\"," - + "\"Job Name\":\"" - + jobName - + "\"," - + "\"Job Type\":\"" - + jobType - + "\"," - + "\"Job Status\":\"" - + jobStatus - + "\"," - + "\"Job StartTime\": \"" - + jobStartTime - + "\"," - + "\"Job EndTime\": \"" - + jobEndTime - + "\"," - + "\"Job Duration\": \"" - + jobDuration - + "\"," - + "\"Exception Log\" :\"" - + exceptionUrl - + "\"" - + "}]"; - } -} diff --git a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/utils/ExcelUtils.java b/dinky-alert/dinky-alert-base/src/main/java/org/dinky/utils/ExcelUtils.java deleted file mode 100644 index 81328a1aa7..0000000000 --- a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/utils/ExcelUtils.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.dinky.utils; - -import org.dinky.alert.AlertException; - -import org.apache.commons.collections4.CollectionUtils; -import org.apache.poi.ss.usermodel.Cell; -import org.apache.poi.ss.usermodel.CellStyle; -import org.apache.poi.ss.usermodel.HorizontalAlignment; -import org.apache.poi.ss.usermodel.Row; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; - -import java.io.File; -import java.io.FileOutputStream; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** ExcelUtils excel工具类 */ -public final class ExcelUtils { - - private static final int XLSX_WINDOW_ROW = 10000; - private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class); - - private ExcelUtils() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - - /** - * generate excel file - * - * @param content the content - * @param title the title - * @param xlsFilePath the xls path - */ - public static void genExcelFile(String content, String title, String xlsFilePath) { - File file = new File(xlsFilePath); - if (!file.exists() && !file.mkdirs()) { - logger.error("Create xlsx directory error, path:{}", xlsFilePath); - throw new AlertException("Create xlsx directory error"); - } - - List itemsList = JsonUtils.toList(content, LinkedHashMap.class); - - if (CollectionUtils.isEmpty(itemsList)) { - logger.error("itemsList is null"); - throw new AlertException("itemsList is null"); - } - - LinkedHashMap headerMap = itemsList.get(0); - - List headerList = new ArrayList<>(); - - for (Map.Entry en : headerMap.entrySet()) { - headerList.add(en.getKey()); - } - try (SXSSFWorkbook wb = new SXSSFWorkbook(XLSX_WINDOW_ROW); - FileOutputStream fos = new FileOutputStream(String.format("%s/%s.xlsx", xlsFilePath, title))) { - // declare a workbook - // generate a table - Sheet sheet = wb.createSheet(); - Row row = sheet.createRow(0); - // set the height of the first line - row.setHeight((short) 500); - - // set Horizontal right - CellStyle cellStyle = wb.createCellStyle(); - cellStyle.setAlignment(HorizontalAlignment.RIGHT); - - // setting excel headers - for (int i = 0; i < headerList.size(); i++) { - Cell cell = row.createCell(i); - cell.setCellStyle(cellStyle); - cell.setCellValue(headerList.get(i)); - } - - // setting excel body - int rowIndex = 1; - for (LinkedHashMap itemsMap : itemsList) { - Object[] values = itemsMap.values().toArray(); - row = sheet.createRow(rowIndex); - // setting excel body height - row.setHeight((short) 500); - rowIndex++; - for (int j = 0; j < values.length; j++) { - Cell cell1 = row.createCell(j); - cell1.setCellStyle(cellStyle); - if (values[j] instanceof Number) { - cell1.setCellValue(Double.parseDouble(String.valueOf(values[j]))); - } else { - cell1.setCellValue(String.valueOf(values[j])); - } - } - } - - for (int i = 0; i < headerList.size(); i++) { - sheet.setColumnWidth(i, headerList.get(i).length() * 800); - } - - // setting file output - wb.write(fos); - wb.dispose(); - } catch (Exception e) { - throw new AlertException("generate excel error", e); - } - } -} diff --git a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/utils/HttpRequestUtil.java b/dinky-alert/dinky-alert-base/src/main/java/org/dinky/utils/HttpRequestUtil.java deleted file mode 100644 index 70ff017dc3..0000000000 --- a/dinky-alert/dinky-alert-base/src/main/java/org/dinky/utils/HttpRequestUtil.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.dinky.utils; - -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; - -public final class HttpRequestUtil { - - private HttpRequestUtil() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - - public static CloseableHttpClient getHttpClient( - boolean enableProxy, String proxy, Integer port, String user, String password) { - if (enableProxy) { - HttpHost httpProxy = new HttpHost(proxy, port); - CredentialsProvider provider = new BasicCredentialsProvider(); - provider.setCredentials(new AuthScope(httpProxy), new UsernamePasswordCredentials(user, password)); - return HttpClients.custom().setDefaultCredentialsProvider(provider).build(); - } else { - return HttpClients.createDefault(); - } - } - - public static HttpPost constructHttpPost(String url, String msg) { - HttpPost post = new HttpPost(url); - StringEntity entity = new StringEntity(msg, ContentType.APPLICATION_JSON); - post.setEntity(entity); - return post; - } -} diff --git a/dinky-alert/dinky-alert-dingtalk/pom.xml b/dinky-alert/dinky-alert-dingtalk/pom.xml index 9828a9c319..c2b76e5817 100644 --- a/dinky-alert/dinky-alert-dingtalk/pom.xml +++ b/dinky-alert/dinky-alert-dingtalk/pom.xml @@ -42,7 +42,7 @@ junit junit - provided + test diff --git a/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/DingTalkConstants.java b/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/DingTalkConstants.java index fdea1ef1f7..7e8051eedf 100644 --- a/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/DingTalkConstants.java +++ b/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/DingTalkConstants.java @@ -27,7 +27,6 @@ public class DingTalkConstants extends AlertBaseConstant { public static final String ALERT_TEMPLATE_TITLE = "title"; public static final String ALERT_TEMPLATE_CONTENT = "content"; public static final String ALERT_TEMPLATE_KEYWORD = "keyword"; - public static final String ALERT_TEMPLATE_AT_MOBILE = "atMobile"; public static final String ALERT_TEMPLATE_AT_MOBILES = "atMobiles"; - public static final String ALERT_TEMPLATE_AT_ALL = "atAll"; + public static final String ALERT_TEMPLATE_AT_ALL = "isAtAll"; } diff --git a/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/DingTalkSender.java b/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/DingTalkSender.java index 9689f5ae68..8146c9e5bc 100644 --- a/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/DingTalkSender.java +++ b/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/DingTalkSender.java @@ -21,6 +21,7 @@ import org.dinky.alert.AlertResult; import org.dinky.alert.AlertSendResponse; +import org.dinky.alert.dingtalk.params.DingTalkParams; import org.dinky.assertion.Asserts; import org.dinky.data.model.ProxyConfig; import org.dinky.utils.HttpUtils; @@ -38,35 +39,26 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import cn.hutool.json.JSONUtil; + /** * DingTalkSender - * */ public class DingTalkSender { private static final Logger logger = LoggerFactory.getLogger(DingTalkSender.class); - private final String url; - private final String keyword; - private final String secret; - private final String atMobiles; - private final Boolean atAll; - private ProxyConfig proxyConfig = null; - DingTalkSender(Map config) { - url = config.get(DingTalkConstants.WEB_HOOK); - keyword = config.get(DingTalkConstants.KEYWORD); - secret = config.get(DingTalkConstants.SECRET); - - atMobiles = config.get(DingTalkConstants.AT_MOBILES); - // String atUserIds = config.get(DingTalkConstants.AT_USERIDS); - atAll = Boolean.valueOf(config.get(DingTalkConstants.AT_ALL)); + private final DingTalkParams dingTalkParams; + private ProxyConfig proxyConfig = null; - Boolean enableProxy = Boolean.valueOf(config.get(DingTalkConstants.PROXY_ENABLE)); - if (Boolean.TRUE.equals(enableProxy)) { - Integer port = Integer.parseInt(config.get(DingTalkConstants.PORT)); - String proxy = config.get(DingTalkConstants.PROXY); - String user = config.get(DingTalkConstants.USER); - String password = config.get(DingTalkConstants.PASSWORD); - proxyConfig = new ProxyConfig(proxy, port, user, password); + DingTalkSender(Map config) { + this.dingTalkParams = JSONUtil.toBean(JSONUtil.toJsonStr(config), DingTalkParams.class); + Asserts.checkNotNull(dingTalkParams, "dingTalkParams is null"); + if (Boolean.TRUE.equals(dingTalkParams.isEnableProxy())) { + proxyConfig = new ProxyConfig( + dingTalkParams.getHostname(), + dingTalkParams.getPort(), + dingTalkParams.getUser(), + dingTalkParams.getPassword()); } } @@ -81,11 +73,9 @@ public Map buildTemplateParams(String title, String content) { Map params = new HashMap<>(); params.put(DingTalkConstants.ALERT_TEMPLATE_TITLE, title); params.put(DingTalkConstants.ALERT_TEMPLATE_CONTENT, content); - params.put(DingTalkConstants.ALERT_TEMPLATE_KEYWORD, keyword); - String[] atMobile = Asserts.isNullString(atMobiles) ? new String[] {} : atMobiles.split(","); - params.put(DingTalkConstants.ALERT_TEMPLATE_AT_MOBILE, atMobile); - params.put(DingTalkConstants.ALERT_TEMPLATE_AT_MOBILES, atMobiles); - params.put(DingTalkConstants.ALERT_TEMPLATE_AT_ALL, atAll.toString()); + params.put(DingTalkConstants.ALERT_TEMPLATE_KEYWORD, dingTalkParams.getKeyword()); + params.put(DingTalkConstants.ALERT_TEMPLATE_AT_MOBILES, dingTalkParams.getAtMobiles()); + params.put(DingTalkConstants.ALERT_TEMPLATE_AT_ALL, dingTalkParams.isAtAll()); return params; } @@ -98,10 +88,12 @@ public Map buildTemplateParams(String title, String content) { public AlertResult send(String content) { AlertResult alertResult; try { - String httpUrl = Asserts.isNotNullString(secret) ? generateSignedUrl() : url; + String httpUrl = Asserts.isNotNullString(dingTalkParams.getSecret()) + ? generateSignedUrl() + : dingTalkParams.getWebhook(); return checkMsgResult(HttpUtils.post(httpUrl, content, proxyConfig)); } catch (Exception e) { - logger.info("send ding talk alert msg exception : {}", e.getMessage()); + logger.error("send ding talk alert msg exception : {}", e.getMessage()); alertResult = new AlertResult(); alertResult.setSuccess(false); alertResult.setMessage("send ding talk alert fail."); @@ -116,17 +108,17 @@ public AlertResult send(String content) { */ private String generateSignedUrl() { Long timestamp = System.currentTimeMillis(); - String stringToSign = timestamp + DingTalkConstants.ENTER_LINE + secret; + String stringToSign = timestamp + DingTalkConstants.ENTER_LINE + dingTalkParams.getSecret(); String sign = ""; try { Mac mac = Mac.getInstance("HmacSHA256"); - mac.init(new SecretKeySpec(secret.getBytes(DingTalkConstants.CHARSET), "HmacSHA256")); + mac.init(new SecretKeySpec(dingTalkParams.getSecret().getBytes(DingTalkConstants.CHARSET), "HmacSHA256")); byte[] signData = mac.doFinal(stringToSign.getBytes(DingTalkConstants.CHARSET)); sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), DingTalkConstants.CHARSET); } catch (Exception e) { logger.error("generate sign error, message:{}", e.getMessage()); } - return url + "×tamp=" + timestamp + "&sign=" + sign; + return dingTalkParams.getWebhook() + "×tamp=" + timestamp + "&sign=" + sign; } /** diff --git a/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/params/DingTalkParams.java b/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/params/DingTalkParams.java new file mode 100644 index 0000000000..610321e330 --- /dev/null +++ b/dinky-alert/dinky-alert-dingtalk/src/main/java/org/dinky/alert/dingtalk/params/DingTalkParams.java @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.dinky.alert.dingtalk.params; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor(onConstructor = @__(@JsonCreator)) +public class DingTalkParams { + + private String webhook = ""; + private String keyword = ""; + private String secret = ""; + private List atMobiles = new ArrayList<>(); + private boolean isAtAll = false; + private boolean isEnableProxy = false; + private String hostname = ""; + private int port; + private String user = ""; + private String password = ""; +} diff --git a/dinky-alert/dinky-alert-dingtalk/src/main/resources/DingTalk.ftl b/dinky-alert/dinky-alert-dingtalk/src/main/resources/DingTalk.ftl index e2afd060ad..22d7b85b92 100644 --- a/dinky-alert/dinky-alert-dingtalk/src/main/resources/DingTalk.ftl +++ b/dinky-alert/dinky-alert-dingtalk/src/main/resources/DingTalk.ftl @@ -1,13 +1,17 @@ { "msgtype": "markdown", "markdown": { - "title": "${keyword?json_string}${title}<#list atMobile as key> @${key} ", + "title": "${keyword?json_string}${title}<#list atMobiles as key> @${key} ", "text": "### Dinky Alert:${title}\n> Your task there is an abnormality, Please troubleshoot\n\n${content?json_string}\n ---\n[Dinky Team](https://github.com/DataLinkDC/dinky)" }, "at": { <#if atMobiles??> - "atMobiles": [${atMobiles}], + "atMobiles": [ + <#list atMobiles as key> + "${key}"<#if key_has_next>, + + ], - "isAtAll": ${atAll}, + "isAtAll": ${isAtAll?c}, } } \ No newline at end of file diff --git a/dinky-alert/dinky-alert-dingtalk/src/test/java/org/dinky/alert/dingtalk/DingTalkTest.java b/dinky-alert/dinky-alert-dingtalk/src/test/java/org/dinky/alert/dingtalk/DingTalkTest.java index e1affc106b..a306e285b5 100644 --- a/dinky-alert/dinky-alert-dingtalk/src/test/java/org/dinky/alert/dingtalk/DingTalkTest.java +++ b/dinky-alert/dinky-alert-dingtalk/src/test/java/org/dinky/alert/dingtalk/DingTalkTest.java @@ -20,6 +20,7 @@ package org.dinky.alert.dingtalk; import org.dinky.alert.Alert; +import org.dinky.alert.AlertBaseConstant; import org.dinky.alert.AlertConfig; import org.dinky.alert.AlertResult; import org.dinky.alert.ShowType; @@ -40,18 +41,7 @@ @Ignore public class DingTalkTest { - private static final Map config = new HashMap<>(); - - String msg = - "> The Dinky platform has detected an abnormality in your task. Please go to the Dinky Task page to check the task status.\n" - + "- **Job Name : Test Job**\n" - + "- **Job Status : FAILED**\n" - + "- **Alert Time : 2023-01-01 12:00:00**\n" - + "- **Start Time : 2023-01-01 12:00:00**\n" - + "- **End Time : 2023-01-01 12:00:00**\n" - + "> **The test exception, your job exception will pass here**\n" - + "\n" - + "> Dinky Team [Go toTask Web](https://github.com/DataLinkDC/dinky)"; + private static final Map config = new HashMap<>(); @Before public void initDingTalkConfig() { @@ -59,13 +49,13 @@ public void initDingTalkConfig() { config.put(DingTalkConstants.KEYWORD, "Dinky"); config.put(DingTalkConstants.WEB_HOOK, "https://oapi.dingtalk.com/robot/send?access_token=key"); config.put(DingTalkConstants.MSG_TYPE, ShowType.MARKDOWN.getValue()); - config.put(DingTalkConstants.AT_ALL, "false"); + config.put(DingTalkConstants.AT_ALL, false); config.put(DingTalkConstants.AT_MOBILES, ""); // config.put(DingTalkConstants.SECRET, ""); - config.put(DingTalkConstants.PROXY_ENABLE, "false"); + config.put(DingTalkConstants.PROXY_ENABLE, false); config.put(DingTalkConstants.PASSWORD, "password"); - config.put(DingTalkConstants.PORT, "9988"); + config.put(DingTalkConstants.PORT, 9988); config.put(DingTalkConstants.USER, "user1,user2"); } @@ -74,7 +64,7 @@ public void initDingTalkConfig() { public void sendMarkDownMsgTest() { AlertConfig config = AlertConfig.build("MarkDownTest", "DingTalk", DingTalkTest.config); Alert alert = Alert.build(config); - AlertResult result = alert.send("Dinky", msg); + AlertResult result = alert.send(AlertBaseConstant.ALERT_TEMPLATE_TITLE, AlertBaseConstant.ALERT_TEMPLATE_MSG); Assert.assertEquals(true, result.getSuccess()); } } diff --git a/dinky-alert/dinky-alert-email/pom.xml b/dinky-alert/dinky-alert-email/pom.xml index d99abfb390..9062d1f647 100644 --- a/dinky-alert/dinky-alert-email/pom.xml +++ b/dinky-alert/dinky-alert-email/pom.xml @@ -44,13 +44,14 @@ org.apache.commons commons-email - - junit - junit - org.commonmark commonmark + + junit + junit + test + diff --git a/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/EmailConstants.java b/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/EmailConstants.java index 4437dc3533..0fe6c44dc3 100644 --- a/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/EmailConstants.java +++ b/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/EmailConstants.java @@ -28,31 +28,35 @@ public class EmailConstants extends AlertBaseConstant { /** Email base constant */ public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERS = "receiver.name"; + public static final String NAME_MAIL_SMTP_PORT = "serverPort"; + public static final String NAME_MAIL_SENDER = "sender"; + public static final String NAME_MAIL_USER = "user"; + public static final String NAME_MAIL_PASSWD = "password"; + public static final String NAME_MAIL_SMTP_STARTTLS_ENABLE = "starttlsEnable"; + public static final String NAME_MAIL_SMTP_SSL_ENABLE = "sslEnable"; + public static final String NAME_MAIL_SMTP_SSL_TRUST = "smtpSslTrust"; + public static final String NAME_MAIL_SMTP_HOST = "serverHost"; + public static final String NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS = "receivers"; - public static final String PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "receiverCcs"; public static final String NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS = "receiverCcs"; + + /** Email base constant */ public static final String NAME_MAIL_PROTOCOL = "mail.protocol"; + public static final String MAIL_SMTP_HOST = "mail.smtp.host"; - public static final String NAME_MAIL_SMTP_HOST = "serverHost"; public static final String MAIL_SMTP_PORT = "mail.smtp.port"; - public static final String NAME_MAIL_SMTP_PORT = "serverPort"; public static final String MAIL_SENDER = "sender.name"; - public static final String NAME_MAIL_SENDER = "sender"; public static final String MAIL_SMTP_AUTH = "mail.smtp.auth"; public static final String NAME_MAIL_SMTP_AUTH = "enableSmtpAuth"; public static final String MAIL_USER = "mail.smtp.user"; - public static final String NAME_MAIL_USER = "User"; public static final String MAIL_PASSWD = "mail.smtp.passwd"; - public static final String NAME_MAIL_PASSWD = "Password"; + public static final String MAIL_SMTP_STARTTLS_ENABLE = "mail.smtp.starttls.enable"; - public static final String NAME_MAIL_SMTP_STARTTLS_ENABLE = "starttlsEnable"; + public static final String MAIL_SMTP_SSL_ENABLE = "mail.smtp.ssl.enable"; - public static final String NAME_MAIL_SMTP_SSL_ENABLE = "sslEnable"; + public static final String MAIL_SMTP_SSL_TRUST = "mail.smtp.ssl.trust"; - public static final String NAME_MAIL_SMTP_SSL_TRUST = "smtpSslTrust"; - public static final String XLS_FILE_PATH = "xls.file.path"; public static final String MAIL_TRANSPORT_PROTOCOL = "mail.transport.protocol"; - public static final String XLS_FILE_DEFAULT_PATH = "/tmp/xls"; public static final String ALERT_TEMPLATE_TITLE = "title"; public static final String ALERT_TEMPLATE_CONTENT = "content"; } diff --git a/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/EmailSender.java b/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/EmailSender.java index 8668d4356f..88bcaa9a77 100644 --- a/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/EmailSender.java +++ b/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/EmailSender.java @@ -23,14 +23,12 @@ import org.dinky.alert.AlertException; import org.dinky.alert.AlertResult; +import org.dinky.alert.email.params.EmailParams; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.mail.HtmlEmail; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import java.util.Map; import java.util.Properties; @@ -43,77 +41,37 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.sun.mail.smtp.SMTPProvider; +import com.sun.mail.smtp.SMTPSSLProvider; -/** EmailSender 邮件发送器 */ +import cn.hutool.core.collection.CollUtil; +import cn.hutool.json.JSONUtil; + +/** + * EmailSender 邮件发送器 + */ public final class EmailSender { private static final Logger logger = LoggerFactory.getLogger(EmailSender.class); + private final EmailParams emailParams; - private final List receivers; - private final List receiverCcs; - private final String mailProtocol = "SMTP"; - private final String mailSmtpHost; - private final String mailSmtpPort; - private final String mailSenderNickName; - private final String enableSmtpAuth; - private final String mailUser; - private final String mailPasswd; - private final String mailUseStartTLS; - private final String mailUseSSL; - private final String sslTrust; - // private final String showType; - private final String mustNotNull = " must not be null"; - private String xlsFilePath; - - public EmailSender(Map config) { - String receiversConfig = config.get(EmailConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS); - if (receiversConfig == null || "".equals(receiversConfig)) { - throw new AlertException(EmailConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS + mustNotNull); - } - - receivers = Arrays.asList(receiversConfig.split(",")); - - String receiverCcsConfig = config.get(EmailConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS); - - receiverCcs = new ArrayList<>(); - if (receiverCcsConfig != null && !"".equals(receiverCcsConfig)) { - receiverCcs.addAll(Arrays.asList(receiverCcsConfig.split(","))); - } - - mailSmtpHost = config.get(EmailConstants.NAME_MAIL_SMTP_HOST); - requireNonNull(mailSmtpHost, EmailConstants.NAME_MAIL_SMTP_HOST + mustNotNull); - - mailSmtpPort = config.get(EmailConstants.NAME_MAIL_SMTP_PORT); - requireNonNull(mailSmtpPort, EmailConstants.NAME_MAIL_SMTP_PORT + mustNotNull); - - mailSenderNickName = config.get(EmailConstants.NAME_MAIL_SENDER); - requireNonNull(mailSenderNickName, EmailConstants.NAME_MAIL_SENDER + mustNotNull); - - enableSmtpAuth = config.get(EmailConstants.NAME_MAIL_SMTP_AUTH); - - mailUser = config.get(EmailConstants.NAME_MAIL_USER); - requireNonNull(mailUser, EmailConstants.NAME_MAIL_USER + mustNotNull); - - mailPasswd = config.get(EmailConstants.NAME_MAIL_PASSWD); - requireNonNull(mailPasswd, EmailConstants.NAME_MAIL_PASSWD + mustNotNull); - - mailUseStartTLS = config.get(EmailConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE); - - mailUseSSL = config.get(EmailConstants.NAME_MAIL_SMTP_SSL_ENABLE); - - sslTrust = config.get(EmailConstants.NAME_MAIL_SMTP_SSL_TRUST); - - xlsFilePath = config.get(EmailConstants.XLS_FILE_PATH); - if (StringUtils.isBlank(xlsFilePath)) { - xlsFilePath = EmailConstants.XLS_FILE_DEFAULT_PATH; + public EmailSender(Map config) { + this.emailParams = JSONUtil.toBean(JSONUtil.toJsonStr(config), EmailParams.class); + if (CollUtil.isEmpty(emailParams.getReceivers())) { + throw new AlertException("receivers is empty, please check config"); } + String mustNotNull = " must not be null"; + requireNonNull(emailParams.getServerHost(), EmailConstants.NAME_MAIL_SMTP_HOST + mustNotNull); + requireNonNull(emailParams.getServerPort(), EmailConstants.NAME_MAIL_SMTP_PORT + mustNotNull); + requireNonNull(emailParams.getReceivers(), EmailConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS + mustNotNull); + requireNonNull(emailParams.getSender(), EmailConstants.NAME_MAIL_SENDER + mustNotNull); + requireNonNull(emailParams.getUser(), EmailConstants.NAME_MAIL_USER + mustNotNull); + requireNonNull(emailParams.getPassword(), EmailConstants.NAME_MAIL_PASSWD + mustNotNull); } /** * send mail * - * @param title title + * @param title title * @param content content */ public AlertResult send(String title, String content) { @@ -121,39 +79,49 @@ public AlertResult send(String title, String content) { alertResult.setSuccess(false); // if there is no receivers && no receiversCc, no need to process - if (CollectionUtils.isEmpty(receivers) && CollectionUtils.isEmpty(receiverCcs)) { + if (CollectionUtils.isEmpty(emailParams.getReceivers()) + && CollectionUtils.isEmpty(emailParams.getReceiverCcs())) { logger.error("no receivers && no receiversCc"); return alertResult; } - receivers.removeIf(StringUtils::isEmpty); Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); HtmlEmail email = new HtmlEmail(); try { Session session = getSession(); + email.setHostName(emailParams.getServerHost()); + email.setSmtpPort(emailParams.getServerPort()); + email.setSSLOnConnect(emailParams.isSslEnable()); + email.setSslSmtpPort(String.valueOf(emailParams.getServerPort())); + email.setStartTLSEnabled(emailParams.isStarttlsEnable()); + email.setSSLCheckServerIdentity(emailParams.isSslEnable()); + if (emailParams.isEnableSmtpAuth()) { + email.setAuthentication(emailParams.getUser(), emailParams.getPassword()); + } email.setMailSession(session); - email.setFrom(mailUser, mailSenderNickName); + email.setFrom(emailParams.getUser(), emailParams.getSender()); email.setCharset(EmailConstants.CHARSET); email.setSubject(title); email.setMsg(content); email.setDebug(true); - if (CollectionUtils.isNotEmpty(receivers)) { + if (CollectionUtils.isNotEmpty(emailParams.getReceivers())) { // receivers mail - for (String receiver : receivers) { + for (String receiver : emailParams.getReceivers()) { email.addTo(receiver); } } - if (CollectionUtils.isNotEmpty(receiverCcs)) { + if (CollectionUtils.isNotEmpty(emailParams.getReceiverCcs())) { // cc - for (String receiverCc : receiverCcs) { + for (String receiverCc : emailParams.getReceiverCcs()) { email.addCc(receiverCc); } } // sender mail - email.send(); + String sendResult = email.send(); + logger.info("Send email info: {}", sendResult); alertResult.setSuccess(true); return alertResult; } catch (Exception e) { @@ -178,26 +146,21 @@ private Session getSession() { CommandMap.setDefaultCommandMap(mc); Properties props = new Properties(); - props.setProperty(EmailConstants.MAIL_SMTP_HOST, mailSmtpHost); - props.setProperty(EmailConstants.MAIL_SMTP_PORT, mailSmtpPort); - - if (StringUtils.isNotEmpty(enableSmtpAuth)) { - props.setProperty(EmailConstants.MAIL_SMTP_AUTH, enableSmtpAuth); - } - if (StringUtils.isNotEmpty(mailProtocol)) { - props.setProperty(EmailConstants.MAIL_TRANSPORT_PROTOCOL, mailProtocol); + props.put(EmailConstants.NAME_MAIL_PROTOCOL, "smtp"); + props.setProperty(EmailConstants.MAIL_SMTP_HOST, emailParams.getServerHost()); + props.setProperty(EmailConstants.MAIL_SMTP_PORT, String.valueOf(emailParams.getServerPort())); + props.setProperty(EmailConstants.MAIL_SMTP_AUTH, String.valueOf(emailParams.isEnableSmtpAuth())); + if (StringUtils.isNotEmpty(emailParams.getMailProtocol())) { + props.setProperty(EmailConstants.MAIL_TRANSPORT_PROTOCOL, emailParams.getMailProtocol()); } - - if (StringUtils.isNotEmpty(mailUseSSL)) { - props.setProperty(EmailConstants.MAIL_SMTP_SSL_ENABLE, mailUseSSL); - } - - if (StringUtils.isNotEmpty(mailUseStartTLS)) { - props.setProperty(EmailConstants.MAIL_SMTP_STARTTLS_ENABLE, mailUseStartTLS); - } - - if (StringUtils.isNotEmpty(sslTrust)) { - props.setProperty(EmailConstants.MAIL_SMTP_SSL_TRUST, sslTrust); + props.setProperty(EmailConstants.MAIL_SMTP_SSL_ENABLE, String.valueOf(emailParams.isSslEnable())); + props.setProperty(EmailConstants.MAIL_SMTP_STARTTLS_ENABLE, String.valueOf(emailParams.isStarttlsEnable())); + props.setProperty(EmailConstants.MAIL_SENDER, emailParams.getSender()); + props.setProperty(EmailConstants.MAIL_USER, emailParams.getUser()); + props.setProperty(EmailConstants.MAIL_PASSWD, emailParams.getPassword()); + + if (StringUtils.isNotEmpty(emailParams.getSmtpSslTrust())) { + props.setProperty(EmailConstants.MAIL_SMTP_SSL_TRUST, emailParams.getSmtpSslTrust()); } Authenticator auth = new Authenticator() { @@ -205,18 +168,21 @@ private Session getSession() { @Override protected PasswordAuthentication getPasswordAuthentication() { // mail username and password - return new PasswordAuthentication(mailUser, mailPasswd); + return new PasswordAuthentication(emailParams.getUser(), emailParams.getPassword()); } }; Session session = Session.getInstance(props, auth); - session.addProvider(new SMTPProvider()); + session.addProvider(new SMTPSSLProvider()); return session; } - /** handle exception */ + /** + * handle exception + */ private void handleException(AlertResult alertResult, Exception e) { - logger.error("Send email to {} failed", receivers, e); - alertResult.setMessage("Send email to {" + String.join(",", receivers) + "} failed," + e.toString()); + logger.error("Send email to {} failed", emailParams.getReceivers(), e); + alertResult.setMessage( + "Send email to {" + String.join(",", emailParams.getReceivers()) + "} failed," + e.toString()); } } diff --git a/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/params/EmailParams.java b/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/params/EmailParams.java new file mode 100644 index 0000000000..589eacb715 --- /dev/null +++ b/dinky-alert/dinky-alert-email/src/main/java/org/dinky/alert/email/params/EmailParams.java @@ -0,0 +1,48 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.dinky.alert.email.params; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor(onConstructor = @__(@JsonCreator)) +public class EmailParams { + + private List receivers = new ArrayList<>(); + private List receiverCcs = new ArrayList<>(); + private String mailProtocol = "SMTP"; + private String serverHost; + private int serverPort; + private String sender; + private boolean enableSmtpAuth; + private boolean starttlsEnable; + private boolean sslEnable; + private String user; + private String password; + private String smtpSslTrust; +} diff --git a/dinky-alert/dinky-alert-email/src/test/java/org/dinky/alert/email/EmailSenderTest.java b/dinky-alert/dinky-alert-email/src/test/java/org/dinky/alert/email/EmailSenderTest.java index ab5004c476..17085ab597 100644 --- a/dinky-alert/dinky-alert-email/src/test/java/org/dinky/alert/email/EmailSenderTest.java +++ b/dinky-alert/dinky-alert-email/src/test/java/org/dinky/alert/email/EmailSenderTest.java @@ -19,9 +19,10 @@ package org.dinky.alert.email; +import org.dinky.alert.AlertBaseConstant; import org.dinky.alert.AlertResult; -import org.dinky.alert.ShowType; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -34,34 +35,32 @@ public class EmailSenderTest { static EmailSender emailSender; - private static final Map emailConfig = new HashMap<>(); - - String title = "Dinky Email Alert"; + private static final Map emailConfig = new HashMap<>(); @Before public void initEmailConfig() { - emailConfig.put(EmailConstants.NAME_MAIL_PROTOCOL, "smtp"); - emailConfig.put(EmailConstants.NAME_MAIL_SMTP_HOST, "alertMsg"); + // emailConfig.put(EmailConstants.NAME_MAIL_PROTOCOL, "smtp"); + emailConfig.put(EmailConstants.NAME_MAIL_SMTP_HOST, "smtp.163.com"); emailConfig.put(EmailConstants.NAME_MAIL_SMTP_PORT, "465"); - emailConfig.put(EmailConstants.NAME_MAIL_SENDER, "xxx"); - emailConfig.put(EmailConstants.NAME_MAIL_USER, "xxxx@163.com"); - emailConfig.put(EmailConstants.NAME_MAIL_PASSWD, "xxxxx"); + emailConfig.put(EmailConstants.NAME_MAIL_SENDER, "zzz"); + emailConfig.put(EmailConstants.NAME_MAIL_USER, "11111111@163.com"); + emailConfig.put(EmailConstants.NAME_MAIL_PASSWD, "1111111111"); emailConfig.put(EmailConstants.NAME_MAIL_SMTP_AUTH, "true"); - emailConfig.put(EmailConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, "false"); - emailConfig.put(EmailConstants.NAME_MAIL_SMTP_SSL_ENABLE, "false"); - emailConfig.put(EmailConstants.NAME_MAIL_SMTP_SSL_TRUST, "smtp.mxhichina.com"); - emailConfig.put(EmailConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, "xxxxx@126.com"); - emailConfig.put(EmailConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, "user3@qq.com"); - emailConfig.put(EmailConstants.MSG_TYPE, ShowType.TEXT.getValue()); + emailConfig.put(EmailConstants.NAME_MAIL_SMTP_STARTTLS_ENABLE, "true"); + emailConfig.put(EmailConstants.NAME_MAIL_SMTP_SSL_ENABLE, "true"); + emailConfig.put(EmailConstants.NAME_MAIL_SMTP_SSL_TRUST, "*"); + emailConfig.put(EmailConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERS, Arrays.asList("111111111@qq.com")); + emailConfig.put(EmailConstants.NAME_PLUGIN_DEFAULT_EMAIL_RECEIVERCCS, Arrays.asList("111111111111@163.com")); + // emailConfig.put(EmailConstants.MSG_TYPE, ShowType.TEXT.getValue()); emailSender = new EmailSender(emailConfig); } @Ignore @Test public void testTextSendMails() { - String alertMsg = "{}"; - AlertResult alertResult = emailSender.send(title, alertMsg); + AlertResult alertResult = + emailSender.send(AlertBaseConstant.ALERT_TEMPLATE_TITLE, AlertBaseConstant.ALERT_TEMPLATE_MSG); Assert.assertEquals(true, alertResult.getSuccess()); // 格式需要调整 } } diff --git a/dinky-alert/dinky-alert-feishu/src/main/java/org/dinky/alert/feishu/FeiShuSender.java b/dinky-alert/dinky-alert-feishu/src/main/java/org/dinky/alert/feishu/FeiShuSender.java index db50a95f72..7995d3cbb7 100644 --- a/dinky-alert/dinky-alert-feishu/src/main/java/org/dinky/alert/feishu/FeiShuSender.java +++ b/dinky-alert/dinky-alert-feishu/src/main/java/org/dinky/alert/feishu/FeiShuSender.java @@ -20,6 +20,7 @@ package org.dinky.alert.feishu; import org.dinky.alert.AlertResult; +import org.dinky.alert.feishu.params.FeiShuParams; import org.dinky.assertion.Asserts; import org.dinky.data.model.ProxyConfig; import org.dinky.utils.HttpUtils; @@ -27,7 +28,9 @@ import org.apache.commons.codec.binary.Base64; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -36,39 +39,31 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.CollectionUtils; import com.fasterxml.jackson.annotation.JsonProperty; +import cn.hutool.json.JSONUtil; + /** * fei shu sender */ public final class FeiShuSender { private static final Logger logger = LoggerFactory.getLogger(FeiShuSender.class); - private final String url; - private final String secret; - private final String keyword; - private String atUserIds; + private final FeiShuParams feiShuParams; private ProxyConfig proxyConfig = null; - FeiShuSender(Map config) { - url = config.get(FeiShuConstants.WEB_HOOK); - - keyword = config.getOrDefault(FeiShuConstants.KEYWORD, "").replace("\r\n", ""); - secret = config.get(FeiShuConstants.SECRET); + FeiShuSender(Map config) { - Boolean enableProxy = Boolean.valueOf(config.get(FeiShuConstants.PROXY_ENABLE)); - if (Boolean.TRUE.equals(enableProxy)) { - String proxy = config.get(FeiShuConstants.PROXY); - Integer port = Integer.parseInt(config.get(FeiShuConstants.PORT)); - String user = config.get(FeiShuConstants.USER); - String password = config.get(FeiShuConstants.PASSWORD); - proxyConfig = new ProxyConfig(proxy, port, user, password); - } + this.feiShuParams = JSONUtil.toBean(JSONUtil.toJsonStr(config), FeiShuParams.class); - Boolean atAll = Boolean.valueOf(config.get(FeiShuConstants.AT_ALL)); - if (Boolean.FALSE.equals(atAll)) { - atUserIds = config.get(FeiShuConstants.AT_USERS); + if (Boolean.TRUE.equals(feiShuParams.isEnableProxy())) { + proxyConfig = new ProxyConfig( + feiShuParams.getHostname(), + feiShuParams.getPort(), + feiShuParams.getUser(), + feiShuParams.getPassword()); } } @@ -83,13 +78,14 @@ public Map buildTemplateParams(String title, String content) { Map params = new HashMap<>(); params.put(FeiShuConstants.ALERT_TEMPLATE_TITLE, title); params.put(FeiShuConstants.ALERT_TEMPLATE_CONTENT, content); - params.put(FeiShuConstants.ALERT_TEMPLATE_KEYWORD, keyword); - if (Asserts.isNotNullString(secret)) { - Integer currentTimeMillis = Math.toIntExact(System.currentTimeMillis() / 1000); + params.put(FeiShuConstants.ALERT_TEMPLATE_KEYWORD, feiShuParams.getKeyword()); + if (Asserts.isNotNullString(feiShuParams.getSecret())) { + Integer currentTimeMillis = Math.toIntExact(System.currentTimeMillis() / 1000) - 1800; params.put(FeiShuConstants.SIGN_TMESTAMP, currentTimeMillis); - params.put(FeiShuConstants.SIGN, getSign(secret, currentTimeMillis)); + params.put(FeiShuConstants.SIGN, getSign(feiShuParams.getSecret(), currentTimeMillis)); } - String[] atUsers = Asserts.isNullString(atUserIds) ? new String[] {"all"} : atUserIds.split(","); + List atUsers = + CollectionUtils.isEmpty(feiShuParams.getAtUsers()) ? Arrays.asList("all") : feiShuParams.getAtUsers(); params.put(FeiShuConstants.ALERT_TEMPLATE_AT_USERS, atUsers); return params; } @@ -102,10 +98,10 @@ public Map buildTemplateParams(String title, String content) { */ public AlertResult send(String content) { try { - return checkSendMsgResult(HttpUtils.post(url, content, proxyConfig)); + return checkSendMsgResult(HttpUtils.post(feiShuParams.getWebhook(), content, proxyConfig)); } catch (Exception e) { e.printStackTrace(); - logger.error("send fei shu alert msg exception : {}", e.getMessage()); + logger.error("send fei shu alert msg exception : {}", e.getMessage(), e); AlertResult alertResult = new AlertResult(); alertResult.setSuccess(false); alertResult.setMessage("send fei shu alert fail."); @@ -121,6 +117,9 @@ public AlertResult send(String content) { * @return */ private String getSign(String secretKey, Integer timestamp) { + if (Math.abs(System.currentTimeMillis() / 1000 - timestamp) > 3600) { + throw new IllegalArgumentException("timestamp is invalid, must be within 1 hour of current time"); + } String stringToSign = timestamp + FeiShuConstants.ENTER_LINE + secretKey; String sign = ""; try { @@ -146,26 +145,23 @@ public static AlertResult checkSendMsgResult(String result) { if (Asserts.isNull(result)) { alertResult.setMessage("send fei shu msg error"); - logger.info("send fei shu msg error,fei shu server resp is null"); + logger.error("send fei shu msg error,fei shu server resp is null"); return alertResult; } FeiShuSendMsgResponse sendMsgResponse = JsonUtils.parseObject(result, FeiShuSendMsgResponse.class); if (null == sendMsgResponse) { alertResult.setMessage("send fei shu msg fail"); - logger.info("send fei shu msg error,resp error"); + logger.error("send fei shu msg error,resp error"); return alertResult; } - if (sendMsgResponse.code == 0) { - alertResult.setSuccess(true); - alertResult.setMessage("send fei shu msg success"); + if (sendMsgResponse.code != 0) { + alertResult.setMessage("send fei shu msg fail" + sendMsgResponse.getStatusMessage()); + logger.error("send fei shu msg error,resp error : {} ", sendMsgResponse.getStatusMessage()); return alertResult; } - alertResult.setMessage(String.format("alert send fei shu msg error : %s", sendMsgResponse.getStatusMessage())); - logger.info( - "alert send fei shu msg error : {} ,Extra : {} ", - sendMsgResponse.getStatusMessage(), - sendMsgResponse.getExtra()); + alertResult.setSuccess(true); + alertResult.setMessage("send fei shu msg success" + sendMsgResponse.getStatusMessage()); return alertResult; } diff --git a/dinky-alert/dinky-alert-feishu/src/main/java/org/dinky/alert/feishu/params/FeiShuParams.java b/dinky-alert/dinky-alert-feishu/src/main/java/org/dinky/alert/feishu/params/FeiShuParams.java new file mode 100644 index 0000000000..23f0ef91ee --- /dev/null +++ b/dinky-alert/dinky-alert-feishu/src/main/java/org/dinky/alert/feishu/params/FeiShuParams.java @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.dinky.alert.feishu.params; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor(onConstructor = @__(@JsonCreator)) +@AllArgsConstructor +public class FeiShuParams { + + private String webhook; + private boolean isEnableProxy; + private boolean isAtAll; + private String secret; + private List atUsers = new ArrayList<>(); + private String keyword = ""; + private String hostname = ""; + private int port; + private String user = ""; + private String password = ""; +} diff --git a/dinky-alert/dinky-alert-feishu/src/test/java/org/dinky/alert/feishu/FeiShuSenderTest.java b/dinky-alert/dinky-alert-feishu/src/test/java/org/dinky/alert/feishu/FeiShuSenderTest.java index 44145e6dd6..baff02e2cf 100644 --- a/dinky-alert/dinky-alert-feishu/src/test/java/org/dinky/alert/feishu/FeiShuSenderTest.java +++ b/dinky-alert/dinky-alert-feishu/src/test/java/org/dinky/alert/feishu/FeiShuSenderTest.java @@ -19,6 +19,7 @@ package org.dinky.alert.feishu; +import org.dinky.alert.AlertBaseConstant; import org.dinky.alert.AlertConfig; import org.dinky.alert.AlertResult; @@ -34,7 +35,7 @@ @Ignore public class FeiShuSenderTest { - private static Map feiShuConfig = new HashMap<>(); + private static Map feiShuConfig = new HashMap<>(); @Before public void initFeiShuConfig() { @@ -48,17 +49,6 @@ public void initFeiShuConfig() { @Test public void testSend() { - String msg = - "> The Dinky platform has detected an abnormality in your task. Please go to the Dinky Task page to check the task status.\n" - + "- **Job Name : Test Job**\n" - + "- **Job Status : FAILED**\n" - + "- **Alert Time : 2023-01-01 12:00:00**\n" - + "- **Start Time : 2023-01-01 12:00:00**\n" - + "- **End Time : 2023-01-01 12:00:00**\n" - + "> **The test exception, your job exception will pass here**\n" - + "\n" - + "> Dinky Team [Go toTask Web](https://github.com/DataLinkDC/dinky)"; - FeiShuAlert feiShuAlert = new FeiShuAlert(); AlertConfig alertConfig = new AlertConfig(); @@ -66,7 +56,8 @@ public void testSend() { alertConfig.setParam(feiShuConfig); feiShuAlert.setConfig(alertConfig); - AlertResult alertResult = feiShuAlert.send("FeiShu Alert", msg); + AlertResult alertResult = + feiShuAlert.send(AlertBaseConstant.ALERT_TEMPLATE_TITLE, AlertBaseConstant.ALERT_TEMPLATE_MSG); Assert.assertEquals(true, alertResult.getSuccess()); } } diff --git a/dinky-alert/dinky-alert-sms/pom.xml b/dinky-alert/dinky-alert-sms/pom.xml index 554e5b9598..c0a004f698 100644 --- a/dinky-alert/dinky-alert-sms/pom.xml +++ b/dinky-alert/dinky-alert-sms/pom.xml @@ -36,11 +36,16 @@ org.dromara.sms4j sms4j-spring-boot-starter - 2.1.0 + 3.0.1 - org.projectlombok - lombok + junit + junit + test + + + org.commonmark + commonmark diff --git a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsAlert.java b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsAlert.java index 9d34ddf4d6..29437c5af4 100644 --- a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsAlert.java +++ b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsAlert.java @@ -20,12 +20,26 @@ package org.dinky.alert.sms; import org.dinky.alert.AbstractAlert; +import org.dinky.alert.AlertException; import org.dinky.alert.AlertResult; -import cn.hutool.json.JSONUtil; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; -/** SmsAlert */ +import org.commonmark.node.Node; +import org.commonmark.parser.Parser; +import org.commonmark.renderer.text.TextContentRenderer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import freemarker.template.TemplateException; + +/** + * SmsAlert + */ public class SmsAlert extends AbstractAlert { + private static final Logger logger = LoggerFactory.getLogger(SmsAlert.class); @Override public String getType() { @@ -34,7 +48,70 @@ public String getType() { @Override public AlertResult send(String title, String content) { - SmsSender sender = new SmsSender(JSONUtil.toJsonStr(getConfig().getParam())); - return sender.send(title, content); + SmsSender sender = new SmsSender(getConfig().getParam()); + try { + Map params = new HashMap<>(); + params.put(SmsConstants.ALERT_TEMPLATE_TITLE, title); + params.put(SmsConstants.ALERT_TEMPLATE_CONTENT, removeHTMLTagsAndUrls(markdownToText(content))); + String built = buildContent(params); + return sender.send(built); + } catch (TemplateException | IOException e) { + logger.error("{}'message send error, Reason:{}", getType(), e.getMessage()); + throw new AlertException(e.getMessage(), e); + } + } + + /** + * remove line from a string by line number + * + * @param inputString input string with line breaks (new lines) + * @param headerLineNumber number of lines to remove from the beginning of the string + * @param keepLineNumber number of lines to keep from the beginning of the string + * @return string with lines removed + */ + public static String removeLine(String inputString, int headerLineNumber, int keepLineNumber) { + String[] lines = inputString.split("\\r?\\n"); + if (keepLineNumber >= lines.length) { + return inputString; + } + if (headerLineNumber >= keepLineNumber) { + throw new IllegalArgumentException(String.format( + "headerLineNumber: %s must be less than keepLineNumber: %s", headerLineNumber, keepLineNumber)); + } + StringBuilder sb = new StringBuilder(); + for (int i = headerLineNumber - 1; i < keepLineNumber; i++) { + sb.append(lines[i]); + sb.append(System.lineSeparator()); + } + return sb.toString(); + } + + /** + * remove html tags from a string + * + * @param text html text + * @return text without html tags + */ + public static String removeHTMLTagsAndUrls(String text) { + if (text == null || text.isEmpty()) { + return ""; + } + // remove all html tags and urls + String pattern = "<[^>]+>|\\-\\s+|\\»|\\«|\""; + text = text.replaceAll(pattern, "").replaceAll(": ", ": "); + return removeLine(text, 1, 5); + } + + /** + * Convert markdown to text + * + * @param markdown Markdown text + * @return text without Markdown tags + */ + public static String markdownToText(String markdown) { + Parser parser = Parser.builder().build(); + Node document = parser.parse(markdown); + TextContentRenderer renderer = TextContentRenderer.builder().build(); + return renderer.render(document); } } diff --git a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsConstants.java b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsConstants.java index 4efdca37c9..fc921ad0aa 100644 --- a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsConstants.java +++ b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsConstants.java @@ -22,30 +22,50 @@ /** SmsConstants */ public class SmsConstants { public static final String TYPE = "Sms"; + public static final String SUPPLIERS = "suppliers"; + public static final String ALERT_TEMPLATE_TITLE = "title"; + public static final String ALERT_TEMPLATE_CONTENT = "content"; - public static final String MANU_FACTURERS = "manufacturers"; + // ==================== common config ==================== public static final String ACCESS_KEY_ID = "accessKeyId"; + public static final String SDK_APP_ID = "sdkAppId"; public static final String ACCESS_KEY_SECRET = "accessKeySecret"; - public static final String TEMPLATE_ID = "templateId"; public static final String SIGNATURE = "signature"; - public static final String TEMPLATE_NAME = "templateName"; - public static final String REQUEST_URL = "requestUrl"; + public static final String TEMPLATE_ID = "templateId"; + public static final String WEIGHT = "weight"; + public static final String CONFIG_ID = "configId"; + public static final String RETRY_INTERVAL = "retryInterval"; + public static final String MAX_RETRY = "maxRetries"; + + // =================== aliyun config ==================== + public static final String TEMPLATE_NAME = "templateName"; // EXTEND YUM PIAN + public static final String REQUEST_URL = "requestUrl"; // extend tencent public static final String REGION_ID = "regionId"; - public static final String ACTION = "action"; - public static final String VERSION = "version"; + public static final String ACTION = "action"; // extend tencent + public static final String VERSION = "version"; // extend tencent - public static final String APP_KEY = "appKey"; - public static final String APP_SECRET = "appSecret"; + // =================== huawei config ==================== public static final String SENDER = "sender"; public static final String STATUS_CALLBACK = "statusCallBack"; public static final String URL = "url"; - public static final String SDK_APP_ID = "sdkAppId"; + // =================== yun pian config ==================== + public static final String CALLBACK_URL = "callbackUrl"; + + // =================== tencent config ==================== public static final String TERRITORY = "territory"; public static final String CONN_TIMEOUT = "connTimeout"; - public static final String IS_SIMPLE = "is-simple"; - public static final String REGION = "region"; - public static final String APP_ID = "appId"; + // service + public static final String SERVICE = "service"; + + // =================== uni config ==================== + public static final String IS_SIMPLE = "isSimple"; + + // =================== Cloopen config ==================== public static final String BASE_URL = "baseUrl"; - public static final String SECRET_KEY = "secretKey"; + + // =================== other config ==================== + + public static final String REGION = "region"; + public static final String PHONE_NUMBERS = "phoneNumbers"; } diff --git a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsSender.java b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsSender.java index 119fdef974..48aa8cdc1e 100644 --- a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsSender.java +++ b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/SmsSender.java @@ -19,81 +19,69 @@ package org.dinky.alert.sms; -import static java.util.Objects.requireNonNull; - import org.dinky.alert.AlertResult; import org.dinky.alert.sms.config.SmsConfigLoader; -import org.dinky.alert.sms.enums.ManuFacturers; -import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; import org.dromara.sms4j.api.SmsBlend; -import org.dromara.sms4j.api.universal.SupplierConfig; -import org.dromara.sms4j.provider.base.BaseProviderFactory; -import org.dromara.sms4j.provider.enumerate.SupplierType; +import org.dromara.sms4j.api.entity.SmsResponse; +import org.dromara.sms4j.provider.config.BaseConfig; +import org.dromara.sms4j.provider.factory.BaseProviderFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import cn.hutool.json.JSONUtil; - -/** SmsSender todo: https://wind.kim/doc/start/springboot.html */ +/** + * SmsSender todo: https://wind.kim/doc/start/springboot.html + */ public class SmsSender { private static final Logger logger = LoggerFactory.getLogger(SmsSender.class); - private static SupplierConfig configLoader = null; - private static BaseProviderFactory providerFactory = null; + private final Optional supplierConfigLoader; + private final BaseProviderFactory baseProviderFactory; + private final SmsBlend smsSendFactory; + private final List phoneNumbers; - private static SmsBlend smsSendFactory = null; - - /** manufacturers of sms */ - private Integer manufacturers; + SmsSender(Map config) { + this.supplierConfigLoader = Optional.of(SmsConfigLoader.getConfigSupplierConfig(config)); + this.baseProviderFactory = SmsConfigLoader.getBaseProviderFactory( + supplierConfigLoader.get().getSupplier()); + this.smsSendFactory = baseProviderFactory.createSms(supplierConfigLoader.get()); + this.phoneNumbers = SmsConfigLoader.getPhoneNumberList(config); + } - SmsSender(String config) { - int manufacturersId = Integer.parseInt(JSONUtil.parseObj(config).getStr(SmsConstants.MANU_FACTURERS)); - this.manufacturers = manufacturersId; - requireNonNull(manufacturers, "manufacturers is null"); - configLoader = SmsConfigLoader.getConfigLoader(config, manufacturers); - providerFactory = getSmsTpye(manufacturersId).getProviderFactory(); + public synchronized AlertResult send(String content) { + SmsResponse smsResponse; + if (supplierConfigLoader.isPresent() && supplierConfigLoader.get().getTemplateId() != null) { + String templateId = supplierConfigLoader.get().getTemplateId(); + LinkedHashMap smsParams = new LinkedHashMap<>(); + smsParams.put(SmsConstants.ALERT_TEMPLATE_CONTENT, content); - logger.info("you choose {} manufacturers", ManuFacturers.getManuFacturers(manufacturersId)); + smsResponse = smsSendFactory.massTexting(phoneNumbers, templateId, smsParams); + } else { + throw new RuntimeException("sms templateId is null"); + } + return validateSendResult(smsResponse); } - public synchronized AlertResult send(String title, String content) { - providerFactory.refresh(configLoader); - smsSendFactory = providerFactory.createSms(configLoader); + private AlertResult validateSendResult(SmsResponse smsResponse) { AlertResult alertResult = new AlertResult(); - logger.info("send sms, title: {}, content: {}", title, content); - // todo: 1. support multi sms manufacturers send - // 使用自定义模板群发短信 || use custom template mass texting - smsSendFactory.massTexting(Arrays.asList("17722226666"), "110", new LinkedHashMap<>()); - // todo: 2. validate sms send result - return alertResult; - } - - public static SupplierType getSmsTpye(Integer manufacturersType) { - - switch (manufacturersType) { - case 1: - return SupplierType.ALIBABA; - case 2: - return SupplierType.HUAWEI; - case 3: - return SupplierType.YUNPIAN; - case 4: - return SupplierType.TENCENT; - case 5: - return SupplierType.UNI_SMS; - case 6: - return SupplierType.JD_CLOUD; - case 7: - return SupplierType.CLOOPEN; - case 8: - return SupplierType.EMAY; - case 9: - return SupplierType.CTYUN; - default: - throw new IllegalArgumentException( - "Unsupported manufacturers type: " + ManuFacturers.getManuFacturers(manufacturersType)); + if (smsResponse.isSuccess()) { + logger.info( + "sms send success, phoneNumbers: {}, message: {}", + phoneNumbers, + smsResponse.getData().toString()); + alertResult.setSuccess(true); + alertResult.setMessage("sms send success"); + } else { + String errorMsg = String.format( + "sms send fail, reason: %s", smsResponse.getData().toString()); + alertResult.setSuccess(false); + alertResult.setMessage(errorMsg); + logger.error(errorMsg); } + return alertResult; } } diff --git a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/config/SmsConfigLoader.java b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/config/SmsConfigLoader.java index fda0dec5c0..de6d6cad06 100644 --- a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/config/SmsConfigLoader.java +++ b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/config/SmsConfigLoader.java @@ -19,157 +19,125 @@ package org.dinky.alert.sms.config; +import static java.util.Objects.requireNonNull; + import org.dinky.alert.sms.SmsConstants; -import org.dinky.alert.sms.enums.ManuFacturers; + +import java.util.List; +import java.util.Map; import org.dromara.sms4j.aliyun.config.AlibabaConfig; -import org.dromara.sms4j.api.SmsBlend; -import org.dromara.sms4j.api.universal.SupplierConfig; +import org.dromara.sms4j.aliyun.config.AlibabaFactory; import org.dromara.sms4j.cloopen.config.CloopenConfig; -import org.dromara.sms4j.core.factory.SmsFactory; +import org.dromara.sms4j.cloopen.config.CloopenFactory; +import org.dromara.sms4j.comm.constant.SupplierConstant; import org.dromara.sms4j.ctyun.config.CtyunConfig; +import org.dromara.sms4j.ctyun.config.CtyunFactory; import org.dromara.sms4j.emay.config.EmayConfig; +import org.dromara.sms4j.emay.config.EmayFactory; import org.dromara.sms4j.huawei.config.HuaweiConfig; +import org.dromara.sms4j.huawei.config.HuaweiFactory; import org.dromara.sms4j.jdcloud.config.JdCloudConfig; -import org.dromara.sms4j.provider.enumerate.SupplierType; +import org.dromara.sms4j.jdcloud.config.JdCloudFactory; +import org.dromara.sms4j.provider.config.BaseConfig; +import org.dromara.sms4j.provider.factory.BaseProviderFactory; import org.dromara.sms4j.tencent.config.TencentConfig; +import org.dromara.sms4j.tencent.config.TencentFactory; import org.dromara.sms4j.unisms.config.UniConfig; +import org.dromara.sms4j.unisms.config.UniFactory; +import org.dromara.sms4j.yunpian.config.YunPianFactory; import org.dromara.sms4j.yunpian.config.YunpianConfig; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; -/** The type Sms config loader. */ +/** + * The type Sms config loader. + */ @Slf4j public class SmsConfigLoader { - public static SupplierConfig getConfigLoader(String config, Integer manufacturersType) { - JSONObject fullConfigParams = JSONUtil.parseObj(config); - switch (manufacturersType) { - case 1: - AlibabaConfig alibabaConfig = AlibabaConfig.builder() - .accessKeyId(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_ID)) - .accessKeySecret(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_SECRET)) - .signature(fullConfigParams.getStr(SmsConstants.SIGNATURE)) - .templateId(fullConfigParams.getStr(SmsConstants.TEMPLATE_ID)) - .templateName(fullConfigParams.getStr(SmsConstants.TEMPLATE_NAME)) - .requestUrl(fullConfigParams.getStr(SmsConstants.REQUEST_URL)) - .action(fullConfigParams.getStr(SmsConstants.ACTION)) - .version(fullConfigParams.getStr(SmsConstants.VERSION)) - .regionId(fullConfigParams.getStr(SmsConstants.REGION_ID)) - .build(); - return alibabaConfig; - case 2: - HuaweiConfig huaweiConfig = HuaweiConfig.builder() - .appKey(fullConfigParams.getStr(SmsConstants.APP_KEY)) - .appSecret(fullConfigParams.getStr(SmsConstants.APP_SECRET)) - .signature(fullConfigParams.getStr(SmsConstants.SIGNATURE)) - .sender(fullConfigParams.getStr(SmsConstants.SENDER)) - .templateId(fullConfigParams.getStr(SmsConstants.TEMPLATE_ID)) - .statusCallBack(fullConfigParams.getStr(SmsConstants.STATUS_CALLBACK)) - .url(fullConfigParams.getStr(SmsConstants.URL)) - .build(); - return huaweiConfig; - case 3: - YunpianConfig yunpianConfig = YunpianConfig.builder() - .accessKeyId(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_ID)) - .accessKeySecret(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_SECRET)) - .signature(fullConfigParams.getStr(SmsConstants.TEMPLATE_ID)) - .templateId(fullConfigParams.getStr(SmsConstants.TEMPLATE_NAME)) - .callbackUrl(fullConfigParams.getStr(SmsConstants.STATUS_CALLBACK)) - .templateName(fullConfigParams.getStr(SmsConstants.TEMPLATE_NAME)) - .build(); - return yunpianConfig; - case 4: - TencentConfig tencentConfig = TencentConfig.builder() - .accessKeyId(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_ID)) - .accessKeySecret(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_SECRET)) - .signature(fullConfigParams.getStr(SmsConstants.SIGNATURE)) - .templateId(fullConfigParams.getStr(SmsConstants.TEMPLATE_ID)) - .sdkAppId(fullConfigParams.getStr(SmsConstants.SDK_APP_ID)) - .territory(fullConfigParams.getStr(SmsConstants.TERRITORY)) - .connTimeout(fullConfigParams.getInt(SmsConstants.CONN_TIMEOUT)) - .requestUrl(fullConfigParams.getStr(SmsConstants.REQUEST_URL)) - .action(fullConfigParams.getStr(SmsConstants.ACTION)) - .version(fullConfigParams.getStr(SmsConstants.VERSION)) - .build(); - return tencentConfig; - case 5: - UniConfig uniConfig = UniConfig.builder() - .accessKeyId(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_ID)) - .accessKeySecret(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_SECRET)) - .isSimple(fullConfigParams.getBool(SmsConstants.IS_SIMPLE)) - .signature(fullConfigParams.getStr(SmsConstants.SIGNATURE)) - .templateId(fullConfigParams.getStr(SmsConstants.TEMPLATE_ID)) - .templateName(fullConfigParams.getStr(SmsConstants.TEMPLATE_NAME)) - .build(); - return uniConfig; - case 6: - JdCloudConfig jdCloudConfig = JdCloudConfig.builder() - .accessKeyId(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_ID)) - .accessKeySecret(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_SECRET)) - .signature(fullConfigParams.getStr(SmsConstants.SIGNATURE)) - .templateId(fullConfigParams.getStr(SmsConstants.TEMPLATE_ID)) - .region(fullConfigParams.getStr(SmsConstants.REGION)) - .build(); - return jdCloudConfig; - case 7: - CloopenConfig cloopenConfig = CloopenConfig.builder() - .accessKeyId(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_ID)) - .accessKeySecret(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_SECRET)) - .templateId(fullConfigParams.getStr(SmsConstants.TEMPLATE_ID)) - .appId(fullConfigParams.getStr(SmsConstants.APP_ID)) - .baseUrl(fullConfigParams.getStr(SmsConstants.BASE_URL)) - .build(); - return cloopenConfig; - case 8: - EmayConfig emayConfig = EmayConfig.builder() - .appId(fullConfigParams.getStr(SmsConstants.APP_ID)) - .secretKey(fullConfigParams.getStr(SmsConstants.SECRET_KEY)) - .requestUrl(fullConfigParams.getStr(SmsConstants.REQUEST_URL)) - .build(); - return emayConfig; - case 9: - CtyunConfig ctyunConfig = CtyunConfig.builder() - .accessKeyId(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_ID)) - .accessKeySecret(fullConfigParams.getStr(SmsConstants.ACCESS_KEY_SECRET)) - .signature(fullConfigParams.getStr(SmsConstants.SIGNATURE)) - .templateId(fullConfigParams.getStr(SmsConstants.TEMPLATE_ID)) - .templateName(fullConfigParams.getStr(SmsConstants.TEMPLATE_NAME)) - .requestUrl(fullConfigParams.getStr(SmsConstants.REQUEST_URL)) - .action(fullConfigParams.getStr(SmsConstants.ACTION)) - .build(); - return ctyunConfig; + /** + * 获取 phone number list + */ + public static List getPhoneNumberList(Map params) { + List phoneNumbers = (List) params.get(SmsConstants.PHONE_NUMBERS); + requireNonNull(phoneNumbers, "phoneNumbers is null"); + return phoneNumbers; + } + + /** + * Parse config params json object. + * + * @param config + * @return + */ + public static JSONObject parseConfigParams(String config) { + return JSONUtil.parseObj(config); + } + + /** + * Gets config supplier config. + * + * @param params the config params + * @return the config supplier config {@link BaseConfig } + */ + public static BaseConfig getConfigSupplierConfig(Map params) { + JSONObject fullConfigParams = parseConfigParams(JSONUtil.toJsonStr(params)); + + String suppliersId = fullConfigParams.getStr(SmsConstants.SUPPLIERS); + requireNonNull(suppliersId, "suppliers is null"); + + switch (suppliersId) { + case SupplierConstant.ALIBABA: + return JSONUtil.toBean(fullConfigParams, AlibabaConfig.class); + case SupplierConstant.TENCENT: + return JSONUtil.toBean(fullConfigParams, TencentConfig.class); + case SupplierConstant.HUAWEI: + return JSONUtil.toBean(fullConfigParams, HuaweiConfig.class); + case SupplierConstant.YUNPIAN: + return JSONUtil.toBean(fullConfigParams, YunpianConfig.class); + case SupplierConstant.UNISMS: + return JSONUtil.toBean(fullConfigParams, UniConfig.class); + case SupplierConstant.JDCLOUD: + return JSONUtil.toBean(fullConfigParams, JdCloudConfig.class); + case SupplierConstant.CLOOPEN: + return JSONUtil.toBean(fullConfigParams, CloopenConfig.class); + case SupplierConstant.EMAY: + return JSONUtil.toBean(fullConfigParams, EmayConfig.class); + case SupplierConstant.CTYUN: + return JSONUtil.toBean(fullConfigParams, CtyunConfig.class); default: - throw new IllegalArgumentException( - "Unsupported manufacturers type: " + ManuFacturers.getManuFacturers(manufacturersType)); + throw new IllegalArgumentException(String.format("Unsupported supplier type: [%s]", suppliersId)); } } - public static SmsBlend getSmsFactory(Integer manufacturersType) { - switch (manufacturersType) { - case 1: - return SmsFactory.createSmsBlend(SupplierType.ALIBABA); - case 2: - return SmsFactory.createSmsBlend(SupplierType.HUAWEI); - case 3: - return SmsFactory.createSmsBlend(SupplierType.YUNPIAN); - case 4: - return SmsFactory.createSmsBlend(SupplierType.TENCENT); - case 5: - return SmsFactory.createSmsBlend(SupplierType.UNI_SMS); - case 6: - return SmsFactory.createSmsBlend(SupplierType.JD_CLOUD); - case 7: - return SmsFactory.createSmsBlend(SupplierType.CLOOPEN); - case 8: - return SmsFactory.createSmsBlend(SupplierType.EMAY); - case 9: - return SmsFactory.createSmsBlend(SupplierType.CTYUN); + /** + * 获取 BaseProviderFactory 实例 + */ + public static BaseProviderFactory getBaseProviderFactory(String supplier) { + switch (supplier) { + case SupplierConstant.ALIBABA: + return AlibabaFactory.instance(); + case SupplierConstant.HUAWEI: + return HuaweiFactory.instance(); + case SupplierConstant.YUNPIAN: + return YunPianFactory.instance(); + case SupplierConstant.TENCENT: + return TencentFactory.instance(); + case SupplierConstant.JDCLOUD: + return JdCloudFactory.instance(); + case SupplierConstant.CLOOPEN: + return CloopenFactory.instance(); + case SupplierConstant.EMAY: + return EmayFactory.instance(); + case SupplierConstant.CTYUN: + return CtyunFactory.instance(); + case SupplierConstant.UNISMS: + return UniFactory.instance(); default: - throw new IllegalArgumentException( - "Unsupported manufacturers type: " + ManuFacturers.getManuFacturers(manufacturersType)); + throw new IllegalArgumentException(String.format("Unsupported supplier type: [%s]", supplier)); } } } diff --git a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/enums/ManuFacturers.java b/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/enums/ManuFacturers.java deleted file mode 100644 index a3c0a089b0..0000000000 --- a/dinky-alert/dinky-alert-sms/src/main/java/org/dinky/alert/sms/enums/ManuFacturers.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.dinky.alert.sms.enums; - -public enum ManuFacturers { - /** 阿里云 */ - ALIBABA(1, "阿里云短信"), - /** 华为云 */ - HUAWEI(2, "华为云短信"), - /** 云片 */ - YUNPIAN(3, "云片短信"), - /** 腾讯云 */ - TENCENT(4, "腾讯云短信"), - /** 合一短信 */ - UNI_SMS(5, "合一短信"), - /** 京东云短信 */ - JD_CLOUD(6, "京东云短信"), - /** 容联云短信 */ - CLOOPEN(7, "容联云短信"), - /** 亿美软通短信 */ - EMAY(8, "亿美软通短信"), - /** 天翼云短信 */ - CTYUN(9, "天翼云短信"), - ; - - private final Integer code; - private final String type; - - ManuFacturers(Integer code, String type) { - this.code = code; - this.type = type; - } - - public Integer getCode() { - return this.code; - } - - public String getType() { - return this.type; - } - - public static ManuFacturers getManuFacturers(Integer code) { - for (ManuFacturers manuFacturers : ManuFacturers.values()) { - if (manuFacturers.getCode().equals(code)) { - return manuFacturers; - } - } - return null; - } -} diff --git a/dinky-alert/dinky-alert-sms/src/main/resources/Sms.ftl b/dinky-alert/dinky-alert-sms/src/main/resources/Sms.ftl new file mode 100644 index 0000000000..4c8b3c2405 --- /dev/null +++ b/dinky-alert/dinky-alert-sms/src/main/resources/Sms.ftl @@ -0,0 +1,2 @@ +${title} +${content} \ No newline at end of file diff --git a/dinky-alert/dinky-alert-sms/src/test/java/org/dinky/alert/sms/SmsSenderTest.java b/dinky-alert/dinky-alert-sms/src/test/java/org/dinky/alert/sms/SmsSenderTest.java new file mode 100644 index 0000000000..4ace0abe1f --- /dev/null +++ b/dinky-alert/dinky-alert-sms/src/test/java/org/dinky/alert/sms/SmsSenderTest.java @@ -0,0 +1,71 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.dinky.alert.sms; + +import org.dinky.alert.AlertBaseConstant; +import org.dinky.alert.AlertConfig; +import org.dinky.alert.AlertResult; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.dromara.sms4j.comm.constant.SupplierConstant; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +/** SmsSenderTest */ +@Ignore +public class SmsSenderTest { + + private static final Map SMS_CONFIG = new HashMap<>(); + + /** init WeChatConfig */ + @Before + public void initSmsConfig() { + // test alibaba sms + SMS_CONFIG.put(SmsConstants.SUPPLIERS, SupplierConstant.ALIBABA); + SMS_CONFIG.put(SmsConstants.ACCESS_KEY_ID, "xxxxxxxxxxxxx"); + SMS_CONFIG.put(SmsConstants.REGION_ID, "cn-shanghai"); + SMS_CONFIG.put(SmsConstants.ACCESS_KEY_SECRET, "xxxxxxxxxxx"); + SMS_CONFIG.put(SmsConstants.SIGNATURE, "xxxxxxxxx"); + SMS_CONFIG.put(SmsConstants.TEMPLATE_ID, "xxxxxx"); + SMS_CONFIG.put(SmsConstants.TEMPLATE_NAME, "content"); + SMS_CONFIG.put(SmsConstants.PHONE_NUMBERS, Arrays.asList("xxxxxx")); + } + + @Ignore + @Test + public void testSendMsg() { + + SmsAlert weChatAlert = new SmsAlert(); + AlertConfig alertConfig = new AlertConfig(); + + alertConfig.setType(SmsConstants.TYPE); + alertConfig.setParam(SMS_CONFIG); + weChatAlert.setConfig(alertConfig); + + AlertResult alertResult = + weChatAlert.send(AlertBaseConstant.ALERT_TEMPLATE_TITLE, AlertBaseConstant.ALERT_TEMPLATE_MSG); + Assert.assertEquals(true, alertResult.getSuccess()); + } +} diff --git a/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatAlert.java b/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatAlert.java index 645d6cb984..200d6b909f 100644 --- a/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatAlert.java +++ b/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatAlert.java @@ -46,7 +46,7 @@ public String getType() { @Override public String getTemplate() { - String sendType = getConfig().getParam().get(WeChatConstants.SEND_TYPE); + String sendType = (String) getConfig().getParam().get(WeChatConstants.SEND_TYPE); return ResourceUtil.readUtf8Str( StrFormatter.format("{}-{}.ftl", getConfig().getType(), sendType)); } @@ -55,11 +55,21 @@ public String getTemplate() { public AlertResult send(String title, String content) { WeChatSender sender = new WeChatSender(getConfig().getParam()); try { - String built = buildContent(sender.buildTemplateParams(title, content)); + String built = buildContent(sender.buildTemplateParams(title, replaceContent(content))); return sender.send(built); } catch (TemplateException | IOException e) { logger.error("{}'message send error, Reason:{}", getType(), e.getMessage()); throw new RuntimeException(e); } } + + /** + * remove - from string + * + * @param content input string with line breaks (new lines) + * @return string with lines removed + */ + private String replaceContent(String content) { + return content.replaceAll("\\n-\\s", "\n"); + } } diff --git a/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatConstants.java b/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatConstants.java index fbaa37267e..6116cd7cbf 100644 --- a/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatConstants.java +++ b/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatConstants.java @@ -25,11 +25,10 @@ public class WeChatConstants extends AlertBaseConstant { public static final String TYPE = "WeChat"; /** WeChat alert baseconstant */ - public static final String WECHAT_PUSH_URL = - "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}"; + public static final String WECHAT_PUSH_URL = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s"; public static final String WECHAT_TOKEN_URL = - "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={secret}"; + "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s"; public static final String CORP_ID = "corpId"; public static final String TEAM_SEND_MSG = "teamSendMsg"; public static final String AGENT_ID = "agentId"; diff --git a/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatSender.java b/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatSender.java index 187b1cb3ef..dda7969304 100644 --- a/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatSender.java +++ b/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/WeChatSender.java @@ -23,6 +23,7 @@ import org.dinky.alert.AlertResult; import org.dinky.alert.AlertSendResponse; +import org.dinky.alert.wechat.params.WechatParams; import org.dinky.utils.HttpUtils; import org.dinky.utils.JsonUtils; @@ -34,7 +35,7 @@ import org.apache.http.util.EntityUtils; import java.io.IOException; -import java.util.Arrays; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory; import cn.hutool.core.text.StrFormatter; +import cn.hutool.json.JSONUtil; /** * WeChatSender @@ -52,36 +54,19 @@ */ public class WeChatSender { private static final Logger logger = LoggerFactory.getLogger(WeChatSender.class); - private static final String CORP_ID_REGEX = "{corpId}"; - private static final String SECRET_REGEX = "{secret}"; - private static final String TOKEN_REGEX = "{token}"; - private final String weChatAgentId; - private String weChatUsers; + private final WechatParams wechatParams; private final String weChatTokenUrlReplace; - private final String sendType; - private final String webhookUrl; - WeChatSender(Map config) { - weChatAgentId = config.getOrDefault(WeChatConstants.AGENT_ID, ""); - weChatUsers = config.getOrDefault(WeChatConstants.AT_USERS, ""); - String isAtAll = config.getOrDefault(WeChatConstants.AT_ALL, ""); - if (Boolean.parseBoolean(isAtAll)) { - weChatUsers = "all"; + WeChatSender(Map config) { + this.wechatParams = JSONUtil.toBean(JSONUtil.toJsonStr(config), WechatParams.class); + if (wechatParams.isAtAll()) { + wechatParams.getAtUsers().add("all"); } - - webhookUrl = config.get(WeChatConstants.WEB_HOOK); - - sendType = config.get(WeChatConstants.SEND_TYPE); - if (sendType.equals(WeChatType.CHAT.getValue())) { - requireNonNull(webhookUrl, WeChatConstants.WEB_HOOK + " must not null"); + if (wechatParams.getSendType().equals(WeChatType.CHAT.getValue())) { + requireNonNull(wechatParams.getWebhook(), WeChatConstants.WEB_HOOK + " must not null"); } - - String weChatCorpId = config.getOrDefault(WeChatConstants.CORP_ID, ""); - String weChatSecret = config.getOrDefault(WeChatConstants.SECRET, ""); - - weChatTokenUrlReplace = WeChatConstants.WECHAT_TOKEN_URL - .replace(CORP_ID_REGEX, weChatCorpId) - .replace(SECRET_REGEX, weChatSecret); + weChatTokenUrlReplace = + String.format(WeChatConstants.WECHAT_TOKEN_URL, wechatParams.getCorpId(), wechatParams.getSecret()); } /** @@ -95,10 +80,14 @@ public Map buildTemplateParams(String title, String content) { Map params = new HashMap<>(); params.put(WeChatConstants.ALERT_TEMPLATE_TITLE, title); params.put(WeChatConstants.ALERT_TEMPLATE_CONTENT, content); - params.put(WeChatConstants.ALERT_TEMPLATE_AGENT_ID, weChatAgentId); - List atUsers = Arrays.stream(weChatUsers.split(",")) - .map(u -> StrFormatter.format("<@{}>", u)) - .collect(Collectors.toList()); + if (wechatParams.getSendType().equals(WeChatType.APP.getValue())) { + params.put(WeChatConstants.ALERT_TEMPLATE_AGENT_ID, wechatParams.getAgentId()); + } + List atUsers = wechatParams.getAtUsers().isEmpty() + ? new ArrayList<>() + : wechatParams.getAtUsers().stream() + .map(u -> StrFormatter.format("<@{}>", u)) + .collect(Collectors.toList()); params.put(WeChatConstants.ALERT_TEMPLATE_AT_USERS, atUsers); return params; } @@ -107,12 +96,12 @@ public AlertResult send(String content) { AlertResult alertResult = new AlertResult(); String url; try { - if (sendType.equals(WeChatType.APP.getValue())) { + if (WeChatType.APP.getValue().equals(wechatParams.getSendType())) { String token = getToken(); assert token != null; - url = WeChatConstants.WECHAT_PUSH_URL.replace(TOKEN_REGEX, token); + url = String.format(WeChatConstants.WECHAT_PUSH_URL, token); } else { - url = webhookUrl; + url = wechatParams.getWebhook(); } return checkWeChatSendMsgResult(HttpUtils.post(url, content)); } catch (Exception e) { @@ -160,6 +149,15 @@ private static AlertResult checkWeChatSendMsgResult(String result) { logger.error("send we chat msg error,resp error"); return alertResult; } + if (sendMsgResponse.getErrcode() != 0) { + logger.error( + "send we chat msg error,resp error,code:{},msg:{}", + sendMsgResponse.getErrcode(), + sendMsgResponse.getErrmsg()); + alertResult.setSuccess(false); + alertResult.setMessage(sendMsgResponse.getErrmsg()); + return alertResult; + } if (sendMsgResponse.getErrcode() == 0) { alertResult.setSuccess(true); alertResult.setMessage("we chat alert send success"); diff --git a/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/params/WechatParams.java b/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/params/WechatParams.java new file mode 100644 index 0000000000..2cbc78c561 --- /dev/null +++ b/dinky-alert/dinky-alert-wechat/src/main/java/org/dinky/alert/wechat/params/WechatParams.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.dinky.alert.wechat.params; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonCreator; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor(onConstructor = @__(@JsonCreator)) +@AllArgsConstructor +public class WechatParams { + + private String sendType; + private boolean isAtAll; + private String corpId; + private String secret; + private int agentId; + private List atUsers = new ArrayList<>(); + private String webhook; + private String keyword; +} diff --git a/dinky-alert/dinky-alert-wechat/src/main/resources/WeChat-app.ftl b/dinky-alert/dinky-alert-wechat/src/main/resources/WeChat-app.ftl index e6370abf4a..1466eac40f 100644 --- a/dinky-alert/dinky-alert-wechat/src/main/resources/WeChat-app.ftl +++ b/dinky-alert/dinky-alert-wechat/src/main/resources/WeChat-app.ftl @@ -10,7 +10,7 @@ "msgtype": "markdown", -"agentid" : ${agentId}, +"agentid": ${agentId}, "markdown": { "content": "### Dinky Alert:${title}\n${content?json_string}" }, diff --git a/dinky-alert/dinky-alert-wechat/src/main/resources/WeChat-wechat.ftl b/dinky-alert/dinky-alert-wechat/src/main/resources/WeChat-wechat.ftl index d45d734dcc..0c23c66bad 100644 --- a/dinky-alert/dinky-alert-wechat/src/main/resources/WeChat-wechat.ftl +++ b/dinky-alert/dinky-alert-wechat/src/main/resources/WeChat-wechat.ftl @@ -1,4 +1,4 @@ { "msgtype": "markdown", - "markdown": {"content": "## Dinky Alert:${title}\n> Your task there is an abnormality, Please troubleshoot <#list atUsers as key>${key}\n${content?json_string}\n ---\n[Dinky Team](https://github.com/DataLinkDC/dinky)"} + "markdown": {"content": "## Dinky Alert:${title}\n> Your task there is an abnormality, Please troubleshoot <#list atUsers as key>${key}\n${content?json_string}\n---\n[Dinky Team](https://github.com/DataLinkDC/dinky)"} } \ No newline at end of file diff --git a/dinky-alert/dinky-alert-wechat/src/test/java/org/dinky/alert/wechat/WeChatSenderTest.java b/dinky-alert/dinky-alert-wechat/src/test/java/org/dinky/alert/wechat/WeChatSenderTest.java index 2085350744..594f0ffd90 100644 --- a/dinky-alert/dinky-alert-wechat/src/test/java/org/dinky/alert/wechat/WeChatSenderTest.java +++ b/dinky-alert/dinky-alert-wechat/src/test/java/org/dinky/alert/wechat/WeChatSenderTest.java @@ -19,6 +19,7 @@ package org.dinky.alert.wechat; +import org.dinky.alert.AlertBaseConstant; import org.dinky.alert.AlertConfig; import org.dinky.alert.AlertResult; import org.dinky.alert.ShowType; @@ -35,18 +36,7 @@ @Ignore public class WeChatSenderTest { - private static final Map weChatConfig = new HashMap<>(); - - String contentTest = - "> The Dinky platform has detected an abnormality in your task. Please go to the Dinky Task page to check the task status.\n" - + "- **Job Name : Test Job**\n" - + "- **Job Status : FAILED**\n" - + "- **Alert Time : 2023-01-01 12:00:00**\n" - + "- **Start Time : 2023-01-01 12:00:00**\n" - + "- **End Time : 2023-01-01 12:00:00**\n" - + "> **The test exception, your job exception will pass here**\n" - + "\n" - + "> Dinky Team [Go toTask Web](https://github.com/DataLinkDC/dinky)"; + private static final Map weChatConfig = new HashMap<>(); /** init WeChatConfig */ @Before @@ -74,7 +64,8 @@ public void testSendMarkDownMsg() { alertConfig.setParam(weChatConfig); weChatAlert.setConfig(alertConfig); - AlertResult alertResult = weChatAlert.send("WeChat Alert Hook", contentTest); + AlertResult alertResult = + weChatAlert.send(AlertBaseConstant.ALERT_TEMPLATE_TITLE, AlertBaseConstant.ALERT_TEMPLATE_MSG); Assert.assertEquals(true, alertResult.getSuccess()); } @@ -90,7 +81,8 @@ public void testSendAPPMarkDownMsg() { alertConfig.setParam(weChatConfig); weChatAlert.setConfig(alertConfig); - AlertResult alertResult = weChatAlert.send("WeChat Alert App", contentTest); + AlertResult alertResult = + weChatAlert.send(AlertBaseConstant.ALERT_TEMPLATE_TITLE, AlertBaseConstant.ALERT_TEMPLATE_MSG); Assert.assertEquals(true, alertResult.getSuccess()); } } diff --git a/dinky-common/src/main/java/org/dinky/utils/HttpUtils.java b/dinky-common/src/main/java/org/dinky/utils/HttpUtils.java index bbdec7cdef..74b823957f 100644 --- a/dinky-common/src/main/java/org/dinky/utils/HttpUtils.java +++ b/dinky-common/src/main/java/org/dinky/utils/HttpUtils.java @@ -79,8 +79,17 @@ public static String post(String url, String jsonParam, ProxyConfig proxyConfig) CloseableHttpResponse response = httpClient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - logger.error("post data error, return http status code: {} ", statusCode); + + if (statusCode == HttpStatus.SC_OK) { + logger.info( + "post data success, return http status code: {} , msg: {}", + statusCode, + response.getStatusLine().getReasonPhrase()); + } else { + logger.warn( + "post data error, return http status code: {}, msg: {} ", + statusCode, + response.getStatusLine().getReasonPhrase()); } String resp; try { @@ -98,6 +107,7 @@ public static String post(String url, String jsonParam, ProxyConfig proxyConfig) /** * build HttpPost + * * @param httpUrl * @param msg * @return diff --git a/dinky-web/package.json b/dinky-web/package.json index d8287a9142..e9b30496a5 100644 --- a/dinky-web/package.json +++ b/dinky-web/package.json @@ -36,18 +36,18 @@ ], "dependencies": { "@andrewray/react-multi-split-pane": "^0.3.5", - "@ant-design/charts": "^1.4.2", + "@ant-design/charts": "^1.4.3", "@ant-design/icons": "^5.2.6", - "@ant-design/pro-components": "^2.6.41", - "@ant-design/pro-layout": "^7.17.15", - "@ant-design/pro-table": "^3.13.9", + "@ant-design/pro-components": "^2.6.43", + "@ant-design/pro-layout": "^7.17.16", + "@ant-design/pro-table": "^3.13.11", "@ant-design/use-emotion-css": "^1.0.4", "@antv/x6": "^2.15.6", "@antv/x6-plugin-selection": "^2.2.1", "@antv/x6-react-shape": "^2.2.2", "@monaco-editor/react": "^4.6.0", "@umijs/route-utils": "^4.0.1", - "antd": "^5.11.1", + "antd": "^5.11.5", "butterfly-dag": "^4.3.28", "classnames": "^2.3.2", "dayjs": "^1.11.10", @@ -63,15 +63,15 @@ "react": "^18.2.0", "react-countup": "^6.5.0", "react-dom": "^18.0.0", - "react-helmet-async": "^1.3.0", + "react-helmet-async": "^2.0.1", "react-lineage-dag": "^2.0.36", - "react-markdown": "^8.0.7", + "react-markdown": "^9.0.1", "react-spring": "^9.7.3", "react-use-cookie": "^1.4.0", "redux-persist": "^6.0.0", "remark-gfm": "^4.0.0", "screenfull": "^6.0.2", - "sql-formatter": "^13.1.0", + "sql-formatter": "^14.0.0", "styled-components": "^6.1.1", "use-sse": "^2.0.1", "uuid": "^9.0.1" @@ -79,16 +79,16 @@ "devDependencies": { "@ant-design/pro-cli": "^3.0.1", "@types/classnames": "^2.3.1", - "@types/express": "^4.17.18", + "@types/express": "^4.17.21", "@types/history": "^5.0.0", "@types/lodash": "^4.14.199", - "@types/react": "^18.2.22", - "@types/react-dom": "^18.0.11", - "@types/react-helmet": "^6.1.5", - "@umijs/lint": "^4.0.81", - "@umijs/max": "^4.0.81", + "@types/react": "^18.2.39", + "@types/react-dom": "^18.2.17", + "@types/react-helmet": "^6.1.9", + "@umijs/lint": "^4.0.89", + "@umijs/max": "^4.0.89", "cross-env": "^7.0.3", - "eslint": "^8.50.0", + "eslint": "^8.54.0", "express": "^4.18.2", "husky": "^8", "lint-staged": "^13", @@ -96,12 +96,15 @@ "react-dev-inspector": "^2.0.0", "react-inspector": "^6.0.2", "sql-formatter": "^13.0.1", - "swagger-ui-dist": "^4.16.1", + "swagger-ui-dist": "^5.10.3", "ts-node": "^10.9.1", "typescript": "^4", "umi-presets-pro": "^2.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0", + "npm": ">=6.0.0", + "umi": ">=3.0.0", + "yarn": ">=1.0.0" } } diff --git a/dinky-web/src/components/FormSingleColumnList/index.tsx b/dinky-web/src/components/FormSingleColumnList/index.tsx new file mode 100644 index 0000000000..efb2f11d90 --- /dev/null +++ b/dinky-web/src/components/FormSingleColumnList/index.tsx @@ -0,0 +1,132 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { DangerDeleteIcon } from '@/components/Icons/CustomIcons'; +import { l } from '@/utils/intl'; +import { ErrorMessageAsync } from '@/utils/messages'; +import { PlusOutlined } from '@ant-design/icons'; +import { Button, Divider, Form, Input, Space, Tooltip } from 'antd'; +import { FormInstance } from 'antd/es/form/hooks/useForm'; +import { Values } from 'async-validator'; +import { Rule } from 'rc-field-form/lib/interface'; +import React from 'react'; + +interface FormSingleColumnListProps { + max: number; + min: number; + namePath: string | string[]; + rules?: Rule[]; + title?: React.ReactNode | string; + inputPlaceholder: string; + form: FormInstance; + plain: boolean; +} + +export const FormSingleColumnList = (props: FormSingleColumnListProps) => { + const { max, min, namePath, rules, title, inputPlaceholder, plain, form } = props; + + return ( + <> + {title && ( + + + {' '} + {title} + + + )} + + {(fields, { add, remove }) => ( + <> +
+ {fields.map((field) => ( + + + + + {fields.length === min ? ( + <> + ) : ( + { + if (fields.length <= min) { + await ErrorMessageAsync(l('rc.ai.atLeast', '', { min })); + return; + } + remove(field.name); + }} + /> + )} + + ))} +
+ {fields.length > max ? ( + <> + ) : ( + <> + + + )} + + )} +
+ + ); +}; diff --git a/dinky-web/src/components/RightContent/AvatarDropdown.tsx b/dinky-web/src/components/RightContent/AvatarDropdown.tsx index 8218320200..ad406e41b4 100644 --- a/dinky-web/src/components/RightContent/AvatarDropdown.tsx +++ b/dinky-web/src/components/RightContent/AvatarDropdown.tsx @@ -36,7 +36,6 @@ import { stringify } from 'querystring'; import { ItemType } from 'rc-menu/es/interface'; import type { MenuInfo } from 'rc-menu/lib/interface'; import { useCallback } from 'react'; -import { flushSync } from 'react-dom'; import HeaderDropdown from '../HeaderDropdown'; export const loginOut = async () => { @@ -124,9 +123,7 @@ const AvatarDropdown = () => { const loginOutHandler = useCallback( async (event: MenuInfo) => { const { key } = event; - flushSync(() => { - setInitialState((s) => ({ ...s, currentUser: undefined })); - }); + setInitialState((s) => ({ ...s, currentUser: undefined })); await loginOut(); return; }, diff --git a/dinky-web/src/locales/en-US/global.ts b/dinky-web/src/locales/en-US/global.ts index 87de687ae8..fd0b51495f 100644 --- a/dinky-web/src/locales/en-US/global.ts +++ b/dinky-web/src/locales/en-US/global.ts @@ -18,6 +18,7 @@ */ export default { + 'button.add': 'Add', 'button.check': 'Check', 'button.graph': 'DAG', 'button.create': 'Create', diff --git a/dinky-web/src/locales/en-US/pages.ts b/dinky-web/src/locales/en-US/pages.ts index 5d075f63e4..f88e6d8833 100644 --- a/dinky-web/src/locales/en-US/pages.ts +++ b/dinky-web/src/locales/en-US/pages.ts @@ -479,6 +479,8 @@ export default { 'rc.ag.search': 'Search Name/Note', 'rc.ai.accessKeyId': 'AccessKeyId', 'rc.ai.accessKeyIdPleaseHolder': 'Please enter AccessKeyId', + 'rc.ai.sdkAppId': 'SdkAppId', + 'rc.ai.sdkAppIdPleaseHolder': 'Please enter SdkAppId', 'rc.ai.accessKeySecret': 'AccessKeySecret', 'rc.ai.accessKeySecretPleaseHolder': 'Please enter AccessKeySecret', 'rc.ai.action': 'Interface method', @@ -493,12 +495,19 @@ export default { 'rc.ai.appKeyPleaseHolder': 'Please enter App Key', 'rc.ai.appSecret': 'App Secret', 'rc.ai.appSecretPleaseHolder': 'Please enter App Secret', - 'rc.ai.atMobiles': 'At Mobiles', - 'rc.ai.atMobilesPleaseHolder': - 'Please enter the members that need @, multiple use, separated by numbers', - 'rc.ai.atUsers': 'At Users', - 'rc.ai.atUsersPleaseHolder': - 'Please enter the user ID (user ID of FeiShu background is required), separated by multiple commas!', + 'rc.ai.atLeast': 'At least [{min}] required', + 'rc.ai.atMost': 'At most [{max}] required', + 'rc.ai.previousItemRequired': 'The previous item is required, so that the next item can be added', + 'rc.ai.atMobiles': 'Phone number', + 'rc.ai.atMobilesPleaseHolder': 'Please enter the phone number', + 'rc.ai.atMobilesRepeat': 'Duplicate phone number', + 'rc.ai.atMobilesFormat': 'Phone number format is incorrect', + 'rc.ai.atMobilesMax': 'Phone number (up to [{max}] digits)', + 'rc.ai.emailPleaseHolderFormat': 'Please enter the correct email address', + 'rc.ai.atUsers': '@User', + 'rc.ai.atUsersPleaseHolder': 'Please enter the @user ID', + 'rc.ai.atUsersRepeat': 'Duplicate @user ID', + 'rc.ai.atUsersMax': '@User (up to [{max}] digits)', 'rc.ai.baseUrl': 'REST API Base URL', 'rc.ai.baseUrlPleaseHolder': 'Please enter the REST API Base URL', 'rc.ai.callbackUrl': 'Official callback address', @@ -527,8 +536,10 @@ export default { 'rc.ai.keyword': 'KeyWord', 'rc.ai.keywordPleaseHolder': 'please enter keyword', 'rc.ai.management': 'Alert Instance Management', - 'rc.ai.manufacturers': 'SMS manufacturers', - 'rc.ai.manufacturersPleaseHolder': 'Please select a SMS manufacturer', + 'rc.ai.suppliers': 'SMS Suppliers', + 'rc.ai.suppliersPleaseHolder': 'Please select a SMS supplier', + 'rc.ai.phoneNumbers': 'Phone Numbers', + 'rc.ai.phoneNumbersPleaseHolder': 'phone number', 'rc.ai.mf.alibaba': 'Aliyun SMS', 'rc.ai.mf.cloopen': 'CloOpen cloud domestic SMS', 'rc.ai.mf.ctyun': 'Tianyi Cloud SMS', @@ -549,16 +560,17 @@ export default { 'rc.ai.proxy': 'Proxy', 'rc.ai.proxyPleaseHolder': 'enter proxy', 'rc.ai.receiverCcs': 'ReceiverCcs', - 'rc.ai.receiverCcsPleaseHolder': - 'Please enter the receiverCcs email address! Separate multiple commas!', + 'rc.ai.receiverCcsPleaseHolder': 'Please enter the receiverCcs email address!', + 'rc.ai.receiverCcsRepeat': 'Duplicate receiverCcs email address', + 'rc.ai.receiverCcsMax': 'ReceiverCcs (up to [{max}] digits)', 'rc.ai.receivers': 'Receivers', - 'rc.ai.receiversPleaseHolder': 'Please enter recipient email address! Separate multiple commas', + 'rc.ai.receiversPleaseHolder': 'Please enter recipient email address!', + 'rc.ai.receiversRepeat': 'Duplicate recipient email address', + 'rc.ai.receiversMax': 'Receivers (up to [{max}] digits)', 'rc.ai.regionId': 'Regional Information', 'rc.ai.regionIdPleaseHolder': 'Please enter the region information', 'rc.ai.requestUrl': 'Request URL', 'rc.ai.requestUrlPleaseHolder': 'Please enter the request URL', - 'rc.ai.sdkAppId': 'Account unique ID', - 'rc.ai.sdkAppIdPleaseHolder': 'Please enter the unique ID of the account', 'rc.ai.secret': 'Secret', 'rc.ai.secretKey': 'Access key secret', 'rc.ai.secretKeyPleaseHolder': 'Please enter the access key secret', @@ -589,6 +601,14 @@ export default { 'rc.ai.templateIdPleaseHolder': 'Please enter the SMS template ID', 'rc.ai.templateName': 'Template variable', 'rc.ai.templateNamePleaseHolder': 'Please enter the SMS template variable', + 'rc.ai.configId': 'Config ID', + 'rc.ai.configIdPleaseHolder': 'Please enter the unique config ID', + 'rc.ai.weight': 'Weight', + 'rc.ai.weightPleaseHolder': 'Please enter the weight', + 'rc.ai.retryInterval': 'Retry Interval(s)', + 'rc.ai.retryIntervalPleaseHolder': 'Please enter the retry interval', + 'rc.ai.maxRetries': 'Max Retries', + 'rc.ai.maxRetriesPleaseHolder': 'Please enter the maximum number of retries', 'rc.ai.type': 'Type', 'rc.ai.url': 'APP access address', 'rc.ai.urlPleaseHolder': @@ -601,7 +621,7 @@ export default { 'rc.ai.webhookPleaseHolder': 'please enter webhook url', 'rc.ai.wechat': 'WeChat', 'rc.ai.wechatAtUsersPleaseHolder': - 'Please enter the @user ID (enterprise and micro user name spelled out), separated by multiple commas!', + 'Please enter the @user ID (enterprise and micro user name spelled out)', 'rc.ai.xls.file.path': 'XLS storage directory', 'rc.ai.xls.file.pathPleaseHolder': 'Please enter the XLS storage directory! The default is /tmp/xls', diff --git a/dinky-web/src/locales/zh-CN/global.ts b/dinky-web/src/locales/zh-CN/global.ts index cb6b9eca91..cd13e27585 100644 --- a/dinky-web/src/locales/zh-CN/global.ts +++ b/dinky-web/src/locales/zh-CN/global.ts @@ -18,6 +18,7 @@ */ export default { + 'button.add': '添加', 'button.check': '检查', 'button.graph': 'DAG', 'button.create': '新建', diff --git a/dinky-web/src/locales/zh-CN/pages.ts b/dinky-web/src/locales/zh-CN/pages.ts index 9c1dbf72ae..ae09f5cfd4 100644 --- a/dinky-web/src/locales/zh-CN/pages.ts +++ b/dinky-web/src/locales/zh-CN/pages.ts @@ -477,10 +477,19 @@ export default { 'rc.ai.appKeyPleaseHolder': '请输入App Key', 'rc.ai.appSecret': 'App Secret', 'rc.ai.appSecretPleaseHolder': '请输入App Secret', - 'rc.ai.atMobiles': '@手机号', - 'rc.ai.atMobilesPleaseHolder': '请输入@手机号 多个使用英文逗号分开 ', + 'rc.ai.atLeast': '最少必须有[{min}]个', + 'rc.ai.atMost': '最多只能有[{max}]个', + 'rc.ai.previousItemRequired': '前一项必须输入,才能添加下一项', + 'rc.ai.atMobiles': '手机号', + 'rc.ai.atMobilesPleaseHolder': '请输入手机号', + 'rc.ai.atMobilesRepeat': '手机号码重复', + 'rc.ai.atMobilesFormat': '手机号码格式不正确', + 'rc.ai.atMobilesMax': '手机号码(最多填写 [{max}] 个)', + 'rc.ai.emailPleaseHolderFormat': '请输入正确的邮箱地址', 'rc.ai.atUsers': '被@用户', - 'rc.ai.atUsersPleaseHolder': '请输入被@用户ID(需要飞书后台的用户ID),多个逗号隔开!', + 'rc.ai.atUsersPleaseHolder': '请输入用户ID(后台用户ID)', + 'rc.ai.atUsersRepeat': '@用户ID重复', + 'rc.ai.atUsersMax': '@用户(最多填写 [{max}] 个),请填写管理后台用户ID', 'rc.ai.baseUrl': 'REST API Base URL', 'rc.ai.baseUrlPleaseHolder': '请输入 REST API Base URL', 'rc.ai.callbackUrl': '官方回调地址', @@ -509,8 +518,8 @@ export default { 'rc.ai.keyword': '关键词', 'rc.ai.keywordPleaseHolder': '请输入关键词', 'rc.ai.management': '告警实例管理', - 'rc.ai.manufacturers': '短信厂商', - 'rc.ai.manufacturersPleaseHolder': '请选择短信厂商', + 'rc.ai.suppliers': '短信厂商', + 'rc.ai.suppliersPleaseHolder': '请选择短信厂商', 'rc.ai.mf.alibaba': '阿里云短信', 'rc.ai.mf.cloopen': '容联云国内短信', 'rc.ai.mf.ctyun': '天翼云短信', @@ -531,15 +540,21 @@ export default { 'rc.ai.proxy': '代理', 'rc.ai.proxyPleaseHolder': '代理主机', 'rc.ai.receiverCcs': '抄送人', - 'rc.ai.receiverCcsPleaseHolder': '请输入抄送人邮箱!多个英文逗号隔开!', + 'rc.ai.receiverCcsPleaseHolder': '请输入抄送人邮箱!', + 'rc.ai.receiverCcsRepeat': '抄送人邮箱重复', + 'rc.ai.receiverCcsMax': '抄送人邮箱(最多填写 [{max}] 个)', 'rc.ai.receivers': '收件人', - 'rc.ai.receiversPleaseHolder': '请输入收件人邮箱!多个英文逗号隔开', + 'rc.ai.receiversPleaseHolder': '请输入收件人邮箱', + 'rc.ai.receiversRepeat': '收件人邮箱重复', + 'rc.ai.receiversMax': '收件人邮箱(最多填写 [{max}] 个)', 'rc.ai.regionId': '地域信息', 'rc.ai.regionIdPleaseHolder': '请输入地域信息', 'rc.ai.requestUrl': '请求地址', 'rc.ai.requestUrlPleaseHolder': '请输入请求地址', - 'rc.ai.sdkAppId': '账号唯一标识', - 'rc.ai.sdkAppIdPleaseHolder': '请输入账号唯一标识', + 'rc.ai.sdkAppId': 'SdkAppId', + 'rc.ai.sdkAppIdPleaseHolder': '请输入SdkAppId', + 'rc.ai.phoneNumbers': '手机号', + 'rc.ai.phoneNumbersPleaseHolder': '手机号', 'rc.ai.secret': '密令', 'rc.ai.secretKey': '访问键秘钥', 'rc.ai.secretKeyPleaseHolder': '请输入访问键秘钥', @@ -567,21 +582,28 @@ export default { 'rc.ai.statusCallBackPleaseHolder': '请输入国内短信状态报告接收地址', 'rc.ai.templateId': '短信模板ID', 'rc.ai.templateIdPleaseHolder': '请输入短信模板ID', - 'rc.ai.templateName': '模板变量', + 'rc.ai.templateName': '模板变量名称', 'rc.ai.templateNamePleaseHolder': '请输入短信模板变量', + 'rc.ai.configId': '配置ID', + 'rc.ai.configIdPleaseHolder': '请输入唯一的配置ID', + 'rc.ai.weight': '权重', + 'rc.ai.weightPleaseHolder': '请输入权重', + 'rc.ai.retryInterval': '重试间隔(秒)', + 'rc.ai.retryIntervalPleaseHolder': '请输入重试间隔', + 'rc.ai.maxRetries': '最大重试次数', + 'rc.ai.maxRetriesPleaseHolder': '请输入最大重试次数', 'rc.ai.type': '类型', 'rc.ai.url': 'APP接入地址', 'rc.ai.urlPleaseHolder': '请输入APP接入地址,建立短信应用后获取到的地址', - 'rc.ai.user': '用户名', + 'rc.ai.user': '用户', 'rc.ai.userPleaseHolder': '代理用户', 'rc.ai.version': '版本号', 'rc.ai.versionPleaseHolder': '请输入版本号', 'rc.ai.webhook': 'WebHook 地址', 'rc.ai.webhookPleaseHolder': '请输入 webhook 地址', 'rc.ai.wechat': '企业微信', - 'rc.ai.wechatAtUsersPleaseHolder': '请输入被@用户ID(企微用户名全拼),多个逗号隔开!', - 'rc.ai.xls.file.path': 'XLS存放目录', - 'rc.ai.xls.file.pathPleaseHolder': '请输入XLS存放目录! 默认为 /tmp/xls', + 'rc.ai.wechatAtUsersPleaseHolder': '请输入被@用户ID(企微用户名全拼)', + 'rc.alert.template.create': '创建模板', 'rc.alert.template.modify': '修改模板', 'rc.alert.template.new': '新建告警模板', diff --git a/dinky-web/src/pages/DataStudio/BottomContainer/index.tsx b/dinky-web/src/pages/DataStudio/BottomContainer/index.tsx index c56b8b2f56..aaaebf8b93 100644 --- a/dinky-web/src/pages/DataStudio/BottomContainer/index.tsx +++ b/dinky-web/src/pages/DataStudio/BottomContainer/index.tsx @@ -217,7 +217,7 @@ const BottomContainer: React.FC = (props: any) => { handlerMinimize={handleMinimize} maxWidth={width} > - < Tabs + = (props: any) => { : '') } items={renderItems()} - tabBarStyle={{display: 'none'}} + tabBarStyle={{ display: 'none' }} /> ); }; export default connect(({ Studio }: { Studio: StateType }) => ({ - bottomContainer: Studio.bottomContainer, + bottomContainer: Studio.bottomContainer }))(BottomContainer); diff --git a/dinky-web/src/pages/DataStudio/index.tsx b/dinky-web/src/pages/DataStudio/index.tsx index 1f8b37d464..13c677c8f3 100644 --- a/dinky-web/src/pages/DataStudio/index.tsx +++ b/dinky-web/src/pages/DataStudio/index.tsx @@ -88,7 +88,11 @@ const DataStudio = (props: any) => { const onResize = () => { setSize(getClientSize()); - const newBottomHeight = !isProject ? 0 : bottomContainer.selectKey === '' ? 0 : bottomContainer.height; + const newBottomHeight = !isProject + ? 0 + : bottomContainer.selectKey === '' + ? 0 + : bottomContainer.height; const centerContentHeight = getClientSize().contentHeight - newBottomHeight; updateCenterContentHeight(centerContentHeight); updateToolContentHeight(centerContentHeight - VIEW.leftMargin); @@ -117,7 +121,11 @@ const DataStudio = (props: any) => { }; useEffect(() => { - const newBottomHeight = !isProject ? 0 : bottomContainer.selectKey === '' ? 0 : bottomContainer.height; + const newBottomHeight = !isProject + ? 0 + : bottomContainer.selectKey === '' + ? 0 + : bottomContainer.height; const centerContentHeight = size.contentHeight - newBottomHeight; updateCenterContentHeight(centerContentHeight); updateToolContentHeight(centerContentHeight - VIEW.leftMargin); diff --git a/dinky-web/src/pages/Other/Login/index.tsx b/dinky-web/src/pages/Other/Login/index.tsx index 4c70edff2f..105ba93141 100644 --- a/dinky-web/src/pages/Other/Login/index.tsx +++ b/dinky-web/src/pages/Other/Login/index.tsx @@ -32,7 +32,6 @@ import { ErrorMessage, SuccessMessageAsync } from '@/utils/messages'; import { useEmotionCss } from '@ant-design/use-emotion-css'; import { useModel } from '@umijs/max'; import React, { useEffect, useState } from 'react'; -import { flushSync } from 'react-dom'; import HelmetTitle from './HelmetTitle'; import LoginForm from './LoginForm'; @@ -57,12 +56,10 @@ const Login: React.FC = () => { const fetchUserInfo = async () => { const userInfo = await initialState?.fetchUserInfo?.(); if (userInfo) { - flushSync(() => { - setInitialState((s) => ({ - ...s, - currentUser: userInfo - })); - }); + setInitialState((s) => ({ + ...s, + currentUser: userInfo + })); } }; diff --git a/dinky-web/src/pages/Other/PersonCenter/index.tsx b/dinky-web/src/pages/Other/PersonCenter/index.tsx index a4bff6fe66..d4d0de9657 100644 --- a/dinky-web/src/pages/Other/PersonCenter/index.tsx +++ b/dinky-web/src/pages/Other/PersonCenter/index.tsx @@ -35,7 +35,6 @@ import { SecurityScanTwoTone } from '@ant-design/icons'; import { PageContainer, PageLoading, ProCard } from '@ant-design/pro-components'; import { Descriptions, Divider, Form, Tag } from 'antd'; import { useEffect, useState } from 'react'; -import { flushSync } from 'react-dom'; const PersonCenter = () => { const [form] = Form.useForm(); @@ -47,12 +46,10 @@ const PersonCenter = () => { const fetchUserInfo = async () => { const userInfo = await initialState?.fetchUserInfo?.(); if (userInfo) { - flushSync(() => { - setInitialState((s) => ({ - ...s, - currentUser: userInfo - })); - }); + setInitialState((s) => ({ + ...s, + currentUser: userInfo + })); } }; diff --git a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertInstanceList/index.tsx b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertInstanceList/index.tsx index b96857b426..19fc639343 100644 --- a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertInstanceList/index.tsx +++ b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertInstanceList/index.tsx @@ -23,11 +23,7 @@ import { EnableSwitchBtn } from '@/components/CallBackButton/EnableSwitchBtn'; import { NormalDeleteBtn } from '@/components/CallBackButton/NormalDeleteBtn'; import { DataAction } from '@/components/StyledComponents'; import { Authorized, HasAuthority } from '@/hooks/useAccess'; -import { - getAlertIcon, - getJSONData, - getSmsType -} from '@/pages/RegCenter/Alert/AlertInstance/function'; +import { getAlertIcon, getSmsType } from '@/pages/RegCenter/Alert/AlertInstance/function'; import { createOrModifyAlertInstance, sendTest @@ -36,7 +32,7 @@ import { handleRemoveById, queryDataByParams, updateDataByParam } from '@/servic import { PROTABLE_OPTIONS_PUBLIC, PRO_LIST_CARD_OPTIONS } from '@/services/constants'; import { API_CONSTANTS } from '@/services/endpoints'; import { Alert } from '@/types/RegCenter/data.d'; -import { InitAlertInstanceState } from '@/types/RegCenter/init.d'; +import { InitAlertInstance, InitAlertInstanceState } from '@/types/RegCenter/init.d'; import { AlertInstanceState } from '@/types/RegCenter/state.d'; import { l } from '@/utils/intl'; import { ProList } from '@ant-design/pro-components'; @@ -68,10 +64,13 @@ const AlertInstanceList: React.FC = () => { ); }; + useEffect(() => { + queryAlertInstanceList(); + }, []); + const executeAndCallbackRefresh = async (callback: () => void) => { setAlertInstanceState((prevState) => ({ ...prevState, loading: true })); await callback(); - await queryAlertInstanceList(); setAlertInstanceState((prevState) => ({ ...prevState, loading: false })); }; @@ -85,10 +84,12 @@ const AlertInstanceList: React.FC = () => { content: l('rc.ai.deleteConfirm'), okText: l('button.confirm'), cancelText: l('button.cancel'), - onOk: async () => - executeAndCallbackRefresh(async () => - handleRemoveById(API_CONSTANTS.ALERT_INSTANCE_DELETE, id) - ) + onOk: async () => { + await executeAndCallbackRefresh( + async () => await handleRemoveById(API_CONSTANTS.ALERT_INSTANCE_DELETE, id) + ); + await queryAlertInstanceList(); + } }); }; @@ -102,15 +103,9 @@ const AlertInstanceList: React.FC = () => { id: item.id }) ); + await queryAlertInstanceList(); }; - /** - * query alert instance list - */ - useEffect(() => { - queryAlertInstanceList(); - }, [alertInstanceState.addedOpen, alertInstanceState.editOpen]); - /** * render alert instance sub title * @param item @@ -155,8 +150,9 @@ const AlertInstanceList: React.FC = () => { }; const renderSubType = (item: Alert.AlertInstance) => { - if (JSON.parse(item.params).manufacturers) { - return ` - ${getSmsType(JSON.parse(item.params).manufacturers)}`; + const params = item.params as Alert.AlertInstanceParamsSms; + if (params.suppliers) { + return ` - ${getSmsType(params.suppliers)}`; } }; @@ -183,12 +179,14 @@ const AlertInstanceList: React.FC = () => { /** * render data source */ - const renderDataSource = alertInstanceState.alertInstanceList.map((item) => ({ - subTitle: renderAlertInstanceSubTitle(item), - actions: {renderAlertInstanceActionButton(item)}, - avatar: getAlertIcon(item.type, 60), - content: renderAlertInstanceContent(item) - })); + const renderDataSource = alertInstanceState.alertInstanceList.map((item) => { + return { + subTitle: renderAlertInstanceSubTitle(item), + actions: {renderAlertInstanceActionButton(item)}, + avatar: getAlertIcon(item.type, 60), + content: renderAlertInstanceContent(item) + }; + }); /** * render right tool bar @@ -219,7 +217,7 @@ const AlertInstanceList: React.FC = () => { ...prevState, addedOpen: false, editOpen: false, - value: {} + value: InitAlertInstance })); actionRef.current?.reload(); }; @@ -229,9 +227,10 @@ const AlertInstanceList: React.FC = () => { * @param values */ const handleSubmit = async (values: any) => { - const success = await createOrModifyAlertInstance(getJSONData(values)); + const success = await createOrModifyAlertInstance(values); if (success) { cancelHandler(); + await queryAlertInstanceList(); } }; /** @@ -239,7 +238,7 @@ const AlertInstanceList: React.FC = () => { * @param values */ const handleTestSend = async (values: any) => { - await sendTest(getJSONData(values)); + await executeAndCallbackRefresh(async () => await sendTest(values)); }; /** @@ -265,7 +264,8 @@ const AlertInstanceList: React.FC = () => { onCancel={cancelHandler} modalVisible={alertInstanceState.addedOpen} onSubmit={handleSubmit} - values={{}} + loading={alertInstanceState.loading} + values={InitAlertInstance} /> )} {/* modify */} @@ -277,6 +277,7 @@ const AlertInstanceList: React.FC = () => { modalVisible={alertInstanceState.editOpen} onSubmit={handleSubmit} values={alertInstanceState.value} + loading={alertInstanceState.loading} /> )} diff --git a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/DingTalk/index.tsx b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/DingTalk/index.tsx index 4ed9e85b61..a4a7e1f4ff 100644 --- a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/DingTalk/index.tsx +++ b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/DingTalk/index.tsx @@ -17,7 +17,9 @@ * */ +import { FormSingleColumnList } from '@/components/FormSingleColumnList'; import { SWITCH_OPTIONS } from '@/services/constants'; +import { Alert } from '@/types/RegCenter/data'; import { l } from '@/utils/intl'; import { ProForm, @@ -26,9 +28,38 @@ import { ProFormText, ProFormTextArea } from '@ant-design/pro-components'; +import { FormInstance } from 'antd/es/form/hooks/useForm'; +import { Values } from 'async-validator'; +import { Rule } from 'rc-field-form/lib/interface'; -const DingTalk = (props: any) => { - const { values } = props; +type DingTalkProps = { + values: Partial; + form: FormInstance; +}; +const DingTalk = (props: DingTalkProps) => { + const { values, form } = props; + + const params = values.params as Alert.AlertInstanceParamsDingTalk; + + const validateDingTalkRules = [ + { + required: true, + validator: async (rule: Rule, value: string) => { + if (!value) { + return Promise.reject(l('rc.ai.atMobiles')); + } + const fieldValue = form.getFieldValue(['params', 'atMobiles']); + const filterField = fieldValue.filter((item: string) => item === value); + if (filterField.length > 1) { + return Promise.reject(l('rc.ai.atMobilesRepeat')); + } + } + }, + { + pattern: /^1[3456789]\d{9}$/, + message: l('rc.ai.atMobilesFormat') + } + ]; return ( <> @@ -37,21 +68,21 @@ const DingTalk = (props: any) => { @@ -60,38 +91,31 @@ const DingTalk = (props: any) => { - + - {/* if not Enable At All this group do render */} - {!values.isAtAll && ( - <> - - - )} {/* if Enable Proxy this group do render */} - {values.isEnableProxy && ( + {params.isEnableProxy && ( <> { { )} + {/* if not Enable At All this group do render */} + {!params.isAtAll && ( + <> + + + )} ); }; diff --git a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Email/index.tsx b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Email/index.tsx index 271f80f300..0042128da7 100644 --- a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Email/index.tsx +++ b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Email/index.tsx @@ -17,18 +17,52 @@ * */ +import { FormSingleColumnList } from '@/components/FormSingleColumnList'; import { SWITCH_OPTIONS } from '@/services/constants'; +import { Alert } from '@/types/RegCenter/data'; import { l } from '@/utils/intl'; import { + ProCard, ProForm, ProFormDigit, ProFormSwitch, - ProFormText, - ProFormTextArea + ProFormText } from '@ant-design/pro-components'; +import { FormInstance } from 'antd/es/form/hooks/useForm'; +import { Values } from 'async-validator'; +import { Rule } from 'rc-field-form/lib/interface'; -const Email = (props: any) => { - const { values } = props; +type EmailProps = { + values: Partial; + form: FormInstance; +}; +const Email = (props: EmailProps) => { + const { values, form } = props; + const params = values.params as Alert.AlertInstanceParamsEmail; + + const validateEmailRules = ( + namePath: string | string[], + nullTips: string, + repeatTips: string + ) => [ + { + required: true, + validator: async (rule: Rule, value: string) => { + if (!value) { + return Promise.reject(nullTips); + } + const fieldValue = form.getFieldValue(namePath); + const filterField = fieldValue.filter((item: string) => item === value); + if (filterField.length > 1) { + return Promise.reject(repeatTips); + } + } + }, + { + pattern: /^([A-Za-z0-9_\-.])+@([A-Za-z0-9_\-.])+\.([A-Za-z]{2,4})$/, + message: l('rc.ai.emailPleaseHolderFormat') + } + ]; return ( <> @@ -36,60 +70,82 @@ const Email = (props: any) => { {/* base columns */} - - - - + + + + + + + + + + {/* switch */} @@ -103,10 +159,10 @@ const Email = (props: any) => { {/* proxy */} - {values.enableSmtpAuth && ( + {params.enableSmtpAuth && ( <> { placeholder={l('rc.ai.emailUserPleaseHolder')} /> { - {/* if choose attachment || table attachment , this input is render */} - {(values.msgtype === 'attachment' || values.msgtype === 'table attachment') && ( - - )} - {/* ssl */} - {values.sslEnable && ( + {params.sslEnable && ( { - const { values } = props; - console.log('FeiShu props', props); +type FeiShuProps = { + values: Partial; + form: FormInstance; +}; +const FeiShu = (props: FeiShuProps) => { + const { values, form } = props; + + const params = values.params as Alert.AlertInstanceParamsFeiShu; + + const validateFeiShuUserRules = [ + { + required: true, + validator: async (rule: Rule, value: string) => { + if (!value) { + return Promise.reject(l('rc.ai.atUsersPleaseHolder')); + } + const fieldValue = form.getFieldValue(['params', 'atUsers']); + const filterField = fieldValue.filter((item: string) => item === value); + if (filterField.length > 1) { + return Promise.reject(l('rc.ai.atUsersRepeat')); + } + } + } + ]; /** * render @@ -40,21 +66,21 @@ const FeiShu = (props: any) => { @@ -64,38 +90,31 @@ const FeiShu = (props: any) => { - + - {/* if not Enable At All this group do render */} - {!values.isAtAll && ( - <> - - - )} {/* if Enable Proxy this group do render */} - {values.isEnableProxy && ( + {params.isEnableProxy && ( <> { { )} + {/* if not Enable At All this group do render */} + {!params.isAtAll && ( + <> + + + )} ); }; diff --git a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Sms/constants.tsx b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Sms/constants.tsx new file mode 100644 index 0000000000..fe920ce7c0 --- /dev/null +++ b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Sms/constants.tsx @@ -0,0 +1,129 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +export const YunArea = [ + { + value: 'cn-hangzhou', + label: '华东1(杭州)' + }, + { + value: 'cn-shanghai', + label: '华东2(上海)' + }, + { + value: 'cn-qingdao', + label: '华北1(青岛)' + }, + { + value: 'cn-beijing', + label: '华北2(北京)' + }, + { + value: 'cn-zhangjiakou', + label: '华北3(张家口)' + }, + { + value: 'cn-huhehaote', + label: '华北5(呼和浩特)' + }, + { + value: 'cn-wulanchabu', + label: '华北6(乌兰察布)' + }, + { + value: 'cn-shenzhen', + label: '华南1(深圳)' + }, + { + value: 'cn-heyuan', + label: '华南2(河源)' + }, + { + value: 'cn-guangzhou', + label: '华南3(广州)' + }, + { + value: 'cn-chengdu', + label: '西南1(成都)' + }, + { + value: 'cn-hongkong', + label: '中国香港' + }, + { + value: 'ap-southeast-1', + label: '新加坡' + }, + { + value: 'ap-southeast-2', + label: '澳大利亚(悉尼)' + }, + { + value: 'ap-southeast-3', + label: '马来西亚(吉隆坡)' + }, + { + value: 'ap-southeast-5', + label: '印度尼西亚(雅加达)' + }, + { + value: 'ap-southeast-6', + label: '菲律宾(马尼拉)' + }, + { + value: 'ap-southeast-7', + label: '泰国(曼谷)' + }, + { + value: 'ap-south-1', + label: '印度(孟买)' + }, + { + value: 'ap-northeast-1', + label: '日本(东京)' + }, + { + value: 'ap-northeast-2', + label: '韩国(首尔)' + }, + { + value: 'us-west-1', + label: '美国(硅谷)' + }, + { + value: 'us-east-1', + label: '美东(弗吉尼亚)' + }, + { + value: 'eu-central-1', + label: '德国(法兰克福)' + }, + { + value: 'eu-west-1', + label: '英国(伦敦)' + }, + { + value: 'me-central-1', + label: '沙特(利雅得)' + }, + { + value: 'me-east-1', + label: '阿联酋(迪拜)' + } +]; diff --git a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Sms/function.tsx b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Sms/function.tsx index a4b6114e63..204bb70c81 100644 --- a/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Sms/function.tsx +++ b/dinky-web/src/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Sms/function.tsx @@ -17,89 +17,134 @@ * */ +import { YunArea } from '@/pages/RegCenter/Alert/AlertInstance/components/AlertTypeChoose/InstanceForm/Sms/constants'; import { l } from '@/utils/intl'; -import { ProForm, ProFormDigit, ProFormSwitch, ProFormTextArea } from '@ant-design/pro-components'; +import { + ProForm, + ProFormDigit, + ProFormSelect, + ProFormSwitch, + ProFormTextArea +} from '@ant-design/pro-components'; import { ProFormText } from '@ant-design/pro-form'; +import { randomStr } from '@antfu/utils'; -export const renderCommonSmsForm = () => { +export const renderCommonSmsForm = (smsType: string) => { return ( <> - + +