Skip to content
This repository has been archived by the owner on May 17, 2021. It is now read-only.

[Telegram] Support for formatted messages #5765

Merged
merged 5 commits into from
Jan 25, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions bundles/action/org.openhab.action.telegram/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<bot-name>`s |
| `<bot name>.chatId` | | Yes | chat id |
| `<bot name>.token` | | Yes | authentication token |
| Property | Default | Required | Description |
|-------------------------|---------|:--------:|--------------------------------------------------------------|
| bots | | Yes | Comma-separated list of `<bot-name>`s |
| `<bot name>.chatId` | | Yes | chat id |
| `<bot name>.token` | | Yes | authentication token |
| `<bot name>.parseMode` | | No | Support for formatted messages, values: `Markdown` or `HTML` |
thorstenbe marked this conversation as resolved.
Show resolved Hide resolved

See https://core.telegram.org/bots/api#markdown-style for formatting options

### Configuration example

Expand All @@ -55,6 +58,7 @@ bots=bot1,bot2

bot1.chatId=22334455
bot1.token=xxxxxxxxxxx
bot1.parseMode=Markdown

bot2.chatId=654321
bot2.token=yyyyyyyyyyy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -139,43 +146,53 @@ 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) {

return sendTelegramPhoto(group, photoURL, caption, null, null, timeoutMillis, HTTP_RETRIES);
}

@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);

}

@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;
}
Expand Down Expand Up @@ -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();
Expand All @@ -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<Part> 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]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,17 @@ public void updated(Dictionary<String, ?> config) throws ConfigurationException
for (String bot : bots) {
String chatIdKey = String.format("%s.chatId", bot);
String tokenKey = String.format("%s.token", bot);
String parseKey = String.format("%s.parseMode", bot);

if (config.get(chatIdKey) != null && config.get(tokenKey) != null) {
Telegram.addToken(bot, (String) config.get(chatIdKey), (String) config.get(tokenKey));

String chatId = (String) config.get(chatIdKey);
thorstenbe marked this conversation as resolved.
Show resolved Hide resolved
String token = (String) config.get(tokenKey);
if (parseKey == null) {
Telegram.addToken(bot, chatId, token);
} else {
Telegram.addToken(bot, chatId, token, (String) config.get(parseKey));
}
logger.info("Bot {} loaded from config file", bot);
} else {
logger.warn("Bot {} is misconfigured. Please check the configuration", bot);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,28 @@ 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;
}

public String getToken() {
return token;
}

public String getParseMode() {
return parseMode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#
# 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
#

# bots=bot1,bot2

# 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