Merge pull request #86 from rubenlagus/dev

Update v2.3.3.2
This commit is contained in:
Ruben Bermudez 2016-05-31 01:15:57 +02:00
commit 946b5438ad
29 changed files with 543 additions and 182 deletions

BIN
.DS_Store vendored

Binary file not shown.

17
.gitignore vendored
View File

@ -8,28 +8,33 @@ release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
### Java template
*.class
# Mobile Tools for Java (J2ME)
### Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
### Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
### virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# logs files
### logs files
*.log
# Certs
### Certs
*.jks
*.cer
*.pem
# IDE files
### IDE files
.idea/
copyright/
*.iml
#File System specific files
.DS_STORE

8
.travis.yml Normal file
View File

@ -0,0 +1,8 @@
language: java
jdk:
- oraclejdk8
script: mvn clean compile package
notifications:
webhooks:
secure: "jC7dK/x67ONWQoeLZg4HfW0mHhcjDerJjsLLkrbcpltiqAbw2p7XfY8Pk4zHoD72a+5o6WKu5WvYvZ4OdldnjP8Y6ZUbliQ5RG3olg3gFDoe0+sc3geeb4HRYVcdI20O0z4Bup/qO0ZihxPBc0D5IpHmFxlaqlZG0WeST4CicU8PNnBh6aX9/VMrwXhkMb2vfzmjmIhMbx/uK5+93bnk/vR5Uwu00/Yd2cTAAWMaqK1MRdtR0WLbxlUNsprEfCjYiH3n9XZnlKXs6cLC8EOU436Wx7aepiAszW0wWFMe/7nVqOqztrQiKNvL0qXYwlQf0BLechJdt458EopL9QCu687TNDFYvg1yERAmCRiaayYZcX3PbUSMr6H5Q+Odntjs3XKyzfgSqqlkgf/SAND5jny1/1uteVoplZmFXuZFIiK4H8Rl2ezy1/8pnbp+JD3YEfiA2NuRjlou1BZXyMhiqqVXbrJqk/tXF6yZSkDlYJfNsWzRCGfra4B6JjEvUP927chIFm1ii3dgNstXDo1evV46+OQQO4HKvMPdtU2FPvWpPlkTxnmpZRZjB+bjmybluJdWT3E+e1C3wm7YbRe3vporhpfNPlnod6M0G10y9CKzl9Fbcku6X1FtM+IoPO/aqZ8S4/CBZoYEuR/Nk6bcvsYouxtyIl6PSuF9E8YjpJE="
email: false

View File

