Merge pull request #605 from rubenlagus/dev

Api version 4.2
This commit is contained in:
Ruben Bermudez 2019-04-16 00:22:09 +01:00 committed by GitHub
commit d62354915d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 629 additions and 133 deletions

View File

@ -65,6 +65,9 @@
<show-object-properties value="true" /> <show-object-properties value="true" />
<loaded-nodes /> <loaded-nodes />
</component> </component>
<component name="DBNavigator.Project.DatabaseFileManager">
<open-files />
</component>
<component name="DBNavigator.Project.EditorStateManager"> <component name="DBNavigator.Project.EditorStateManager">
<last-used-providers /> <last-used-providers />
</component> </component>
@ -191,11 +194,11 @@
<data-length-threshold value="100" /> <data-length-threshold value="100" />
<popup-delay value="1000" /> <popup-delay value="1000" />
</text-editor-popup> </text-editor-popup>
<values-list-popup> <values-actions-popup>
<show-popup-button value="true" /> <show-popup-button value="true" />
<element-count-threshold value="1000" /> <element-count-threshold value="1000" />
<data-length-threshold value="250" /> <data-length-threshold value="250" />
</values-list-popup> </values-actions-popup>
<general> <general>
<fetch-block-size value="100" /> <fetch-block-size value="100" />
<fetch-timeout value="30" /> <fetch-timeout value="30" />
@ -983,26 +986,15 @@
<root url="jar://$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.1.3/error_prone_annotations-2.1.3-sources.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.1.3/error_prone_annotations-2.1.3-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
<library name="Maven: com.google.guava:guava:19.0"> <library name="Maven: com.google.guava:guava:25.1-jre">
<CLASSES> <CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/19.0/guava-19.0.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/25.1-jre/guava-25.1-jre.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC> <JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/19.0/guava-19.0-javadoc.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/25.1-jre/guava-25.1-jre-javadoc.jar!/" />
</JAVADOC> </JAVADOC>
<SOURCES> <SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/19.0/guava-19.0-sources.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/25.1-jre/guava-25.1-jre-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: com.google.guava:guava:25.1-android">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/25.1-android/guava-25.1-android.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/25.1-android/guava-25.1-android-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/google/guava/guava/25.1-android/guava-25.1-android-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
<library name="Maven: com.google.inject:guice:4.2.2"> <library name="Maven: com.google.inject:guice:4.2.2">
@ -1335,15 +1327,15 @@
<root url="jar://$MAVEN_REPOSITORY$/org/assertj/assertj-core/3.9.1/assertj-core-3.9.1-sources.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/org/assertj/assertj-core/3.9.1/assertj-core-3.9.1-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
<library name="Maven: org.checkerframework:checker-compat-qual:2.0.0"> <library name="Maven: org.checkerframework:checker-qual:2.0.0">
<CLASSES> <CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.0.0/checker-compat-qual-2.0.0.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/2.0.0/checker-qual-2.0.0.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC> <JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.0.0/checker-compat-qual-2.0.0-javadoc.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/2.0.0/checker-qual-2.0.0-javadoc.jar!/" />
</JAVADOC> </JAVADOC>
<SOURCES> <SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.0.0/checker-compat-qual-2.0.0-sources.jar!/" /> <root url="jar://$MAVEN_REPOSITORY$/org/checkerframework/checker-qual/2.0.0/checker-qual-2.0.0-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
<library name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14"> <library name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14">

View File

@ -27,16 +27,16 @@ Just import add the library to your project with one of these options:
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
``` ```
```gradle ```gradle
compile "org.telegram:telegrambots:4.1.2" compile "org.telegram:telegrambots:4.2"
``` ```
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.1.2) 2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.2)
3. Download the jar(including all dependencies) from [here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.1.2) 3. Download the jar(including all dependencies) from [here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.2)
In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`. In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`.

View File

@ -1,3 +1,7 @@
### <a id="4.2"></a>4.2 ###
1. Update to Api version [4.2](https://core.telegram.org/bots/api-changelog#april-14-2019)
2. Fixed: #498, #578
### <a id="4.1.2"></a>4.1.2 ### ### <a id="4.1.2"></a>4.1.2 ###
1. Removed unsafe dependencies 1. Removed unsafe dependencies
2. Fix bugs: #535, #524, #563, #562 and #557 2. Fix bugs: #535, #524, #563, #562 and #557

View File

@ -22,9 +22,7 @@ public PhotoSize getPhoto(Update update) {
// We fetch the bigger photo // We fetch the bigger photo
return photos.stream() return photos.stream()
.sorted(Comparator.comparing(PhotoSize::getFileSize).reversed()) .max(Comparator.comparing(PhotoSize::getFileSize)).orElse(null);
.findFirst()
.orElse(null);
} }
// Return null if not found // Return null if not found

View File

