2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.telegram.internal.action;
15 import static org.openhab.binding.telegram.internal.TelegramBindingConstants.PHOTO_EXTENSIONS;
17 import java.io.ByteArrayInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.net.MalformedURLException;
23 import java.nio.charset.StandardCharsets;
24 import java.nio.file.Path;
25 import java.util.Base64;
26 import java.util.concurrent.ExecutionException;
27 import java.util.concurrent.TimeUnit;
29 import org.eclipse.jdt.annotation.NonNullByDefault;
30 import org.eclipse.jdt.annotation.Nullable;
31 import org.eclipse.jetty.client.HttpClient;
32 import org.eclipse.jetty.client.api.Authentication;
33 import org.eclipse.jetty.client.api.AuthenticationStore;
34 import org.eclipse.jetty.client.api.ContentResponse;
35 import org.eclipse.jetty.client.api.Request;
36 import org.eclipse.jetty.client.util.FutureResponseListener;
37 import org.eclipse.jetty.http.HttpHeader;
38 import org.eclipse.jetty.http.HttpMethod;
39 import org.openhab.binding.telegram.internal.TelegramHandler;
40 import org.openhab.core.automation.annotation.ActionInput;
41 import org.openhab.core.automation.annotation.RuleAction;
42 import org.openhab.core.thing.binding.ThingActions;
43 import org.openhab.core.thing.binding.ThingActionsScope;
44 import org.openhab.core.thing.binding.ThingHandler;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
49 import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
50 import com.pengrad.telegrambot.request.AnswerCallbackQuery;
51 import com.pengrad.telegrambot.request.EditMessageReplyMarkup;
52 import com.pengrad.telegrambot.request.SendAnimation;
53 import com.pengrad.telegrambot.request.SendMessage;
54 import com.pengrad.telegrambot.request.SendPhoto;
55 import com.pengrad.telegrambot.request.SendVideo;
56 import com.pengrad.telegrambot.response.BaseResponse;
57 import com.pengrad.telegrambot.response.SendResponse;
60 * Provides the actions for the Telegram API.
62 * @author Alexander Krasnogolowy - Initial contribution
64 @ThingActionsScope(name = "telegram")
66 public class TelegramActions implements ThingActions {
67 private final Logger logger = LoggerFactory.getLogger(TelegramActions.class);
68 private @Nullable TelegramHandler handler;
70 private boolean evaluateResponse(@Nullable BaseResponse response) {
71 if (response != null && !response.isOk()) {
72 logger.warn("Failed to send telegram message: {}", response.description());
78 private static class BasicResult implements Authentication.Result {
80 private final HttpHeader header;
81 private final URI uri;
82 private final String value;
84 public BasicResult(HttpHeader header, URI uri, String value) {
96 public void apply(@Nullable Request request) {
97 if (request != null) {
98 request.header(this.header, this.value);
103 public String toString() {
104 return String.format("Basic authentication result for %s", this.uri);
108 @RuleAction(label = "send an answer", description = "Send a Telegram answer using the Telegram API.")
109 public boolean sendTelegramAnswer(@ActionInput(name = "chatId") @Nullable Long chatId,
110 @ActionInput(name = "callbackId") @Nullable String callbackId,
111 @ActionInput(name = "messageId") @Nullable Long messageId,
112 @ActionInput(name = "message") @Nullable String message) {
113 if (chatId == null) {
114 logger.warn("chatId not defined; action skipped.");
117 if (messageId == null) {
118 logger.warn("messageId not defined; action skipped.");
121 TelegramHandler localHandler = handler;
122 if (localHandler != null) {
123 if (callbackId != null) {
124 AnswerCallbackQuery answerCallbackQuery = new AnswerCallbackQuery(callbackId);
125 // we could directly set the text here, but this
126 // doesn't result in a real message only in a
127 // little popup or in an alert, so the only purpose
128 // is to stop the progress bar on client side
129 logger.debug("Answering query with callbackId '{}'", callbackId);
130 if (!evaluateResponse(localHandler.execute(answerCallbackQuery))) {
134 EditMessageReplyMarkup editReplyMarkup = new EditMessageReplyMarkup(chatId, messageId.intValue())
135 .replyMarkup(new InlineKeyboardMarkup(new InlineKeyboardButton[0]));// remove reply markup from
137 if (!evaluateResponse(localHandler.execute(editReplyMarkup))) {
140 return message != null ? sendTelegram(chatId, message) : true;
145 @RuleAction(label = "send an answer", description = "Send a Telegram answer using the Telegram API.")
146 public boolean sendTelegramAnswer(@ActionInput(name = "chatId") @Nullable Long chatId,
147 @ActionInput(name = "replyId") @Nullable String replyId,
148 @ActionInput(name = "message") @Nullable String message) {
149 if (replyId == null) {
150 logger.warn("ReplyId not defined; action skipped.");
153 if (chatId == null) {
154 logger.warn("chatId not defined; action skipped.");
157 TelegramHandler localHandler = handler;
158 if (localHandler != null) {
159 String callbackId = localHandler.getCallbackId(chatId, replyId);
160 if (callbackId != null) {
161 logger.debug("AnswerCallbackQuery for chatId {} and replyId {} is the callbackId {}", chatId, replyId,
164 Integer messageId = localHandler.removeMessageId(chatId, replyId);
165 logger.debug("remove messageId {} for chatId {} and replyId {}", messageId, chatId, replyId);
167 return sendTelegramAnswer(chatId, callbackId, messageId != null ? Long.valueOf(messageId) : null, message);
172 @RuleAction(label = "send an answer", description = "Send a Telegram answer using the Telegram API.")
173 public boolean sendTelegramAnswer(@ActionInput(name = "replyId") @Nullable String replyId,
174 @ActionInput(name = "message") @Nullable String message) {
175 TelegramHandler localHandler = handler;
176 if (localHandler != null) {
177 for (Long chatId : localHandler.getReceiverChatIds()) {
178 if (!sendTelegramAnswer(chatId, replyId, message)) {
186 @RuleAction(label = "send a message", description = "Send a Telegram message using the Telegram API.")
187 public boolean sendTelegram(@ActionInput(name = "chatId") @Nullable Long chatId,
188 @ActionInput(name = "message") @Nullable String message) {
189 return sendTelegramGeneral(chatId, message, (String) null);
192 @RuleAction(label = "send a message", description = "Send a Telegram message using the Telegram API.")
193 public boolean sendTelegram(@ActionInput(name = "message") @Nullable String message) {
194 TelegramHandler localHandler = handler;
195 if (localHandler != null) {
196 for (Long chatId : localHandler.getReceiverChatIds()) {
197 if (!sendTelegram(chatId, message)) {
205 @RuleAction(label = "send a message", description = "Send a Telegram using the Telegram API.")
206 public boolean sendTelegramQuery(@ActionInput(name = "chatId") @Nullable Long chatId,
207 @ActionInput(name = "message") @Nullable String message,
208 @ActionInput(name = "replyId") @Nullable String replyId,
209 @ActionInput(name = "buttons") @Nullable String... buttons) {
210 return sendTelegramGeneral(chatId, message, replyId, buttons);
213 @RuleAction(label = "send a message", description = "Send a Telegram using the Telegram API.")
214 public boolean sendTelegramQuery(@ActionInput(name = "message") @Nullable String message,
215 @ActionInput(name = "replyId") @Nullable String replyId,
216 @ActionInput(name = "buttons") @Nullable String... buttons) {
217 TelegramHandler localHandler = handler;
218 if (localHandler != null) {
219 for (Long chatId : localHandler.getReceiverChatIds()) {
220 if (!sendTelegramQuery(chatId, message, replyId, buttons)) {
228 private boolean sendTelegramGeneral(@ActionInput(name = "chatId") @Nullable Long chatId, @Nullable String message,
229 @Nullable String replyId, @Nullable String... buttons) {
230 if (message == null) {
231 logger.warn("Message not defined; action skipped.");
234 if (chatId == null) {
235 logger.warn("chatId not defined; action skipped.");
238 TelegramHandler localHandler = handler;
239 if (localHandler != null) {
240 SendMessage sendMessage = new SendMessage(chatId, message);
241 if (localHandler.getParseMode() != null) {
242 sendMessage.parseMode(localHandler.getParseMode());
244 if (replyId != null) {
245 if (!replyId.contains(" ")) {
246 if (buttons.length > 0) {
247 InlineKeyboardButton[][] keyboard2D = new InlineKeyboardButton[1][];
248 InlineKeyboardButton[] keyboard = new InlineKeyboardButton[buttons.length];
249 keyboard2D[0] = keyboard;
250 for (int i = 0; i < buttons.length; i++) {
251 keyboard[i] = new InlineKeyboardButton(buttons[i]).callbackData(replyId + " " + buttons[i]);
253 InlineKeyboardMarkup keyBoardMarkup = new InlineKeyboardMarkup(keyboard2D);
254 sendMessage.replyMarkup(keyBoardMarkup);
257 "The replyId {} for message {} is given, but no buttons are defined. ReplyMarkup will be ignored.",
261 logger.warn("replyId {} must not contain spaces. ReplyMarkup will be ignored.", replyId);
264 SendResponse retMessage = null;
266 retMessage = localHandler.execute(sendMessage);
267 } catch (Exception e) {
268 logger.warn("Exception occured whilst sending message:{}", e.getMessage());
270 if (!evaluateResponse(retMessage)) {
273 if (replyId != null && retMessage != null) {
274 logger.debug("Adding chatId {}, replyId {} and messageId {}", chatId, replyId,
275 retMessage.message().messageId());
276 localHandler.addMessageId(chatId, replyId, retMessage.message().messageId());
283 @RuleAction(label = "send a message", description = "Send a Telegram using the Telegram API.")
284 public boolean sendTelegram(@ActionInput(name = "chatId") @Nullable Long chatId,
285 @ActionInput(name = "message") @Nullable String message,
286 @ActionInput(name = "args") @Nullable Object... args) {
287 if (message == null) {
290 return sendTelegram(chatId, String.format(message, args));
293 @RuleAction(label = "send a message", description = "Send a Telegram using the Telegram API.")
294 public boolean sendTelegram(@ActionInput(name = "message") @Nullable String message,
295 @ActionInput(name = "args") @Nullable Object... args) {
296 TelegramHandler localHandler = handler;
297 if (localHandler != null) {
298 for (Long chatId : localHandler.getReceiverChatIds()) {
299 if (!sendTelegram(chatId, message, args)) {
307 @RuleAction(label = "send a photo", description = "Send a picture using the Telegram API.")
308 public boolean sendTelegramPhoto(@ActionInput(name = "chatId") @Nullable Long chatId,
309 @ActionInput(name = "photoURL") @Nullable String photoURL,
310 @ActionInput(name = "caption") @Nullable String caption) {
311 return sendTelegramPhoto(chatId, photoURL, caption, null, null);
314 @RuleAction(label = "send a photo", description = "Send a picture using the Telegram API.")
315 public boolean sendTelegramPhoto(@ActionInput(name = "chatId") @Nullable Long chatId,
316 @ActionInput(name = "photoURL") @Nullable String photoURL,
317 @ActionInput(name = "caption") @Nullable String caption,
318 @ActionInput(name = "username") @Nullable String username,
319 @ActionInput(name = "password") @Nullable String password) {
320 if (photoURL == null) {
321 logger.warn("Photo URL not defined; unable to retrieve photo for sending.");
324 if (chatId == null) {
325 logger.warn("chatId not defined; action skipped.");
328 String lowercasePhotoUrl = photoURL.toLowerCase();
329 TelegramHandler localHandler = handler;
330 if (localHandler != null) {
331 final SendPhoto sendPhoto;
332 if (lowercasePhotoUrl.startsWith("http")) {
333 logger.debug("Http based URL for photo provided.");
334 HttpClient client = localHandler.getClient();
335 if (client == null) {
338 Request request = client.newRequest(photoURL).method(HttpMethod.GET).timeout(30, TimeUnit.SECONDS);
339 if (username != null && password != null) {
340 AuthenticationStore auth = client.getAuthenticationStore();
341 URI uri = URI.create(photoURL);
342 auth.addAuthenticationResult(
343 new BasicResult(HttpHeader.AUTHORIZATION, uri, "Basic " + Base64.getEncoder()
344 .encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF_8))));
347 // API has 10mb limit to jpg file size, without this it can only accept 2mb
348 FutureResponseListener listener = new FutureResponseListener(request, 10 * 1024 * 1024);
349 request.send(listener);
350 ContentResponse contentResponse = listener.get();
351 if (contentResponse.getStatus() == 200) {
352 byte[] fileContent = contentResponse.getContent();
353 sendPhoto = new SendPhoto(chatId, fileContent);
355 if (contentResponse.getStatus() == 401
356 && contentResponse.getHeaders().get(HttpHeader.WWW_AUTHENTICATE).contains("igest")) {
357 logger.warn("Download from {} failed due to no BASIC http auth support.", photoURL);
359 logger.warn("Download from {} failed with status: {}", photoURL,
360 contentResponse.getStatus());
362 sendTelegram(chatId, caption + ":Download failed with status " + contentResponse.getStatus());
365 } catch (InterruptedException | ExecutionException e) {
366 logger.warn("Download from {} failed with exception: {}", photoURL, e.getMessage());
369 } else if (lowercasePhotoUrl.startsWith("file:")
370 || PHOTO_EXTENSIONS.stream().anyMatch(lowercasePhotoUrl::endsWith)) {
371 logger.debug("Read file from local file system: {}", photoURL);
372 String temp = photoURL;
373 if (!lowercasePhotoUrl.startsWith("file:")) {
374 temp = "file://" + photoURL;
377 sendPhoto = new SendPhoto(chatId, Path.of(new URL(temp).getPath()).toFile());
378 } catch (MalformedURLException e) {
379 logger.warn("Malformed URL: {}", photoURL);
383 logger.debug("Base64 image provided; converting to binary.");
384 final String photoB64Data;
385 if (photoURL.startsWith("data:")) { // support data URI scheme
386 String[] photoURLParts = photoURL.split(",");
387 if (photoURLParts.length > 1) {
388 photoB64Data = photoURLParts[1];
390 logger.warn("The provided base64 string is not a valid data URI scheme");
394 photoB64Data = photoURL;
396 InputStream is = Base64.getDecoder()
397 .wrap(new ByteArrayInputStream(photoB64Data.getBytes(StandardCharsets.UTF_8)));
399 byte[] photoBytes = is.readAllBytes();
400 sendPhoto = new SendPhoto(chatId, photoBytes);
401 } catch (IOException e) {
402 logger.warn("Malformed base64 string: {}", e.getMessage());
406 if (caption != null) {
407 sendPhoto.caption(caption);
409 if (localHandler.getParseMode() != null) {
410 sendPhoto.parseMode(localHandler.getParseMode());
412 return evaluateResponse(localHandler.execute(sendPhoto));
417 @RuleAction(label = "send a photo", description = "Send a Picture using the Telegram API.")
418 public boolean sendTelegramPhoto(@ActionInput(name = "photoURL") @Nullable String photoURL,
419 @ActionInput(name = "caption") @Nullable String caption,
420 @ActionInput(name = "username") @Nullable String username,
421 @ActionInput(name = "password") @Nullable String password) {
422 TelegramHandler localHandler = handler;
423 if (localHandler != null) {
424 for (Long chatId : localHandler.getReceiverChatIds()) {
425 if (!sendTelegramPhoto(chatId, photoURL, caption, username, password)) {
433 @RuleAction(label = "send a photo", description = "Send a Picture using the Telegram API.")
434 public boolean sendTelegramPhoto(@ActionInput(name = "photoURL") @Nullable String photoURL,
435 @ActionInput(name = "caption") @Nullable String caption) {
436 return sendTelegramPhoto(photoURL, caption, null, null);
439 @RuleAction(label = "send animation", description = "Send an Animation using the Telegram API.")
440 public boolean sendTelegramAnimation(@ActionInput(name = "animationURL") @Nullable String animationURL,
441 @ActionInput(name = "caption") @Nullable String caption) {
442 TelegramHandler localHandler = handler;
443 if (localHandler != null) {
444 for (Long chatId : localHandler.getReceiverChatIds()) {
445 if (!sendTelegramAnimation(chatId, animationURL, caption)) {
453 @RuleAction(label = "send animation", description = "Send an Animation using the Telegram API.")
454 public boolean sendTelegramAnimation(@ActionInput(name = "chatId") @Nullable Long chatId,
455 @ActionInput(name = "animationURL") @Nullable String animationURL,
456 @ActionInput(name = "caption") @Nullable String caption) {
457 if (animationURL == null) {
458 logger.warn("Animation URL not defined; unable to retrieve video for sending.");
461 if (chatId == null) {
462 logger.warn("chatId not defined; action skipped.");
465 TelegramHandler localHandler = handler;
466 if (localHandler != null) {
467 final SendAnimation sendAnimation;
468 if (animationURL.toLowerCase().startsWith("http")) {
469 // load image from url
470 logger.debug("Animation URL provided.");
471 HttpClient client = localHandler.getClient();
472 if (client == null) {
475 Request request = client.newRequest(animationURL).method(HttpMethod.GET).timeout(30, TimeUnit.SECONDS);
477 // 50mb limit to file size
478 FutureResponseListener listener = new FutureResponseListener(request, 50 * 1024 * 1024);
479 request.send(listener);
480 ContentResponse contentResponse = listener.get();
481 if (contentResponse.getStatus() == 200) {
482 byte[] fileContent = contentResponse.getContent();
483 sendAnimation = new SendAnimation(chatId, fileContent);
485 logger.warn("Download from {} failed with status: {}", animationURL,
486 contentResponse.getStatus());
487 sendTelegram(chatId, caption + ":Download failed with status " + contentResponse.getStatus());
490 } catch (InterruptedException | ExecutionException e) {
491 logger.warn("Download from {} failed with exception: {}", animationURL, e.getMessage());
495 String temp = animationURL;
496 if (!animationURL.toLowerCase().startsWith("file:")) {
497 temp = "file://" + animationURL;
499 // Load video from local file system
500 logger.debug("Read file from local file system: {}", animationURL);
502 sendAnimation = new SendAnimation(chatId, Path.of(new URL(temp).getPath()).toFile());
503 } catch (MalformedURLException e) {
504 logger.warn("Malformed URL, should start with http or file: {}", animationURL);
508 if (caption != null) {
509 sendAnimation.caption(caption);
511 if (localHandler.getParseMode() != null) {
512 sendAnimation.parseMode(localHandler.getParseMode());
514 return evaluateResponse(localHandler.execute(sendAnimation));
519 @RuleAction(label = "send video", description = "Send a Video using the Telegram API.")
520 public boolean sendTelegramVideo(@ActionInput(name = "videoURL") @Nullable String videoURL,
521 @ActionInput(name = "caption") @Nullable String caption) {
522 TelegramHandler localHandler = handler;
523 if (localHandler != null) {
524 for (Long chatId : localHandler.getReceiverChatIds()) {
525 if (!sendTelegramVideo(chatId, videoURL, caption)) {
533 @RuleAction(label = "send video", description = "Send a Video using the Telegram API.")
534 public boolean sendTelegramVideo(@ActionInput(name = "chatId") @Nullable Long chatId,
535 @ActionInput(name = "videoURL") @Nullable String videoURL,
536 @ActionInput(name = "caption") @Nullable String caption) {
537 final SendVideo sendVideo;
538 if (videoURL == null) {
539 logger.warn("Video URL not defined; unable to retrieve video for sending.");
542 if (chatId == null) {
543 logger.warn("chatId not defined; action skipped.");
546 TelegramHandler localHandler = handler;
547 if (localHandler != null) {
548 if (videoURL.toLowerCase().startsWith("http")) {
549 logger.debug("Video http://URL provided.");
550 HttpClient client = localHandler.getClient();
551 if (client == null) {
554 Request request = client.newRequest(videoURL).method(HttpMethod.GET).timeout(30, TimeUnit.SECONDS);
556 // 50mb limit to file size
557 FutureResponseListener listener = new FutureResponseListener(request, 50 * 1024 * 1024);
558 request.send(listener);
559 ContentResponse contentResponse = listener.get();
560 if (contentResponse.getStatus() == 200) {
561 byte[] fileContent = contentResponse.getContent();
562 sendVideo = new SendVideo(chatId, fileContent);
564 if (contentResponse.getStatus() == 401
565 && contentResponse.getHeaders().get(HttpHeader.WWW_AUTHENTICATE).contains("igest")) {
566 logger.warn("Download from {} failed due to no BASIC http auth support.", videoURL);
568 logger.warn("Download from {} failed with status: {}", videoURL,
569 contentResponse.getStatus());
571 sendTelegram(chatId, caption + ":Download failed with status " + contentResponse.getStatus());
574 } catch (InterruptedException | ExecutionException e) {
575 logger.warn("Download from {} failed with exception: {}", videoURL, e.getMessage());
579 String temp = videoURL;
580 if (!videoURL.toLowerCase().startsWith("file:")) {
581 temp = "file://" + videoURL;
583 // Load video from local file system with file://path
584 logger.debug("Read file from local file: {}", videoURL);
586 sendVideo = new SendVideo(chatId, Path.of(new URL(temp).getPath()).toFile());
587 } catch (MalformedURLException e) {
588 logger.warn("Malformed URL, should start with http or file: {}", videoURL);
592 if (caption != null) {
593 sendVideo.caption(caption);
595 if (localHandler.getParseMode() != null) {
596 sendVideo.parseMode(localHandler.getParseMode());
598 return evaluateResponse(localHandler.execute(sendVideo));
603 // legacy delegate methods
604 /* APIs without chatId parameter */
605 public static boolean sendTelegram(ThingActions actions, @Nullable String format, @Nullable Object... args) {
606 return ((TelegramActions) actions).sendTelegram(format, args);
609 public static boolean sendTelegramQuery(ThingActions actions, @Nullable String message, @Nullable String replyId,
610 @Nullable String... buttons) {
611 return ((TelegramActions) actions).sendTelegramQuery(message, replyId, buttons);
614 public static boolean sendTelegramPhoto(ThingActions actions, @Nullable String photoURL, @Nullable String caption) {
615 return ((TelegramActions) actions).sendTelegramPhoto(photoURL, caption, null, null);
618 public static boolean sendTelegramPhoto(ThingActions actions, @Nullable String photoURL, @Nullable String caption,
619 @Nullable String username, @Nullable String password) {
620 return ((TelegramActions) actions).sendTelegramPhoto(photoURL, caption, username, password);
623 public static boolean sendTelegramAnimation(ThingActions actions, @Nullable String animationURL,
624 @Nullable String caption) {
625 return ((TelegramActions) actions).sendTelegramVideo(animationURL, caption);
628 public static boolean sendTelegramVideo(ThingActions actions, @Nullable String videoURL, @Nullable String caption) {
629 return ((TelegramActions) actions).sendTelegramVideo(videoURL, caption);
632 public static boolean sendTelegramAnswer(ThingActions actions, @Nullable String replyId, @Nullable String message) {
633 return ((TelegramActions) actions).sendTelegramAnswer(replyId, message);
636 /* APIs with chatId parameter */
638 public static boolean sendTelegram(ThingActions actions, @Nullable Long chatId, @Nullable String format,
639 @Nullable Object... args) {
640 return ((TelegramActions) actions).sendTelegram(chatId, format, args);
643 public static boolean sendTelegramQuery(ThingActions actions, @Nullable Long chatId, @Nullable String message,
644 @Nullable String replyId, @Nullable String... buttons) {
645 return ((TelegramActions) actions).sendTelegramQuery(chatId, message, replyId, buttons);
648 public static boolean sendTelegramPhoto(ThingActions actions, @Nullable Long chatId, @Nullable String photoURL,
649 @Nullable String caption) {
650 return ((TelegramActions) actions).sendTelegramPhoto(chatId, photoURL, caption, null, null);
653 public static boolean sendTelegramPhoto(ThingActions actions, @Nullable Long chatId, @Nullable String photoURL,
654 @Nullable String caption, @Nullable String username, @Nullable String password) {
655 return ((TelegramActions) actions).sendTelegramPhoto(chatId, photoURL, caption, username, password);
658 public static boolean sendTelegramAnimation(ThingActions actions, @Nullable Long chatId,
659 @Nullable String animationURL, @Nullable String caption) {
660 return ((TelegramActions) actions).sendTelegramVideo(chatId, animationURL, caption);
663 public static boolean sendTelegramVideo(ThingActions actions, @Nullable Long chatId, @Nullable String videoURL,
664 @Nullable String caption) {
665 return ((TelegramActions) actions).sendTelegramVideo(chatId, videoURL, caption);
668 public static boolean sendTelegramAnswer(ThingActions actions, @Nullable Long chatId, @Nullable String replyId,
669 @Nullable String message) {
670 return ((TelegramActions) actions).sendTelegramAnswer(chatId, replyId, message);
673 public static boolean sendTelegramAnswer(ThingActions actions, @Nullable String chatId, @Nullable String replyId,
674 @Nullable String message) {
675 if (actions instanceof TelegramActions telegramActions) {
676 if (chatId == null) {
679 return telegramActions.sendTelegramAnswer(Long.valueOf(chatId), replyId, message);
681 throw new IllegalArgumentException("Actions is not an instance of TelegramActions");
685 public static boolean sendTelegramAnswer(ThingActions actions, @Nullable Long chatId, @Nullable String callbackId,
686 @Nullable Long messageId, @Nullable String message) {
687 return ((TelegramActions) actions).sendTelegramAnswer(chatId, callbackId, messageId, message);
690 public static boolean sendTelegramAnswer(ThingActions actions, @Nullable String chatId, @Nullable String callbackId,
691 @Nullable String messageId, @Nullable String message) {
692 if (actions instanceof TelegramActions telegramActions) {
693 if (chatId == null) {
696 return telegramActions.sendTelegramAnswer(Long.valueOf(chatId), callbackId,
697 messageId != null ? Long.parseLong(messageId) : null, message);
699 throw new IllegalArgumentException("Actions is not an instance of TelegramActions");
704 public void setThingHandler(@Nullable ThingHandler handler) {
705 this.handler = (TelegramHandler) handler;
709 public @Nullable ThingHandler getThingHandler() {