├── .gitignore ├── EchoBot ├── build.gradle └── src │ └── main │ └── java │ └── co │ └── vandenham │ └── telegram │ └── botapi │ └── examples │ └── EchoBot.java ├── GMTBot ├── build.gradle └── src │ └── main │ └── java │ └── co │ └── vandenham │ └── telegram │ └── bots │ └── gmtbot │ ├── GMTBotChatContext.java │ └── TimeZones.java ├── LICENSE ├── README.md ├── api ├── build.gradle └── src │ ├── main │ └── java │ │ └── co │ │ └── vandenham │ │ └── telegram │ │ └── botapi │ │ ├── AbstractChatContextFactory.java │ │ ├── ChatContext.java │ │ ├── ChatContextTelegramBot.java │ │ ├── CommandHandler.java │ │ ├── DefaultHandler.java │ │ ├── HandlerNotifier.java │ │ ├── MessageHandler.java │ │ ├── RegistrableTelegramBot.java │ │ ├── TelegramBot.java │ │ ├── package-info.java │ │ ├── requests │ │ ├── ApiException.java │ │ ├── ApiRequest.java │ │ ├── ApiRequestExecutor.java │ │ ├── ApiResponse.java │ │ ├── ApiResult.java │ │ ├── ChatAction.java │ │ ├── ForwardMessageRequest.java │ │ ├── GetMeRequest.java │ │ ├── GetUpdatesRequest.java │ │ ├── GetUserProfilePhotosRequest.java │ │ ├── OptionalArgs.java │ │ ├── SendAudioRequest.java │ │ ├── SendChatActionRequest.java │ │ ├── SendDocumentRequest.java │ │ ├── SendLocationRequest.java │ │ ├── SendMessageRequest.java │ │ ├── SendPhotoRequest.java │ │ ├── SendStickerRequest.java │ │ ├── SendVideoRequest.java │ │ ├── SendVoiceRequest.java │ │ ├── TelegramApi.java │ │ └── package-info.java │ │ └── types │ │ ├── Audio.java │ │ ├── Chat.java │ │ ├── Contact.java │ │ ├── Document.java │ │ ├── ForceReply.java │ │ ├── GroupChat.java │ │ ├── Location.java │ │ ├── Message.java │ │ ├── PhotoSize.java │ │ ├── ReplyKeyboardHide.java │ │ ├── ReplyKeyboardMarkup.java │ │ ├── ReplyMarkup.java │ │ ├── Sticker.java │ │ ├── Update.java │ │ ├── User.java │ │ ├── UserProfilePhotos.java │ │ ├── Video.java │ │ ├── Voice.java │ │ └── package-info.java │ └── test │ └── java │ └── co │ └── vandenham │ └── telegram │ └── botapi │ ├── requests │ ├── RequestTest.java │ ├── SendMessageRequestTest.java │ └── SendPhotoRequestTest.java │ └── types │ └── TypesTest.java ├── build.gradle ├── docs ├── allclasses-frame.html ├── allclasses-noframe.html ├── co │ └── vandenham │ │ └── telegram │ │ └── botapi │ │ ├── AbstractChatContextFactory.html │ │ ├── ChatContext.html │ │ ├── ChatContextTelegramBot.html │ │ ├── CommandHandler.html │ │ ├── DefaultHandler.html │ │ ├── HandlerNotifier.html │ │ ├── MessageHandler.html │ │ ├── RegistrableTelegramBot.MessageListener.html │ │ ├── RegistrableTelegramBot.html │ │ ├── TelegramBot.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ ├── requests │ │ ├── ApiException.html │ │ ├── ApiRequestExecutor.html │ │ ├── ApiResponse.html │ │ ├── ApiResult.html │ │ ├── ChatAction.html │ │ ├── ForwardMessageRequest.html │ │ ├── GetMeRequest.html │ │ ├── GetUpdatesRequest.html │ │ ├── GetUserProfilePhotosRequest.html │ │ ├── OptionalArgs.html │ │ ├── SendAudioRequest.html │ │ ├── SendChatActionRequest.html │ │ ├── SendDocumentRequest.html │ │ ├── SendLocationRequest.html │ │ ├── SendMessageRequest.html │ │ ├── SendPhotoRequest.html │ │ ├── SendStickerRequest.html │ │ ├── SendVideoRequest.html │ │ ├── TelegramApi.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ │ └── types │ │ ├── Audio.html │ │ ├── Chat.html │ │ ├── Contact.html │ │ ├── Document.html │ │ ├── ForceReply.html │ │ ├── GroupChat.html │ │ ├── Location.html │ │ ├── Message.Type.html │ │ ├── Message.html │ │ ├── PhotoSize.html │ │ ├── ReplyKeyboardHide.html │ │ ├── ReplyKeyboardMarkup.Builder.html │ │ ├── ReplyKeyboardMarkup.html │ │ ├── ReplyMarkup.html │ │ ├── Sticker.html │ │ ├── Update.html │ │ ├── User.html │ │ ├── UserProfilePhotos.html │ │ ├── Video.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html ├── constant-values.html ├── deprecated-list.html ├── help-doc.html ├── index-all.html ├── index.html ├── overview-frame.html ├── overview-summary.html ├── overview-tree.html ├── package-list ├── resources │ ├── background.gif │ ├── tab.gif │ ├── titlebar.gif │ └── titlebar_end.gif ├── serialized-form.html └── stylesheet.css ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | ### JetBrains template 2 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 3 | 4 | *.iml 5 | 6 | ## Directory-based project format: 7 | .idea/ 8 | 9 | # Gradle: 10 | .gradle/ 11 | */build/ 12 | 13 | ## File-based project format: 14 | *.ipr 15 | *.iws 16 | 17 | ## Plugin-specific files: 18 | 19 | # IntelliJ 20 | /out/ 21 | 22 | # mpeltonen/sbt-idea plugin 23 | .idea_modules/ 24 | 25 | # JIRA plugin 26 | atlassian-ide-plugin.xml 27 | 28 | # Crashlytics plugin (for Android Studio and IntelliJ) 29 | com_crashlytics_export_strings.xml 30 | crashlytics.properties 31 | crashlytics-build.properties 32 | 33 | # Created by .ignore support plugin (hsz.mobi) 34 | /.nb-gradle/ 35 | -------------------------------------------------------------------------------- /EchoBot/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies { 3 | compile project(':api') 4 | } -------------------------------------------------------------------------------- /EchoBot/src/main/java/co/vandenham/telegram/botapi/examples/EchoBot.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.examples; 2 | 3 | import co.vandenham.telegram.botapi.CommandHandler; 4 | import co.vandenham.telegram.botapi.DefaultHandler; 5 | import co.vandenham.telegram.botapi.MessageHandler; 6 | import co.vandenham.telegram.botapi.TelegramBot; 7 | import co.vandenham.telegram.botapi.types.Message; 8 | 9 | import java.util.logging.Logger; 10 | 11 | public class EchoBot extends TelegramBot { 12 | 13 | private static final Logger log = Logger.getLogger(EchoBot.class.getName()); 14 | 15 | public EchoBot(boolean async) { 16 | super(System.getenv("TOKEN"), async); 17 | } 18 | 19 | public static void main(String[] args) { 20 | TelegramBot bot = new EchoBot(true); 21 | bot.start(); 22 | } 23 | 24 | @CommandHandler({"start", "help"}) 25 | public void handleHelp(Message message) { 26 | replyTo(message, "Hi there! I am here to echo all your kind words back to you!"); 27 | } 28 | 29 | @MessageHandler(contentTypes = Message.Type.TEXT) 30 | public void handleTextMessage(Message message) { 31 | log.info(String.format("%s: %s", message.getChat().getId(), message.getText())); 32 | replyTo(message, message.getText()); 33 | } 34 | 35 | @DefaultHandler 36 | public void handleDefault(Message message) { 37 | replyTo(message, "Say what?"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /GMTBot/build.gradle: -------------------------------------------------------------------------------- 1 | archivesBaseName = 'gmtbot' 2 | version = '1.0' 3 | 4 | dependencies { 5 | compile project(':api') 6 | } 7 | 8 | jar { 9 | from { 10 | 11 | configurations.runtime.collect { 12 | it.isDirectory() ? it : zipTree(it) 13 | } 14 | 15 | configurations.compile.collect { 16 | it.isDirectory() ? it : zipTree(it) 17 | } 18 | } 19 | 20 | manifest { 21 | attributes 'Main-Class': 'co.vandenham.telegram.bots.gmtbot.GMTBotChatContext' 22 | } 23 | 24 | exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA' 25 | } -------------------------------------------------------------------------------- /GMTBot/src/main/java/co/vandenham/telegram/bots/gmtbot/TimeZones.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.bots.gmtbot; 2 | 3 | 4 | import java.text.SimpleDateFormat; 5 | import java.util.Calendar; 6 | import java.util.Comparator; 7 | import java.util.TimeZone; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | public class TimeZones { 12 | 13 | 14 | private final static SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm a (EEEE)"); 15 | private final static Pattern timeZoneRegex = Pattern.compile("(GMT)([+-])([0-9]{1,2})"); 16 | 17 | public static String getCurrentTime(TimeZone timeZone) { 18 | Calendar calendar = Calendar.getInstance(timeZone); 19 | dateFormat.setTimeZone(timeZone); 20 | return "(" + timeZone.getID() + ") " + dateFormat.format(calendar.getTime()); 21 | } 22 | 23 | public static boolean isValidTimeZone(String text) { 24 | text = text.toUpperCase(); 25 | Matcher matcher = timeZoneRegex.matcher(text); 26 | if (!matcher.matches()) { 27 | return false; 28 | } 29 | 30 | int timeZoneModifier = Integer.valueOf(matcher.group(3)); 31 | return timeZoneModifier >= -12 && timeZoneModifier <= 12; 32 | } 33 | 34 | public static class TimeZoneComparator implements Comparator { 35 | public final static TimeZoneComparator INSTANCE = new TimeZoneComparator(); 36 | 37 | private TimeZoneComparator() {} 38 | 39 | @Override 40 | public int compare(TimeZone t1, TimeZone t2) { 41 | return t1.getRawOffset() - t2.getRawOffset(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Pieter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TelegramBots4Java 2 | 3 | ##### TelegramBots4Java is a Java implementation of the [Telegram Bot API](https://core.telegram.org/bots/api) 4 | 5 | This API is designed to be *extensible*, while preserving *simplicity* and *conciseness*. 6 | It provides [core classes](https://cdn.rawgit.com/pevdh/telegram-bots-java-api/master/docs/co/vandenham/telegram/botapi/requests/package-summary.html) to interact with the Telegram Bot API, and it encapsulates these classes in [one simple, extensible class](https://cdn.rawgit.com/pevdh/telegram-bots-java-api/master/docs/co/vandenham/telegram/botapi/TelegramBot.html). 7 | However, nothing holds you back to use the [core classes](https://cdn.rawgit.com/pevdh/telegram-bots-java-api/master/docs/co/vandenham/telegram/botapi/requests/package-summary.html) directly. 8 | 9 | ## How to obtain a Jar 10 | 11 | - [Download the most recent release](https://github.com/pevdh/telegram-bots-java-api/releases) 12 | 13 | - Compile from source 14 | 15 | ``` 16 | $ git clone https://github.com/pevdh/telegram-bots-java-api.git 17 | $ cd telegram-bots-java-api/ 18 | $ ./gradlew :api:jar 19 | ``` 20 | You'll find the .jar file in the api/build/libs directory. 21 | 22 | ## How to use 23 | 24 | ### A simple echo bot 25 | *The import statements are left out for simplicity.* 26 | 27 | ```java 28 | public class EchoBot extends TelegramBot { 29 | 30 | public EchoBot() { 31 | super(""); 32 | } 33 | 34 | // This handler gets called whenever a user sends /start or /help 35 | @CommandHandler({"start", "help"}) 36 | public void handleHelp(Message message) { 37 | replyTo(message, "Hi there! I am here to echo all your kind words back to you!"); 38 | } 39 | 40 | // This handler gets called whenever a user sends a general text message. 41 | @MessageHandler(contentTypes = Message.Type.TEXT) 42 | public void handleTextMessage(Message message) { 43 | System.out.println(String.format("%s: %s", message.getChat().getId(), message.getText())); 44 | replyTo(message, message.getText()); 45 | } 46 | 47 | // This is the default handler, called when the other two handlers don't apply. 48 | @DefaultHandler 49 | public void handleDefault(Message message) { 50 | replyTo(message, "Say what?"); 51 | } 52 | 53 | public static void main(String[] args) { 54 | TelegramBot bot = new EchoBot(); 55 | bot.start(); 56 | } 57 | } 58 | ``` 59 | ### Further reference 60 | This project has [Javadocs](https://cdn.rawgit.com/pevdh/telegram-bots-java-api/master/docs/index.html). 61 | 62 | *TelegramBot.java* provides a good entry point into this API. You can have a look at the [Javadoc reference](https://cdn.rawgit.com/pevdh/telegram-bots-java-api/master/docs/co/vandenham/telegram/botapi/TelegramBot.html) for this class, or look at the [source code](https://github.com/pevdh/TelegramBots4Java/blob/master/api/src/main/java/co/vandenham/telegram/botapi/TelegramBot.java) directly. 63 | -------------------------------------------------------------------------------- /api/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | archivesBaseName = project.projectName 3 | sourceCompatibility = 1.7 4 | version = '1.1' 5 | 6 | test { 7 | if (System.getenv("TOKEN") == null || System.getenv("CHAT_ID") == null) 8 | exclude 'co/vandenham/telegram/botapi/requests/*' 9 | } 10 | 11 | task copyDocs(type: Copy) { 12 | from 'build/docs/javadoc' 13 | into '../docs' 14 | } 15 | 16 | javadoc << { 17 | copyDocs.execute() 18 | } 19 | 20 | javadoc { 21 | options.windowTitle project.projectName 22 | options.docTitle project.projectName 23 | options.links "http://docs.oracle.com/javase/7/docs/api/" 24 | options.addStringOption('Xdoclint:none', '-quiet') 25 | } 26 | 27 | dependencies { 28 | compile 'com.google.code.gson:gson:2.3.1' 29 | testCompile 'junit:junit:4.+' 30 | } -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/AbstractChatContextFactory.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi; 2 | 3 | public interface AbstractChatContextFactory { 4 | 5 | ChatContext createChatContext(int chatId, TelegramBot bot); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/ChatContext.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi; 2 | 3 | import co.vandenham.telegram.botapi.requests.ApiResponse; 4 | import co.vandenham.telegram.botapi.requests.ChatAction; 5 | import co.vandenham.telegram.botapi.requests.OptionalArgs; 6 | import co.vandenham.telegram.botapi.types.Message; 7 | import co.vandenham.telegram.botapi.types.User; 8 | import co.vandenham.telegram.botapi.types.UserProfilePhotos; 9 | 10 | import java.io.File; 11 | 12 | public class ChatContext { 13 | 14 | private int chatId; 15 | private TelegramBot bot; 16 | private HandlerNotifier handlerNotifier; 17 | 18 | public ChatContext(int chatId, TelegramBot bot) { 19 | this.chatId = chatId; 20 | this.bot = bot; 21 | 22 | handlerNotifier = new HandlerNotifier(this); 23 | } 24 | 25 | public final void passMessage(Message message) { 26 | if (message.getChat().getId() != chatId) 27 | throw new IllegalArgumentException("A Message was passed to the wrong ChatContext."); 28 | 29 | onMessage(message); 30 | handlerNotifier.notifyHandlers(message); 31 | } 32 | 33 | public void onStart() { 34 | 35 | } 36 | 37 | public void onStop() { 38 | 39 | } 40 | 41 | protected void onMessage(Message message) { 42 | 43 | } 44 | 45 | public ApiResponse forwardMessage(int fromChatId, int toChatId, int messageId) { 46 | return bot.forwardMessage(toChatId, fromChatId, messageId); 47 | } 48 | 49 | public ApiResponse getMe() { 50 | return bot.getMe(); 51 | } 52 | 53 | public ApiResponse getUserProfilePhotos(int userId) { 54 | return bot.getUserProfilePhotos(userId); 55 | } 56 | 57 | public ApiResponse getUserProfilePhotos(int userId, OptionalArgs optionalArgs) { 58 | return bot.getUserProfilePhotos(userId, optionalArgs); 59 | } 60 | 61 | public ApiResponse sendAudio(File audioFile) { 62 | return bot.sendAudio(chatId, audioFile); 63 | } 64 | 65 | public ApiResponse sendAudio(File audioFile, OptionalArgs optionalArgs) { 66 | return bot.sendAudio(chatId, audioFile, optionalArgs); 67 | } 68 | 69 | public ApiResponse sendAudio(String audioFileId) { 70 | return bot.sendAudio(chatId, audioFileId); 71 | } 72 | 73 | public ApiResponse sendAudio(String audioFileId, OptionalArgs optionalArgs) { 74 | return bot.sendAudio(chatId, audioFileId, optionalArgs); 75 | } 76 | 77 | public ApiResponse sendChatAction(ChatAction chatAction) { 78 | return bot.sendChatAction(chatId, chatAction); 79 | } 80 | 81 | public ApiResponse sendDocument(File documentFile) { 82 | return bot.sendDocument(chatId, documentFile); 83 | } 84 | 85 | public ApiResponse sendDocument(File documentFile, OptionalArgs optionalArgs) { 86 | return bot.sendDocument(chatId, documentFile, optionalArgs); 87 | } 88 | 89 | public ApiResponse sendDocument(String documentFileId) { 90 | return bot.sendDocument(chatId, documentFileId); 91 | } 92 | 93 | public ApiResponse sendDocument(String documentFileId, OptionalArgs optionalArgs) { 94 | return bot.sendDocument(chatId, documentFileId, optionalArgs); 95 | } 96 | 97 | public ApiResponse sendLocation(float latitude, float longitude) { 98 | return bot.sendLocation(chatId, latitude, longitude); 99 | } 100 | 101 | public ApiResponse sendLocation(float latitude, float longitude, OptionalArgs optionalArgs) { 102 | return bot.sendLocation(chatId, latitude, longitude, optionalArgs); 103 | } 104 | 105 | public ApiResponse sendMessage(String text) { 106 | return bot.sendMessage(chatId, text); 107 | } 108 | 109 | public ApiResponse sendMessage(String text, OptionalArgs optionalArgs) { 110 | return bot.sendMessage(chatId, text, optionalArgs); 111 | } 112 | 113 | public ApiResponse sendPhoto(File photoFile) { 114 | return bot.sendPhoto(chatId, photoFile); 115 | } 116 | 117 | public ApiResponse sendPhoto(File photoFile, OptionalArgs optionalArgs) { 118 | return bot.sendPhoto(chatId, photoFile, optionalArgs); 119 | } 120 | 121 | public ApiResponse sendPhoto(String photoFileId) { 122 | return bot.sendPhoto(chatId, photoFileId); 123 | } 124 | 125 | public ApiResponse sendPhoto(String photoFileId, OptionalArgs optionalArgs) { 126 | return bot.sendPhoto(chatId, photoFileId, optionalArgs); 127 | } 128 | 129 | public ApiResponse sendSticker(File stickerFile) { 130 | return bot.sendSticker(chatId, stickerFile); 131 | } 132 | 133 | public ApiResponse sendSticker(File stickerFile, OptionalArgs optionalArgs) { 134 | return bot.sendSticker(chatId, stickerFile, optionalArgs); 135 | } 136 | 137 | public ApiResponse sendSticker(String stickerFileId) { 138 | return bot.sendSticker(chatId, stickerFileId); 139 | } 140 | 141 | public ApiResponse sendSticker(String stickerFileId, OptionalArgs optionalArgs) { 142 | return bot.sendSticker(chatId, stickerFileId, optionalArgs); 143 | } 144 | 145 | public ApiResponse sendVideo(File videoFile) { 146 | return bot.sendVideo(chatId, videoFile); 147 | } 148 | 149 | public ApiResponse sendVideo(File videoFile, OptionalArgs optionalArgs) { 150 | return bot.sendVideo(chatId, videoFile, optionalArgs); 151 | } 152 | 153 | public ApiResponse sendVideo(String videoFileId) { 154 | return bot.sendVideo(chatId, videoFileId); 155 | } 156 | 157 | public ApiResponse sendVideo(String videoFileId, OptionalArgs optionalArgs) { 158 | return bot.sendVideo(chatId, videoFileId, optionalArgs); 159 | } 160 | 161 | public ApiResponse sendVoice(int chatId, File voiceFile) { 162 | return bot.sendVoice(chatId, voiceFile); 163 | } 164 | 165 | public ApiResponse sendVoice(int chatId, File voiceFile, OptionalArgs optionalArgs) { 166 | return bot.sendVoice(chatId, voiceFile, optionalArgs); 167 | } 168 | 169 | public ApiResponse sendVoice(int chatId, String voiceFileId) { 170 | return bot.sendVoice(chatId, voiceFileId); 171 | } 172 | 173 | public ApiResponse sendVoice(int chatId, String voiceFileId, OptionalArgs optionalArgs) { 174 | return bot.sendVoice(chatId, voiceFileId, optionalArgs); 175 | } 176 | 177 | public ApiResponse replyTo(Message message, String text) { 178 | return bot.sendMessage(chatId, text, new OptionalArgs().replyToMessageId(message.getMessageId())); 179 | } 180 | 181 | public int getChatId() { 182 | return chatId; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/ChatContextTelegramBot.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public class ChatContextTelegramBot extends TelegramBot { 10 | 11 | private final Map contextMap = new HashMap<>(); 12 | private AbstractChatContextFactory chatContextFactory; 13 | 14 | public ChatContextTelegramBot(String botToken, AbstractChatContextFactory chatContextFactory) { 15 | this(botToken, chatContextFactory, true); 16 | } 17 | 18 | public ChatContextTelegramBot(String botToken, AbstractChatContextFactory chatContextFactory, boolean sendAsync) { 19 | super(botToken); 20 | this.chatContextFactory = chatContextFactory; 21 | } 22 | 23 | public void add(ChatContext context) { 24 | contextMap.put(context.getChatId(), context); 25 | } 26 | 27 | public void addAll(List contextList) { 28 | for (ChatContext chatContext : contextList) 29 | add(chatContext); 30 | } 31 | 32 | @Override 33 | protected void onStart() { 34 | for (ChatContext chatContext : contextMap.values()) 35 | chatContext.onStart(); 36 | } 37 | 38 | @Override 39 | protected void onStop() { 40 | for (ChatContext chatContext : contextMap.values()) 41 | chatContext.onStop(); 42 | } 43 | 44 | @Override 45 | protected void onMessage(Message message) { 46 | int chatId = message.getChat().getId(); 47 | 48 | ChatContext chatContext; 49 | synchronized (contextMap) { 50 | chatContext = contextMap.get(chatId); 51 | if (chatContext == null) 52 | chatContext = createNewChatContext(chatId); 53 | } 54 | 55 | chatContext.passMessage(message); 56 | } 57 | 58 | private ChatContext createNewChatContext(int chatId) { 59 | ChatContext chatContext = chatContextFactory.createChatContext(chatId, this); 60 | contextMap.put(chatId, chatContext); 61 | return chatContext; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/CommandHandler.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Documented 6 | @Target(ElementType.METHOD) 7 | @Retention(RetentionPolicy.RUNTIME) 8 | public @interface CommandHandler { 9 | String[] value(); 10 | } 11 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/DefaultHandler.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Documented 6 | @Target(ElementType.METHOD) 7 | @Retention(RetentionPolicy.RUNTIME) 8 | public @interface DefaultHandler { 9 | 10 | } -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/HandlerNotifier.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.lang.reflect.Method; 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.List; 10 | import java.util.logging.Level; 11 | import java.util.logging.Logger; 12 | 13 | public class HandlerNotifier { 14 | 15 | private final static Logger logger = Logger.getLogger(HandlerNotifier.class.getName()); 16 | 17 | private Object objectWithHandlers; 18 | private Method defaultHandler; 19 | private List messageHandlers = new ArrayList<>(); 20 | 21 | public HandlerNotifier(Object objectWithHandlers) { 22 | this.objectWithHandlers = objectWithHandlers; 23 | 24 | indexHandlers(); 25 | } 26 | 27 | private void indexHandlers() { 28 | Method[] declaredMethods = objectWithHandlers.getClass().getDeclaredMethods(); 29 | for (Method method : declaredMethods) { 30 | if (method.isAnnotationPresent(MessageHandler.class)) { 31 | logger.info("Found MessageHandler: " + method.getName()); 32 | MessageHandler messageHandlerAnnotation = method.getAnnotation(MessageHandler.class); 33 | messageHandlers.add(new MessageHandlerFilter(messageHandlerAnnotation.contentTypes(), method)); 34 | } else if (method.isAnnotationPresent(CommandHandler.class)) { 35 | logger.info("Found CommandHandler: " + method.getName()); 36 | CommandHandler commandHandlerAnnotation = method.getAnnotation(CommandHandler.class); 37 | messageHandlers.add(new CommandHandlerFilter(commandHandlerAnnotation.value(), method)); 38 | } else if (method.isAnnotationPresent(DefaultHandler.class)) { 39 | logger.info("Found DefaultHandler: " + method.getName()); 40 | defaultHandler = method; 41 | } 42 | } 43 | } 44 | 45 | public void notifyHandlers(final Message message) { 46 | Method handler = null; 47 | for (MessageFilter filter : messageHandlers) { 48 | if (filter.valid(message)) { 49 | handler = filter.getHandler(); 50 | break; 51 | } 52 | } 53 | 54 | if (handler == null) 55 | handler = defaultHandler; 56 | 57 | final Method handlerToExecute = handler; 58 | notifyMessageHandler(handlerToExecute, message); 59 | } 60 | 61 | private void notifyMessageHandler(Method handler, Message message) { 62 | try { 63 | handler.invoke(objectWithHandlers, message); 64 | } catch (IllegalAccessException | InvocationTargetException e) { 65 | logger.log(Level.SEVERE, "An exception occurred while trying to invoke handler '" + handler.getName() + "'", e); 66 | } 67 | } 68 | 69 | private interface MessageFilter { 70 | boolean valid(Message message); 71 | Method getHandler(); 72 | } 73 | 74 | private static class MessageHandlerFilter implements MessageFilter { 75 | 76 | private Method handler; 77 | private List contentTypes; 78 | 79 | public MessageHandlerFilter(Message.Type[] contentTypes, Method handler) { 80 | this.contentTypes = Arrays.asList(contentTypes); 81 | this.handler = handler; 82 | } 83 | 84 | @Override 85 | public boolean valid(Message message) { 86 | return contentTypes.contains(message.getType()); 87 | } 88 | 89 | @Override 90 | public Method getHandler() { 91 | return handler; 92 | } 93 | } 94 | 95 | private static class CommandHandlerFilter implements MessageFilter { 96 | 97 | private Method handler; 98 | private List commands; 99 | 100 | public CommandHandlerFilter(String[] commands, Method handler) { 101 | this.handler = handler; 102 | this.commands = Arrays.asList(commands); 103 | } 104 | 105 | @Override 106 | public boolean valid(Message message) { 107 | return message.getType() == Message.Type.TEXT && commands.contains(extractCommand(message)); 108 | } 109 | 110 | private String extractCommand(Message message) { 111 | if (isCommand(message)) { 112 | String text = message.getText(); 113 | return text.split(" ")[0].split("@")[0].substring(1); 114 | } 115 | return null; 116 | } 117 | 118 | private boolean isCommand(Message message) { 119 | return message.getType() == Message.Type.TEXT && message.getText().startsWith("/"); 120 | } 121 | 122 | @Override 123 | public Method getHandler() { 124 | return handler; 125 | } 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/MessageHandler.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.lang.annotation.*; 6 | 7 | @Documented 8 | @Target(ElementType.METHOD) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface MessageHandler { 11 | Message.Type[] contentTypes() default Message.Type.TEXT; 12 | } -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/RegistrableTelegramBot.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.util.List; 6 | import java.util.concurrent.CopyOnWriteArrayList; 7 | import java.util.concurrent.ExecutorService; 8 | import java.util.concurrent.Executors; 9 | 10 | public class RegistrableTelegramBot extends TelegramBot { 11 | 12 | private boolean async; 13 | private List messageListeners = new CopyOnWriteArrayList<>(); 14 | private ExecutorService executorService = Executors.newCachedThreadPool(); 15 | 16 | public RegistrableTelegramBot(String botToken) { 17 | this(botToken, false); 18 | } 19 | 20 | public RegistrableTelegramBot(String botToken, boolean async) { 21 | super(botToken, async); 22 | } 23 | 24 | public void register(MessageListener messageListener) { 25 | messageListeners.add(messageListener); 26 | } 27 | 28 | public void unregister(MessageListener messageListener) { 29 | messageListeners.remove(messageListener); 30 | } 31 | 32 | @Override 33 | protected ExecutorService provideExecutorService() { 34 | return null; 35 | } 36 | 37 | 38 | @Override 39 | protected void notifyNewMessages(List messages) { 40 | for (final Message message : messages) { 41 | for (final MessageListener messageListener : messageListeners) { 42 | executorService.submit(new Runnable() { 43 | @Override 44 | public void run() { 45 | messageListener.onMessage(RegistrableTelegramBot.this, message); 46 | } 47 | }); 48 | } 49 | } 50 | } 51 | 52 | public interface MessageListener { 53 | 54 | void onMessage(TelegramBot bot, Message message); 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * TelegramBots4Java is a Java implementation of the Telegram Bot API (https://core.telegram.org/bots/api). 3 | */ 4 | package co.vandenham.telegram.botapi; -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/ApiException.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.requests.ApiResult; 4 | 5 | 6 | public class ApiException extends RuntimeException { 7 | 8 | private String methodName; 9 | 10 | public ApiException(String methodName) { 11 | super(String.format("An exception occurred while accessing %s.", methodName)); 12 | this.methodName = methodName; 13 | } 14 | 15 | public ApiException(String methodName, Throwable cause) { 16 | super(String.format("An exception occurred while accessing %s.", methodName), cause); 17 | this.methodName = methodName; 18 | } 19 | 20 | public ApiException(String methodName, ApiResult unexpectedResult) { 21 | super(String.format("Unexpected result received from Telegram while accessing %s: %s.", methodName, unexpectedResult)); 22 | this.methodName = methodName; 23 | } 24 | 25 | public String getMethodName() { 26 | return methodName; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | if (getCause() == null) 32 | return super.toString(); 33 | else 34 | return super.toString() + " Caused by: " + getCause().toString(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/ApiRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | import co.vandenham.telegram.botapi.types.Update; 5 | import co.vandenham.telegram.botapi.types.User; 6 | import co.vandenham.telegram.botapi.types.UserProfilePhotos; 7 | import com.google.gson.reflect.TypeToken; 8 | 9 | import java.io.File; 10 | import java.lang.reflect.Type; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | interface ApiRequest { 15 | 16 | String getMethodName(); 17 | 18 | ResultTypes getResultType(); 19 | 20 | Map getArgs(); 21 | 22 | RequestStrategy getRequestStrategy(); 23 | 24 | enum ResultTypes { 25 | USER(new TypeToken>() {}.getType()), 26 | MESSAGE(new TypeToken>() {}.getType()), 27 | BOOLEAN(new TypeToken>() {}.getType()), 28 | USER_PROFILE_PHOTOS(new TypeToken>() {}.getType()), 29 | LIST_OF_UPDATES(new TypeToken>>() {}.getType()); 30 | 31 | private Type type; 32 | 33 | ResultTypes(Type type) { 34 | this.type = type; 35 | } 36 | 37 | public Type getType() { 38 | return type; 39 | } 40 | } 41 | 42 | interface RequestStrategy { 43 | 44 | String makeRequest(ApiRequest request, TelegramApi api); 45 | 46 | } 47 | 48 | final class PostStrategy implements RequestStrategy { 49 | 50 | @Override 51 | public String makeRequest(ApiRequest request, TelegramApi api) { 52 | return api.makePostRequest(request.getMethodName(), request.getArgs()); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return "POST"; 58 | } 59 | } 60 | 61 | final class GetStrategy implements RequestStrategy { 62 | 63 | @Override 64 | public String makeRequest(ApiRequest request, TelegramApi api) { 65 | return api.makeGetRequest(request.getMethodName()); 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | return "GET"; 71 | } 72 | } 73 | 74 | final class MultipartStrategy implements RequestStrategy { 75 | 76 | private File file; 77 | private String fieldName; 78 | 79 | public MultipartStrategy(File file, String fieldName) { 80 | this.file = file; 81 | this.fieldName = fieldName; 82 | } 83 | 84 | @Override 85 | public String makeRequest(ApiRequest request, TelegramApi api) { 86 | return api.makeMultipartRequest(request.getMethodName(), request.getArgs(), fieldName, file); 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return "MULTIPART"; 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/ApiRequestExecutor.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import com.google.gson.Gson; 4 | 5 | import java.util.concurrent.*; 6 | import java.util.logging.Logger; 7 | 8 | abstract public class ApiRequestExecutor { 9 | 10 | private static final Logger log = Logger.getLogger(ApiRequestExecutor.class.getName()); 11 | private static final Gson gson = new Gson(); 12 | 13 | private static final ApiRequestExecutor synchronousExecutor = new SyncApiRequestExecutor(); 14 | private static final ApiRequestExecutor asynchronousExecutor = new AsyncApiRequestExecutor(); 15 | 16 | // Non instantiable/subclassable 17 | private ApiRequestExecutor() { 18 | } 19 | 20 | public static ApiRequestExecutor getSynchronousExecutor() { 21 | return synchronousExecutor; 22 | } 23 | 24 | public static ApiRequestExecutor getAsynchronousExecutor() { 25 | return asynchronousExecutor; 26 | } 27 | 28 | protected ApiResult deserialize(String json, ApiRequest.ResultTypes resultType) { 29 | return gson.fromJson(json, resultType.getType()); 30 | } 31 | 32 | protected T makeRequest(TelegramApi api, ApiRequest request) { 33 | log.info(request.toString()); 34 | 35 | String response = request.getRequestStrategy().makeRequest(request, api); 36 | 37 | ApiResult result = deserialize(response, request.getResultType()); 38 | 39 | if (!result.isOk()) 40 | throw new ApiException(request.getMethodName(), result); 41 | 42 | return result.getResult(); 43 | } 44 | 45 | abstract public ApiResponse execute(TelegramApi api, ApiRequest request); 46 | 47 | private static class SyncApiResponse implements ApiResponse { 48 | 49 | private T result; 50 | 51 | public SyncApiResponse(T result) { 52 | this.result = result; 53 | } 54 | 55 | @Override 56 | public T getResult() { 57 | return result; 58 | } 59 | } 60 | 61 | private static class SyncApiRequestExecutor extends ApiRequestExecutor { 62 | 63 | public ApiResponse execute(TelegramApi api, ApiRequest request) { 64 | return new SyncApiResponse<>(makeRequest(api, request)); 65 | } 66 | 67 | } 68 | 69 | private static class AsyncApiResponse implements ApiResponse { 70 | 71 | private Future result; 72 | 73 | public AsyncApiResponse(Future result) { 74 | this.result = result; 75 | } 76 | 77 | @Override 78 | public T getResult() { 79 | try { 80 | return result.get(); 81 | } catch (InterruptedException | ExecutionException e) { 82 | e.printStackTrace(); 83 | } 84 | return null; 85 | } 86 | } 87 | 88 | private static class AsyncApiRequestExecutor extends ApiRequestExecutor { 89 | 90 | private static final ExecutorService executorService = Executors.newCachedThreadPool(); 91 | 92 | @Override 93 | public ApiResponse execute(final TelegramApi api, final ApiRequest request) { 94 | Future future = executorService.submit(new Callable() { 95 | @Override 96 | public T call() throws Exception { 97 | return makeRequest(api, request); 98 | } 99 | }); 100 | 101 | return new AsyncApiResponse<>(future); 102 | } 103 | 104 | } 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/ApiResponse.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | public interface ApiResponse { 4 | 5 | T getResult(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/ApiResult.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class ApiResult { 6 | 7 | @SerializedName("ok") 8 | private boolean ok; 9 | 10 | @SerializedName("description") 11 | private String description; 12 | 13 | @SerializedName("error_code") 14 | private int errorCode; 15 | 16 | @SerializedName("result") 17 | private T result; 18 | 19 | public ApiResult() { 20 | } 21 | 22 | public boolean isOk() { 23 | return ok; 24 | } 25 | 26 | public String getDescription() { 27 | return description; 28 | } 29 | 30 | public int getErrorCode() { 31 | return errorCode; 32 | } 33 | 34 | public T getResult() { 35 | return result; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/ChatAction.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | public enum ChatAction { 4 | TYPING, 5 | UPLOAD_PHOTO, 6 | RECORD_VIDEO, 7 | UPLOAD_VIDEO, 8 | RECORD_AUDIO, 9 | UPLOAD_AUDIO, 10 | UPLOAD_DOCUMENT, 11 | FIND_LOCATION; 12 | 13 | public String getAction() { 14 | return name().toLowerCase(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/ForwardMessageRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class ForwardMessageRequest implements ApiRequest { 9 | 10 | private Map args = new HashMap<>(); 11 | 12 | public ForwardMessageRequest(int chatId, int fromChatId, int messageId) { 13 | args.put("chat_id", String.valueOf(chatId)); 14 | args.put("from_chat_id", String.valueOf(fromChatId)); 15 | args.put("message_id", String.valueOf(messageId)); 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return "ForwardMessageRequest{" + 21 | "args=" + args + 22 | '}'; 23 | } 24 | 25 | @Override 26 | public String getMethodName() { 27 | return "forwardMessage"; 28 | } 29 | 30 | @Override 31 | public ResultTypes getResultType() { 32 | return ResultTypes.MESSAGE; 33 | } 34 | 35 | @Override 36 | public Map getArgs() { 37 | return args; 38 | } 39 | 40 | @Override 41 | public RequestStrategy getRequestStrategy() { 42 | return new PostStrategy(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/GetMeRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.User; 4 | 5 | import java.util.Map; 6 | 7 | public class GetMeRequest implements ApiRequest { 8 | 9 | @Override 10 | public String getMethodName() { 11 | return "getMe"; 12 | } 13 | 14 | @Override 15 | public ResultTypes getResultType() { 16 | return ResultTypes.USER; 17 | } 18 | 19 | @Override 20 | public Map getArgs() { 21 | return null; 22 | } 23 | 24 | @Override 25 | public RequestStrategy getRequestStrategy() { 26 | return new GetStrategy(); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "GetMeRequest{}"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/GetUpdatesRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Update; 4 | 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | public class GetUpdatesRequest implements ApiRequest> { 10 | 11 | private Map args = new HashMap<>(); 12 | 13 | public GetUpdatesRequest() { 14 | } 15 | 16 | public GetUpdatesRequest(OptionalArgs optionalArgs) { 17 | if (optionalArgs != null) 18 | args.putAll(optionalArgs.options()); 19 | } 20 | 21 | @Override 22 | public String getMethodName() { 23 | return "getUpdates"; 24 | } 25 | 26 | @Override 27 | public ResultTypes getResultType() { 28 | return ResultTypes.LIST_OF_UPDATES; 29 | } 30 | 31 | @Override 32 | public Map getArgs() { 33 | return args; 34 | } 35 | 36 | @Override 37 | public RequestStrategy getRequestStrategy() { 38 | return new PostStrategy(); 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "GetUpdatesRequest{" + 44 | "args=" + args + 45 | '}'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/GetUserProfilePhotosRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.UserProfilePhotos; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class GetUserProfilePhotosRequest implements ApiRequest { 9 | 10 | private Map args = new HashMap<>(); 11 | 12 | public GetUserProfilePhotosRequest(int userId) { 13 | this(userId, null); 14 | } 15 | 16 | public GetUserProfilePhotosRequest(int userId, OptionalArgs optionalArgs) { 17 | args.put("user_id", String.valueOf(userId)); 18 | 19 | if (optionalArgs != null) 20 | args.putAll(optionalArgs.options()); 21 | } 22 | 23 | @Override 24 | public String getMethodName() { 25 | return "getUserProfilePhotos"; 26 | } 27 | 28 | @Override 29 | public ResultTypes getResultType() { 30 | return ResultTypes.USER_PROFILE_PHOTOS; 31 | } 32 | 33 | @Override 34 | public Map getArgs() { 35 | return args; 36 | } 37 | 38 | @Override 39 | public RequestStrategy getRequestStrategy() { 40 | return new PostStrategy(); 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "GetUserProfilePhotosRequest{" + 46 | "args=" + args + 47 | '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/OptionalArgs.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.ReplyMarkup; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class OptionalArgs { 9 | 10 | private boolean disableWebPagePreview = false; 11 | private int replyToMessageId = -1; 12 | private ReplyMarkup replyMarkup = null; 13 | private int offset = -1; 14 | private int limit = -1; 15 | private int timeout = -1; 16 | private int duration = -1; 17 | private String caption = null; 18 | private String performer = null; 19 | private String title = null; 20 | 21 | private Map options; 22 | 23 | public Map options() { 24 | options = new HashMap<>(); 25 | 26 | if (disableWebPagePreview) 27 | putBoolean("disable_web_page_preview", true); 28 | 29 | if (replyToMessageId != -1) 30 | putInt("reply_to_message_id", replyToMessageId); 31 | 32 | if (offset != -1) 33 | putInt("offset", offset); 34 | 35 | if (limit != -1) 36 | putInt("limit", limit); 37 | 38 | if (timeout != -1) 39 | putInt("timeout", timeout); 40 | 41 | if (duration != -1) 42 | putInt("duration", duration); 43 | 44 | if (replyMarkup != null) 45 | options.put("reply_markup", replyMarkup.serialize()); 46 | 47 | if (caption != null) 48 | options.put("caption", caption); 49 | 50 | if (performer != null) 51 | options.put("performer", performer); 52 | 53 | if (title != null) 54 | options.put("title", title); 55 | 56 | return options; 57 | } 58 | 59 | private void putBoolean(String key, boolean b) { 60 | options.put(key, String.valueOf(b)); 61 | } 62 | 63 | private void putInt(String key, int i) { 64 | options.put(key, String.valueOf(i)); 65 | } 66 | 67 | public OptionalArgs disableWebPagePreview() { 68 | this.disableWebPagePreview = true; 69 | return this; 70 | } 71 | 72 | public OptionalArgs replyToMessageId(int replyToMessageId) { 73 | this.replyToMessageId = replyToMessageId; 74 | return this; 75 | } 76 | 77 | public OptionalArgs replyMarkup(ReplyMarkup replyMarkup) { 78 | this.replyMarkup = replyMarkup; 79 | return this; 80 | } 81 | 82 | public OptionalArgs offset(int offset) { 83 | this.offset = offset; 84 | return this; 85 | } 86 | 87 | public OptionalArgs limit(int limit) { 88 | this.limit = limit; 89 | return this; 90 | } 91 | 92 | public OptionalArgs timeout(int timeout) { 93 | this.timeout = timeout; 94 | return this; 95 | } 96 | 97 | public OptionalArgs duration(int duration) { 98 | this.duration = duration; 99 | return this; 100 | } 101 | 102 | public OptionalArgs caption(String caption) { 103 | this.caption = caption; 104 | return this; 105 | } 106 | 107 | public OptionalArgs performer(String performer) { 108 | this.performer = performer; 109 | return this; 110 | } 111 | 112 | public OptionalArgs title(String title) { 113 | this.title = title; 114 | return this; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendAudioRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.io.File; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class SendAudioRequest implements ApiRequest { 10 | 11 | private Map args = new HashMap<>(); 12 | private RequestStrategy requestStrategy; 13 | 14 | public SendAudioRequest(int chatId, File audioFile) { 15 | this(chatId, audioFile, null); 16 | } 17 | 18 | public SendAudioRequest(int chatId, File audioFile, OptionalArgs optionalArgs) { 19 | args.put("chat_id", String.valueOf(chatId)); 20 | 21 | if (optionalArgs != null) 22 | args.putAll(optionalArgs.options()); 23 | 24 | requestStrategy = new MultipartStrategy(audioFile, "audio"); 25 | } 26 | 27 | public SendAudioRequest(int chatId, String audioString) { 28 | this(chatId, audioString, null); 29 | } 30 | 31 | public SendAudioRequest(int chatId, String audioString, OptionalArgs optionalArgs) { 32 | args.put("chat_id", String.valueOf(chatId)); 33 | args.put("audio", audioString); 34 | 35 | if (optionalArgs != null) 36 | args.putAll(optionalArgs.options()); 37 | 38 | requestStrategy = new PostStrategy(); 39 | } 40 | 41 | @Override 42 | public String getMethodName() { 43 | return "sendAudio"; 44 | } 45 | 46 | @Override 47 | public ResultTypes getResultType() { 48 | return ResultTypes.MESSAGE; 49 | } 50 | 51 | @Override 52 | public Map getArgs() { 53 | return args; 54 | } 55 | 56 | @Override 57 | public RequestStrategy getRequestStrategy() { 58 | return requestStrategy; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "SendAudioRequest{" + 64 | "args=" + args + 65 | ", requestStrategy=" + requestStrategy + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendChatActionRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class SendChatActionRequest implements ApiRequest { 7 | 8 | private Map args = new HashMap<>(); 9 | 10 | public SendChatActionRequest(int chatId, ChatAction chatAction) { 11 | args.put("chat_id", String.valueOf(chatId)); 12 | args.put("action", chatAction.getAction()); 13 | } 14 | 15 | @Override 16 | public String getMethodName() { 17 | return "sendChatAction"; 18 | } 19 | 20 | @Override 21 | public ResultTypes getResultType() { 22 | return ResultTypes.BOOLEAN; 23 | } 24 | 25 | @Override 26 | public Map getArgs() { 27 | return args; 28 | } 29 | 30 | @Override 31 | public RequestStrategy getRequestStrategy() { 32 | return new PostStrategy(); 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return "SendChatActionRequest{" + 38 | "args=" + args + 39 | '}'; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendDocumentRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.io.File; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class SendDocumentRequest implements ApiRequest { 10 | 11 | private Map args = new HashMap<>(); 12 | private RequestStrategy requestStrategy; 13 | 14 | public SendDocumentRequest(int chatId, File document) { 15 | this(chatId, document, null); 16 | } 17 | 18 | public SendDocumentRequest(int chatId, File document, OptionalArgs optionalArgs) { 19 | args.put("chat_id", String.valueOf(chatId)); 20 | 21 | if (optionalArgs != null) 22 | args.putAll(optionalArgs.options()); 23 | 24 | requestStrategy = new MultipartStrategy(document, "document"); 25 | } 26 | 27 | public SendDocumentRequest(int chatId, String document) { 28 | this(chatId, document, null); 29 | } 30 | 31 | public SendDocumentRequest(int chatId, String document, OptionalArgs optionalArgs) { 32 | args.put("chat_id", String.valueOf(chatId)); 33 | args.put("document", document); 34 | 35 | if (optionalArgs != null) 36 | args.putAll(optionalArgs.options()); 37 | 38 | requestStrategy = new PostStrategy(); 39 | } 40 | 41 | @Override 42 | public String getMethodName() { 43 | return "sendDocument"; 44 | } 45 | 46 | @Override 47 | public ResultTypes getResultType() { 48 | return ResultTypes.MESSAGE; 49 | } 50 | 51 | @Override 52 | public Map getArgs() { 53 | return args; 54 | } 55 | 56 | @Override 57 | public RequestStrategy getRequestStrategy() { 58 | return requestStrategy; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "SendDocumentRequest{" + 64 | "args=" + args + 65 | ", requestStrategy=" + requestStrategy + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendLocationRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class SendLocationRequest implements ApiRequest { 9 | 10 | private Map args = new HashMap<>(); 11 | 12 | public SendLocationRequest(int chatId, float latitude, float longitude) { 13 | this(chatId, latitude, longitude, null); 14 | } 15 | 16 | public SendLocationRequest(int chatId, float latitude, float longitude, OptionalArgs optionalArgs) { 17 | args.put("chat_id", String.valueOf(chatId)); 18 | args.put("latitude", String.valueOf(latitude)); 19 | args.put("longitude", String.valueOf(longitude)); 20 | 21 | if (optionalArgs != null) 22 | args.putAll(optionalArgs.options()); 23 | } 24 | 25 | @Override 26 | public String getMethodName() { 27 | return "sendLocation"; 28 | } 29 | 30 | @Override 31 | public ResultTypes getResultType() { 32 | return ResultTypes.MESSAGE; 33 | } 34 | 35 | @Override 36 | public Map getArgs() { 37 | return args; 38 | } 39 | 40 | @Override 41 | public RequestStrategy getRequestStrategy() { 42 | return new PostStrategy(); 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "SendLocationRequest{" + 48 | "args=" + args + 49 | '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendMessageRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public final class SendMessageRequest implements ApiRequest { 9 | 10 | private Map args = new HashMap<>(); 11 | 12 | public SendMessageRequest(int chatId, String text) { 13 | this(chatId, text, null); 14 | } 15 | 16 | public SendMessageRequest(int chatId, String text, OptionalArgs optionalArgs) { 17 | args.put("chat_id", String.valueOf(chatId)); 18 | args.put("text", text); 19 | 20 | if (optionalArgs != null) 21 | args.putAll(optionalArgs.options()); 22 | } 23 | 24 | @Override 25 | public String getMethodName() { 26 | return "sendMessage"; 27 | } 28 | 29 | @Override 30 | public ResultTypes getResultType() { 31 | return ResultTypes.MESSAGE; 32 | } 33 | 34 | @Override 35 | public Map getArgs() { 36 | return args; 37 | } 38 | 39 | @Override 40 | public RequestStrategy getRequestStrategy() { 41 | return new PostStrategy(); 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return "SendMessageRequest{" + 47 | "args=" + args + 48 | '}'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendPhotoRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.io.File; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class SendPhotoRequest implements ApiRequest { 10 | 11 | private Map args = new HashMap<>(); 12 | private RequestStrategy requestStrategy; 13 | 14 | public SendPhotoRequest(int chatId, File photo) { 15 | this(chatId, photo, null); 16 | } 17 | 18 | public SendPhotoRequest(int chatId, File photo, OptionalArgs optionalArgs) { 19 | args.put("chat_id", String.valueOf(chatId)); 20 | 21 | if (optionalArgs != null) 22 | args.putAll(optionalArgs.options()); 23 | 24 | requestStrategy = new MultipartStrategy(photo, "photo"); 25 | } 26 | 27 | public SendPhotoRequest(int chatId, String photo) { 28 | this(chatId, photo, null); 29 | } 30 | 31 | public SendPhotoRequest(int chatId, String photo, OptionalArgs optionalArgs) { 32 | args.put("chat_id", String.valueOf(chatId)); 33 | args.put("photo", photo); 34 | 35 | if (optionalArgs != null) 36 | args.putAll(optionalArgs.options()); 37 | 38 | requestStrategy = new PostStrategy(); 39 | } 40 | 41 | @Override 42 | public String getMethodName() { 43 | return "sendPhoto"; 44 | } 45 | 46 | @Override 47 | public ResultTypes getResultType() { 48 | return ResultTypes.MESSAGE; 49 | } 50 | 51 | @Override 52 | public Map getArgs() { 53 | return args; 54 | } 55 | 56 | @Override 57 | public RequestStrategy getRequestStrategy() { 58 | return requestStrategy; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "SendPhotoRequest{" + 64 | "args=" + args + 65 | ", requestStrategy=" + requestStrategy + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendStickerRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.io.File; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class SendStickerRequest implements ApiRequest { 10 | 11 | private Map args = new HashMap<>(); 12 | private RequestStrategy requestStrategy; 13 | 14 | public SendStickerRequest(int chatId, File sticker) { 15 | this(chatId, sticker, null); 16 | } 17 | 18 | public SendStickerRequest(int chatId, File sticker, OptionalArgs optionalArgs) { 19 | args.put("chat_id", String.valueOf(chatId)); 20 | 21 | if (optionalArgs != null) 22 | args.putAll(optionalArgs.options()); 23 | 24 | requestStrategy = new MultipartStrategy(sticker, "sticker"); 25 | } 26 | 27 | public SendStickerRequest(int chatId, String sticker) { 28 | this(chatId, sticker, null); 29 | } 30 | 31 | public SendStickerRequest(int chatId, String sticker, OptionalArgs optionalArgs) { 32 | args.put("chat_id", String.valueOf(chatId)); 33 | args.put("sticker", sticker); 34 | 35 | if (optionalArgs != null) 36 | args.putAll(optionalArgs.options()); 37 | 38 | requestStrategy = new PostStrategy(); 39 | } 40 | 41 | 42 | @Override 43 | public String getMethodName() { 44 | return "sendSticker"; 45 | } 46 | 47 | @Override 48 | public ResultTypes getResultType() { 49 | return ResultTypes.MESSAGE; 50 | } 51 | 52 | @Override 53 | public Map getArgs() { 54 | return args; 55 | } 56 | 57 | @Override 58 | public RequestStrategy getRequestStrategy() { 59 | return requestStrategy; 60 | } 61 | 62 | @Override 63 | public String toString() { 64 | return "SendStickerRequest{" + 65 | "args=" + args + 66 | ", requestStrategy=" + requestStrategy + 67 | '}'; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendVideoRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.io.File; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class SendVideoRequest implements ApiRequest { 10 | 11 | private Map args = new HashMap<>(); 12 | private RequestStrategy requestStrategy; 13 | 14 | public SendVideoRequest(int chatId, File video) { 15 | this(chatId, video, null); 16 | } 17 | 18 | public SendVideoRequest(int chatId, File video, OptionalArgs optionalArgs) { 19 | args.put("chat_id", String.valueOf(chatId)); 20 | 21 | if (optionalArgs != null) 22 | args.putAll(optionalArgs.options()); 23 | 24 | requestStrategy = new MultipartStrategy(video, "video"); 25 | } 26 | 27 | public SendVideoRequest(int chatId, String video) { 28 | this(chatId, video, null); 29 | } 30 | 31 | public SendVideoRequest(int chatId, String video, OptionalArgs optionalArgs) { 32 | args.put("chat_id", String.valueOf(chatId)); 33 | args.put("video", video); 34 | 35 | if (optionalArgs != null) 36 | args.putAll(optionalArgs.options()); 37 | 38 | requestStrategy = new PostStrategy(); 39 | } 40 | 41 | @Override 42 | public String getMethodName() { 43 | return "sendVideo"; 44 | } 45 | 46 | @Override 47 | public ResultTypes getResultType() { 48 | return ResultTypes.MESSAGE; 49 | } 50 | 51 | @Override 52 | public Map getArgs() { 53 | return args; 54 | } 55 | 56 | @Override 57 | public RequestStrategy getRequestStrategy() { 58 | return requestStrategy; 59 | } 60 | 61 | @Override 62 | public String toString() { 63 | return "SendVideoRequest{" + 64 | "args=" + args + 65 | ", requestStrategy=" + requestStrategy + 66 | '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/SendVoiceRequest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | 5 | import java.io.File; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class SendVoiceRequest implements ApiRequest { 10 | 11 | private Map args = new HashMap<>(); 12 | private RequestStrategy requestStrategy; 13 | 14 | public SendVoiceRequest(int chatId, File audioFile) { 15 | this(chatId, audioFile, null); 16 | } 17 | 18 | public SendVoiceRequest(int chatId, File audioFile, OptionalArgs optionalArgs) { 19 | args.put("chat_id", String.valueOf(chatId)); 20 | 21 | if (optionalArgs != null) 22 | args.putAll(optionalArgs.options()); 23 | 24 | requestStrategy = new MultipartStrategy(audioFile, "voice"); 25 | } 26 | 27 | public SendVoiceRequest(int chatId, String audioString) { 28 | this(chatId, audioString, null); 29 | } 30 | 31 | public SendVoiceRequest(int chatId, String audioString, OptionalArgs optionalArgs) { 32 | args.put("chat_id", String.valueOf(chatId)); 33 | args.put("voice", audioString); 34 | 35 | if (optionalArgs != null) 36 | args.putAll(optionalArgs.options()); 37 | 38 | requestStrategy = new PostStrategy(); 39 | } 40 | 41 | @Override 42 | public String getMethodName() { 43 | return "sendVoice"; 44 | } 45 | 46 | @Override 47 | public ResultTypes getResultType() { 48 | return ResultTypes.MESSAGE; 49 | } 50 | 51 | @Override 52 | public Map getArgs() { 53 | return args; 54 | } 55 | 56 | @Override 57 | public RequestStrategy getRequestStrategy() { 58 | return requestStrategy; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/TelegramApi.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import javax.net.ssl.HttpsURLConnection; 4 | import java.io.*; 5 | import java.net.URL; 6 | import java.net.URLConnection; 7 | import java.net.URLEncoder; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Scanner; 12 | 13 | 14 | public final class TelegramApi { 15 | 16 | public static final String API_URL = "https://api.telegram.org/bot%s/%s"; 17 | private final String token; 18 | 19 | public TelegramApi(String token) { 20 | this.token = token; 21 | } 22 | 23 | private static String createQueryString(Map arguments) throws UnsupportedEncodingException { 24 | StringBuilder stringBuilder = new StringBuilder(); 25 | 26 | for (Map.Entry entry : arguments.entrySet()) { 27 | stringBuilder.append(URLEncoder.encode(entry.getKey(), "UTF-8")) 28 | .append("=") 29 | .append(URLEncoder.encode(entry.getValue(), "UTF-8")) 30 | .append("&"); 31 | } 32 | return stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString(); 33 | } 34 | 35 | private static String readAll(InputStream input) { 36 | Scanner scanner = new Scanner(input); 37 | scanner.useDelimiter("\\A"); 38 | return scanner.hasNext() ? scanner.next() : null; 39 | } 40 | 41 | public String makeGetRequest(String method) { 42 | try { 43 | HttpsURLConnection connection = buildConnection(method); 44 | connection.setRequestMethod("GET"); 45 | connection.setDoInput(true); 46 | 47 | return readAll(connection.getInputStream()); 48 | } catch (IOException exception) { 49 | throw new ApiException(method, exception); 50 | } 51 | } 52 | 53 | public String makePostRequest(String method, Map arguments) { 54 | try { 55 | String query = createQueryString(arguments); 56 | 57 | HttpsURLConnection connection = buildConnection(method); 58 | connection.setRequestMethod("POST"); 59 | connection.setRequestProperty("Content-length", String.valueOf(query.length())); 60 | connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 61 | connection.setRequestProperty("User-Agent", "TelegramBots4Java API Agent"); 62 | 63 | connection.setDoInput(true); 64 | connection.setDoOutput(true); 65 | 66 | DataOutputStream output = new DataOutputStream(connection.getOutputStream()); 67 | output.writeBytes(query); 68 | output.close(); 69 | 70 | return readAll(connection.getInputStream()); 71 | } catch (IOException exception) { 72 | throw new ApiException(method, exception); 73 | } 74 | } 75 | 76 | public String makeMultipartRequest(String method, Map args, String fieldName, File uploadFile) { 77 | try { 78 | MultipartUtility multipartUtility = new MultipartUtility(buildConnection(method), "UTF-8"); 79 | 80 | for (Map.Entry entry : args.entrySet()) 81 | multipartUtility.addFormField(entry.getKey(), entry.getValue()); 82 | 83 | multipartUtility.addFilePart(fieldName, uploadFile); 84 | 85 | return multipartUtility.finish(); 86 | } catch (IOException e) { 87 | throw new ApiException(method, e); 88 | } 89 | } 90 | 91 | private HttpsURLConnection buildConnection(String methodName) { 92 | try { 93 | return (HttpsURLConnection) new URL(String.format(API_URL, token, methodName)).openConnection(); 94 | } catch (IOException e) { 95 | throw new ApiException(methodName, e); 96 | } 97 | } 98 | 99 | private static class MultipartUtility { 100 | private static final String LINE_FEED = "\r\n"; 101 | private final String boundary; 102 | private HttpsURLConnection httpConn; 103 | private String charset; 104 | private OutputStream outputStream; 105 | private PrintWriter writer; 106 | 107 | /** 108 | * This constructor initializes a new HTTP POST request with content type 109 | * is set to multipart/form-data 110 | * 111 | * @param httpConn 112 | * @param charset 113 | * @throws IOException 114 | */ 115 | public MultipartUtility(HttpsURLConnection httpConn, String charset) 116 | throws IOException { 117 | this.charset = charset; 118 | 119 | // creates a unique boundary based on time stamp 120 | boundary = "===" + System.currentTimeMillis() + "==="; 121 | this.httpConn = httpConn; 122 | 123 | httpConn.setUseCaches(false); 124 | httpConn.setDoOutput(true); // indicates POST method 125 | httpConn.setDoInput(true); 126 | httpConn.setRequestProperty("Content-Type", 127 | "multipart/form-data; boundary=" + boundary); 128 | httpConn.setRequestProperty("User-Agent", "TelegramBots4Java API Agent"); 129 | httpConn.setRequestProperty("Test", "Bonjour"); 130 | outputStream = httpConn.getOutputStream(); 131 | writer = new PrintWriter(new OutputStreamWriter(outputStream, charset), 132 | true); 133 | } 134 | 135 | /** 136 | * Adds a form field to the request 137 | * 138 | * @param name field name 139 | * @param value field value 140 | */ 141 | public void addFormField(String name, String value) { 142 | writer.append("--" + boundary).append(LINE_FEED); 143 | writer.append("Content-Disposition: form-data; name=\"" + name + "\"") 144 | .append(LINE_FEED); 145 | writer.append("Content-Type: text/plain; charset=" + charset).append( 146 | LINE_FEED); 147 | writer.append(LINE_FEED); 148 | writer.append(value).append(LINE_FEED); 149 | writer.flush(); 150 | } 151 | 152 | /** 153 | * Adds a upload file section to the request 154 | * 155 | * @param fieldName name attribute in 156 | * @param uploadFile a File to be uploaded 157 | * @throws IOException 158 | */ 159 | public void addFilePart(String fieldName, File uploadFile) 160 | throws IOException { 161 | String fileName = uploadFile.getName(); 162 | writer.append("--" + boundary).append(LINE_FEED); 163 | writer.append( 164 | "Content-Disposition: form-data; name=\"" + fieldName 165 | + "\"; filename=\"" + fileName + "\"") 166 | .append(LINE_FEED); 167 | writer.append( 168 | "Content-Type: " 169 | + URLConnection.guessContentTypeFromName(fileName)) 170 | .append(LINE_FEED); 171 | writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED); 172 | writer.append(LINE_FEED); 173 | writer.flush(); 174 | 175 | FileInputStream inputStream = new FileInputStream(uploadFile); 176 | byte[] buffer = new byte[4096]; 177 | int bytesRead = -1; 178 | while ((bytesRead = inputStream.read(buffer)) != -1) { 179 | outputStream.write(buffer, 0, bytesRead); 180 | } 181 | outputStream.flush(); 182 | inputStream.close(); 183 | 184 | writer.append(LINE_FEED); 185 | writer.flush(); 186 | } 187 | 188 | /** 189 | * Adds a header field to the request. 190 | * 191 | * @param name - name of the header field 192 | * @param value - value of the header field 193 | */ 194 | public void addHeaderField(String name, String value) { 195 | writer.append(name + ": " + value).append(LINE_FEED); 196 | writer.flush(); 197 | } 198 | 199 | /** 200 | * Completes the request and receives response from the server. 201 | * 202 | * @return a list of Strings as response in case the server returned 203 | * status OK, otherwise an exception is thrown. 204 | * @throws IOException 205 | */ 206 | public String finish() throws IOException { 207 | List response = new ArrayList(); 208 | 209 | writer.append(LINE_FEED).flush(); 210 | writer.append("--" + boundary + "--").append(LINE_FEED); 211 | writer.close(); 212 | 213 | outputStream.close(); 214 | return readAll(httpConn.getInputStream()); 215 | } 216 | } 217 | 218 | } 219 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/requests/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package encapsulates all calls to the Telegram API. 3 | */ 4 | package co.vandenham.telegram.botapi.requests; -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Audio.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * This object represents an audio file (voice note). 7 | * 8 | * Any getters labeled optional might return a default value (such as {@code null}). 9 | * 10 | * @see https://core.telegram.org/bots/api#audio 11 | */ 12 | public class Audio { 13 | 14 | @SerializedName("file_id") 15 | private String fileId; 16 | 17 | @SerializedName("duration") 18 | private int duration; 19 | 20 | @SerializedName("performer") 21 | private String performer; 22 | 23 | @SerializedName("title") 24 | private String title; 25 | 26 | @SerializedName("mime_type") 27 | private String mimeType; 28 | 29 | @SerializedName("file_size") 30 | private int fileSize; 31 | 32 | /** 33 | * @return Unique identifier for this file 34 | */ 35 | public String getFileId() { 36 | return fileId; 37 | } 38 | 39 | /** 40 | * @return Duration of the audio in seconds as defined by sender 41 | */ 42 | public int getDuration() { 43 | return duration; 44 | } 45 | 46 | /** 47 | * Optional. 48 | * 49 | * @return MIME type of the file as defined by sender 50 | */ 51 | public String getMimeType() { 52 | return mimeType; 53 | } 54 | 55 | /** 56 | * Optional. 57 | * 58 | * @return The size of this audio file. 59 | */ 60 | public int getFileSize() { 61 | return fileSize; 62 | } 63 | 64 | /** 65 | * Optional. 66 | * 67 | * @return Performer of the audio as defined by sender or by audio tags 68 | */ 69 | public String getPerformer() { 70 | return performer; 71 | } 72 | 73 | /** 74 | * Optional. 75 | * 76 | * @return Title of the audio as defined by sender or by audio tags 77 | */ 78 | public String getTitle() { 79 | return title; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | final StringBuilder sb = new StringBuilder("Audio{"); 85 | sb.append("fileId='").append(fileId).append('\''); 86 | sb.append(", duration=").append(duration); 87 | sb.append(", performer='").append(performer).append('\''); 88 | sb.append(", title='").append(title).append('\''); 89 | sb.append(", mimeType='").append(mimeType).append('\''); 90 | sb.append(", fileSize=").append(fileSize); 91 | sb.append('}'); 92 | return sb.toString(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Chat.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Represents a chat. 7 | * This might be a chat with a {@link User} or a {@link GroupChat} 8 | */ 9 | public class Chat { 10 | 11 | @SerializedName("id") 12 | private int id; 13 | 14 | @SerializedName("first_name") 15 | private String firstName; 16 | 17 | @SerializedName("last_name") 18 | private String lastName; 19 | 20 | @SerializedName("username") 21 | private String username; 22 | 23 | @SerializedName("title") 24 | private String title; 25 | 26 | /** 27 | * @return Whether this is a chat with a {@link User} 28 | */ 29 | public boolean isUser() { 30 | return title == null; 31 | } 32 | 33 | /** 34 | * @return Whether this is a {@link GroupChat} 35 | */ 36 | public boolean isGroupChat() { 37 | return !isUser(); 38 | } 39 | 40 | /** 41 | * @return Unique identifier for this chat 42 | */ 43 | public int getId() { 44 | return id; 45 | } 46 | 47 | /** 48 | * Returns this chat as a {@link User}. 49 | * Before invoking, check whether this chat is actually a chat with a user 50 | * by calling {@link Chat#isUser()}. 51 | * 52 | * @return This chat as a {@link User} object 53 | */ 54 | public User asUser() { 55 | return new User(id, firstName, username, lastName); 56 | } 57 | 58 | /** 59 | * Returns this chat as a {@link GroupChat}. 60 | * Before invoking this method, check whether this chat is actually a group chat 61 | * by calling {@link Chat#isGroupChat()}. 62 | * 63 | * @return This chat as a {@link GroupChat} object 64 | */ 65 | public GroupChat asGroupChat() { 66 | return new GroupChat(id, title); 67 | } 68 | 69 | @Override 70 | public String toString() { 71 | if (isUser()) 72 | return "Chat {" + asUser().toString() + "}"; 73 | else 74 | return "Chat {" + asGroupChat().toString() + "}"; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Contact.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * This object represents a phone contact. 7 | * 8 | * Any getters labeled optional might return a default value (such as {@code null}). 9 | * 10 | * @see https://core.telegram.org/bots/api#contact 11 | */ 12 | public class Contact { 13 | 14 | @SerializedName("phone_number") 15 | private String phoneNumber; 16 | 17 | @SerializedName("first_name") 18 | private String firstName; 19 | 20 | @SerializedName("last_name") 21 | private String lastName; 22 | 23 | @SerializedName("user_id") 24 | private int userId; 25 | 26 | /** 27 | * @return Contact's phone number 28 | */ 29 | public String getPhoneNumber() { 30 | return phoneNumber; 31 | } 32 | 33 | /** 34 | * @return Contact's first name 35 | */ 36 | public String getFirstName() { 37 | return firstName; 38 | } 39 | 40 | /** 41 | * Optional. 42 | * 43 | * @return Contact's last name 44 | */ 45 | public String getLastName() { 46 | return lastName; 47 | } 48 | 49 | /** 50 | * Optional. 51 | * 52 | * @return Contact's user identifier in Telegram 53 | */ 54 | public int getUserId() { 55 | return userId; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Document.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * This object represents a general file (as opposed to photos ({@link PhotoSize}) and audio ({@link Audio}) files). 7 | * 8 | * Any getters labeled optional might return a default value (such as {@code null}). 9 | * 10 | * @see Optional. 38 | * 39 | * @return Document thumbnail as defined by sender 40 | */ 41 | public PhotoSize getThumb() { 42 | return thumb; 43 | } 44 | 45 | /** 46 | * Optional. 47 | * 48 | * @return Original filename as defined by sender 49 | */ 50 | public String getFileName() { 51 | return fileName; 52 | } 53 | 54 | /** 55 | * Optional. 56 | * 57 | * @return MIME type of the file as defined by sender 58 | */ 59 | public String getMimeType() { 60 | return mimeType; 61 | } 62 | 63 | /** 64 | * Optional. 65 | * 66 | * @return File size of this document 67 | */ 68 | public int getFileSize() { 69 | return fileSize; 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | final StringBuilder sb = new StringBuilder("Document{"); 75 | sb.append("fileId='").append(fileId).append('\''); 76 | sb.append(", thumb=").append(thumb); 77 | sb.append(", fileName='").append(fileName).append('\''); 78 | sb.append(", mimeType='").append(mimeType).append('\''); 79 | sb.append(", fileSize=").append(fileSize); 80 | sb.append('}'); 81 | return sb.toString(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/ForceReply.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | /** 7 | * Upon receiving a message with this object, Telegram clients will display a reply interface to the user (act as if the user has selected the bot's message and tapped 'Reply'). 8 | * This can be extremely useful if you want to create user-friendly step-by-step interfaces without having to sacrifice privacy mode. 9 | * 10 | * See {@link co.vandenham.telegram.botapi.requests.OptionalArgs} to see how to pass this class as an argument. 11 | * 12 | * @see https://core.telegram.org/bots/api#groupchat 9 | */ 10 | public class GroupChat { 11 | 12 | @SerializedName("id") 13 | private int id; 14 | 15 | @SerializedName("title") 16 | private String title; 17 | 18 | /** 19 | * Parameterless constructor for gson. 20 | */ 21 | public GroupChat() { 22 | } 23 | 24 | public GroupChat(int id, String title) { 25 | this.id = id; 26 | this.title = title; 27 | } 28 | 29 | /** 30 | * @return Unique identifier for this group chat 31 | */ 32 | public int getId() { 33 | return id; 34 | } 35 | 36 | /** 37 | * @return Group name 38 | */ 39 | public String getTitle() { 40 | return title; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | final StringBuilder sb = new StringBuilder("GroupChat{"); 46 | sb.append("id=").append(id); 47 | sb.append(", title='").append(title).append('\''); 48 | sb.append('}'); 49 | return sb.toString(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Location.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * This object represents a point on the map. 7 | * 8 | * @see https://core.telegram.org/bots/api#location 9 | */ 10 | public class Location { 11 | 12 | @SerializedName("longitude") 13 | private float longitude; 14 | 15 | @SerializedName("latitude") 16 | private float latitude; 17 | 18 | /** 19 | * @return Longitude as defined by sender 20 | */ 21 | public float getLongitude() { 22 | return longitude; 23 | } 24 | 25 | /** 26 | * @return Latitude as defined by sender 27 | */ 28 | public float getLatitude() { 29 | return latitude; 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | final StringBuilder sb = new StringBuilder("Location{"); 35 | sb.append("longitude=").append(longitude); 36 | sb.append(", latitude=").append(latitude); 37 | sb.append('}'); 38 | return sb.toString(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/PhotoSize.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * This object represents one size of a photo or a file / sticker thumbnail. 7 | * 8 | * Any getters labeled optional might return a default value (such as {@code null}). 9 | * 10 | * @see https://core.telegram.org/bots/api#photosize 11 | */ 12 | public class PhotoSize { 13 | 14 | @SerializedName("file_id") 15 | private String fileId; 16 | 17 | @SerializedName("width") 18 | private int width; 19 | 20 | @SerializedName("height") 21 | private int height; 22 | 23 | @SerializedName("file_size") 24 | private int fileSize = -1; 25 | 26 | /** 27 | * @return Unique identifier for this file 28 | */ 29 | public String getFileId() { 30 | return fileId; 31 | } 32 | 33 | /** 34 | * @return Photo width 35 | */ 36 | public int getWidth() { 37 | return width; 38 | } 39 | 40 | /** 41 | * @return Photo height 42 | */ 43 | public int getHeight() { 44 | return height; 45 | } 46 | 47 | /** 48 | * Optional. 49 | * 50 | * @return File size 51 | */ 52 | public int getFileSize() { 53 | return fileSize; 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | final StringBuilder sb = new StringBuilder("PhotoSize{"); 59 | sb.append("fileId='").append(fileId).append('\''); 60 | sb.append(", width=").append(width); 61 | sb.append(", height=").append(height); 62 | sb.append(", fileSize=").append(fileSize); 63 | sb.append('}'); 64 | return sb.toString(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/ReplyKeyboardHide.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | /** 7 | * Upon receiving a message with this object, Telegram clients will hide the current custom keyboard and display the default letter-keyboard. 8 | * By default, custom keyboards are displayed until a new keyboard is sent by a bot. 9 | * An exception is made for one-time keyboards that are hidden immediately after the user presses a button (see {@link ReplyKeyboardMarkup}) 10 | * 11 | * @see https://core.telegram.org/bots/api#replykeyboardhide 12 | */ 13 | public class ReplyKeyboardHide implements ReplyMarkup { 14 | 15 | private final static ReplyKeyboardHide NON_SELECTIVE = new ReplyKeyboardHide(false); 16 | private final static ReplyKeyboardHide SELECTIVE = new ReplyKeyboardHide(true); 17 | 18 | @SerializedName("hide_keyboard") 19 | private boolean hideKeyboard = true; 20 | @SerializedName("selective") 21 | private boolean selective = false; 22 | 23 | private ReplyKeyboardHide(boolean selective) { 24 | this.selective = selective; 25 | } 26 | 27 | /** 28 | * Returns a selective instance of this class ({@code selective} is set to {@code true}). 29 | * 30 | * @return a selective instance of this class 31 | */ 32 | public static ReplyKeyboardHide getSelectiveInstance() { 33 | return SELECTIVE; 34 | } 35 | 36 | /** 37 | * Returns a non-selective instance of this class ({@code selective} is set to {@code false}). 38 | * 39 | * @return a non-selective instance of this class 40 | */ 41 | public static ReplyKeyboardHide getNonSelectiveInstance() { 42 | return NON_SELECTIVE; 43 | } 44 | 45 | /** 46 | * Serializes this object to a JSON String. 47 | * 48 | * @return A JSON String representation of this object. 49 | */ 50 | @Override 51 | public String serialize() { 52 | return new Gson().toJson(this); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/ReplyKeyboardMarkup.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | /** 11 | * This object represents a custom keyboard with reply options. 12 | * 13 | * @see https://core.telegram.org/bots/api#replykeyboardmarkup 14 | */ 15 | public class ReplyKeyboardMarkup implements ReplyMarkup { 16 | 17 | @SerializedName("keyboard") 18 | private List> keyboard; 19 | 20 | @SerializedName("resize_keyboard") 21 | private boolean resizeKeyboard; 22 | 23 | @SerializedName("one_time_keyboard") 24 | private boolean oneTimeKeyboard; 25 | 26 | @SerializedName("selective") 27 | private boolean selective; 28 | 29 | private ReplyKeyboardMarkup(Builder builder) { 30 | keyboard = builder.keyboard; 31 | resizeKeyboard = builder.resizeKeyboard; 32 | oneTimeKeyboard = builder.oneTimeKeyboard; 33 | selective = builder.selective; 34 | } 35 | 36 | /** 37 | * Serializes this object to a JSON String. 38 | * 39 | * @return A JSON String representation of this object. 40 | */ 41 | @Override 42 | public String serialize() { 43 | return new Gson().toJson(this); 44 | } 45 | 46 | /** 47 | * A convenience Builder for this class. 48 | * 49 | * An example: 50 | *
 51 |      * {@code
 52 |      * ReplyKeyboardMarkup markup = new ReplyKeyboardMarkup.Builder()
 53 |      *                                          .row("A", "B", "C")
 54 |      *                                          .row("D")
 55 |      *                                          .row("E", "F")
 56 |      *                                          .build();
 57 |      * }
 58 |      * 
