diff --git a/bundles/action/org.openhab.action.telegram/README.md b/bundles/action/org.openhab.action.telegram/README.md index 8d0212ac242..60fb5f421a4 100644 --- a/bundles/action/org.openhab.action.telegram/README.md +++ b/bundles/action/org.openhab.action.telegram/README.md @@ -42,11 +42,14 @@ The URL can be specified using the http, https, and file protocols. The action can be configured in `services/telegram.cfg`. -| Property | Default | Required | Description | -|---------------------|---------|:--------:|---------------------------------------| -| bots | | Yes | Comma-separated list of ``s | -| `.chatId` | | Yes | chat id | -| `.token` | | Yes | authentication token | +| Property | Default | Required | Description | +|-------------------------|---------|:--------:|----------------------------------------------------------------------------------------------| +| bots | | Yes | Comma-separated list of ``s | +| `.chatId` | | Yes | chat id | +| `.token` | | Yes | authentication token | +| `.parseMode` | | No | Support for formatted messages, values: `Markdown` or `HTML`. Default: no formatting is used | + +See https://core.telegram.org/bots/api#markdown-style for formatting options if `Markdown` or `HTML` is set as `parseMode`. ### Configuration example @@ -55,6 +58,7 @@ bots=bot1,bot2 bot1.chatId=22334455 bot1.token=xxxxxxxxxxx +bot1.parseMode=Markdown bot2.chatId=654321 bot2.token=yyyyyyyyyyy diff --git a/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/Telegram.java b/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/Telegram.java index acb3d16b8e2..9d549dda630 100644 --- a/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/Telegram.java +++ b/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/Telegram.java @@ -15,9 +15,11 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.zip.GZIPInputStream; import java.util.zip.InflaterInputStream; @@ -45,6 +47,7 @@ import org.apache.commons.httpclient.methods.multipart.StringPart; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; import org.openhab.core.scriptengine.action.ActionDoc; import org.openhab.core.scriptengine.action.ParamDoc; import org.slf4j.Logger; @@ -74,26 +77,30 @@ public static void addToken(String group, String chatId, String token) { groupTokens.put(group, new TelegramBot(chatId, token)); } + public static void addToken(String group, String chatId, String token, String parseMode) { + groupTokens.put(group, new TelegramBot(chatId, token, parseMode)); + } + @ActionDoc(text = "Sends a Telegram via Telegram REST API - direct message") - static public boolean sendTelegram(@ParamDoc(name = "group") String group, + public static boolean sendTelegram(@ParamDoc(name = "group") String group, @ParamDoc(name = "message") String message) { - if (groupTokens.get(group) == null) { + TelegramBot bot = groupTokens.get(group); + if (bot == null) { logger.warn("Bot '{}' not defined; action skipped.", group); return false; } - String url = String.format(TELEGRAM_URL, groupTokens.get(group).getToken()); + String url = String.format(TELEGRAM_URL, bot.getToken()); HttpClient client = new HttpClient(); - PostMethod postMethod = new PostMethod(url); - postMethod.getParams().setContentCharset("UTF-8"); - postMethod.getParams().setSoTimeout(HTTP_TIMEOUT); - postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, - new DefaultHttpMethodRetryHandler(HTTP_RETRIES, false)); - NameValuePair[] data = { new NameValuePair("chat_id", groupTokens.get(group).getChatId()), - new NameValuePair("text", message) }; + PostMethod postMethod = createPostMethod(url, HTTP_TIMEOUT, HTTP_RETRIES); + NameValuePair[] data = { + new NameValuePair("chat_id", bot.getChatId()), + new NameValuePair("text", message), + new NameValuePair("parse_mode", bot.getParseMode()) + }; postMethod.setRequestBody(data); try { @@ -139,22 +146,31 @@ static public boolean sendTelegram(@ParamDoc(name = "group") String group, } } + private static PostMethod createPostMethod(String url, int timeOut, int retries) { + PostMethod postMethod = new PostMethod(url); + postMethod.getParams().setContentCharset("UTF-8"); + postMethod.getParams().setSoTimeout(timeOut); + postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, + new DefaultHttpMethodRetryHandler(retries, false)); + return postMethod; + } + @ActionDoc(text = "Sends a Telegram via Telegram REST API - build message with format and args") - static public boolean sendTelegram(@ParamDoc(name = "group") String group, @ParamDoc(name = "format") String format, + public static boolean sendTelegram(@ParamDoc(name = "group") String group, @ParamDoc(name = "format") String format, @ParamDoc(name = "args") Object... args) { return sendTelegram(group, String.format(format, args)); } @ActionDoc(text = "Sends a Picture via Telegram REST API") - static public boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, + public static boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, @ParamDoc(name = "photoURL") String photoURL, @ParamDoc(name = "caption") String caption) { return sendTelegramPhoto(group, photoURL, caption, null, null, HTTP_PHOTO_TIMEOUT, HTTP_RETRIES); } @ActionDoc(text = "Sends a Picture via Telegram REST API, using custom HTTP timeout") - static public boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, + public static boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, @ParamDoc(name = "photoURL") String photoURL, @ParamDoc(name = "caption") String caption, @ParamDoc(name = "timeoutMillis") Integer timeoutMillis) { @@ -162,7 +178,7 @@ static public boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, } @ActionDoc(text = "Sends a Picture, protected by username/password authentication, via Telegram REST API") - static public boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, + public static boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, @ParamDoc(name = "photoURL") String photoURL, @ParamDoc(name = "caption") String caption, @ParamDoc(name = "username") String username, @ParamDoc(name = "password") String password) { return sendTelegramPhoto(group, photoURL, caption, username, password, HTTP_PHOTO_TIMEOUT, HTTP_RETRIES); @@ -170,12 +186,13 @@ static public boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, } @ActionDoc(text = "Sends a Picture, protected by username/password authentication, using custom HTTP timeout and retries, via Telegram REST API") - static public boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, + public static boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, @ParamDoc(name = "photoURL") String photoURL, @ParamDoc(name = "caption") String caption, @ParamDoc(name = "username") String username, @ParamDoc(name = "password") String password, @ParamDoc(name = "timeoutMillis") int timeoutMillis, @ParamDoc(name = "retries") int retries) { - if (groupTokens.get(group) == null) { + TelegramBot bot = groupTokens.get(group); + if (bot == null) { logger.warn("Bot '{}' not defined; action skipped.", group); return false; } @@ -281,20 +298,11 @@ static public boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, } // post photo to telegram - String url = String.format(TELEGRAM_PHOTO_URL, groupTokens.get(group).getToken()); + String url = String.format(TELEGRAM_PHOTO_URL, bot.getToken()); - PostMethod postMethod = new PostMethod(url); + PostMethod postMethod = createPostMethod(url, timeoutMillis, retries); try { - postMethod.getParams().setContentCharset("UTF-8"); - postMethod.getParams().setSoTimeout(timeoutMillis); - postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, - new DefaultHttpMethodRetryHandler(retries, false)); - Part[] parts = new Part[caption != null ? 3 : 2]; - parts[0] = new StringPart("chat_id", groupTokens.get(group).getChatId()); - parts[1] = new FilePart("photo", new ByteArrayPartSource(String.format("image.%s", imageType), image)); - if (caption != null) { - parts[2] = new StringPart("caption", caption, "UTF-8"); - } + Part[] parts = createSendPhotoRequestParts(bot, image, imageType, caption); postMethod.setRequestEntity(new MultipartRequestEntity(parts, postMethod.getParams())); HttpClient client = new HttpClient(); @@ -320,4 +328,19 @@ static public boolean sendTelegramPhoto(@ParamDoc(name = "group") String group, postMethod.releaseConnection(); } } + + private static Part[] createSendPhotoRequestParts(TelegramBot bot, byte[] image, String imageType, String caption) { + List partList = new ArrayList<>(); + partList.add(new StringPart("chat_id", bot.getChatId())); + partList.add(new FilePart("photo", new ByteArrayPartSource(String.format("image.%s", imageType), image))); + + if (StringUtils.isNotBlank(caption)) { + partList.add(new StringPart("caption", caption, "UTF-8")); + } + + if (StringUtils.isNotBlank(bot.getParseMode())) { + partList.add(new StringPart("parse_mode", bot.getParseMode())); + } + return partList.toArray(new Part[0]); + } } diff --git a/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/TelegramActionService.java b/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/TelegramActionService.java index f40e0751bf0..192cc002527 100644 --- a/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/TelegramActionService.java +++ b/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/TelegramActionService.java @@ -9,6 +9,7 @@ package org.openhab.action.telegram.internal; import java.util.Dictionary; +import java.util.Objects; import org.openhab.core.scriptengine.action.ActionService; import org.osgi.service.cm.ConfigurationException; @@ -62,8 +63,18 @@ public void updated(Dictionary config) throws ConfigurationException for (String bot : bots) { String chatIdKey = String.format("%s.chatId", bot); String tokenKey = String.format("%s.token", bot); - if (config.get(chatIdKey) != null && config.get(tokenKey) != null) { - Telegram.addToken(bot, (String) config.get(chatIdKey), (String) config.get(tokenKey)); + String parseModeKey = String.format("%s.parseMode", bot); + + String chatId = Objects.toString(config.get(chatIdKey), null); + String token = Objects.toString(config.get(tokenKey), null); + String parseMode = Objects.toString(config.get(parseModeKey), null); + + if (chatId != null && token != null) { + if (parseMode == null) { + Telegram.addToken(bot, chatId, token); + } else { + Telegram.addToken(bot, chatId, token, parseMode); + } logger.info("Bot {} loaded from config file", bot); } else { logger.warn("Bot {} is misconfigured. Please check the configuration", bot); diff --git a/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/TelegramBot.java b/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/TelegramBot.java index b4ff61290e3..4ddf2d8ab02 100644 --- a/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/TelegramBot.java +++ b/bundles/action/org.openhab.action.telegram/src/main/java/org/openhab/action/telegram/internal/TelegramBot.java @@ -20,12 +20,19 @@ public class TelegramBot { private String chatId; private String token; + private String parseMode; public TelegramBot(String chatId, String token) { this.chatId = chatId; this.token = token; } + public TelegramBot(String chatId, String token, String parseMode) { + this.chatId = chatId; + this.token = token; + this.parseMode = parseMode; + } + public String getChatId() { return chatId; } @@ -33,4 +40,8 @@ public String getChatId() { public String getToken() { return token; } + + public String getParseMode() { + return parseMode; + } } diff --git a/distribution/openhabhome/configurations/openhab_default.cfg b/distribution/openhabhome/configurations/openhab_default.cfg index 3e99837f78f..03c67a4a0fc 100644 --- a/distribution/openhabhome/configurations/openhab_default.cfg +++ b/distribution/openhabhome/configurations/openhab_default.cfg @@ -2493,6 +2493,7 @@ tcp:refreshinterval=250 # telegram:bots=bot1,bot2 # telegram:bot1.chatId=22334455 # telegram:bot1.token=xxxxxx +# telegram:bot1.parseMode=Markdown # telegram:bot2.chatId=654321 # telegram:bot2.token=yyyyyyyyyyy diff --git a/features/openhab-addons-external/src/main/resources/conf/telegram.cfg b/features/openhab-addons-external/src/main/resources/conf/telegram.cfg index fbc4e9f93cb..b8be52d46bd 100644 --- a/features/openhab-addons-external/src/main/resources/conf/telegram.cfg +++ b/features/openhab-addons-external/src/main/resources/conf/telegram.cfg @@ -1,5 +1,5 @@ # -# Read http://www.instructables.com/id/Telegram-Bots-for-beginners/ +# Read https://www.openhab.org/addons/actions/telegram/#telegram-actions # to see how to set up bots and find your chat ids # @@ -7,6 +7,8 @@ # bot1.chatId=22334455 # bot1.token=xxxxxx +# Optional: Either 'Markdown' or 'HTML' see https://core.telegram.org/bots/api#markdown-style +# bot1.parseMode=Markdown # bot2.chatId=654321 # bot2.token=yyyyyyyyyyy