@ -11,13 +11,13 @@ First you need ot get the library and add it to your project. There are few poss
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
``` ```
* With **Gradle**: * With **Gradle**:
```groovy ```groovy
compile group: 'org.telegram', name: 'telegrambots', version: '4.1.2' compile group: 'org.telegram', name: 'telegrambots', version: '4.2'
``` ```
2. Don't like **Maven Central Repository**? It can also be taken from [Jitpack](https://jitpack.io/#rubenlagus/TelegramBots). 2. Don't like **Maven Central Repository**? It can also be taken from [Jitpack](https://jitpack.io/#rubenlagus/TelegramBots).

View File

@ -9,12 +9,12 @@ As with any Java project, you will need to set your dependencies.
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-abilities</artifactId> <artifactId>telegrambots-abilities</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
``` ```
* **Gradle** * **Gradle**
```groovy ```groovy
compile group: 'org.telegram', name: 'telegrambots-abilties', version: '4.1.2' compile group: 'org.telegram', name: 'telegrambots-abilities', version: '4.2'
``` ```
* [JitPack](https://jitpack.io/#rubenlagus/TelegramBots) * [JitPack](https://jitpack.io/#rubenlagus/TelegramBots)
@ -115,4 +115,4 @@ Since you've implemented an AbilityBot, you get **factory abilities** as well. T
## Conclusion ## Conclusion
Congratulation on creating your first AbilityBot. What's next? So far we've only considered the case of commands, but what about images and inline replies? AbilityBots can also handle that! Oh and, did you know that all ability bots have an embedded database that you can use? Congratulation on creating your first AbilityBot. What's next? So far we've only considered the case of commands, but what about images and inline replies? AbilityBots can also handle that! Oh and, did you know that all ability bots have an embedded database that you can use?
The following sections of the tutorial will describe in detail **abilities** and **replies**. It will also bring into attention how to effectively in-code test your bot, handle the embedded DB and administer your user access levels. The following sections of the tutorial will describe in detail **abilities** and **replies**. It will also bring into attention how to effectively in-code test your bot, handle the embedded DB and administer your user access levels.

View File

@ -7,7 +7,7 @@
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>Bots</artifactId> <artifactId>Bots</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>4.1.2</version> <version>4.2</version>
<modules> <modules>
<module>telegrambots</module> <module>telegrambots</module>

View File

@ -18,19 +18,19 @@ Usage
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-abilities</artifactId> <artifactId>telegrambots-abilities</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
``` ```
**Gradle** **Gradle**
```gradle ```gradle
compile "org.telegram:telegrambots-abilities:4.1.2" compile "org.telegram:telegrambots-abilities:4.2"
``` ```
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.1.2) **JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.2)
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.1.2) **Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.2)
Motivation Motivation
---------- ----------

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-abilities</artifactId> <artifactId>telegrambots-abilities</artifactId>
<version>4.1.2</version> <version>4.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Ability Bot</name> <name>Telegram Ability Bot</name>
@ -67,14 +67,13 @@
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<commonslang.version>3.5</commonslang.version> <commonslang.version>3.5</commonslang.version>
<mapdb.version>3.0.4</mapdb.version> <mapdb.version>3.0.4</mapdb.version>
<guava.version>27.0.1-jre</guava.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
@ -85,35 +84,13 @@
<groupId>org.mapdb</groupId> <groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId> <artifactId>mapdb</artifactId>
<version>${mapdb.version}</version> <version>${mapdb.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>com.google.code.findbugs</groupId> <groupId>com.google.guava</groupId>
<artifactId>jsr305</artifactId> <artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.j2objc</groupId>
<artifactId>j2objc-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-compat-qual</artifactId>
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId> <artifactId>mockito-all</artifactId>

View File

@ -0,0 +1,36 @@
package org.telegram.abilitybots.api.db;
import org.telegram.abilitybots.api.util.Pair;
import java.util.*;
final class BackupMap<K, V> extends AbstractCollection<Pair<K, V>> implements Collection<Pair<K, V>> {
private Collection<Pair<K, V>> entries = new HashSet<>();
public BackupMap(){}
public BackupMap(Map<K, V> map) {
map.forEach((key, value) -> entries.add(Pair.of(key, value)));
}
public Map<K, V> toMap() {
Map<K, V> map = new HashMap<>();
entries.forEach(e -> map.put(e.a(), e.b()));
return map;
}
@Override
public Iterator<Pair<K, V>> iterator() {
return entries.iterator();
}
@Override
public int size() {
return entries.size();
}
@Override
public boolean add(Pair<K, V> kvPair) {
return entries.add(kvPair);
}
}

View File

@ -184,7 +184,7 @@ public class MapDBContext implements DBContext {
else if (struct instanceof List) else if (struct instanceof List)
return Pair.of(entry.getKey(), newArrayList((List) struct)); return Pair.of(entry.getKey(), newArrayList((List) struct));
else if (struct instanceof Map) else if (struct instanceof Map)
return Pair.of(entry.getKey(), newHashMap((Map) struct)); return Pair.of(entry.getKey(), new BackupMap((Map) struct));
else else
return Pair.of(entry.getKey(), struct); return Pair.of(entry.getKey(), struct);
}).collect(toMap(pair -> (String) pair.a(), Pair::b)); }).collect(toMap(pair -> (String) pair.a(), Pair::b));
@ -197,17 +197,8 @@ public class MapDBContext implements DBContext {
if (value instanceof Set) { if (value instanceof Set) {
Set entrySet = (Set) value; Set entrySet = (Set) value;
getSet(name).addAll(entrySet); getSet(name).addAll(entrySet);
} else if (value instanceof Map) { } else if (value instanceof BackupMap) {
Map<Object, Object> entryMap = (Map) value; Map<Object, Object> entryMap = ((BackupMap) value).toMap();
// TODO: This is ugly
// Special handling of USERS since the key is an integer. JSON by default considers a map a JSONObject.
// Keys are serialized and deserialized as String
if (name.equals(USERS))
entryMap = entryMap.entrySet().stream()
.map(entry -> Pair.of(Integer.parseInt(entry.getKey().toString()), entry.getValue()))
.collect(toMap(Pair::a, Pair::b));
getMap(name).putAll(entryMap); getMap(name).putAll(entryMap);
} else if (value instanceof List) { } else if (value instanceof List) {
List entryList = (List) value; List entryList = (List) value;

View File

@ -15,7 +15,7 @@ Usage
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-chat-session-bot</artifactId> <artifactId>telegrambots-chat-session-bot</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
``` ```

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-chat-session-bot</artifactId> <artifactId>telegrambots-chat-session-bot</artifactId>
<version>4.1.2</version> <version>4.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots Chat Session Bot</name> <name>Telegram Bots Chat Session Bot</name>
@ -73,7 +73,7 @@
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core --> <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->

View File

@ -16,12 +16,12 @@ Just import add the library to your project with one of these options:
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambotsextensions</artifactId> <artifactId>telegrambotsextensions</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
``` ```
2. Using Gradle: 2. Using Gradle:
```gradle ```gradle
compile "org.telegram:telegrambotsextensions:4.1.2" compile "org.telegram:telegrambotsextensions:4.2"
``` ```

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambotsextensions</artifactId> <artifactId>telegrambotsextensions</artifactId>
<version>4.1.2</version> <version>4.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots Extensions</name> <name>Telegram Bots Extensions</name>
@ -65,7 +65,7 @@
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-meta</artifactId> <artifactId>telegrambots-meta</artifactId>
<version>4.1.2</version> <version>4.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots Meta</name> <name>Telegram Bots Meta</name>
@ -64,6 +64,7 @@
<jacksonanotation.version>2.9.0</jacksonanotation.version> <jacksonanotation.version>2.9.0</jacksonanotation.version>
<json.version>20180813</json.version> <json.version>20180813</json.version>
<junit.version>4.12</junit.version> <junit.version>4.12</junit.version>
<guava.version>25.1-jre</guava.version>
</properties> </properties>
<dependencies> <dependencies>
@ -71,6 +72,12 @@
<groupId>com.google.inject</groupId> <groupId>com.google.inject</groupId>
<artifactId>guice</artifactId> <artifactId>guice</artifactId>
<version>${guice.version}</version> <version>${guice.version}</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
@ -88,6 +95,11 @@
<artifactId>jackson-annotations</artifactId> <artifactId>jackson-annotations</artifactId>
<version>${jacksonanotation.version}</version> <version>${jacksonanotation.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.json</groupId> <groupId>org.json</groupId>
<artifactId>json</artifactId> <artifactId>json</artifactId>

View File

@ -15,10 +15,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 3.1 * @version 3.1
* Use this method to pin a message in a supergroup or channel. * Use this method to pin a message in a group, a supergroup or a channel.
* The bot must be an administrator in the chat for this to work and must have the can_pin_messages * The bot must be an administrator in the chat for this to work and must
* admin right in the supergroup or can_edit_messages admin right in the channel. * have the can_pin_messages admin right in the supergroup or can_edit_messages
* Returns True on success. * admin right in the channel. Returns True on success.
*/ */
public class PinChatMessage extends BotApiMethod<Boolean> { public class PinChatMessage extends BotApiMethod<Boolean> {
public static final String PATH = "pinChatMessage"; public static final String PATH = "pinChatMessage";

View File

@ -15,9 +15,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 3.1 * @version 3.1
* Use this method to unpin a message in a supergroup or channel. * Use this method to unpin a message in a group, a supergroup or a channel.
* The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. * The bot must be an administrator in the chat for this to work and must have
* Returns True on success. * the can_pin_messages admin right in the supergroup or can_edit_messages
* admin right in the channel. Returns True on success.
*/ */
public class UnpinChatMessage extends BotApiMethod<Boolean> { public class UnpinChatMessage extends BotApiMethod<Boolean> {
public static final String PATH = "unpinChatMessage"; public static final String PATH = "unpinChatMessage";

View File

@ -0,0 +1,209 @@
package org.telegram.telegrambots.meta.api.methods.polls;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ApiResponse;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Ruben Bermudez
* @version 1.0
* Use this method to send a native poll.
* A native poll can't be sent to a private chat.
*
* On success, the sent Message is returned.
*/
public class SendPoll extends BotApiMethod<Message> {
public static final String PATH = "sendPoll";
private static final String CHATID_FIELD = "chat_id";
private static final String QUESTION_FIELD = "question";
private static final String OPTIONS_FIELD = "options";
private static final String DISABLENOTIFICATION_FIELD = "disable_notification";
private static final String REPLYTOMESSAGEID_FIELD = "reply_to_message_id";
private static final String REPLYMARKUP_FIELD = "reply_markup";
@JsonProperty(CHATID_FIELD)
/**
* Unique identifier for the target chat or username of the target channel (in the format @channelusername).
* A native poll can't be sent to a private chat.
*/
private String chatId;
@JsonProperty(QUESTION_FIELD)
private String question; ///< Poll question, 1-255 characters
@JsonProperty(OPTIONS_FIELD)
private List<String> options; ///< List of answer options, 1-10 strings 1-100 characters each
@JsonProperty(DISABLENOTIFICATION_FIELD)
private Boolean disableNotification; ///< Optional. Sends the message silently. Users will receive a notification with no sound.
@JsonProperty(REPLYTOMESSAGEID_FIELD)
private Integer replyToMessageId; ///< Optional. If the message is a reply, ID of the original message
@JsonProperty(REPLYMARKUP_FIELD)
private ReplyKeyboard replyMarkup; ///< Optional. JSON-serialized object for a custom reply keyboard
public SendPoll() {
super();
}
public SendPoll(String chatId, String question, List<String> options) {
this.chatId = checkNotNull(chatId);
this.question = checkNotNull(question);
this.options = checkNotNull(options);
}
public SendPoll(Long chatId, String question, List<String> options) {
this.chatId = checkNotNull(chatId).toString();
this.question = checkNotNull(question);
this.options = checkNotNull(options);
}
public String getChatId() {
return chatId;
}
public SendPoll setChatId(String chatId) {
this.chatId = chatId;
return this;
}
public SendPoll setChatId(Long chatId) {
Objects.requireNonNull(chatId);
this.chatId = chatId.toString();
return this;
}
public String getQuestion() {
return question;
}
public SendPoll setQuestion(String question) {
this.question = question;
return this;
}
public List<String> getOptions() {
return options;
}
public SendPoll setOptions(List<String> options) {
this.options = options;
return this;
}
public Integer getReplyToMessageId() {
return replyToMessageId;
}
public SendPoll setReplyToMessageId(Integer replyToMessageId) {
this.replyToMessageId = replyToMessageId;
return this;
}
public ReplyKeyboard getReplyMarkup() {
return replyMarkup;
}
public SendPoll setReplyMarkup(ReplyKeyboard replyMarkup) {
this.replyMarkup = replyMarkup;
return this;
}
public Boolean getDisableNotification() {
return disableNotification;
}
public SendPoll enableNotification() {
this.disableNotification = null;
return this;
}
public SendPoll disableNotification() {
this.disableNotification = true;
return this;
}
@Override
public String getMethod() {
return PATH;
}
@Override
public Message deserializeResponse(String answer) throws TelegramApiRequestException {
try {
ApiResponse<Message> result = OBJECT_MAPPER.readValue(answer,
new TypeReference<ApiResponse<Message>>(){});
if (result.getOk()) {
return result.getResult();
} else {
throw new TelegramApiRequestException("Error sending poll", result);
}
} catch (IOException e) {
throw new TelegramApiRequestException("Unable to deserialize response", e);
}
}
@Override
public void validate() throws TelegramApiValidationException {
if (chatId == null) {
throw new TelegramApiValidationException("ChatId parameter can't be empty", this);
}
if (question == null || question.isEmpty()) {
throw new TelegramApiValidationException("Question parameter can't be empty", this);
}
if (options == null || options.isEmpty()) {
throw new TelegramApiValidationException("Options parameter can't be empty", this);
}
if (replyMarkup != null) {
replyMarkup.validate();
}
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof SendPoll)) {
return false;
}
SendPoll sendMessage = (SendPoll) o;
return Objects.equals(chatId, sendMessage.chatId)
&& Objects.equals(disableNotification, sendMessage.disableNotification)
&& Objects.equals(question, sendMessage.question)
&& Objects.equals(options, sendMessage.options)
&& Objects.equals(replyMarkup, sendMessage.replyMarkup)
&& Objects.equals(replyToMessageId, sendMessage.replyToMessageId)
;
}
@Override
public int hashCode() {
return Objects.hash(
chatId,
disableNotification,
options,
replyMarkup,
replyToMessageId,
question);
}
@Override
public String toString() {
return "SendPoll{" +
"chatId='" + chatId + '\'' +
", question='" + question + '\'' +
", options=" + options +
", disableNotification=" + disableNotification +
", replyToMessageId=" + replyToMessageId +
", replyMarkup=" + replyMarkup +
'}';
}
}

View File

@ -0,0 +1,119 @@
package org.telegram.telegrambots.meta.api.methods.polls;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
import org.telegram.telegrambots.meta.api.objects.polls.Poll;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ApiResponse;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
import java.io.IOException;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Ruben Bermudez
* @version 1.0
* Use this method to stop a poll which was sent by the bot.
*
* On success, the stopped Poll with the final results is returned.
*/
public class StopPoll extends BotApiMethod<Poll> {
public static final String PATH = "stopPoll";
private static final String CHATID_FIELD = "chat_id";
private static final String MESSAGEID_FIELD = "message_id";
@JsonProperty(CHATID_FIELD)
private String chatId; ///< Unique identifier for the target chat or username of the target channel (in the format @channelusername)
@JsonProperty(MESSAGEID_FIELD)
private Integer messageId; ///< Identifier of the original message with the poll
public StopPoll() {
super();
}
public StopPoll(String chatId, Integer messageId) {
this.chatId = checkNotNull(chatId);
this.messageId = checkNotNull(messageId);
}
public StopPoll(Long chatId, Integer messageId) {
this.chatId = checkNotNull(chatId).toString();
this.messageId = checkNotNull(messageId);
}
public String getChatId() {
return chatId;
}
public StopPoll setChatId(String chatId) {
this.chatId = chatId;
return this;
}
public StopPoll setChatId(Long chatId) {
Objects.requireNonNull(chatId);
this.chatId = chatId.toString();
return this;
}
@Override
public String getMethod() {
return PATH;
}
@Override
public Poll deserializeResponse(String answer) throws TelegramApiRequestException {
try {
ApiResponse<Poll> result = OBJECT_MAPPER.readValue(answer,
new TypeReference<ApiResponse<Poll>>(){});
if (result.getOk()) {
return result.getResult();
} else {
throw new TelegramApiRequestException("Error stopping poll", result);
}
} catch (IOException e) {
throw new TelegramApiRequestException("Unable to deserialize response", e);
}
}
@Override
public void validate() throws TelegramApiValidationException {
if (chatId == null) {
throw new TelegramApiValidationException("ChatId parameter can't be empty", this);
}
if (messageId == null || messageId == 0) {
throw new TelegramApiValidationException("Message Id parameter can't be empty", this);
}
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof StopPoll)) {
return false;
}
StopPoll sendMessage = (StopPoll) o;
return Objects.equals(chatId, sendMessage.chatId)
&& Objects.equals(messageId, sendMessage.messageId)
;
}
@Override
public int hashCode() {
return Objects.hash(
chatId,
messageId);
}
@Override
public String toString() {
return "StopPoll{" +
"chatId='" + chatId + '\'' +
", messageId=" + messageId +
'}';
}
}

View File

@ -55,7 +55,7 @@ public class SendAnimation extends PartialBotApiMethod<Message> {
private String parseMode; ///< Optional. Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. private String parseMode; ///< Optional. Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
/** /**
* Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name> * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name>
* if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -50,7 +50,7 @@ public class SendAudio extends PartialBotApiMethod<Message> {
private String parseMode; ///< Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. private String parseMode; ///< Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
/** /**
* Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass
* attach://<file_attach_name> if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * attach://<file_attach_name> if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -40,7 +40,7 @@ public class SendDocument extends PartialBotApiMethod<Message> {
private String parseMode; ///< Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. private String parseMode; ///< Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
/** /**
* Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name> * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name>
* if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -49,7 +49,7 @@ public class SendVideo extends PartialBotApiMethod<Message> {
private String parseMode; ///< Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption. private String parseMode; ///< Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
/** /**
* Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name> * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name>
* if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -44,7 +44,7 @@ public class SendVideoNote extends PartialBotApiMethod<Message> {
private ReplyKeyboard replyMarkup; ///< Optional. JSON-serialized object for a custom reply keyboard private ReplyKeyboard replyMarkup; ///< Optional. JSON-serialized object for a custom reply keyboard
/** /**
* Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name> * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name>
* if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -16,12 +16,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* *
* Use this method to delete a message. A message can only be deleted if it was sent less than * Use this method to delete a message, including service messages, with the following limitations:
* 48 hours ago. Any sent outgoing message may be deleted. * - A message can only be deleted if it was sent less than 48 hours ago.
* Additionally, if the bot is an administrator in a group chat, it can delete any message. * - Bots can delete outgoing messages in private chats, groups, and supergroups.
* If the bot is an administrator of a supergroup or channel, * - Bots can delete incoming messages in private chats.
* it can delete ordinary messages from any other user, * - Bots granted can_post_messages permissions can delete outgoing messages in channels.
* including service messages about people added or removed from the chat. * - If the bot is an administrator of a group, it can delete any message there.
* - If the bot has can_delete_messages permission in a supergroup or a channel, it can delete any message there.
* Returns True on success.
*/ */
public class DeleteMessage extends BotApiMethod<Boolean> { public class DeleteMessage extends BotApiMethod<Boolean> {
public static final String PATH = "deleteMessage"; public static final String PATH = "deleteMessage";

View File

@ -16,8 +16,8 @@ import java.io.Serializable;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* Use this method to edit captions of messages sent by the bot or via the bot (for inline * Use this method to edit captions of messages.
* bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. * On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
*/ */
public class EditMessageCaption extends BotApiMethod<Serializable> { public class EditMessageCaption extends BotApiMethod<Serializable> {
public static final String PATH = "editmessagecaption"; public static final String PATH = "editmessagecaption";

View File

@ -17,7 +17,7 @@ import java.util.Objects;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* Use this method to edit live location messages sent by the bot or via the bot (for inline bots). * Use this method to edit live location.
* A location can be edited until its live_period expires or editing is explicitly disabled by a call to * A location can be edited until its live_period expires or editing is explicitly disabled by a call to
* stopMessageLiveLocation. On success, if the edited message was sent by the bot, the edited Message is returned, * stopMessageLiveLocation. On success, if the edited message was sent by the bot, the edited Message is returned,
* otherwise True is returned. * otherwise True is returned.

View File

@ -16,8 +16,8 @@ import java.io.Serializable;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* @brief Use this method to edit only the reply markup of messages sent by the bot or via the bot * @brief Use this method to edit only the reply markup of messages.
* (for inline bots). On success, if edited message is sent by the bot, the edited Message is returned, * On success, if edited message is sent by the bot, the edited Message is returned,
* therwise True is returned. * therwise True is returned.
* @date 10 of April of 2016 * @date 10 of April of 2016
*/ */

View File

@ -17,7 +17,7 @@ import java.io.Serializable;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* @brief Use this method to edit text messages sent by the bot or via the bot (for inline bots). On * @brief Use this method to edit text messages. On
* success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. * success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned.
* @date 10 of April of 2016 * @date 10 of April of 2016
*/ */

View File

@ -61,7 +61,7 @@ public class Chat implements BotApiObject {
@JsonProperty(INVITELINK_FIELD) @JsonProperty(INVITELINK_FIELD)
private String inviteLink; ///< Optional. Chat invite link, for supergroups and channel chats. Returned only in getChat. private String inviteLink; ///< Optional. Chat invite link, for supergroups and channel chats. Returned only in getChat.
@JsonProperty(PINNEDMESSAGE_FIELD) @JsonProperty(PINNEDMESSAGE_FIELD)
private Message pinnedMessage; ///< Optional. Pinned message, for supergroups. Returned only in getChat. private Message pinnedMessage; ///< Optional. Pinned message, for groups, supergroups and channels. Returned only in getChat.
@JsonProperty(STICKERSETNAME_FIELD) @JsonProperty(STICKERSETNAME_FIELD)
private String stickerSetName; ///< Optional. For supergroups, name of Group sticker set. Returned only in getChat. private String stickerSetName; ///< Optional. For supergroups, name of Group sticker set. Returned only in getChat.
@JsonProperty(CANSETSTICKERSET_FIELD) @JsonProperty(CANSETSTICKERSET_FIELD)

View File

@ -29,6 +29,7 @@ public class ChatMember implements BotApiObject {
private static final String CANSENDMEDIAMESSAGES_FIELD = "can_send_media_messages"; private static final String CANSENDMEDIAMESSAGES_FIELD = "can_send_media_messages";
private static final String CANSENDOTHERMESSAGES_FIELD = "can_send_other_messages"; private static final String CANSENDOTHERMESSAGES_FIELD = "can_send_other_messages";
private static final String CANADDWEBPAGEPREVIEWS_FIELD = "can_add_web_page_previews"; private static final String CANADDWEBPAGEPREVIEWS_FIELD = "can_add_web_page_previews";
private static final String ISMEMBER_FIELD = "is_member";
@JsonProperty(USER_FIELD) @JsonProperty(USER_FIELD)
private User user; ///< Information about the user private User user; ///< Information about the user
@ -51,7 +52,7 @@ public class ChatMember implements BotApiObject {
@JsonProperty(CANRESTRICTUSERS_FIELD) @JsonProperty(CANRESTRICTUSERS_FIELD)
private Boolean canRestrictUsers; ///< Optional. Administrators only. True, if the administrator can restrict, ban or unban chat members private Boolean canRestrictUsers; ///< Optional. Administrators only. True, if the administrator can restrict, ban or unban chat members
@JsonProperty(CANPINMESSAGES_FIELD) @JsonProperty(CANPINMESSAGES_FIELD)
private Boolean canPinMessages; ///< Optional. Administrators only. True, if the administrator can pin messages private Boolean canPinMessages; ///< Optional. Administrators only. True, if the administrator can pin messages, groups and supergroups only
@JsonProperty(CANPROMOTEMEMBERS_FIELD) @JsonProperty(CANPROMOTEMEMBERS_FIELD)
private Boolean canPromoteMembers; ///< Optional. Administrators only. True, if the administrator can add new administrators with a subset of his own privileges or demote administrators that it has promoted, directly or indirectly (promoted by administrators that were appointed by the bot) private Boolean canPromoteMembers; ///< Optional. Administrators only. True, if the administrator can add new administrators with a subset of his own privileges or demote administrators that it has promoted, directly or indirectly (promoted by administrators that were appointed by the bot)
@JsonProperty(CANSENDMESSAGES_FIELD) @JsonProperty(CANSENDMESSAGES_FIELD)
@ -62,6 +63,8 @@ public class ChatMember implements BotApiObject {
private Boolean canSendOtherMessages; ///< Optional. Restricted only. True, if the user can send animations, games, stickers and use inline bots, implies can_send_media_messages private Boolean canSendOtherMessages; ///< Optional. Restricted only. True, if the user can send animations, games, stickers and use inline bots, implies can_send_media_messages
@JsonProperty(CANADDWEBPAGEPREVIEWS_FIELD) @JsonProperty(CANADDWEBPAGEPREVIEWS_FIELD)
private Boolean canAddWebPagePreviews; ///< Optional. Restricted only. True, if user may add web page previews Э to his messages, implies can_send_messages private Boolean canAddWebPagePreviews; ///< Optional. Restricted only. True, if user may add web page previews Э to his messages, implies can_send_messages
@JsonProperty(ISMEMBER_FIELD)
private Boolean isMemberField; ///< True, if the user is a member of the chat at the moment of the request. For example, it can be false for the chat creator or for a restricted user.
public ChatMember() { public ChatMember() {
super(); super();

View File

@ -9,6 +9,7 @@ import org.telegram.telegrambots.meta.api.objects.payments.Invoice;
import org.telegram.telegrambots.meta.api.objects.payments.SuccessfulPayment; import org.telegram.telegrambots.meta.api.objects.payments.SuccessfulPayment;
import org.telegram.telegrambots.meta.api.objects.stickers.Sticker; import org.telegram.telegrambots.meta.api.objects.stickers.Sticker;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -61,6 +62,7 @@ public class Message implements BotApiObject {
private static final String MEDIAGROUPID_FIELD = "media_group_id"; private static final String MEDIAGROUPID_FIELD = "media_group_id";
private static final String CONNECTEDWEBSITE_FIELD = "connected_website"; private static final String CONNECTEDWEBSITE_FIELD = "connected_website";
private static final String PASSPORTDATA_FIELD = "passport_data"; private static final String PASSPORTDATA_FIELD = "passport_data";
private static final String FORWARDSENDERNAME_FIELD = "forward_sender_name";
@JsonProperty(MESSAGEID_FIELD) @JsonProperty(MESSAGEID_FIELD)
private Integer messageId; ///< Integer Unique message identifier private Integer messageId; ///< Integer Unique message identifier
@ -190,6 +192,8 @@ public class Message implements BotApiObject {
private String connectedWebsite; ///< Optional. The domain name of the website on which the user has logged in private String connectedWebsite; ///< Optional. The domain name of the website on which the user has logged in
@JsonProperty(PASSPORTDATA_FIELD) @JsonProperty(PASSPORTDATA_FIELD)
private PassportData passportData; ///< Optional. Telegram Passport data private PassportData passportData; ///< Optional. Telegram Passport data
@JsonProperty(FORWARDSENDERNAME_FIELD)
private String forwardSenderName; ///< Optional. Sender's name for messages forwarded from users who disallow adding a link to their account in forwarded messages.
public Message() { public Message() {
super(); super();
@ -282,7 +286,7 @@ public class Message implements BotApiObject {
} }
public List<User> getNewChatMembers() { public List<User> getNewChatMembers() {
return newChatMembers; return newChatMembers == null ? new ArrayList<>() : newChatMembers;
} }
public User getLeftChatMember() { public User getLeftChatMember() {
@ -381,6 +385,14 @@ public class Message implements BotApiObject {
return this.video != null; return this.video != null;
} }
public boolean hasAudio(){
return this.audio != null;
}
public boolean hasVoice(){
return this.voice != null;
}
public boolean isReply() { public boolean isReply() {
return this.replyToMessage != null; return this.replyToMessage != null;
} }
@ -469,6 +481,14 @@ public class Message implements BotApiObject {
return animation != null; return animation != null;
} }
public String getForwardSenderName() {
return forwardSenderName;
}
public void setForwardSenderName(String forwardSenderName) {
this.forwardSenderName = forwardSenderName;
}
@Override @Override
public String toString() { public String toString() {
return "Message{" + return "Message{" +

View File

@ -1,12 +1,12 @@
package org.telegram.telegrambots.meta.api.objects; package org.telegram.telegrambots.meta.api.objects;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject; import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
import org.telegram.telegrambots.meta.api.objects.inlinequery.ChosenInlineQuery; import org.telegram.telegrambots.meta.api.objects.inlinequery.ChosenInlineQuery;
import org.telegram.telegrambots.meta.api.objects.inlinequery.InlineQuery; import org.telegram.telegrambots.meta.api.objects.inlinequery.InlineQuery;
import org.telegram.telegrambots.meta.api.objects.payments.PreCheckoutQuery; import org.telegram.telegrambots.meta.api.objects.payments.PreCheckoutQuery;
import org.telegram.telegrambots.meta.api.objects.payments.ShippingQuery; import org.telegram.telegrambots.meta.api.objects.payments.ShippingQuery;
import org.telegram.telegrambots.meta.api.objects.polls.Poll;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
@ -27,6 +27,7 @@ public class Update implements BotApiObject {
private static final String EDITEDCHANNELPOST_FIELD = "edited_channel_post"; private static final String EDITEDCHANNELPOST_FIELD = "edited_channel_post";
private static final String SHIPPING_QUERY_FIELD = "shipping_query"; private static final String SHIPPING_QUERY_FIELD = "shipping_query";
private static final String PRE_CHECKOUT_QUERY_FIELD = "pre_checkout_query"; private static final String PRE_CHECKOUT_QUERY_FIELD = "pre_checkout_query";
private static final String POLL_FIELD = "poll";
@JsonProperty(UPDATEID_FIELD) @JsonProperty(UPDATEID_FIELD)
private Integer updateId; private Integer updateId;
@ -48,6 +49,8 @@ public class Update implements BotApiObject {
private ShippingQuery shippingQuery; ///< Optional. New incoming shipping query. Only for invoices with flexible price private ShippingQuery shippingQuery; ///< Optional. New incoming shipping query. Only for invoices with flexible price
@JsonProperty(PRE_CHECKOUT_QUERY_FIELD) @JsonProperty(PRE_CHECKOUT_QUERY_FIELD)
private PreCheckoutQuery preCheckoutQuery; ///< Optional. New incoming pre-checkout query. Contains full information about checkout private PreCheckoutQuery preCheckoutQuery; ///< Optional. New incoming pre-checkout query. Contains full information about checkout
@JsonProperty(POLL_FIELD)
private Poll poll; ///< Optional. New poll state. Bots receive only updates about polls, which are sent by the bot.
public Update() { public Update() {
super(); super();
@ -93,6 +96,10 @@ public class Update implements BotApiObject {
return preCheckoutQuery; return preCheckoutQuery;
} }
public Poll getPoll() {
return poll;
}
public boolean hasMessage() { public boolean hasMessage() {
return message != null; return message != null;
} }
@ -129,6 +136,10 @@ public class Update implements BotApiObject {
return preCheckoutQuery != null; return preCheckoutQuery != null;
} }
public boolean hasPoll() {
return poll != null;
}
@Override @Override
public String toString() { public String toString() {
return "Update{" + return "Update{" +

View File

@ -27,7 +27,7 @@ public class InputMediaAnimation extends InputMedia<InputMediaAnimation> {
private Integer duration; ///< Optional. Animation duration private Integer duration; ///< Optional. Animation duration
/** /**
* Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name> * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name>
* if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -27,7 +27,7 @@ public class InputMediaAudio extends InputMedia<InputMediaAudio> {
private String title; ///< Optional. Title of the audio private String title; ///< Optional. Title of the audio
/** /**
* Optional. Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Optional. Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name> * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name>
* if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -16,7 +16,7 @@ public class InputMediaDocument extends InputMedia<InputMediaDocument> {
/** /**
* Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name> * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name>
* if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -30,7 +30,7 @@ public class InputMediaVideo extends InputMedia<InputMediaVideo> {
private Boolean supportsStreaming; ///< Optional. Pass True, if the uploaded video is suitable for streaming private Boolean supportsStreaming; ///< Optional. Pass True, if the uploaded video is suitable for streaming
/** /**
* Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. * Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size.
* A thumbnails width and height should not exceed 90. * A thumbnails width and height should not exceed 320.
* Ignored if the file is not uploaded using multipart/form-data. * Ignored if the file is not uploaded using multipart/form-data.
* Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name> * Thumbnails cant be reused and can be only uploaded as a new file, so you can pass attach://<file_attach_name>
* if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. * if the thumbnail was uploaded using multipart/form-data under <file_attach_name>.

View File

@ -0,0 +1,73 @@
package org.telegram.telegrambots.meta.api.objects.polls;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
import java.util.List;
/**
* @author Ruben Bermudez
* @version 4.2
*
* This object contains information about a poll.
*/
public class Poll implements BotApiObject {
private static final String ID_FIELD = "id";
private static final String QUESTION_FIELD = "question";
private static final String OPTIONS_FIELD = "options";
private static final String ISCLOSED_FIELD = "is_closed";
@JsonProperty(ID_FIELD)
private String id; ///< Unique poll identifier
@JsonProperty(QUESTION_FIELD)
private String question; ///< Poll question, 1-255 characters
@JsonProperty(OPTIONS_FIELD)
private List<PollOption> options; ///< List of poll options
@JsonProperty(ISCLOSED_FIELD)
private Boolean isClosed; ///< True, if the poll is closed
public Poll() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public List<PollOption> getOptions() {
return options;
}
public void setOptions(List<PollOption> options) {
this.options = options;
}
public Boolean getClosed() {
return isClosed;
}
public void setClosed(Boolean closed) {
isClosed = closed;
}
@Override
public String toString() {
return "Poll{" +
"id='" + id + '\'' +
", question='" + question + '\'' +
", options=" + options +
", isClosed=" + isClosed +
'}';
}
}

View File

@ -0,0 +1,47 @@
package org.telegram.telegrambots.meta.api.objects.polls;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
/**
* @author Ruben Bermudez
* @version 4.2
*
* This object contains information about one answer option in a poll.
*/
public class PollOption implements BotApiObject {
private static final String TEXT_FIELD = "text";
private static final String VOTERCOUNT_FIELD = "voter_count";
@JsonProperty(TEXT_FIELD)
private String text; ///< Option text, 1-100 characters
@JsonProperty(VOTERCOUNT_FIELD)
private Integer voterCount; ///< Number of users that voted for this option
public PollOption() {
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Integer getVoterCount() {
return voterCount;
}
public void setVoterCount(Integer voterCount) {
this.voterCount = voterCount;
}
@Override
public String toString() {
return "PollOption{" +
"text='" + text + '\'' +
", voterCount=" + voterCount +
'}';
}
}

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-spring-boot-starter</artifactId> <artifactId>telegrambots-spring-boot-starter</artifactId>
<version>4.1.2</version> <version>4.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots Spring Boot Starter</name> <name>Telegram Bots Spring Boot Starter</name>
@ -67,7 +67,7 @@
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.1.2</version> <version>4.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots</name> <name>Telegram Bots</name>
@ -84,7 +84,7 @@
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-meta</artifactId> <artifactId>telegrambots-meta</artifactId>
<version>4.1.2</version> <version>4.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>

View File

@ -29,6 +29,7 @@ import java.nio.charset.StandardCharsets;
import java.security.InvalidParameterException; import java.security.InvalidParameterException;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.telegram.telegrambots.Constants.SOCKET_TIMEOUT; import static org.telegram.telegrambots.Constants.SOCKET_TIMEOUT;
@ -40,7 +41,7 @@ import static org.telegram.telegrambots.Constants.SOCKET_TIMEOUT;
public class DefaultBotSession implements BotSession { public class DefaultBotSession implements BotSession {
private static final String LOGTAG = "BOTSESSION"; private static final String LOGTAG = "BOTSESSION";
private volatile boolean running = false; private AtomicBoolean running = new AtomicBoolean(false);
private final ConcurrentLinkedDeque<Update> receivedUpdates = new ConcurrentLinkedDeque<>(); private final ConcurrentLinkedDeque<Update> receivedUpdates = new ConcurrentLinkedDeque<>();
private final ObjectMapper objectMapper = new ObjectMapper(); private final ObjectMapper objectMapper = new ObjectMapper();
@ -59,11 +60,11 @@ public class DefaultBotSession implements BotSession {
@Override @Override
public synchronized void start() { public synchronized void start() {
if (running) { if (running.get()) {
throw new IllegalStateException("Session already running"); throw new IllegalStateException("Session already running");
} }
running = true; running.set(true);
lastReceivedUpdate = 0; lastReceivedUpdate = 0;
@ -78,11 +79,11 @@ public class DefaultBotSession implements BotSession {
@Override @Override
public synchronized void stop() { public synchronized void stop() {
if (!running) { if (!running.get()) {
throw new IllegalStateException("Session already stopped"); throw new IllegalStateException("Session already stopped");
} }
running = false; running.set(false);
if (readerThread != null) { if (readerThread != null) {
readerThread.interrupt(); readerThread.interrupt();
@ -126,8 +127,8 @@ public class DefaultBotSession implements BotSession {
} }
@Override @Override
public synchronized boolean isRunning() { public boolean isRunning() {
return running; return running.get();
} }
private class ReaderThread extends Thread implements UpdatesReader { private class ReaderThread extends Thread implements UpdatesReader {
@ -178,9 +179,9 @@ public class DefaultBotSession implements BotSession {
@Override @Override
public void run() { public void run() {
setPriority(Thread.MIN_PRIORITY); setPriority(Thread.MIN_PRIORITY);
while (running) { while (running.get()) {
synchronized (lock) { synchronized (lock) {
if (running) { if (running.get()) {
try { try {
List<Update> updates = updatesSupplier.getUpdates(); List<Update> updates = updatesSupplier.getUpdates();
if (updates.isEmpty()) { if (updates.isEmpty()) {
@ -199,7 +200,7 @@ public class DefaultBotSession implements BotSession {
} }
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
if (!running) { if (!running.get()) {
receivedUpdates.clear(); receivedUpdates.clear();
} }
BotLogger.debug(LOGTAG, e); BotLogger.debug(LOGTAG, e);
@ -211,7 +212,7 @@ public class DefaultBotSession implements BotSession {
lock.wait(exponentialBackOff.nextBackOffMillis()); lock.wait(exponentialBackOff.nextBackOffMillis());
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
if (!running) { if (!running.get()) {
receivedUpdates.clear(); receivedUpdates.clear();
} }
BotLogger.debug(LOGTAG, e); BotLogger.debug(LOGTAG, e);
@ -290,7 +291,7 @@ public class DefaultBotSession implements BotSession {
@Override @Override
public void run() { public void run() {
setPriority(Thread.MIN_PRIORITY); setPriority(Thread.MIN_PRIORITY);
while (running) { while (running.get()) {
try { try {
List<Update> updates = getUpdateList(); List<Update> updates = getUpdateList();
if (updates.isEmpty()) { if (updates.isEmpty()) {