[Feature-8245][Alert] Add Alert Plugin Telegram (#8246)
parent
a680089a6a
commit
84b004d960
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2fc905b1875f2e6b91c4201a4dc6eaa21b86547e
|
Subproject commit c2fa3e5a37b75a5819e2c8127caec1c2a0d088e8
|
||||||
|
|
@ -39,7 +39,7 @@ public final class SlackAlertChannelFactory implements AlertChannelFactory {
|
||||||
public List<PluginParams> params() {
|
public List<PluginParams> params() {
|
||||||
List<PluginParams> paramsList = new LinkedList<>();
|
List<PluginParams> paramsList = new LinkedList<>();
|
||||||
|
|
||||||
InputParam webHookParam = InputParam.newBuilder(SlackParamsConstants.SLACK_WEN_HOOK_URL_NAME, SlackParamsConstants.SLACK_WEB_HOOK_URL)
|
InputParam webHookParam = InputParam.newBuilder(SlackParamsConstants.SLACK_WEB_HOOK_URL_NAME, SlackParamsConstants.SLACK_WEB_HOOK_URL)
|
||||||
.addValidate(Validate.newBuilder()
|
.addValidate(Validate.newBuilder()
|
||||||
.setRequired(true)
|
.setRequired(true)
|
||||||
.build())
|
.build())
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ package org.apache.dolphinscheduler.plugin.alert.slack;
|
||||||
|
|
||||||
public final class SlackParamsConstants {
|
public final class SlackParamsConstants {
|
||||||
public static final String SLACK_WEB_HOOK_URL = "$t('webhook')";
|
public static final String SLACK_WEB_HOOK_URL = "$t('webhook')";
|
||||||
public static final String SLACK_WEN_HOOK_URL_NAME = "webHook";
|
public static final String SLACK_WEB_HOOK_URL_NAME = "webHook";
|
||||||
public static final String SLACK_BOT = "$t('Username')";
|
public static final String SLACK_BOT = "$t('Username')";
|
||||||
public static final String SLACK_BOT_NAME = "username";
|
public static final String SLACK_BOT_NAME = "username";
|
||||||
public static final String TEXT = "text";
|
public static final String TEXT = "text";
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public final class SlackSender {
|
||||||
private final String botName;
|
private final String botName;
|
||||||
|
|
||||||
public SlackSender(Map<String, String> slackAlertParam) {
|
public SlackSender(Map<String, String> slackAlertParam) {
|
||||||
webHookUrl = slackAlertParam.get(SlackParamsConstants.SLACK_WEN_HOOK_URL_NAME);
|
webHookUrl = slackAlertParam.get(SlackParamsConstants.SLACK_WEB_HOOK_URL_NAME);
|
||||||
botName = slackAlertParam.get(SlackParamsConstants.SLACK_BOT_NAME);
|
botName = slackAlertParam.get(SlackParamsConstants.SLACK_BOT_NAME);
|
||||||
Preconditions.checkArgument(!Objects.isNull(webHookUrl), "SlackWebHookURL can not be null");
|
Preconditions.checkArgument(!Objects.isNull(webHookUrl), "SlackWebHookURL can not be null");
|
||||||
Preconditions.checkArgument(webHookUrl.startsWith("https://hooks.slack.com/services/"), "SlackWebHookURL invalidate");
|
Preconditions.checkArgument(webHookUrl.startsWith("https://hooks.slack.com/services/"), "SlackWebHookURL invalidate");
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ public class SlackSenderTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSendMessage() {
|
public void testSendMessage() {
|
||||||
Map<String, String> alertparam = new HashMap<>();
|
Map<String, String> alertparam = new HashMap<>();
|
||||||
alertparam.put(SlackParamsConstants.SLACK_WEN_HOOK_URL_NAME,
|
alertparam.put(SlackParamsConstants.SLACK_WEB_HOOK_URL_NAME,
|
||||||
"https://hooks.slack.com/services/123456");
|
"https://hooks.slack.com/services/123456");
|
||||||
alertparam.put(SlackParamsConstants.SLACK_BOT_NAME, "Dolphinscheduler");
|
alertparam.put(SlackParamsConstants.SLACK_BOT_NAME, "Dolphinscheduler");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>dolphinscheduler-alert-plugins</artifactId>
|
||||||
|
<groupId>org.apache.dolphinscheduler</groupId>
|
||||||
|
<version>2.0.4-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>dolphinscheduler-alert-telegram</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.apache.dolphinscheduler.plugin.alert.telegram;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertChannel;
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertData;
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertInfo;
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertResult;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class TelegramAlertChannel implements AlertChannel {
|
||||||
|
@Override
|
||||||
|
public AlertResult process(AlertInfo info) {
|
||||||
|
Map<String, String> alertParams = info.getAlertParams();
|
||||||
|
if (alertParams == null || alertParams.isEmpty()) {
|
||||||
|
return new AlertResult("false", "Telegram alert params is empty");
|
||||||
|
}
|
||||||
|
AlertData data = info.getAlertData();
|
||||||
|
return new TelegramSender(alertParams).sendMessage(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* 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.apache.dolphinscheduler.plugin.alert.telegram;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertChannel;
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertChannelFactory;
|
||||||
|
import org.apache.dolphinscheduler.spi.params.PasswordParam;
|
||||||
|
import org.apache.dolphinscheduler.spi.params.base.ParamsOptions;
|
||||||
|
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
|
||||||
|
import org.apache.dolphinscheduler.spi.params.base.Validate;
|
||||||
|
import org.apache.dolphinscheduler.spi.params.input.InputParam;
|
||||||
|
import org.apache.dolphinscheduler.spi.params.radio.RadioParam;
|
||||||
|
import org.apache.dolphinscheduler.spi.params.select.SelectParam;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.apache.dolphinscheduler.spi.utils.Constants.*;
|
||||||
|
|
||||||
|
@AutoService(AlertChannelFactory.class)
|
||||||
|
public final class TelegramAlertChannelFactory implements AlertChannelFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "Telegram";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlertChannel create() {
|
||||||
|
return new TelegramAlertChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PluginParams> params() {
|
||||||
|
|
||||||
|
|
||||||
|
InputParam webHookParam = InputParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_WEB_HOOK, TelegramParamsConstants.TELEGRAM_WEB_HOOK)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(true)
|
||||||
|
.build())
|
||||||
|
.setPlaceholder("telegram web hook")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InputParam botTokenParam = InputParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_BOT_TOKEN, TelegramParamsConstants.TELEGRAM_BOT_TOKEN)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(true)
|
||||||
|
.build())
|
||||||
|
.setPlaceholder("telegram bot token")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InputParam chatIdParam = InputParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_CHAT_ID, TelegramParamsConstants.TELEGRAM_CHAT_ID)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(true)
|
||||||
|
.build())
|
||||||
|
.setPlaceholder("telegram channel chat id")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SelectParam parseMode = SelectParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_PARSE_MODE, TelegramParamsConstants.TELEGRAM_PARSE_MODE)
|
||||||
|
.addOptions(new ParamsOptions(TelegramAlertConstants.PARSE_MODE_TXT, TelegramAlertConstants.PARSE_MODE_TXT, false))
|
||||||
|
.addOptions(new ParamsOptions(TelegramAlertConstants.PARSE_MODE_MARKDOWN, TelegramAlertConstants.PARSE_MODE_MARKDOWN, false))
|
||||||
|
.addOptions(new ParamsOptions(TelegramAlertConstants.PARSE_MODE_MARKDOWN_V2, TelegramAlertConstants.PARSE_MODE_MARKDOWN_V2, false))
|
||||||
|
.addOptions(new ParamsOptions(TelegramAlertConstants.PARSE_MODE_HTML, TelegramAlertConstants.PARSE_MODE_HTML, false))
|
||||||
|
.setValue(TelegramAlertConstants.PARSE_MODE_TXT)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(true)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
RadioParam isEnableProxy = RadioParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_PROXY_ENABLE, TelegramParamsConstants.TELEGRAM_PROXY_ENABLE)
|
||||||
|
.addParamsOptions(new ParamsOptions(STRING_YES, STRING_TRUE, false))
|
||||||
|
.addParamsOptions(new ParamsOptions(STRING_NO, STRING_FALSE, false))
|
||||||
|
.setValue(STRING_FALSE)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(false)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InputParam proxyParam = InputParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_PROXY, TelegramParamsConstants.TELEGRAM_PROXY)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(false)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InputParam portParam = InputParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_PORT, TelegramParamsConstants.TELEGRAM_PORT)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(false)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InputParam userParam = InputParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_USER, TelegramParamsConstants.TELEGRAM_USER)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(false)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
PasswordParam passwordParam = PasswordParam.newBuilder(TelegramParamsConstants.NAME_TELEGRAM_PASSWORD, TelegramParamsConstants.TELEGRAM_PASSWORD)
|
||||||
|
.addValidate(Validate.newBuilder()
|
||||||
|
.setRequired(false)
|
||||||
|
.build())
|
||||||
|
.setPlaceholder("if enable use authentication, you need input password")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return Arrays.asList(webHookParam, botTokenParam, chatIdParam, parseMode, isEnableProxy, proxyParam, portParam, userParam, passwordParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.apache.dolphinscheduler.plugin.alert.telegram;
|
||||||
|
|
||||||
|
public final class TelegramAlertConstants {
|
||||||
|
|
||||||
|
static final String PARSE_MODE_TXT = "Txt";
|
||||||
|
|
||||||
|
static final String PARSE_MODE_MARKDOWN = "Markdown";
|
||||||
|
|
||||||
|
static final String PARSE_MODE_MARKDOWN_V2 = "MarkdownV2";
|
||||||
|
|
||||||
|
static final String PARSE_MODE_HTML = "Html";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TELEGRAM_PUSH_URL
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* https://api.telegram.org/bot{botToken}/sendMessage
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
static final String TELEGRAM_PUSH_URL = "https://api.telegram.org/bot{botToken}/sendMessage";
|
||||||
|
|
||||||
|
private TelegramAlertConstants() {
|
||||||
|
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.apache.dolphinscheduler.plugin.alert.telegram;
|
||||||
|
|
||||||
|
|
||||||
|
public final class TelegramParamsConstants {
|
||||||
|
|
||||||
|
static final String TELEGRAM_WEB_HOOK = "$t('webHook')";
|
||||||
|
static final String NAME_TELEGRAM_WEB_HOOK = "webHook";
|
||||||
|
|
||||||
|
static final String TELEGRAM_BOT_TOKEN = "botToken";
|
||||||
|
static final String NAME_TELEGRAM_BOT_TOKEN = "botToken";
|
||||||
|
|
||||||
|
static final String TELEGRAM_CHAT_ID = "chatId";
|
||||||
|
static final String NAME_TELEGRAM_CHAT_ID = "chatId";
|
||||||
|
|
||||||
|
static final String TELEGRAM_PARSE_MODE = "parseMode";
|
||||||
|
static final String NAME_TELEGRAM_PARSE_MODE = "parseMode";
|
||||||
|
|
||||||
|
static final String TELEGRAM_PROXY_ENABLE = "$t('isEnableProxy')";
|
||||||
|
static final String NAME_TELEGRAM_PROXY_ENABLE = "IsEnableProxy";
|
||||||
|
|
||||||
|
static final String TELEGRAM_PROXY = "$t('proxy')";
|
||||||
|
static final String NAME_TELEGRAM_PROXY = "Proxy";
|
||||||
|
|
||||||
|
static final String TELEGRAM_PORT = "$t('port')";
|
||||||
|
static final String NAME_TELEGRAM_PORT = "Port";
|
||||||
|
|
||||||
|
static final String TELEGRAM_USER = "$t('user')";
|
||||||
|
static final String NAME_TELEGRAM_USER = "User";
|
||||||
|
|
||||||
|
static final String TELEGRAM_PASSWORD = "$t('password')";
|
||||||
|
static final String NAME_TELEGRAM_PASSWORD = "Password";
|
||||||
|
|
||||||
|
private TelegramParamsConstants() {
|
||||||
|
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
* 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.apache.dolphinscheduler.plugin.alert.telegram;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertData;
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertResult;
|
||||||
|
import org.apache.dolphinscheduler.spi.utils.JSONUtils;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpHeaders;
|
||||||
|
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.config.RequestConfig;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
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;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class TelegramSender {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(TelegramSender.class);
|
||||||
|
|
||||||
|
private static final String BOT_TOKEN_REGEX = "{botToken}";
|
||||||
|
|
||||||
|
private final String chatId;
|
||||||
|
|
||||||
|
private final String parseMode;
|
||||||
|
|
||||||
|
private final Boolean enableProxy;
|
||||||
|
|
||||||
|
private String botToken;
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
private String proxy;
|
||||||
|
|
||||||
|
private Integer port;
|
||||||
|
|
||||||
|
private String user;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
|
||||||
|
TelegramSender(Map<String, String> config) {
|
||||||
|
url = config.get(TelegramParamsConstants.NAME_TELEGRAM_WEB_HOOK);
|
||||||
|
botToken = config.get(TelegramParamsConstants.NAME_TELEGRAM_BOT_TOKEN);
|
||||||
|
chatId = config.get(TelegramParamsConstants.NAME_TELEGRAM_CHAT_ID);
|
||||||
|
parseMode = config.get(TelegramParamsConstants.NAME_TELEGRAM_PARSE_MODE);
|
||||||
|
if (url == null || url.isEmpty()) {
|
||||||
|
url = TelegramAlertConstants.TELEGRAM_PUSH_URL.replace(BOT_TOKEN_REGEX, botToken);
|
||||||
|
} else {
|
||||||
|
url = url.replace(BOT_TOKEN_REGEX, botToken);
|
||||||
|
}
|
||||||
|
enableProxy = Boolean.valueOf(config.get(TelegramParamsConstants.NAME_TELEGRAM_PROXY_ENABLE));
|
||||||
|
if (Boolean.TRUE.equals(enableProxy)) {
|
||||||
|
port = Integer.parseInt(config.get(TelegramParamsConstants.NAME_TELEGRAM_PORT));
|
||||||
|
proxy = config.get(TelegramParamsConstants.NAME_TELEGRAM_PROXY);
|
||||||
|
user = config.get(TelegramParamsConstants.NAME_TELEGRAM_USER);
|
||||||
|
password = config.get(TelegramParamsConstants.NAME_TELEGRAM_PASSWORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sendMessage
|
||||||
|
*
|
||||||
|
* @param alertData alert data
|
||||||
|
* @return alert result
|
||||||
|
* @see <a href="https://core.telegram.org/bots/api#sendmessage">telegram bot api</a>
|
||||||
|
*/
|
||||||
|
public AlertResult sendMessage(AlertData alertData) {
|
||||||
|
AlertResult result;
|
||||||
|
try {
|
||||||
|
String resp = sendInvoke(alertData.getTitle(), alertData.getContent());
|
||||||
|
result = parseRespToResult(resp);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("send telegram alert msg exception : {}", e.getMessage());
|
||||||
|
result = new AlertResult();
|
||||||
|
result.setStatus("false");
|
||||||
|
result.setMessage(String.format("send telegram alert fail. %s", e.getMessage()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlertResult parseRespToResult(String resp) {
|
||||||
|
AlertResult result = new AlertResult();
|
||||||
|
result.setStatus("false");
|
||||||
|
if (null == resp || resp.isEmpty()) {
|
||||||
|
result.setMessage("send telegram msg error. telegram server resp is empty");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
TelegramSendMsgResponse response = JSONUtils.parseObject(resp, TelegramSendMsgResponse.class);
|
||||||
|
if (null == response) {
|
||||||
|
result.setMessage("send telegram msg fail.");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (!response.isOk()) {
|
||||||
|
result.setMessage(String.format("send telegram alert fail. telegram server error_code: %d, description: %s",
|
||||||
|
response.errorCode, response.description));
|
||||||
|
} else {
|
||||||
|
result.setStatus("true");
|
||||||
|
result.setMessage("send telegram msg success.");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String sendInvoke(String title, String content) throws IOException {
|
||||||
|
HttpPost httpPost = buildHttpPost(url, buildMsgJsonStr(content));
|
||||||
|
CloseableHttpClient httpClient;
|
||||||
|
if (Boolean.TRUE.equals(enableProxy)) {
|
||||||
|
httpClient = getProxyClient(proxy, port, user, password);
|
||||||
|
RequestConfig rcf = getProxyConfig(proxy, port);
|
||||||
|
httpPost.setConfig(rcf);
|
||||||
|
} else {
|
||||||
|
httpClient = getDefaultClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
CloseableHttpResponse response = httpClient.execute(httpPost);
|
||||||
|
String resp;
|
||||||
|
try {
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
resp = EntityUtils.toString(entity, "UTF-8");
|
||||||
|
EntityUtils.consume(entity);
|
||||||
|
} finally {
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
logger.info("Telegram send title :{},content : {}, resp: {}", title, content, resp);
|
||||||
|
return resp;
|
||||||
|
} finally {
|
||||||
|
httpClient.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildMsgJsonStr(String content) {
|
||||||
|
Map<String, Object> items = new HashMap<>();
|
||||||
|
items.put("chat_id", chatId);
|
||||||
|
if (!isTextParseMode()) {
|
||||||
|
items.put("parse_mode", parseMode);
|
||||||
|
}
|
||||||
|
items.put("text", content);
|
||||||
|
return JSONUtils.toJsonString(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTextParseMode() {
|
||||||
|
return null == parseMode || TelegramAlertConstants.PARSE_MODE_TXT.equals(parseMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TelegramSendMsgResponse {
|
||||||
|
@JsonProperty("ok")
|
||||||
|
private Boolean ok;
|
||||||
|
@JsonProperty("error_code")
|
||||||
|
private Integer errorCode;
|
||||||
|
@JsonProperty("description")
|
||||||
|
private String description;
|
||||||
|
@JsonProperty("result")
|
||||||
|
private Object result;
|
||||||
|
|
||||||
|
public boolean isOk() {
|
||||||
|
return null != ok && ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getOk() {
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty("ok")
|
||||||
|
public void setOk(Boolean ok) {
|
||||||
|
this.ok = ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty("error_code")
|
||||||
|
public void setErrorCode(Integer errorCode) {
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getErrorCode() {
|
||||||
|
return errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty("description")
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty("result")
|
||||||
|
public void setResult(Object result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpPost buildHttpPost(String url, String msg) {
|
||||||
|
HttpPost post = new HttpPost(url);
|
||||||
|
StringEntity entity = new StringEntity(msg, StandardCharsets.UTF_8);
|
||||||
|
post.setEntity(entity);
|
||||||
|
post.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
|
||||||
|
return post;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CloseableHttpClient getDefaultClient() {
|
||||||
|
return HttpClients.createDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CloseableHttpClient getProxyClient(String proxy, int port, String user, String password) {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RequestConfig getProxyConfig(String proxy, int port) {
|
||||||
|
HttpHost httpProxy = new HttpHost(proxy, port);
|
||||||
|
return RequestConfig.custom().setProxy(httpProxy).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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.apache.dolphinscheduler.plugin.alert.telegram;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertChannel;
|
||||||
|
import org.apache.dolphinscheduler.spi.params.base.PluginParams;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TelegramAlertChannelFactoryTest {
|
||||||
|
|
||||||
|
private TelegramAlertChannelFactory telegramAlertChannelFactory = new TelegramAlertChannelFactory();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTestGetName() {
|
||||||
|
Assert.assertEquals("Telegram", telegramAlertChannelFactory.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetParams() {
|
||||||
|
List<PluginParams> params = telegramAlertChannelFactory.params();
|
||||||
|
Assert.assertEquals(9, params.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreate() {
|
||||||
|
AlertChannel alertChannel = telegramAlertChannelFactory.create();
|
||||||
|
Assert.assertTrue(alertChannel instanceof TelegramAlertChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* 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.apache.dolphinscheduler.plugin.alert.telegram;
|
||||||
|
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertData;
|
||||||
|
import org.apache.dolphinscheduler.alert.api.AlertResult;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TelegramSenderTest {
|
||||||
|
|
||||||
|
private static Map<String, String> telegramConfig = new HashMap<>();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initConfig() {
|
||||||
|
telegramConfig.put(TelegramParamsConstants.NAME_TELEGRAM_WEB_HOOK,
|
||||||
|
"https://api.telegram.org/bot{botToken}/sendMessage");
|
||||||
|
telegramConfig.put(
|
||||||
|
TelegramParamsConstants.NAME_TELEGRAM_BOT_TOKEN, "BOT_TOKEN");
|
||||||
|
telegramConfig.put(
|
||||||
|
TelegramParamsConstants.NAME_TELEGRAM_CHAT_ID, "CHAT_ID");
|
||||||
|
telegramConfig.put(
|
||||||
|
TelegramParamsConstants.NAME_TELEGRAM_PARSE_MODE, TelegramAlertConstants.PARSE_MODE_TXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendMessageFailByParamToken() {
|
||||||
|
AlertData alertData = new AlertData();
|
||||||
|
alertData.setTitle("[telegram alert] test title");
|
||||||
|
alertData.setContent("telegram test content");
|
||||||
|
telegramConfig.put(
|
||||||
|
TelegramParamsConstants.NAME_TELEGRAM_BOT_TOKEN, "XXXXXXX");
|
||||||
|
TelegramSender telegramSender = new TelegramSender(telegramConfig);
|
||||||
|
AlertResult result = telegramSender.sendMessage(alertData);
|
||||||
|
Assert.assertEquals("false", result.getStatus());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendMessageFailByChatId() {
|
||||||
|
AlertData alertData = new AlertData();
|
||||||
|
alertData.setTitle("[telegram alert] test title");
|
||||||
|
alertData.setContent("telegram test content");
|
||||||
|
telegramConfig.put(
|
||||||
|
TelegramParamsConstants.NAME_TELEGRAM_CHAT_ID, "-XXXXXXX");
|
||||||
|
TelegramSender telegramSender = new TelegramSender(telegramConfig);
|
||||||
|
AlertResult result = telegramSender.sendMessage(alertData);
|
||||||
|
Assert.assertEquals("false", result.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendMessage() {
|
||||||
|
AlertData alertData = new AlertData();
|
||||||
|
alertData.setTitle("[telegram alert] test title");
|
||||||
|
alertData.setContent("telegram test content");
|
||||||
|
TelegramSender telegramSender = new TelegramSender(telegramConfig);
|
||||||
|
AlertResult result = telegramSender.sendMessage(alertData);
|
||||||
|
Assert.assertEquals("false", result.getStatus());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendMessageByMarkdown() {
|
||||||
|
AlertData alertData = new AlertData();
|
||||||
|
alertData.setTitle("[telegram alert]test markdown");
|
||||||
|
alertData.setContent("```python \npre-formatted fixed-width code block written in the Python programming language```");
|
||||||
|
telegramConfig.put(
|
||||||
|
TelegramParamsConstants.NAME_TELEGRAM_PARSE_MODE, TelegramAlertConstants.PARSE_MODE_MARKDOWN);
|
||||||
|
TelegramSender telegramSender = new TelegramSender(telegramConfig);
|
||||||
|
AlertResult result = telegramSender.sendMessage(alertData);
|
||||||
|
Assert.assertEquals("false", result.getStatus());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSendMessageByHtml() {
|
||||||
|
AlertData alertData = new AlertData();
|
||||||
|
alertData.setTitle("[telegram alert]test html");
|
||||||
|
alertData.setContent("<b>bold</b>");
|
||||||
|
telegramConfig.put(
|
||||||
|
TelegramParamsConstants.NAME_TELEGRAM_PARSE_MODE, TelegramAlertConstants.PARSE_MODE_HTML);
|
||||||
|
TelegramSender telegramSender = new TelegramSender(telegramConfig);
|
||||||
|
AlertResult result = telegramSender.sendMessage(alertData);
|
||||||
|
Assert.assertEquals("false", result.getStatus());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
<module>dolphinscheduler-alert-slack</module>
|
<module>dolphinscheduler-alert-slack</module>
|
||||||
<module>dolphinscheduler-alert-pagerduty</module>
|
<module>dolphinscheduler-alert-pagerduty</module>
|
||||||
<module>dolphinscheduler-alert-webexteams</module>
|
<module>dolphinscheduler-alert-webexteams</module>
|
||||||
|
<module>dolphinscheduler-alert-telegram</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,11 @@
|
||||||
<artifactId>dolphinscheduler-alert-webexteams</artifactId>
|
<artifactId>dolphinscheduler-alert-webexteams</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dolphinscheduler</groupId>
|
||||||
|
<artifactId>dolphinscheduler-alert-telegram</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dolphinscheduler</groupId>
|
<groupId>org.apache.dolphinscheduler</groupId>
|
||||||
<artifactId>dolphinscheduler-dao</artifactId>
|
<artifactId>dolphinscheduler-dao</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -664,7 +664,10 @@ const security = {
|
||||||
path: 'Script Path',
|
path: 'Script Path',
|
||||||
type: 'Type',
|
type: 'Type',
|
||||||
sendType: 'Send Type',
|
sendType: 'Send Type',
|
||||||
username: 'Username'
|
username: 'Username',
|
||||||
|
botToken: 'Bot Token',
|
||||||
|
chatId: 'Channel Chat Id',
|
||||||
|
parseMode: 'Parse Mode'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -660,7 +660,10 @@ const security = {
|
||||||
path: '脚本路径',
|
path: '脚本路径',
|
||||||
type: '类型',
|
type: '类型',
|
||||||
sendType: '发送类型',
|
sendType: '发送类型',
|
||||||
username: '用户名'
|
username: '用户名',
|
||||||
|
botToken: '机器人Token',
|
||||||
|
chatId: '频道ID',
|
||||||
|
parseMode: '解析类型'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
5
pom.xml
5
pom.xml
|
|
@ -362,6 +362,11 @@
|
||||||
<artifactId>dolphinscheduler-alert-webexteams</artifactId>
|
<artifactId>dolphinscheduler-alert-webexteams</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dolphinscheduler</groupId>
|
||||||
|
<artifactId>dolphinscheduler-alert-telegram</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dolphinscheduler</groupId>
|
<groupId>org.apache.dolphinscheduler</groupId>
|
||||||
<artifactId>dolphinscheduler-registry-api</artifactId>
|
<artifactId>dolphinscheduler-registry-api</artifactId>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue