diff --git a/readme.md b/readme.md
index 2a4276a..afe0f00 100644
--- a/readme.md
+++ b/readme.md
@@ -149,6 +149,7 @@ import com.n1netails.n1netails.telegram.model.InlineKeyboardMarkup;
import com.n1netails.n1netails.telegram.model.TelegramMessage;
import com.n1netails.n1netails.telegram.service.BotService;
+import java.util.Arrays;
import java.util.Collections;
public class ExampleService {
@@ -158,7 +159,7 @@ public class ExampleService {
this.telegramClient = new TelegramClientImpl(new BotService());
}
- public void telegramNotificationExample(String content) {
+ public void telegramNotificationExample(String content) throws TelegramClientException {
Button button = new Button("Visit N1netails", "https://n1netails.com");
InlineKeyboardMarkup keyboardMarkup = new InlineKeyboardMarkup(Collections.singletonList(Collections.singletonList(button)));
TelegramMessage telegramMessage = new TelegramMessage("N1netails Telegram Works!", false, keyboardMarkup);
@@ -169,7 +170,7 @@ public class ExampleService {
telegramClient.sendMessage(chatId, botToken, telegramMessage);
}
- public void telegramGifNotificationExample() {
+ public void telegramGifNotificationExample() throws TelegramClientException {
TelegramMessage telegramMessage = new TelegramMessage("Check out this GIF!", "https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExaDRhOWtpMnVsM2NiMzJ4aXpoOXpuamZzcHpudG4zbzIzenVlaHN0eSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/xsE65jaPsUKUo/giphy.gif", false);
// replace with your telegram chat id
String chatId = "your-telegram-chat-id";
@@ -178,7 +179,7 @@ public class ExampleService {
telegramClient.sendMessage(chatId, botToken, telegramMessage);
}
- public void telegramGifNotificationWithCtaButtonsExample() {
+ public void telegramGifNotificationWithCtaButtonsExample() throws TelegramClientException {
Button button = new Button("Visit N1netails", "https://n1netails.com");
InlineKeyboardMarkup keyboardMarkup = new InlineKeyboardMarkup(Collections.singletonList(Collections.singletonList(button)));
TelegramMessage telegramMessage = new TelegramMessage("Check out this GIF!", "https://media1.giphy.com/media/v1.Y2lkPTc5MGI3NjExaDRhOWtpMnVsM2NiMzJ4aXpoOXpuamZzcHpudG4zbzIzenVlaHN0eSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/xsE65jaPsUKUo/giphy.gif", false, keyboardMarkup);
@@ -188,9 +189,45 @@ public class ExampleService {
String botToken = "your-telegram-bot-token";
telegramClient.sendMessage(chatId, botToken, telegramMessage);
}
+
+ public void telegramImageNotificationExample() throws TelegramClientException {
+ TelegramMessage telegramMessage = new TelegramMessage();
+ telegramMessage.setText("Check out this photo!");
+ telegramMessage.setImages(Collections.singletonList("https://n1netails.com/img/n1netails_icon_transparent.png"));
+ // replace with your telegram chat id
+ String chatId = "your-telegram-chat-id";
+ // replace with your telegram bot token
+ String botToken = "your-telegram-bot-token";
+ telegramClient.sendMessage(chatId, botToken, telegramMessage);
+ }
+
+ public void telegramVideoNotificationExample() throws TelegramClientException {
+ TelegramMessage telegramMessage = new TelegramMessage();
+ telegramMessage.setText("Check out this video!");
+ telegramMessage.setVideos(Collections.singletonList("https://n1netails.nyc3.cdn.digitaloceanspaces.com/video_2026-02-11_18-16-07.mp4"));
+ // replace with your telegram chat id
+ String chatId = "your-telegram-chat-id";
+ // replace with your telegram bot token
+ String botToken = "your-telegram-bot-token";
+ telegramClient.sendMessage(chatId, botToken, telegramMessage);
+ }
+
+ public void telegramMediaGroupNotificationExample() throws TelegramClientException {
+ TelegramMessage telegramMessage = new TelegramMessage();
+ telegramMessage.setText("Check out these photos and videos!");
+ telegramMessage.setImages(Arrays.asList("https://n1netails.com/img/n1netails_icon_transparent.png", "https://n1netails.com/img/quickstart/n1netails-letter.jpg"));
+ telegramMessage.setVideos(Collections.singletonList("https://n1netails.nyc3.cdn.digitaloceanspaces.com/video_2026-02-11_18-16-07.mp4"));
+ // replace with your telegram chat id
+ String chatId = "your-telegram-chat-id";
+ // replace with your telegram bot token
+ String botToken = "your-telegram-bot-token";
+ telegramClient.sendMessage(chatId, botToken, telegramMessage);
+ }
}
```
+> 📌 **Note:** Media (images, videos, animations) must be provided as public URLs. Telegram does not support `replyMarkup` (CTA buttons) when sending multiple media items (Media Group).
+
#### Example message output

@@ -206,6 +243,22 @@ public class ExampleService {
+#### Example message Image output
+
+

+
+
+#### Example message Video output
+
+

+
+
+#### Example message Media group output
+
+

+
+
+
# Develop
## Build
Build the project using the following command
diff --git a/src/main/java/com/n1netails/n1netails/telegram/model/TelegramMessage.java b/src/main/java/com/n1netails/n1netails/telegram/model/TelegramMessage.java
index 2c3eb87..74e908b 100644
--- a/src/main/java/com/n1netails/n1netails/telegram/model/TelegramMessage.java
+++ b/src/main/java/com/n1netails/n1netails/telegram/model/TelegramMessage.java
@@ -3,6 +3,8 @@
import lombok.Getter;
import lombok.Setter;
+import java.util.List;
+
/**
* Telegram Message
* @author shahid foy
@@ -13,6 +15,8 @@ public class TelegramMessage {
private String text;
private String animation;
+ private List images;
+ private List videos;
private boolean disableNotification;
private InlineKeyboardMarkup replyMarkup;
@@ -68,4 +72,34 @@ public TelegramMessage(String text, String animation, boolean disableNotificatio
this.disableNotification = disableNotification;
this.replyMarkup = replyMarkup;
}
+
+ /**
+ * Telegram Message Constructor
+ * @param text telegram content
+ * @param images list of image urls
+ * @param videos list of video urls
+ * @param disableNotification disable telegram notification
+ */
+ public TelegramMessage(String text, List images, List videos, boolean disableNotification) {
+ this.text = text;
+ this.images = images;
+ this.videos = videos;
+ this.disableNotification = disableNotification;
+ }
+
+ /**
+ * Telegram Message Constructor
+ * @param text telegram content
+ * @param images list of image urls
+ * @param videos list of video urls
+ * @param disableNotification disable telegram notification
+ * @param replyMarkup the reply markup
+ */
+ public TelegramMessage(String text, List images, List videos, boolean disableNotification, InlineKeyboardMarkup replyMarkup) {
+ this.text = text;
+ this.images = images;
+ this.videos = videos;
+ this.disableNotification = disableNotification;
+ this.replyMarkup = replyMarkup;
+ }
}
diff --git a/src/main/java/com/n1netails/n1netails/telegram/service/BotService.java b/src/main/java/com/n1netails/n1netails/telegram/service/BotService.java
index a8072b6..c97c88d 100644
--- a/src/main/java/com/n1netails/n1netails/telegram/service/BotService.java
+++ b/src/main/java/com/n1netails/n1netails/telegram/service/BotService.java
@@ -2,9 +2,11 @@
import com.n1netails.n1netails.telegram.exception.TelegramClientException;
import com.n1netails.n1netails.telegram.model.TelegramMessage;
+import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
+import java.util.List;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
@@ -32,28 +34,72 @@ public BotService() {}
*/
public void send(String chatId, String botToken, TelegramMessage message) throws TelegramClientException {
try {
- boolean isAnimation = message.getAnimation() != null && !message.getAnimation().isEmpty();
- String method = isAnimation ? "sendAnimation" : "sendMessage";
- String apiUrl = "https://api.telegram.org/bot" + botToken + "/" + method;
-
+ String method;
JSONObject jsonPayload = new JSONObject();
jsonPayload.put("chat_id", chatId);
- if (isAnimation) {
+ List images = message.getImages();
+ List videos = message.getVideos();
+ int imageCount = (images != null) ? images.size() : 0;
+ int videoCount = (videos != null) ? videos.size() : 0;
+ int totalMedia = imageCount + videoCount;
+
+ if (totalMedia > 1) {
+ method = "sendMediaGroup";
+ JSONArray mediaArray = new JSONArray();
+ if (images != null) {
+ for (int i = 0; i < images.size(); i++) {
+ JSONObject media = new JSONObject();
+ media.put("type", "photo");
+ media.put("media", images.get(i));
+ if (i == 0 && message.getText() != null) {
+ media.put("caption", message.getText());
+ }
+ mediaArray.put(media);
+ }
+ }
+ if (videos != null) {
+ for (int i = 0; i < videos.size(); i++) {
+ JSONObject media = new JSONObject();
+ media.put("type", "video");
+ media.put("media", videos.get(i));
+ if (imageCount == 0 && i == 0 && message.getText() != null) {
+ media.put("caption", message.getText());
+ }
+ mediaArray.put(media);
+ }
+ }
+ jsonPayload.put("media", mediaArray);
+ } else if (imageCount == 1) {
+ method = "sendPhoto";
+ jsonPayload.put("photo", images.get(0));
+ if (message.getText() != null) {
+ jsonPayload.put("caption", message.getText());
+ }
+ } else if (videoCount == 1) {
+ method = "sendVideo";
+ jsonPayload.put("video", videos.get(0));
+ if (message.getText() != null) {
+ jsonPayload.put("caption", message.getText());
+ }
+ } else if (message.getAnimation() != null && !message.getAnimation().isEmpty()) {
+ method = "sendAnimation";
jsonPayload.put("animation", message.getAnimation());
if (message.getText() != null) {
jsonPayload.put("caption", message.getText());
}
} else {
+ method = "sendMessage";
jsonPayload.put("text", message.getText());
}
jsonPayload.put("disable_notification", message.isDisableNotification());
- if (message.getReplyMarkup() != null) {
+ if (message.getReplyMarkup() != null && !method.equals("sendMediaGroup")) {
jsonPayload.put("reply_markup", new JSONObject(message.getReplyMarkup()));
}
+ String apiUrl = "https://api.telegram.org/bot" + botToken + "/" + method;
HttpURLConnection conn = openConnection(apiUrl);
conn.setRequestMethod("POST");
conn.setDoOutput(true);
diff --git a/src/test/java/com/n1netails/n1netails/telegram/service/BotServiceTest.java b/src/test/java/com/n1netails/n1netails/telegram/service/BotServiceTest.java
index 9368ed9..b047ebd 100644
--- a/src/test/java/com/n1netails/n1netails/telegram/service/BotServiceTest.java
+++ b/src/test/java/com/n1netails/n1netails/telegram/service/BotServiceTest.java
@@ -8,6 +8,7 @@
import org.junit.jupiter.api.Test;
import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
import java.util.Collections;
import java.net.HttpURLConnection;
@@ -76,4 +77,58 @@ void testSendAnimationWithKeyboard() throws Exception {
JSONObject replyMarkup = payload.getJSONObject("reply_markup");
assertEquals("Click me", replyMarkup.getJSONArray("inline_keyboard").getJSONArray(0).getJSONObject(0).getString("text"));
}
+
+ @Test
+ void testSendSinglePhoto() throws Exception {
+ TelegramMessage message = new TelegramMessage();
+ message.setText("My Photo");
+ message.setImages(Collections.singletonList("http://example.com/photo.jpg"));
+ botService.send("chat123", "token123", message);
+
+ assertEquals("https://api.telegram.org/bottoken123/sendPhoto", lastApiUrl);
+ JSONObject payload = new JSONObject(outputStream.toString());
+ assertEquals("chat123", payload.getString("chat_id"));
+ assertEquals("http://example.com/photo.jpg", payload.getString("photo"));
+ assertEquals("My Photo", payload.getString("caption"));
+ }
+
+ @Test
+ void testSendSingleVideo() throws Exception {
+ TelegramMessage message = new TelegramMessage();
+ message.setText("My Video");
+ message.setVideos(Collections.singletonList("http://example.com/video.mp4"));
+ botService.send("chat123", "token123", message);
+
+ assertEquals("https://api.telegram.org/bottoken123/sendVideo", lastApiUrl);
+ JSONObject payload = new JSONObject(outputStream.toString());
+ assertEquals("chat123", payload.getString("chat_id"));
+ assertEquals("http://example.com/video.mp4", payload.getString("video"));
+ assertEquals("My Video", payload.getString("caption"));
+ }
+
+ @Test
+ void testSendMediaGroup() throws Exception {
+ TelegramMessage message = new TelegramMessage();
+ message.setText("Our Trip");
+ message.setImages(Arrays.asList("http://example.com/photo1.jpg", "http://example.com/photo2.jpg"));
+ message.setVideos(Collections.singletonList("http://example.com/video1.mp4"));
+ botService.send("chat123", "token123", message);
+
+ assertEquals("https://api.telegram.org/bottoken123/sendMediaGroup", lastApiUrl);
+ JSONObject payload = new JSONObject(outputStream.toString());
+ assertEquals("chat123", payload.getString("chat_id"));
+
+ org.json.JSONArray media = payload.getJSONArray("media");
+ assertEquals(3, media.length());
+
+ assertEquals("photo", media.getJSONObject(0).getString("type"));
+ assertEquals("http://example.com/photo1.jpg", media.getJSONObject(0).getString("media"));
+ assertEquals("Our Trip", media.getJSONObject(0).getString("caption"));
+
+ assertEquals("photo", media.getJSONObject(1).getString("type"));
+ assertEquals("http://example.com/photo2.jpg", media.getJSONObject(1).getString("media"));
+
+ assertEquals("video", media.getJSONObject(2).getString("type"));
+ assertEquals("http://example.com/video1.mp4", media.getJSONObject(2).getString("media"));
+ }
}
diff --git a/telegram-group-media-message.png b/telegram-group-media-message.png
new file mode 100644
index 0000000..73b0adf
Binary files /dev/null and b/telegram-group-media-message.png differ
diff --git a/telegram-image-message.png b/telegram-image-message.png
new file mode 100644
index 0000000..4cc04d6
Binary files /dev/null and b/telegram-image-message.png differ
diff --git a/telegram-video-message.png b/telegram-video-message.png
new file mode 100644
index 0000000..26dbaec
Binary files /dev/null and b/telegram-video-message.png differ