@ -1,4 +1,5 @@
# Telegram Bot Java Library
[![Build Status](https://travis-ci.org/rubenlagus/TelegramBots.svg?branch=master)](https://travis-ci.org/rubenlagus/TelegramBots)
[![Telegram](http://trellobot.doomdns.org/telegrambadge.svg)](https://telegram.me/JavaBotsApi)
A simple to use library to create Telegram Bots in Java
@ -9,13 +10,11 @@ Feel free to fork this project, work on it and then make a pull request against
Please, **DO NOT PUSH ANY TOKEN OR API KEY**, I will never accept a pull request with that content.
## Webhooks vs GetUpdates
Both ways are supported (but I still didn't tested webhooks).
I recommend using getUpdates methods.
Both ways are supported, but I recommend long polling method.
## Usage
Just import add the library to your project using [Maven, Gradly, ...](https://jitpack.io/#rubenlagus/TelegramBots/v2.3.3.1) or download the jar(including all dependencies) from [here](https://github.com/rubenlagus/TelegramBots/releases/tag/v2.3.3.1)
Just import add the library to your project using [Maven, Gradly, ...](https://jitpack.io/#rubenlagus/TelegramBots/v2.3.3.2) or download the jar(including all dependencies) from [here](https://github.com/rubenlagus/TelegramBots/releases/tag/v2.3.3.2)
In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`.
@ -50,15 +49,15 @@ Once done, you just need to creat a `org.telegram.telegrambots.TelegramBotsApi`a
## Example bots
Open them and send them */help* command to get some information about their capabilities:
https://telegram.me/weatherbot
https://telegram.me/weatherbot (**Use custom keyboards**)
https://telegram.me/directionsbot
https://telegram.me/directionsbot (**Basic messages**)
https://telegram.me/filesbot
https://telegram.me/filesbot (**Send files by file_id**)
https://telegram.me/TGlanguagesbot
https://telegram.me/TGlanguagesbot (**Send files uploding them**)
https://telegram.me/RaeBot
https://telegram.me/RaeBot (**Inline support**)
You can see code for those bots at [TelegramBotsExample](https://github.com/rubenlagus/TelegramBotsExample) project.

View File

@ -1,5 +1,8 @@
# How to use TelegramBots with Eclipse
If you **don't** need to modify the sources, you can just download the jar file from [here](https://github.com/rubenlagus/TelegramBots/releases) and import it as an external library.
If you need to modify the sources, follow these steps:
### Step 1: Install Maven
To get started, you need to install the Maven-Plugin for Eclipse. Click on Help > Eclipse Marketplace. After it finished loading, search for “Maven”.
@ -16,11 +19,9 @@ Now lets setup the project-folder. Go to your Eclipse-Workspace and create a
To import your project into the workspace you have to go to File > Import > (Folder) Maven > Existing Maven Projects > Next. Choose the folder, you have created in Step 3. In my case: **“TelegramBotApi”**. Click on finish and let Maven import the dependencies.
### Step 5: Setting the compliance level
In this last step you need to change the Compiler compliance level. To do this right-click on your Project (in my case **“TelegramBotApi”**) > Properties > Java Compiler. Uncheck the “Use compliance from…” if necessary and set it to 1.7
In this last step you need to change the Compiler compliance level. To do this right-click on your Project (in my case **“TelegramBotApi”**) > Properties > Java Compiler. Uncheck the “Use compliance from…” if necessary and set it to 1.8
*Now you are done. Everything should work fine. You need to set your Bot-Token in the BotConfig.java, afterwards you can run Main.java to check.*
**For a better intstruction sheet, visit [Google Drive]**
*Now you are done. Everything should work fine.*
[Google Drive]:https://goo.gl/5jd40w
[here]:https://github.com/rubenlagus/TelegramBots/archive/master.zip

148
pom.xml
View File

@ -6,7 +6,7 @@
<packaging>jar</packaging>
<groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId>
<version>2.3.3.1</version>
<version>2.3.3.2</version>
<name>Telegram Bots</name>
<url>https://telegram.me/JavaBotsApi</url>
@ -26,6 +26,7 @@
<jerseybundle.version>1.19.1</jerseybundle.version>
<httpcompontents.version>4.5.2</httpcompontents.version>
<json.version>20160212</json.version>
<jackson.version>2.7.4</jackson.version>
</properties>
<dependencyManagement>
@ -44,6 +45,7 @@
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
@ -83,91 +85,69 @@
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>clean-project</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>site</phase>
<goals>
<goal>javadoc-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin> <!-- Create sources.jar -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>org.telegram.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.telegram.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>

BIN
src/.DS_Store vendored

Binary file not shown.

BIN
src/main/.DS_Store vendored

Binary file not shown.

Binary file not shown.

View File

@ -8,6 +8,7 @@ package org.telegram.telegrambots;
*/
public class Constants {
public static final String BASEURL = "https://api.telegram.org/bot";
public static final int GETUPDATESTIMEOUT = 50;
public static final String RESPONSEFIELDOK = "ok";
public static final String RESPONSEFIELDRESULT = "result";
public static final String ERRORDESCRIPTIONFIELD = "description";

View File

@ -21,6 +21,7 @@ import org.telegram.telegrambots.updatesreceivers.Webhook;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import static org.telegram.telegrambots.Constants.ERRORCODEFIELD;
import static org.telegram.telegrambots.Constants.ERRORDESCRIPTIONFIELD;
@ -32,11 +33,11 @@ import static org.telegram.telegrambots.Constants.ERRORDESCRIPTIONFIELD;
* @date 14 of January of 2016
*/
public class TelegramBotsApi {
private static final String webhookUrlFormat = "{0}callback/";
private boolean useWebhook; ///<
private Webhook webhook; ///<
private String extrenalUrl; ///<
private String pathToCertificate; ///<
private String publicCertificateName; ///<
/**
*
@ -52,6 +53,13 @@ public class TelegramBotsApi {
* @param internalUrl
*/
public TelegramBotsApi(String keyStore, String keyStorePassword, String externalUrl, String internalUrl) throws TelegramApiException {
if (externalUrl == null || externalUrl.isEmpty()) {
throw new TelegramApiException("Parameter externalUrl can not be null or empty");
}
if (internalUrl == null || internalUrl.isEmpty()) {
throw new TelegramApiException("Parameter internalUrl can not be null or empty");
}
this.useWebhook = true;
this.extrenalUrl = fixExternalUrl(externalUrl);
webhook = new Webhook(keyStore, keyStorePassword, internalUrl);
@ -64,14 +72,18 @@ public class TelegramBotsApi {
* @param keyStorePassword
* @param externalUrl
* @param internalUrl
* @param pathToCertificate
* @param publicCertificateName
* @param pathToCertificate Full path until .pem public certificate keys
*/
public TelegramBotsApi(String keyStore, String keyStorePassword, String externalUrl, String internalUrl, String pathToCertificate, String publicCertificateName) throws TelegramApiException {
public TelegramBotsApi(String keyStore, String keyStorePassword, String externalUrl, String internalUrl, String pathToCertificate) throws TelegramApiException {
if (externalUrl == null || externalUrl.isEmpty()) {
throw new TelegramApiException("Parameter externalUrl can not be null or empty");
}
if (internalUrl == null || internalUrl.isEmpty()) {
throw new TelegramApiException("Parameter internalUrl can not be null or empty");
}
this.useWebhook = true;
this.extrenalUrl = fixExternalUrl(externalUrl);
this.pathToCertificate = pathToCertificate;
this.publicCertificateName = publicCertificateName;
webhook = new Webhook(keyStore, keyStorePassword, internalUrl);
webhook.startServer();
}
@ -85,7 +97,7 @@ public class TelegramBotsApi {
if (externalUrl != null && !externalUrl.endsWith("/")) {
externalUrl = externalUrl + "/";
}
return externalUrl;
return MessageFormat.format(webhookUrlFormat, externalUrl);
}
/**
@ -96,7 +108,7 @@ public class TelegramBotsApi {
* @param publicCertificateName
* @throws TelegramApiException
*/
private static void setWebhook(String webHookURL, String botToken, String publicCertificatePath, String publicCertificateName) throws TelegramApiException {
private static void setWebhook(String webHookURL, String botToken, String publicCertificatePath) throws TelegramApiException {
try (CloseableHttpClient httpclient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build()) {
String url = Constants.BASEURL + botToken + "/" + SetWebhook.PATH;
@ -104,7 +116,10 @@ public class TelegramBotsApi {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody(SetWebhook.URL_FIELD, webHookURL);
if (publicCertificatePath != null) {
builder.addBinaryBody(SetWebhook.CERTIFICATE_FIELD, new File(publicCertificatePath), ContentType.APPLICATION_OCTET_STREAM, publicCertificateName);
File certificate = new File(publicCertificatePath);
if (certificate.exists()) {
builder.addBinaryBody(SetWebhook.CERTIFICATE_FIELD, certificate, ContentType.TEXT_PLAIN, certificate.getName());
}
}
HttpEntity multipart = builder.build();
httppost.setEntity(multipart);
@ -126,10 +141,10 @@ public class TelegramBotsApi {
/**
* Register a bot. The Bot Session is started immediately, and may be disconnected by calling close.
* @param bot
* @param bot the bot to register
*/
public BotSession registerBot(TelegramLongPollingBot bot) throws TelegramApiException {
setWebhook(bot.getBotToken());
setWebhook(bot.getBotToken(), null);
return new BotSession(bot.getBotToken(), bot);
}
@ -140,7 +155,7 @@ public class TelegramBotsApi {
public void registerBot(TelegramWebhookBot bot) throws TelegramApiException {
if (useWebhook) {
webhook.registerWebhook(bot);
setWebhook(bot.getBotToken());
setWebhook(bot.getBotToken(), bot.getBotPath());
}
}
@ -148,10 +163,11 @@ public class TelegramBotsApi {
*
* @param botToken
*/
private void setWebhook(String botToken) throws TelegramApiException {
private void setWebhook(String botToken, String urlPath) throws TelegramApiException {
if (botToken == null) {
throw new TelegramApiException("Parameter botToken can not be null");
}
setWebhook(extrenalUrl == null ? "" : extrenalUrl, botToken, pathToCertificate, publicCertificateName);
String completeExternalUrl = urlPath == null ? "" : extrenalUrl + urlPath;
setWebhook(completeExternalUrl, botToken, pathToCertificate);
}
}

View File

@ -381,6 +381,18 @@ public class Message implements IBotApiObject {
return text != null && !text.isEmpty();
}
public boolean isCommand() {
if (hasText() && entities != null) {
for (MessageEntity entity : entities) {
if (entity != null && entity.getOffset() == 0 &&
EntityType.BOTCOMMAND.equals(entity.getType())) {
return true;
}
}
}
return false;
}
public boolean hasDocument() {
return this.document != null;
}

View File

@ -107,9 +107,9 @@ public class InlineQueryResultVoice implements InlineQueryResult {
JSONObject jsonObject = new JSONObject();
jsonObject.put(TYPE_FIELD, type);
jsonObject.put(ID_FIELD, this.id);
jsonObject.put(VOICE_DURATION_FIELD, voiceUrl);
jsonObject.put(VOICEURL_FIELD, voiceUrl);
if (title != null) {
jsonObject.put(TITLE_FIELD, this.title);
jsonObject.put(TITLE_FIELD, title);
}
if (voiceDuration != null) {
jsonObject.put(VOICE_DURATION_FIELD, voiceDuration);
@ -130,7 +130,7 @@ public class InlineQueryResultVoice implements InlineQueryResult {
gen.writeStringField(ID_FIELD, id);
gen.writeStringField(VOICEURL_FIELD, voiceUrl);
if (title != null) {
gen.writeStringField(TITLE_FIELD, this.title);
gen.writeStringField(TITLE_FIELD, title);
}
if (voiceDuration != null) {
gen.writeNumberField(VOICE_DURATION_FIELD, voiceDuration);

View File

@ -87,7 +87,7 @@ public class InlineQueryResultCachedAudio implements InlineQueryResult {
jsonObject.put(ID_FIELD, id);
jsonObject.put(AUDIO_FILE_ID_FIELD, audioFileId);
if (replyMarkup != null) {
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup);
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup.toJson());
}
if (inputMessageContent != null) {
jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent);

View File

@ -128,7 +128,7 @@ public class InlineQueryResultCachedDocument implements InlineQueryResult {
jsonObject.put(DESCRIPTION_FIELD, this.description);
}
if (replyMarkup != null) {
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup);
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup.toJson());
}
if (inputMessageContent != null) {
jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent);

View File

@ -115,7 +115,7 @@ public class InlineQueryResultCachedGif implements InlineQueryResult {
jsonObject.put(CAPTION_FIELD, this.caption);
}
if (replyMarkup != null) {
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup);
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup.toJson());
}
if (inputMessageContent != null) {
jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent);

View File

@ -115,7 +115,7 @@ public class InlineQueryResultCachedMpeg4Gif implements InlineQueryResult {
jsonObject.put(CAPTION_FIELD, this.caption);
}
if (replyMarkup != null) {
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup);
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup.toJson());
}
if (inputMessageContent != null) {
jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent);

View File

@ -130,7 +130,7 @@ public class InlineQueryResultCachedPhoto implements InlineQueryResult {
jsonObject.put(CAPTION_FIELD, this.caption);
}
if (replyMarkup != null) {
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup);
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup.toJson());
}
if (inputMessageContent != null) {
jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent);

View File

@ -87,7 +87,7 @@ public class InlineQueryResultCachedSticker implements InlineQueryResult {
jsonObject.put(ID_FIELD, this.id);
jsonObject.put(STICKER_FILE_ID_FIELD, stickerFileId);
if (replyMarkup != null) {
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup);
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup.toJson());
}
if (inputMessageContent != null) {
jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent);

View File

@ -130,7 +130,7 @@ public class InlineQueryResultCachedVideo implements InlineQueryResult {
jsonObject.put(DESCRIPTION_FIELD, this.description);
}
if (replyMarkup != null) {
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup);
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup.toJson());
}
if (inputMessageContent != null) {
jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent);

View File

@ -102,7 +102,7 @@ public class InlineQueryResultCachedVoice implements InlineQueryResult {
jsonObject.put(TITLE_FIELD, this.title);
}
if (replyMarkup != null) {
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup);
jsonObject.put(REPLY_MARKUP_FIELD, replyMarkup.toJson());
}
if (inputMessageContent != null) {
jsonObject.put(INPUTMESSAGECONTENT_FIELD, inputMessageContent);

View File

@ -104,7 +104,7 @@ public abstract class AbsSender {
throw new TelegramApiException("Parameter sendMessage can not be null");
}
return (Message) sendApiMethod(sendMessage);
return sendApiMethod(sendMessage);
}
public Boolean answerInlineQuery(AnswerInlineQuery answerInlineQuery) throws TelegramApiException {
@ -112,7 +112,7 @@ public abstract class AbsSender {
throw new TelegramApiException("Parameter answerInlineQuery can not be null");
}
return (Boolean) sendApiMethod(answerInlineQuery);
return sendApiMethod(answerInlineQuery);
}
public Boolean sendChatAction(SendChatAction sendChatAction) throws TelegramApiException {
@ -120,7 +120,7 @@ public abstract class AbsSender {
throw new TelegramApiException("Parameter sendChatAction can not be null");
}
return (Boolean) sendApiMethod(sendChatAction);
return sendApiMethod(sendChatAction);
}
public Message forwardMessage(ForwardMessage forwardMessage) throws TelegramApiException {
@ -128,7 +128,7 @@ public abstract class AbsSender {
throw new TelegramApiException("Parameter forwardMessage can not be null");
}
return (Message) sendApiMethod(forwardMessage);
return sendApiMethod(forwardMessage);
}
public Message sendLocation(SendLocation sendLocation) throws TelegramApiException {
@ -136,7 +136,7 @@ public abstract class AbsSender {
throw new TelegramApiException("Parameter sendLocation can not be null");
}
return (Message) sendApiMethod(sendLocation);
return sendApiMethod(sendLocation);
}
public Message sendVenue(SendVenue sendVenue) throws TelegramApiException {
@ -144,7 +144,7 @@ public abstract class AbsSender {
throw new TelegramApiException("Parameter sendVenue can not be null");
}
return (Message) sendApiMethod(sendVenue);
return sendApiMethod(sendVenue);
}
public Message sendContact(SendContact sendContact) throws TelegramApiException {
@ -152,84 +152,84 @@ public abstract class AbsSender {
throw new TelegramApiException("Parameter sendContact can not be null");
}
return (Message) sendApiMethod(sendContact);
return sendApiMethod(sendContact);
}
public Boolean kickMember(KickChatMember kickChatMember) throws TelegramApiException {
if (kickChatMember == null) {
throw new TelegramApiException("Parameter kickChatMember can not be null");
}
return (Boolean) sendApiMethod(kickChatMember);
return sendApiMethod(kickChatMember);
}
public Boolean unbanMember(UnbanChatMember unbanChatMember) throws TelegramApiException {
if (unbanChatMember == null) {
throw new TelegramApiException("Parameter unbanChatMember can not be null");
}
return (Boolean) sendApiMethod(unbanChatMember);
return sendApiMethod(unbanChatMember);
}
public Boolean leaveChat(LeaveChat leaveChat) throws TelegramApiException {
if (leaveChat == null) {
throw new TelegramApiException("Parameter leaveChat can not be null");
}
return (Boolean) sendApiMethod(leaveChat);
return sendApiMethod(leaveChat);
}
public Chat getChat(GetChat getChat) throws TelegramApiException {
if (getChat == null) {
throw new TelegramApiException("Parameter getChat can not be null");
}
return (Chat) sendApiMethod(getChat);
return sendApiMethod(getChat);
}
public List<ChatMember> getChatAdministrators(GetChatAdministrators getChatAdministrators) throws TelegramApiException {
if (getChatAdministrators == null) {
throw new TelegramApiException("Parameter getChatAdministrators can not be null");
}
return (ArrayList<ChatMember>) sendApiMethod(getChatAdministrators);
return sendApiMethod(getChatAdministrators);
}
public ChatMember getChatMember(GetChatMember getChatMember) throws TelegramApiException {
if (getChatMember == null) {
throw new TelegramApiException("Parameter getChatMember can not be null");
}
return (ChatMember) sendApiMethod(getChatMember);
return sendApiMethod(getChatMember);
}
public Integer getChatMemberCount(GetChatMemberCount getChatMemberCount) throws TelegramApiException {
if (getChatMemberCount == null) {
throw new TelegramApiException("Parameter getChatMemberCount can not be null");
}
return (Integer) sendApiMethod(getChatMemberCount);
return sendApiMethod(getChatMemberCount);
}
public Message editMessageText(EditMessageText editMessageText) throws TelegramApiException {
if (editMessageText == null) {
throw new TelegramApiException("Parameter editMessageText can not be null");
}
return (Message) sendApiMethod(editMessageText);
return sendApiMethod(editMessageText);
}
public Message editMessageCaption(EditMessageCaption editMessageCaption) throws TelegramApiException {
if (editMessageCaption == null) {
throw new TelegramApiException("Parameter editMessageCaption can not be null");
}
return (Message) sendApiMethod(editMessageCaption);
return sendApiMethod(editMessageCaption);
}
public Message editMessageReplyMarkup(EditMessageReplyMarkup editMessageReplyMarkup) throws TelegramApiException {
if (editMessageReplyMarkup == null) {
throw new TelegramApiException("Parameter editMessageReplyMarkup can not be null");
}
return (Message) sendApiMethod(editMessageReplyMarkup);
return sendApiMethod(editMessageReplyMarkup);
}
public Boolean answerCallbackQuery(AnswerCallbackQuery answerCallbackQuery) throws TelegramApiException {
if (answerCallbackQuery == null) {
throw new TelegramApiException("Parameter answerCallbackQuery can not be null");
}
return (Boolean) sendApiMethod(answerCallbackQuery);
return sendApiMethod(answerCallbackQuery);
}
public UserProfilePhotos getUserProfilePhotos(GetUserProfilePhotos getUserProfilePhotos) throws TelegramApiException {
@ -237,7 +237,7 @@ public abstract class AbsSender {
throw new TelegramApiException("Parameter getUserProfilePhotos can not be null");
}
return (UserProfilePhotos) sendApiMethod(getUserProfilePhotos);
return sendApiMethod(getUserProfilePhotos);
}
public File getFile(GetFile getFile) throws TelegramApiException{
@ -247,13 +247,13 @@ public abstract class AbsSender {
else if(getFile.getFileId() == null){
throw new TelegramApiException("Attribute file_id in parameter getFile can not be null");
}
return (File) sendApiMethod(getFile);
return sendApiMethod(getFile);
}
public User getMe() throws TelegramApiException {
GetMe getMe = new GetMe();
return (User) sendApiMethod(getMe);
return sendApiMethod(getMe);
}
// Send Requests Async
@ -928,7 +928,7 @@ public abstract class AbsSender {
});
}
private Serializable sendApiMethod(BotApiMethod method) throws TelegramApiException {
private <T extends Serializable> T sendApiMethod(BotApiMethod<T> method) throws TelegramApiException {
String responseContent;
try {
String url = getBaseUrl() + method.getPath();

View File

@ -0,0 +1,82 @@
package org.telegram.telegrambots.bots;
import org.telegram.telegrambots.bots.commands.BotCommand;
import org.telegram.telegrambots.bots.commands.CommandRegistry;
import org.telegram.telegrambots.bots.commands.ICommandRegistry;
import org.telegram.telegrambots.api.objects.Message;
import org.telegram.telegrambots.api.objects.Update;
import java.util.Collection;
import java.util.Map;
import java.util.function.BiConsumer;
/**
* This class adds command functionality to the TelegramLongPollingBot
*
* @author tschulz
*/
public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingBot implements ICommandRegistry {
private final CommandRegistry commandRegistry;
/**
* construct creates CommandRegistry for this bot.
* Use ICommandRegistry's methods on this bot to register commands
*/
public TelegramLongPollingCommandBot() {
super();
this.commandRegistry = new CommandRegistry();
}
@Override
public final void onUpdateReceived(Update update) {
if (update.hasMessage()) {
Message message = update.getMessage();
if (message.isCommand()) {
if (commandRegistry.executeCommand(this, message)) {
return;
}
}
}
processNonCommandUpdate(update);
}
@Override
public final boolean register(BotCommand botCommand) {
return commandRegistry.register(botCommand);
}
@Override
public final Map<BotCommand, Boolean> registerAll(BotCommand... botCommands) {
return commandRegistry.registerAll(botCommands);
}
@Override
public final boolean deregister(BotCommand botCommand) {
return commandRegistry.deregister(botCommand);
}
@Override
public final Map<BotCommand, Boolean> deregisterAll(BotCommand... botCommands) {
return commandRegistry.deregisterAll(botCommands);
}
@Override
public final Collection<BotCommand> getRegisteredCommands() {
return commandRegistry.getRegisteredCommands();
}
@Override
public void registerDefaultAction(BiConsumer<AbsSender, Message> defaultConsumer) {
commandRegistry.registerDefaultAction(defaultConsumer);
}
/**
* Process all updates, that are not commands.
* @warning Commands that have valid syntax but are not registered on this bot,
* won't be forwarded to this method <b>if a default action is present</b>.
*
* @param update the update
*/
public abstract void processNonCommandUpdate(Update update);
}

View File

@ -0,0 +1,76 @@
package org.telegram.telegrambots.bots.commands;
import org.telegram.telegrambots.api.objects.Chat;
import org.telegram.telegrambots.bots.AbsSender;
/**
* Representation of a command, which can be executed
*
* @author tschulz
*/
public abstract class BotCommand {
public final static String COMMAND_INIT_CHARACTER = "/";
public static final String COMMAND_PARAMETER_SEPARATOR = " ";
private final static int COMMAND_MAX_LENGTH = 32;
private final String commandIdentifier;
private final String description;
/**
* Construct a command
*
* @param commandIdentifier the unique identifier of this command (e.g. the command string to
* enter into chat)
* @param description the description of this command
*/
public BotCommand(String commandIdentifier, String description) {
if (commandIdentifier == null || commandIdentifier.isEmpty()) {
throw new IllegalArgumentException("commandIdentifier for command cannot be null or empty");
}
if (commandIdentifier.startsWith(COMMAND_INIT_CHARACTER)) {
commandIdentifier = commandIdentifier.substring(1);
}
if (commandIdentifier.length() + 1 > COMMAND_MAX_LENGTH) {
throw new IllegalArgumentException("commandIdentifier cannot be longer than " + COMMAND_MAX_LENGTH + " (including " + COMMAND_INIT_CHARACTER + ")");
}
this.commandIdentifier = commandIdentifier.toLowerCase();
this.description = description;
}
/**
* Get the identifier of this command
*
* @return the identifier
*/
public final String getCommandIdentifier() {
return commandIdentifier;
}
/**
* Get the description of this command
*
* @return the description as String
*/
public final String getDescription() {
return description;
}
@Override
public String toString() {
return "<b>" + COMMAND_INIT_CHARACTER + getCommandIdentifier() +
"</b>\n" + getDescription();
}
/**
* Execute the command
*
* @param absSender absSender to send messages over
* @param chat the chat, to be able to send replies
* @param arguments passed arguments
*/
public abstract void execute(AbsSender absSender, Chat chat, String[] arguments);
}

View File

@ -0,0 +1,100 @@
package org.telegram.telegrambots.bots.commands;
import org.telegram.telegrambots.api.objects.Message;
import org.telegram.telegrambots.bots.AbsSender;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
/**
* @author tschulz
*/
public final class CommandRegistry implements ICommandRegistry {
private final Map<String, BotCommand> commandRegistryMap = new HashMap<>();
private BiConsumer<AbsSender, Message> defaultConsumer;
public CommandRegistry() {
}
@Override
public void registerDefaultAction(BiConsumer<AbsSender, Message> defaultConsumer) {
this.defaultConsumer = defaultConsumer;
}
@Override
public final boolean register(BotCommand botCommand) {
if (commandRegistryMap.containsKey(botCommand.getCommandIdentifier())) {
return false;
}
commandRegistryMap.put(botCommand.getCommandIdentifier(), botCommand);
return true;
}
@Override
public final Map<BotCommand, Boolean> registerAll(BotCommand... botCommands) {
Map<BotCommand, Boolean> resultMap = new HashMap<>(botCommands.length);
for (BotCommand botCommand : botCommands) {
resultMap.put(botCommand, register(botCommand));
}
return resultMap;
}
@Override
public final boolean deregister(BotCommand botCommand) {
if (commandRegistryMap.containsKey(botCommand.getCommandIdentifier())) {
commandRegistryMap.remove(botCommand.getCommandIdentifier());
return true;
}
return false;
}
@Override
public final Map<BotCommand, Boolean> deregisterAll(BotCommand... botCommands) {
Map<BotCommand, Boolean> resultMap = new HashMap<>(botCommands.length);
for (BotCommand botCommand : botCommands) {
resultMap.put(botCommand, deregister(botCommand));
}
return resultMap;
}
@Override
public final Collection<BotCommand> getRegisteredCommands() {
return commandRegistryMap.values();
}
/**
* Executes a command action if the command is registered.
*
* @note If the command is not registered and there is a default consumer,
* that action will be performed
*
* @param absSender absSender
* @param message input message
* @return True if a command or default action is executed, false otherwise
*/
public final boolean executeCommand(AbsSender absSender, Message message) {
if (message.hasText()) {
String text = message.getText();
if (text.startsWith(BotCommand.COMMAND_INIT_CHARACTER)) {
String commandMessage = text.substring(1);
String[] commandSplit = commandMessage.split(BotCommand.COMMAND_PARAMETER_SEPARATOR);
String command = commandSplit[0];
if (commandRegistryMap.containsKey(command)) {
String[] parameters = Arrays.copyOfRange(commandSplit, 1, commandSplit.length);
commandRegistryMap.get(command).execute(absSender, message.getChat(), parameters);
return true;
} else if (defaultConsumer != null) {
defaultConsumer.accept(absSender, message);
return true;
}
}
}
return false;
}
}

View File

@ -0,0 +1,63 @@
package org.telegram.telegrambots.bots.commands;
import org.telegram.telegrambots.api.objects.Message;
import org.telegram.telegrambots.bots.AbsSender;
import java.util.Collection;
import java.util.Map;
import java.util.function.BiConsumer;
/**
*
*/
public interface ICommandRegistry {
/**
* Register a default action when there is no command register that match the message sent
* @param defaultConsumer Consumer to evaluate the message
*
* @note Use this method if you want your bot to execute a default action when the user
* sends a command that is not registered.
*/
void registerDefaultAction(BiConsumer<AbsSender, Message> defaultConsumer);
/**
* register a command
*
* @param botCommand the command to register
* @return whether the command could be registered, was not already registered
*/
boolean register(BotCommand botCommand);
/**
* register multiple commands
*
* @param botCommands commands to register
* @return map with results of the command register per command
*/
Map<BotCommand, Boolean> registerAll(BotCommand... botCommands);
/**
* deregister a command
*
* @param botCommand the command to deregister
* @return whether the command could be deregistered, was registered
*/
boolean deregister(BotCommand botCommand);
/**
* deregister multiple commands
*
* @param botCommands commands to deregister
* @return map with results of the command deregistered per command
*/
Map<BotCommand, Boolean> deregisterAll(BotCommand... botCommands);
/**
* get a collection of all registered commands
*
* @return a collection of registered commands
*/
Collection<BotCommand> getRegisteredCommands();
}

View File

@ -14,12 +14,12 @@ import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.telegram.telegrambots.logging.BotLogger;
import org.telegram.telegrambots.Constants;
import org.telegram.telegrambots.TelegramApiException;
import org.telegram.telegrambots.api.methods.updates.GetUpdates;
import org.telegram.telegrambots.api.objects.Update;
import org.telegram.telegrambots.bots.ITelegramLongPollingBot;
import org.telegram.telegrambots.logging.BotLogger;
import java.io.IOException;
import java.io.InvalidObjectException;
@ -27,9 +27,6 @@ import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.TimeUnit;
import static org.telegram.telegrambots.Constants.ERRORCODEFIELD;
import static org.telegram.telegrambots.Constants.ERRORDESCRIPTIONFIELD;
/**
* @author Ruben Bermudez
* @version 1.0
@ -54,49 +51,55 @@ public class BotSession {
public BotSession(String token, ITelegramLongPollingBot callback) {
this.token = token;
this.callback = callback;
httpclient = HttpClientBuilder.create()
.setSSLHostnameVerifier(new NoopHostnameVerifier())
.setConnectionTimeToLive(70, TimeUnit.SECONDS)
.setMaxConnTotal(100)
.build();
requestConfig = RequestConfig.copy(RequestConfig.custom().build())
.setSocketTimeout(SOCKET_TIMEOUT)
.setConnectTimeout(SOCKET_TIMEOUT)
.setConnectionRequestTimeout(SOCKET_TIMEOUT).build();
this.readerThread = new ReaderThread();
readerThread = new ReaderThread();
readerThread.setName(callback.getBotUsername() + " Telegram Connection");
this.readerThread.start();
this.handlerThread = new HandlerThread();
handlerThread.setName(callback.getBotUsername() + " Executor");
this.handlerThread.start();
readerThread.start();
handlerThread = new HandlerThread();
handlerThread.setName(callback.getBotUsername() + " Telegram Executor");
handlerThread.start();
}
public void close()
{
running = false;
if(httpclient != null)
{
try
{
httpclient.close();
httpclient = null;
public void close() {
running = false;
if (readerThread != null) {
readerThread.interrupt();
}
if (handlerThread != null) {
handlerThread.interrupt();
}
if (httpclient != null) {
try {
httpclient.close();
httpclient = null;
} catch (IOException e) {
BotLogger.severe(LOGTAG, e);
}
}
}
}
private class ReaderThread extends Thread {
@Override
@Override
public void run() {
setPriority(Thread.MIN_PRIORITY);
while(running) {
while (running) {
try {
GetUpdates request = new GetUpdates();
request.setLimit(100);
request.setTimeout(50);
request.setTimeout(Constants.GETUPDATESTIMEOUT);
request.setOffset(lastReceivedUpdate + 1);
String url = Constants.BASEURL + token + "/" + GetUpdates.PATH;
//http client
@ -111,7 +114,9 @@ public class BotSession {
String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
JSONObject jsonObject = new JSONObject(responseContent);
if (!jsonObject.getBoolean(Constants.RESPONSEFIELDOK)) {
throw new TelegramApiException("Error getting updates", jsonObject.getString(ERRORDESCRIPTIONFIELD), jsonObject.getInt(ERRORCODEFIELD));
throw new TelegramApiException("Error getting updates",
jsonObject.getString(Constants.ERRORDESCRIPTIONFIELD),
jsonObject.getInt(Constants.ERRORCODEFIELD));
}
JSONArray jsonArray = jsonObject.getJSONArray(Constants.RESPONSEFIELDRESULT);
if (jsonArray.length() != 0) {
@ -155,7 +160,7 @@ public class BotSession {
@Override
public void run() {
setPriority(Thread.MIN_PRIORITY);
while(running) {
while (running) {
try {
Update update = receivedUpdates.pollLast();
if (update == null) {

View File

@ -3,10 +3,16 @@ package org.telegram.telegrambots.updatesreceivers;
import org.telegram.telegrambots.api.objects.Update;
import org.telegram.telegrambots.bots.ITelegramWebhookBot;
import javax.ws.rs.*;
import java.util.concurrent.ConcurrentHashMap;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Ruben Bermudez
@ -15,7 +21,7 @@ import java.util.concurrent.ConcurrentHashMap;
* @date 20 of June of 2015
*/
@Path("callback")
class RestApi {
public class RestApi {
private final ConcurrentHashMap<String, ITelegramWebhookBot> callbacks = new ConcurrentHashMap<>();

View File

@ -10,6 +10,7 @@ import org.glassfish.jersey.server.ResourceConfig;
import org.telegram.telegrambots.TelegramApiException;
import org.telegram.telegrambots.bots.ITelegramWebhookBot;
import java.io.File;
import java.io.IOException;
import java.net.URI;
@ -20,17 +21,16 @@ import java.net.URI;
* @date 20 of June of 2015
*/
public class Webhook {
private static final String LOGTAG = "WEBHOOK";
private final String KEYSTORE_SERVER_FILE;
private final String KEYSTORE_SERVER_PWD;
private final RestApi restApi;
private final String internalUrl;
public Webhook(String keyStore, String keyStorePassword, String internalUrl) {
public Webhook(String keyStore, String keyStorePassword, String internalUrl) throws TelegramApiException {
this.KEYSTORE_SERVER_FILE = keyStore;
this.KEYSTORE_SERVER_PWD = keyStorePassword;
validateServerKeystoreFile(keyStore);
this.internalUrl = internalUrl;
this.restApi = new RestApi();
}
@ -65,4 +65,11 @@ public class Webhook {
private URI getBaseURI() {
return URI.create(internalUrl);
}
}
private static void validateServerKeystoreFile(String keyStore) throws TelegramApiException {
File file = new File(keyStore);
if (!file.exists() || !file.canRead()) {
throw new TelegramApiException("Can't find or access server keystore file.");
}
}
}