59 | */ 60 | public static class Builder { 61 | 62 | private List> keyboard; 63 | private boolean resizeKeyboard; 64 | private boolean oneTimeKeyboard; 65 | private boolean selective; 66 | 67 | public Builder() { 68 | keyboard = new ArrayList<>(); 69 | } 70 | 71 | /** 72 | * Adds a row of "buttons" to the keyboard. 73 | * 74 | * @param buttons the row of buttons, represented as a String array. 75 | * @return This Builder instance, to allow method chaining. 76 | */ 77 | public Builder row(String... buttons) { 78 | keyboard.add(Arrays.asList(buttons)); 79 | return this; 80 | } 81 | 82 | /** 83 | * Adds all {@code buttons} with a maximum {@code width} per row. 84 | * 85 | * @param width The maximum amount of buttons per row. 86 | * @param buttons The buttons to add. 87 | * @return This Builder instance, to allow method chaining. 88 | */ 89 | public Builder add(int width, String... buttons) { 90 | List row = new ArrayList<>(width); 91 | for (int i = 0; i < buttons.length; i++) { 92 | row.add(buttons[i]); 93 | 94 | if ((i + 1) % width == 0) { 95 | keyboard.add(row); 96 | row.clear(); 97 | } 98 | } 99 | 100 | if (row.size() > 0) 101 | keyboard.add(row); 102 | 103 | return this; 104 | } 105 | 106 | /** 107 | * Requests clients to resize the keyboard vertically for optimal fit (e.g., make the keyboard smaller if there are just two rows of buttons). 108 | * Defaults to false, in which case the custom keyboard is always of the same height as the app's standard keyboard. 109 | * 110 | * @return This Builder instance, to allow method chaining. 111 | */ 112 | public Builder setResizeKeyboard() { 113 | this.resizeKeyboard = true; 114 | return this; 115 | } 116 | 117 | /** 118 | * Requests clients to hide the keyboard as soon as it's been used. 119 | * Defaults to false. 120 | * 121 | * @return This Builder instance, to allow method chaining. 122 | */ 123 | public Builder setOneTimeKeyboard() { 124 | this.oneTimeKeyboard = true; 125 | return this; 126 | } 127 | 128 | /** 129 | * Use this parameter if you want to show the keyboard to specific users only. 130 | * Targets: 131 | * 1) users that are @mentioned in the text of the Message object; 132 | * 2) if the bot's message is a reply (has reply_to_message_id), sender of the original message. 133 | * 134 | * Example: A user requests to change the bot‘s language, 135 | * bot replies to the request with a keyboard to select the new language. 136 | * Other users in the group don’t see the keyboard. 137 | * 138 | * @return This Builder instance, to allow method chaining. 139 | */ 140 | public Builder setSelective() { 141 | this.selective = true; 142 | return this; 143 | } 144 | 145 | /** 146 | * Builds the {@link ReplyKeyboardMarkup} object. 147 | * 148 | * @return The freshly created {@link ReplyKeyboardMarkup} 149 | */ 150 | public ReplyKeyboardMarkup build() { 151 | return new ReplyKeyboardMarkup(this); 152 | } 153 | } 154 | 155 | @Override 156 | public String toString() { 157 | final StringBuilder sb = new StringBuilder("ReplyKeyboardMarkup{"); 158 | sb.append("keyboard=").append(keyboard); 159 | sb.append(", resizeKeyboard=").append(resizeKeyboard); 160 | sb.append(", oneTimeKeyboard=").append(oneTimeKeyboard); 161 | sb.append(", selective=").append(selective); 162 | sb.append('}'); 163 | return sb.toString(); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/ReplyMarkup.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | /** 4 | * Defines a general interface for reply markups. 5 | */ 6 | public interface ReplyMarkup { 7 | 8 | /** 9 | * @return This instance converted to a JSON String. 10 | */ 11 | String serialize(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Sticker.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * This object represents a sticker. 7 | * 8 | * Getters labeled optional might return a default value (such as {@code null}). 9 | * 10 | * @see https://core.telegram.org/bots/api#sticker 11 | */ 12 | public class Sticker { 13 | 14 | @SerializedName("file_id") 15 | private String fileId; 16 | 17 | @SerializedName("width") 18 | private int width; 19 | 20 | @SerializedName("height") 21 | private int height; 22 | 23 | @SerializedName("thumb") 24 | private PhotoSize thumb; 25 | 26 | @SerializedName("file_size") 27 | private int fileSize; 28 | 29 | /** 30 | * @return Unique identifier for this file 31 | */ 32 | public String getFileId() { 33 | return fileId; 34 | } 35 | 36 | /** 37 | * @return Sticker width 38 | */ 39 | public int getWidth() { 40 | return width; 41 | } 42 | 43 | /** 44 | * @return Sticker height 45 | */ 46 | public int getHeight() { 47 | return height; 48 | } 49 | 50 | /** 51 | * Optional. 52 | * 53 | * @return Sticker thumbnail in .webp or .jpg format 54 | */ 55 | public PhotoSize getThumb() { 56 | return thumb; 57 | } 58 | 59 | /** 60 | * Optional. 61 | * 62 | * @return File size 63 | */ 64 | public int getFileSize() { 65 | return fileSize; 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | final StringBuilder sb = new StringBuilder("Sticker{"); 71 | sb.append("fileId='").append(fileId).append('\''); 72 | sb.append(", width=").append(width); 73 | sb.append(", height=").append(height); 74 | sb.append(", thumb=").append(thumb); 75 | sb.append(", fileSize=").append(fileSize); 76 | sb.append('}'); 77 | return sb.toString(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Update.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * This object represents an incoming update. 7 | * 8 | * Any getters labeled optional might return a default value (such as {@code null}). 9 | * 10 | * @see https://core.telegram.org/bots/api#update 11 | */ 12 | public class Update { 13 | 14 | @SerializedName("update_id") 15 | private int updateId; 16 | 17 | @SerializedName("message") 18 | private Message message; 19 | 20 | /** 21 | * @return The update‘s unique identifier. 22 | * Update identifiers start from a certain positive number and increase sequentially. 23 | * This ID becomes especially handy if you’re using Webhooks, since it allows you to ignore repeated updates or to restore the correct update sequence, should they get out of order. 24 | */ 25 | public int getUpdateId() { 26 | return updateId; 27 | } 28 | 29 | /** 30 | * Optional. 31 | * 32 | * @return New incoming message of any kind — text, photo, sticker, etc. 33 | */ 34 | public Message getMessage() { 35 | return message; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/User.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | /** 7 | * This object represents a Telegram user or bot. 8 | * 9 | * Any getters labeled optional might return a default value (such as {@code null}). 10 | * 11 | * @see https://core.telegram.org/bots/api#user 12 | */ 13 | public class User { 14 | 15 | @SerializedName("id") 16 | private int id; 17 | 18 | @SerializedName("first_name") 19 | private String firstName; 20 | 21 | @SerializedName("last_name") 22 | private String lastName; 23 | 24 | @SerializedName("username") 25 | private String username; 26 | 27 | /** 28 | * Parameterless constructor for gson. 29 | */ 30 | public User() { 31 | 32 | } 33 | 34 | public User(int id, String firstName, String lastName, String username) { 35 | this.id = id; 36 | this.firstName = firstName; 37 | this.lastName = lastName; 38 | this.username = username; 39 | } 40 | 41 | /** 42 | * @return Unique identifier for this user or bot 43 | */ 44 | public int getId() { 45 | return id; 46 | } 47 | 48 | /** 49 | * @return User‘s or bot’s first name 50 | */ 51 | public String getFirstName() { 52 | return firstName; 53 | } 54 | 55 | /** 56 | * Optional. 57 | * 58 | * @return User‘s or bot’s last name 59 | */ 60 | public String getLastName() { 61 | return lastName; 62 | } 63 | 64 | /** 65 | * Optional. 66 | * 67 | * @return User‘s or bot’s username 68 | */ 69 | public String getUsername() { 70 | return username; 71 | } 72 | 73 | @Override 74 | public String toString() { 75 | final StringBuilder sb = new StringBuilder("User{"); 76 | sb.append("id=").append(id); 77 | sb.append(", firstName='").append(firstName).append('\''); 78 | sb.append(", lastName='").append(lastName).append('\''); 79 | sb.append(", username='").append(username).append('\''); 80 | sb.append('}'); 81 | return sb.toString(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/UserProfilePhotos.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * This object represent a user's profile pictures. 9 | * 10 | * @see https://core.telegram.org/bots/api#userprofilephotos 11 | */ 12 | public class UserProfilePhotos { 13 | 14 | @SerializedName("total_count") 15 | private int totalCount; 16 | 17 | @SerializedName("photos") 18 | private List> photos; 19 | 20 | /** 21 | * @return Total number of profile pictures the target user has 22 | */ 23 | public int getTotalCount() { 24 | return totalCount; 25 | } 26 | 27 | /** 28 | * @return Requested profile pictures (in up to 4 sizes each) 29 | */ 30 | public List> getPhotos() { 31 | return photos; 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | final StringBuilder sb = new StringBuilder("UserProfilePhotos{"); 37 | sb.append("totalCount=").append(totalCount); 38 | sb.append(", photos=").append(photos); 39 | sb.append('}'); 40 | return sb.toString(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Video.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * This object represents a video file. 7 | * 8 | * Any getters labeled optional might return a default value (such as {@code null}). 9 | * 10 | * @see https://core.telegram.org/bots/api#video 11 | */ 12 | public class Video { 13 | 14 | @SerializedName("file_id") 15 | private String fileId; 16 | 17 | @SerializedName("width") 18 | private int width; 19 | 20 | @SerializedName("height") 21 | private int height; 22 | 23 | @SerializedName("duration") 24 | private int duration; 25 | 26 | @SerializedName("thumb") 27 | private PhotoSize thumb; 28 | 29 | @SerializedName("mime_type") 30 | private String mimeType; 31 | 32 | @SerializedName("file_size") 33 | private int fileSize; 34 | 35 | /** 36 | * @return Unique identifier for this file 37 | */ 38 | public String getFileId() { 39 | return fileId; 40 | } 41 | 42 | /** 43 | * @return Video width as defined by sender 44 | */ 45 | public int getWidth() { 46 | return width; 47 | } 48 | 49 | /** 50 | * @return Video height as defined by sender 51 | */ 52 | public int getHeight() { 53 | return height; 54 | } 55 | 56 | /** 57 | * @return Duration of the video in seconds as defined by sender 58 | */ 59 | public int getDuration() { 60 | return duration; 61 | } 62 | 63 | /** 64 | * Optional. 65 | * 66 | * @return Video thumbnail 67 | */ 68 | public PhotoSize getThumb() { 69 | return thumb; 70 | } 71 | 72 | /** 73 | * Optional. 74 | * 75 | * @return Mime type of a file as defined by sender 76 | */ 77 | public String getMimeType() { 78 | return mimeType; 79 | } 80 | 81 | /** 82 | * Optional. 83 | * 84 | * @return File size 85 | */ 86 | public int getFileSize() { 87 | return fileSize; 88 | } 89 | 90 | @Override 91 | public String toString() { 92 | final StringBuilder sb = new StringBuilder("Video{"); 93 | sb.append("fileId='").append(fileId).append('\''); 94 | sb.append(", width=").append(width); 95 | sb.append(", height=").append(height); 96 | sb.append(", duration=").append(duration); 97 | sb.append(", thumb=").append(thumb); 98 | sb.append(", mimeType='").append(mimeType).append('\''); 99 | sb.append(", fileSize=").append(fileSize); 100 | sb.append('}'); 101 | return sb.toString(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/Voice.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Voice { 6 | 7 | @SerializedName("file_id") 8 | private String fileId; 9 | 10 | @SerializedName("duration") 11 | private int duration; 12 | 13 | @SerializedName("mime_type") 14 | private String mimeType; 15 | 16 | @SerializedName("file_size") 17 | private int fileSize; 18 | 19 | /** 20 | * @return Unique identifier for this file 21 | */ 22 | public String getFileId() { 23 | return fileId; 24 | } 25 | 26 | /** 27 | * @return Duration of the audio in seconds as defined by sender 28 | */ 29 | public int getDuration() { 30 | return duration; 31 | } 32 | 33 | /** 34 | * Optional. 35 | * 36 | * @return MIME type of the file as defined by sender 37 | */ 38 | public String getMimeType() { 39 | return mimeType; 40 | } 41 | 42 | /** 43 | * Optional. 44 | * 45 | * @return The size of this audio file. 46 | */ 47 | public int getFileSize() { 48 | return fileSize; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | final StringBuilder sb = new StringBuilder("Audio{"); 54 | sb.append("fileId='").append(fileId).append('\''); 55 | sb.append(", duration=").append(duration); 56 | sb.append(", mimeType='").append(mimeType).append('\''); 57 | sb.append(", fileSize=").append(fileSize); 58 | sb.append('}'); 59 | return sb.toString(); 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /api/src/main/java/co/vandenham/telegram/botapi/types/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains all types as defined by https://core.telegram.org/bots/api#available-types 3 | * In addition, a {@link co.vandenham.telegram.botapi.types.Chat} type is created for convenience. 4 | */ 5 | package co.vandenham.telegram.botapi.types; -------------------------------------------------------------------------------- /api/src/test/java/co/vandenham/telegram/botapi/requests/RequestTest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import org.junit.Before; 4 | 5 | /** 6 | * Created by pieter on 25-7-15. 7 | */ 8 | public class RequestTest { 9 | 10 | protected final static int CHAT_ID = Integer.valueOf(System.getenv("CHAT_ID")); 11 | protected final static String TOKEN = System.getenv("TOKEN"); 12 | protected TelegramApi api; 13 | protected ApiRequestExecutor requestExecutor; 14 | 15 | @Before 16 | public void setUp() throws Exception { 17 | api = new TelegramApi(TOKEN); 18 | requestExecutor = ApiRequestExecutor.getSynchronousExecutor(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /api/src/test/java/co/vandenham/telegram/botapi/requests/SendMessageRequestTest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | import co.vandenham.telegram.botapi.types.ReplyKeyboardMarkup; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | /** 10 | * Created by pieter on 25-7-15. 11 | */ 12 | public class SendMessageRequestTest extends RequestTest { 13 | 14 | @Test 15 | public void testMakeRequest() throws Exception { 16 | ReplyKeyboardMarkup markup = new ReplyKeyboardMarkup.Builder().row("A", "B", "C").build(); 17 | 18 | OptionalArgs optionalArgs = new OptionalArgs().replyMarkup(markup); 19 | SendMessageRequest request = new SendMessageRequest(CHAT_ID, "Building TelegramBots4Java", optionalArgs); 20 | 21 | Message message = requestExecutor.execute(api, request).getResult(); 22 | 23 | assertEquals(message.getText(), "Building TelegramBots4Java"); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /api/src/test/java/co/vandenham/telegram/botapi/requests/SendPhotoRequestTest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.requests; 2 | 3 | import co.vandenham.telegram.botapi.types.Message; 4 | import org.junit.Test; 5 | 6 | import java.io.File; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | /** 11 | * Created by pieter on 25-7-15. 12 | */ 13 | public class SendPhotoRequestTest extends RequestTest { 14 | 15 | @Test 16 | public void testMakeRequest() throws Exception { 17 | File photo = new File(getClass().getClassLoader().getResource("logo.png").getPath()); 18 | 19 | OptionalArgs optionalArgs = new OptionalArgs().caption("Sent you a photo..."); 20 | SendPhotoRequest request = new SendPhotoRequest(4663724, photo, optionalArgs); 21 | Message message = requestExecutor.execute(api, request).getResult(); 22 | assertTrue(message.getMessageId() > 0); 23 | } 24 | } -------------------------------------------------------------------------------- /api/src/test/java/co/vandenham/telegram/botapi/types/TypesTest.java: -------------------------------------------------------------------------------- 1 | package co.vandenham.telegram.botapi.types; 2 | 3 | import com.google.gson.Gson; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | /** 10 | * Created by pieter on 25-7-15. 11 | */ 12 | public class TypesTest { 13 | 14 | private Gson gson; 15 | 16 | @Before 17 | public void setUp() throws Exception { 18 | gson = new Gson(); 19 | } 20 | 21 | @Test 22 | public void testUser() { 23 | String json = "{\"id\":101176298,\"first_name\":\"RDSSBOT\",\"username\":\"rdss_bot\"}"; 24 | User user = createSubject(json, User.class); 25 | assertEquals(101176298, user.getId()); 26 | assertEquals("RDSSBOT", user.getFirstName()); 27 | assertEquals("rdss_bot", user.getUsername()); 28 | } 29 | 30 | @Test 31 | public void testGroupChat() { 32 | String json = "{\"id\":8926,\"title\":\"\\u5c4e\\u4f2f\\u98ef\\u98ef\\u4e4b\\u4ea4\"}"; 33 | GroupChat groupChat = createSubject(json, GroupChat.class); 34 | assertEquals(groupChat.getId(), 8926); 35 | } 36 | 37 | @Test 38 | public void testDocument() { 39 | String json = "{\"file_name\":\"Text File\",\"thumb\":{},\"file_id\":\"BQADBQADMwIAAsYifgZ_CEh0u682xwI\",\"file_size\":446}"; 40 | Document document = createSubject(json, Document.class); 41 | 42 | assertEquals("BQADBQADMwIAAsYifgZ_CEh0u682xwI", document.getFileId()); 43 | assertEquals("Text File", document.getFileName()); 44 | } 45 | 46 | @Test 47 | public void testUserProfilePhotos() { 48 | String json = "{\"total_count\":1,\"photos\":[[{\"file_id\":\"AgADAgADqacxG6wpRwABvEB6fpeIcKS4HAIkAATZH_SpyZjzIwdVAAIC\",\"file_size\":6150,\"width\":160,\"height\":160},{\"file_id\":\"AgADAgADqacxG6wpRwABvEB6fpeIcKS4HAIkAATOiTNi_YoJMghVAAIC\",\"file_size\":13363,\"width\":320,\"height\":320},{\"file_id\":\"AgADAgADqacxG6wpRwABvEB6fpeIcKS4HAIkAAQW4DyFv0-lhglVAAIC\",\"file_size\":28347,\"width\":640,\"height\":640},{\"file_id\":\"AgADAgADqacxG6wpRwABvEB6fpeIcKS4HAIkAAT50RvJCg0GQApVAAIC\",\"file_size\":33953,\"width\":800,\"height\":800}]]}"; 49 | UserProfilePhotos upp = createSubject(json, UserProfilePhotos.class); 50 | assertEquals(160, upp.getPhotos().get(0).get(0).getWidth()); 51 | assertEquals(800, upp.getPhotos().get(0).get(3).getHeight()); 52 | } 53 | 54 | @Test 55 | public void testContact() { 56 | String json = "{\"phone_number\":\"00011111111\",\"first_name\":\"dd\",\"last_name\":\"ddl\",\"user_id\":8633}"; 57 | Contact contact = createSubject(json, Contact.class); 58 | assertEquals("dd", contact.getFirstName()); 59 | assertEquals("ddl", contact.getLastName()); 60 | } 61 | 62 | @Test 63 | public void testMessageGroup() { 64 | String json = "{\"message_id\":10,\"from\":{\"id\":12345,\"first_name\":\"g\",\"last_name\":\"G\",\"username\":\"GG\"},\"chat\":{\"id\":-866,\"title\":\"\\u4ea4\"},\"date\":1435303157,\"text\":\"HIHI\"}"; 65 | Message msg = createSubject(json, Message.class); 66 | assertEquals(Message.Type.TEXT, msg.getType()); 67 | assertEquals("HIHI", msg.getText()); 68 | assertTrue(msg.getChat().isGroupChat()); 69 | assertEquals("GG", msg.getFrom().getUsername()); 70 | } 71 | 72 | @Test 73 | public void testMessageAudio() { 74 | String json = "{\"message_id\":100,\"from\":{\"id\":10734,\"first_name\":\"dd\",\"last_name\":\"dd\",\"username\":\"dd\"},\"chat\":{\"id\":10734,\"first_name\":\"dd\",\"last_name\":\"dd\",\"username\":\"dd\"},\"date\":1435481343,\"audio\":{\"duration\":3,\"mime_type\":\"audio\\/ogg\",\"file_id\":\"ddg\",\"file_size\":8249}}"; 75 | Message msg = createSubject(json, Message.class); 76 | assertEquals(Message.Type.AUDIO, msg.getType()); 77 | assertEquals(3, msg.getAudio().getDuration()); 78 | } 79 | 80 | @Test 81 | public void testMessageSticker() { 82 | String json = "{\"message_id\":98,\"from\":{\"id\":10734,\"first_name\":\"Fd\",\"last_name\":\"Wd\",\"username\":\"dd\"},\"chat\":{\"id\":10734,\"first_name\":\"Fd\",\"last_name\":\"Wd\",\"username\":\"dd\"},\"date\":1435479551,\"sticker\":{\"width\":550,\"height\":368,\"thumb\":{\"file_id\":\"AAQFABPJLB0sAAQq17w-li3bzoIfAAIC\",\"file_size\":1822,\"width\":90,\"height\":60},\"file_id\":\"BQADBQADNAIAAsYifgYdGJOa6bGAsQI\",\"file_size\":30320}}"; 83 | Message msg = createSubject(json, Message.class); 84 | assertEquals(Message.Type.STICKER, msg.getType()); 85 | assertEquals(368, msg.getSticker().getHeight()); 86 | assertEquals(60, msg.getSticker().getThumb().getHeight()); 87 | } 88 | 89 | @Test 90 | public void testMessageDocument() { 91 | String json = "{\"message_id\":97,\"from\":{\"id\":10734,\"first_name\":\"Fd\",\"last_name\":\"Wd\",\"username\":\"dd\"},\"chat\":{\"id\":10,\"first_name\":\"Fd\",\"last_name\":\"Wd\",\"username\":\"dd\"},\"date\":1435478744,\"document\":{\"file_name\":\"Text File\",\"thumb\":{},\"file_id\":\"BQADBQADMwIAAsYifgZ_CEh0u682xwI\",\"file_size\":446}}"; 92 | Message msg = createSubject(json, Message.class); 93 | assertEquals(Message.Type.DOCUMENT, msg.getType()); 94 | assertEquals("Text File", msg.getDocument().getFileName()); 95 | } 96 | 97 | @Test 98 | public void testMessagePhoto() { 99 | String json = "{\"message_id\":96,\"from\":{\"id\":109734,\"first_name\":\"Fd\",\"last_name\":\"Wd\",\"username\":\"dd\"},\"chat\":{\"id\":10734,\"first_name\":\"Fd\",\"last_name\":\"dd\",\"username\":\"dd\"},\"date\":1435478191,\"photo\":[{\"file_id\":\"AgADBQADIagxG8YifgYv8yLSj76i-dd\",\"file_size\":615,\"width\":90,\"height\":67},{\"file_id\":\"AgADBQADIagxG8YifgYv8yLSj76i-dd\",\"file_size\":10174,\"width\":320,\"height\":240},{\"file_id\":\"dd-A_LsTIABFNx-FUOaEa_3AABAQABAg\",\"file_size\":53013,\"width\":759,\"height\":570}]}"; 100 | Message msg = createSubject(json, Message.class); 101 | assertEquals(Message.Type.PHOTO, msg.getType()); 102 | assertEquals(3, msg.getPhoto().size()); 103 | } 104 | 105 | @Test 106 | public void testMessageVideo() { 107 | String json = "{\"message_id\":101,\"from\":{\"id\":109734,\"first_name\":\"dd\",\"last_name\":\"dd\",\"username\":\"dd\"},\"chat\":{\"id\":109734,\"first_name\":\"dd\",\"last_name\":\"dd\",\"username\":\"dd\"},\"date\":1435481960,\"video\":{\"duration\":3,\"caption\":\"\",\"width\":360,\"height\":640,\"thumb\":{\"file_id\":\"AAQFABPiYnBjkDwMAAIC\",\"file_size\":1597,\"width\":50,\"height\":90},\"file_id\":\"BAADBQADNifgb_TOPEKErGoQI\",\"file_size\":260699}}"; 108 | Message msg = createSubject(json, Message.class); 109 | assertEquals(Message.Type.VIDEO, msg.getType()); 110 | assertEquals(3, msg.getVideo().getDuration()); 111 | assertEquals(50, msg.getVideo().getThumb().getWidth()); 112 | } 113 | 114 | @Test 115 | public void testMessageLocation() { 116 | String json = "{\"message_id\":102,\"from\":{\"id\":108734,\"first_name\":\"dd\",\"last_name\":\"dd\",\"username\":\"dd\"},\"chat\":{\"id\":1089734,\"first_name\":\"dd\",\"last_name\":\"dd\",\"username\":\"dd\"},\"date\":1535482469,\"location\":{\"longitude\":127.479471,\"latitude\":26.090577}}"; 117 | Message msg = createSubject(json, Message.class); 118 | assertEquals(Message.Type.LOCATION, msg.getType()); 119 | assertTrue(msg.getLocation().getLatitude() > 26); 120 | } 121 | 122 | 123 | 124 | private T createSubject(String json, Class clsOf) { 125 | return gson.fromJson(json, clsOf); 126 | } 127 | 128 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | project.ext.set("projectName", "TelegramBots4Java") 2 | 3 | subprojects { 4 | 5 | apply plugin: 'java' 6 | apply plugin: 'maven' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /docs/allclasses-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 |

All Classes

13 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /docs/allclasses-noframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | All Classes (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 |

All Classes

13 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /docs/co/vandenham/telegram/botapi/AbstractChatContextFactory.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AbstractChatContextFactory (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 28 | 31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 48 |
49 | 91 | 92 | 93 |
94 |
co.vandenham.telegram.botapi
95 |

Interface AbstractChatContextFactory

96 |
97 |
98 |
99 |
    100 |
  • 101 |
    102 |
    103 |
    public interface AbstractChatContextFactory
    104 |
  • 105 |
106 |
107 |
108 | 132 |
133 |
134 | 156 |
157 |
158 | 159 | 160 |
161 | 162 | 163 | 164 | 165 | 166 | 167 | 176 |
177 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /docs/co/vandenham/telegram/botapi/DefaultHandler.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DefaultHandler (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 42 |
43 | 83 | 84 | 85 |
86 |
co.vandenham.telegram.botapi
87 |

Annotation Type DefaultHandler

88 |
89 |
90 |
91 | 101 |
102 |
103 | 104 | 105 |
106 | 107 | 108 | 109 | 110 | 111 | 112 | 121 |
122 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /docs/co/vandenham/telegram/botapi/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | co.vandenham.telegram.botapi (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 |

co.vandenham.telegram.botapi

13 |
14 |

Interfaces

15 | 19 |

Classes

20 | 27 |

Annotation Types

28 | 33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/co/vandenham/telegram/botapi/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | co.vandenham.telegram.botapi (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Package co.vandenham.telegram.botapi

73 |
74 |
TelegramBots4Java is a Java implementation of the Telegram Bot API (https://core.telegram.org/bots/api).
75 |
76 |

See: Description

77 |
78 |
79 | 156 | 157 | 158 | 159 |

Package co.vandenham.telegram.botapi Description

160 |
TelegramBots4Java is a Java implementation of the Telegram Bot API (https://core.telegram.org/bots/api).
161 |
162 | 163 |
164 | 165 | 166 | 167 | 168 | 169 | 170 | 179 |
180 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /docs/co/vandenham/telegram/botapi/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | co.vandenham.telegram.botapi Class Hierarchy (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Hierarchy For Package co.vandenham.telegram.botapi

73 | Package Hierarchies: 74 | 77 |
78 |
79 |

Class Hierarchy

80 | 94 |

Interface Hierarchy

95 | 99 |

Annotation Type Hierarchy

100 | 105 |
106 | 107 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 123 |
124 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /docs/co/vandenham/telegram/botapi/requests/ApiResponse.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ApiResponse (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 28 | 31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 48 |
49 | 91 | 92 | 93 |
94 |
co.vandenham.telegram.botapi.requests
95 |

Interface ApiResponse<T>

96 |
97 |
98 |
99 |
    100 |
  • 101 |
    102 |
    103 |
    public interface ApiResponse<T>
    104 |
  • 105 |
106 |
107 |
108 | 131 |
132 |
133 |
    134 |
  • 135 | 136 | 152 |
  • 153 |
154 |
155 |
156 | 157 | 158 |
159 | 160 | 161 | 162 | 163 | 164 | 165 | 174 |
175 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /docs/co/vandenham/telegram/botapi/requests/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | co.vandenham.telegram.botapi.requests (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 |

co.vandenham.telegram.botapi.requests

13 |
14 |

Interfaces

15 | 18 |

Classes

19 | 38 |

Enums

39 | 42 |

Exceptions

43 | 46 |
47 | 48 | 49 | -------------------------------------------------------------------------------- /docs/co/vandenham/telegram/botapi/types/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | co.vandenham.telegram.botapi.types (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 |

co.vandenham.telegram.botapi.types

13 |
14 |

Interfaces

15 | 18 |

Classes

19 | 39 |

Enums

40 | 43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/constant-values.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Constant Field Values (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Constant Field Values

73 |

Contents

74 | 77 |
78 |
79 | 80 | 81 |

co.vandenham.*

82 |
    83 |
  • 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 96 | 97 | 98 | 99 | 100 |
    co.vandenham.telegram.botapi.requests.TelegramApi 
    Modifier and TypeConstant FieldValue
    94 | 95 | public static final StringAPI_URL"https://api.telegram.org/bot%s/%s"
    101 |
  • 102 |
103 |
104 | 105 |
106 | 107 | 108 | 109 | 110 | 111 | 112 | 121 |
122 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /docs/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Deprecated List (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Deprecated API

73 |

Contents

74 |
75 | 76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 92 |
93 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TelegramBots4Java 7 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <noscript> 68 | <div>JavaScript is disabled on your browser.</div> 69 | </noscript> 70 | <h2>Frame Alert</h2> 71 | <p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /docs/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview List (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 |

 

22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/overview-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Overview (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

TelegramBots4Java

73 |
74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 87 | 88 | 89 | 90 | 93 | 94 | 95 | 96 | 100 | 101 | 102 |
Packages 
PackageDescription
co.vandenham.telegram.botapi 85 |
TelegramBots4Java is a Java implementation of the Telegram Bot API (https://core.telegram.org/bots/api).
86 |
co.vandenham.telegram.botapi.requests 91 |
This package encapsulates all calls to the Telegram API.
92 |
co.vandenham.telegram.botapi.types 97 |
This package contains all types as defined by https://core.telegram.org/bots/api#available-types 98 | In addition, a Chat type is created for convenience.
99 |
103 |
104 | 105 |
106 | 107 | 108 | 109 | 110 | 111 | 112 | 121 |
122 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /docs/package-list: -------------------------------------------------------------------------------- 1 | co.vandenham.telegram.botapi 2 | co.vandenham.telegram.botapi.requests 3 | co.vandenham.telegram.botapi.types 4 | -------------------------------------------------------------------------------- /docs/resources/background.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pevdh/telegram-bots-java-api/5b561da620b13bf1c760da27cc01c7b72057bd7a/docs/resources/background.gif -------------------------------------------------------------------------------- /docs/resources/tab.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pevdh/telegram-bots-java-api/5b561da620b13bf1c760da27cc01c7b72057bd7a/docs/resources/tab.gif -------------------------------------------------------------------------------- /docs/resources/titlebar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pevdh/telegram-bots-java-api/5b561da620b13bf1c760da27cc01c7b72057bd7a/docs/resources/titlebar.gif -------------------------------------------------------------------------------- /docs/resources/titlebar_end.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pevdh/telegram-bots-java-api/5b561da620b13bf1c760da27cc01c7b72057bd7a/docs/resources/titlebar_end.gif -------------------------------------------------------------------------------- /docs/serialized-form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Serialized Form (TelegramBots4Java) 7 | 8 | 9 | 10 | 11 | 12 | 22 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 42 |
43 | 70 | 71 |
72 |

Serialized Form

73 |
74 |
75 | 98 |
99 | 100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 116 |
117 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pevdh/telegram-bots-java-api/5b561da620b13bf1c760da27cc01c7b72057bd7a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jul 29 21:18:26 CEST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':api', ':EchoBot' 2 | include 'GMTBot' 3 | 4 | --------------------------------------------------------------------------------