Merge pull request #640 from rubenlagus/dev

Dev
This commit is contained in:
Ruben Bermudez 2019-07-30 02:14:10 +01:00 committed by GitHub
commit f85409f852
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 2870 additions and 2423 deletions

View File

@ -1,11 +1,18 @@
language: java language: java
jdk: jdk:
- oraclejdk8 - oraclejdk11
install: mvn install -Dgpg.skip - oraclejdk-ea
script: mvn clean compile test - openjdk11
- openjdk-ea
install: mvn -q install -Dgpg.skip
script: mvn -q clean compile test
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)
notifications: notifications:
webhooks: 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=" 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 email: false
matrix:
allow_failures:
- jdk: openjdk-ea
- jdk: oraclejdk-ea

803
Bots.ipr

File diff suppressed because it is too large Load Diff

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.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
``` ```
```gradle ```gradle
compile "org.telegram:telegrambots:4.3.1" compile "org.telegram:telegrambots:4.4.0"
``` ```
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.3.1) 2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.4.0)
3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.3.1) 3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.4.0)
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,11 @@
### <a id="4.4.0"></a>4.4.0 ###
1. Update Api version [4.4](https://core.telegram.org/bots/api-changelog#july-29-2019)
2. Removed BotLogger, replaced with [log4j2](https://logging.apache.org/log4j/2.x/)
3. Library is now built using [Java11](https://www.oracle.com/technetwork/java/javase/overview/index.html)
4. Updated dependencies to use last versions
5. Files can be downloaded into a stream. Allowing it to be processed immediately.
6. A java.io.File can be passed into the methods. The downloaded file is copied into that file instead of a temp file then (does not work with the async methods)
### <a id="4.3.1"></a>4.3.1 ### ### <a id="4.3.1"></a>4.3.1 ###
1. Fix bug #625 1. Fix bug #625
2. Moved ApiResponse to different package, deprecated old one (will be removed in next mayor version) 2. Moved ApiResponse to different package, deprecated old one (will be removed in next mayor version)

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.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
``` ```
* With **Gradle**: * With **Gradle**:
```groovy ```groovy
compile group: 'org.telegram', name: 'telegrambots', version: '4.3.1' compile group: 'org.telegram', name: 'telegrambots', version: '4.4.0'
``` ```
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.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
``` ```
* **Gradle** * **Gradle**
```groovy ```groovy
compile group: 'org.telegram', name: 'telegrambots-abilities', version: '4.3.1' compile group: 'org.telegram', name: 'telegrambots-abilities', version: 'permissions'
``` ```
* [JitPack](https://jitpack.io/#rubenlagus/TelegramBots) * [JitPack](https://jitpack.io/#rubenlagus/TelegramBots)

86
pom.xml
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.3.1</version> <version>4.4.0</version>
<modules> <modules>
<module>telegrambots</module> <module>telegrambots</module>
@ -27,6 +27,90 @@
</licenses> </licenses>
<properties> <properties>
<java.version>11</java.version>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.deploy.skip>true</maven.deploy.skip> <maven.deploy.skip>true</maven.deploy.skip>
<junit.version>5.5.1</junit.version>
<mockito.version>3.0.0</mockito.version>
<mockitojupiter.version>3.0.0</mockitojupiter.version>
<jacksonbase.version>2.9.9</jacksonbase.version>
<jackson.version>2.9.9.1</jackson.version>
<log4j.version>2.12.0</log4j.version>
</properties> </properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jacksonbase.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>${jacksonbase.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockitojupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</project> </project>

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.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
``` ```
**Gradle** **Gradle**
```gradle ```gradle
compile "org.telegram:telegrambots-abilities:4.3.1" compile "org.telegram:telegrambots-abilities:4.4.0"
``` ```
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.3.1) **JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.4.0)
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.3.1) **Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.4.0)
Motivation Motivation
---------- ----------

View File

@ -3,9 +3,14 @@
xmlns="http://maven.apache.org/POM/4.0.0" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId>
<parent>
<groupId>org.telegram</groupId>
<artifactId>Bots</artifactId>
<version>4.4.0</version>
</parent>
<artifactId>telegrambots-abilities</artifactId> <artifactId>telegrambots-abilities</artifactId>
<version>4.3.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Ability Bot</name> <name>Telegram Ability Bot</name>
@ -63,17 +68,23 @@
</distributionManagement> </distributionManagement>
<properties> <properties>
<java.version>11</java.version>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<commonslang.version>3.5</commonslang.version>
<mapdb.version>3.0.4</mapdb.version> <commonslang.version>3.9</commonslang.version>
<mapdb.version>3.0.7</mapdb.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
@ -91,18 +102,6 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -112,10 +111,15 @@
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version> <version>1.6</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@ -129,7 +133,7 @@
<plugin> <plugin>
<groupId>org.sonatype.plugins</groupId> <groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId> <artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version> <version>1.6.8</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<serverId>ossrh</serverId> <serverId>ossrh</serverId>
@ -139,7 +143,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<id>clean-project</id> <id>clean-project</id>
@ -152,7 +156,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version> <version>3.1.1</version>
<configuration> <configuration>
<descriptorRefs> <descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <descriptorRef>jar-with-dependencies</descriptorRef>
@ -171,7 +175,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -183,14 +187,14 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
<configuration> <configuration>
<additionalparam>-Xdoclint:none</additionalparam> <doclint>none</doclint>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@ -198,7 +202,7 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version> <version>0.8.4</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -217,7 +221,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version> <version>3.0.0-M2</version>
<executions> <executions>
<execution> <execution>
<id>enforce-versions</id> <id>enforce-versions</id>
@ -235,7 +239,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version> <version>3.1.1</version>
<executions> <executions>
<execution> <execution>
<id>copy</id> <id>copy</id>
@ -249,9 +253,10 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration> <configuration>
<source>1.8</source> <source>${java.version}</source>
<target>1.8</target> <target>${java.version}</target>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
</plugin> </plugin>

View File

@ -11,7 +11,7 @@ import java.util.Set;
/** /**
* This interface represents the high-level methods exposed to the user when handling an {@link Update}. * This interface represents the high-level methods exposed to the user when handling an {@link Update}.
* Example usage: * Example usage:
* <p><code>Ability.builder().action(ctx -> {db.getSet(USERS); doSomething();})* </code></p> * <p><code>Ability.builder().action(ctx -> {db.getSet(USERS); doSomething();})</code></p>
* {@link BaseAbilityBot} contains a handle on the <code>db</code> that the user can use inside his declared abilities. * {@link BaseAbilityBot} contains a handle on the <code>db</code> that the user can use inside his declared abilities.
* *
* @author Abbas Abou Daya * @author Abbas Abou Daya

View File

@ -3,25 +3,29 @@ package org.telegram.abilitybots.api.db;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mapdb.Atomic; import org.mapdb.Atomic;
import org.mapdb.DB; import org.mapdb.DB;
import org.mapdb.DBMaker; import org.mapdb.DBMaker;
import org.mapdb.Serializer; import org.mapdb.Serializer;
import org.telegram.abilitybots.api.util.Pair; import org.telegram.abilitybots.api.util.Pair;
import org.telegram.telegrambots.meta.logging.BotLogger;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet; import static com.google.common.collect.Sets.newHashSet;
import static java.lang.String.format; import static java.lang.String.format;
import static java.util.Objects.isNull; import static java.util.Objects.isNull;
import static java.util.stream.Collectors.toMap; import static java.util.stream.Collectors.toMap;
import static java.util.stream.StreamSupport.stream; import static java.util.stream.StreamSupport.stream;
import static org.mapdb.Serializer.JAVA; import static org.mapdb.Serializer.JAVA;
import static org.telegram.abilitybots.api.bot.BaseAbilityBot.USERS;
/** /**
* An implementation of {@link DBContext} that relies on a {@link DB}. * An implementation of {@link DBContext} that relies on a {@link DB}.
@ -31,7 +35,7 @@ import static org.telegram.abilitybots.api.bot.BaseAbilityBot.USERS;
*/ */
@SuppressWarnings({"unchecked", "WeakerAccess"}) @SuppressWarnings({"unchecked", "WeakerAccess"})
public class MapDBContext implements DBContext { public class MapDBContext implements DBContext {
private static final String TAG = DBContext.class.getSimpleName(); private static final Logger log = LogManager.getLogger(MapDBContext.class);
private final DB db; private final DB db;
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
@ -71,7 +75,6 @@ public class MapDBContext implements DBContext {
.fileDB(name) .fileDB(name)
.fileMmapEnableIfSupported() .fileMmapEnableIfSupported()
.closeOnJvmShutdown() .closeOnJvmShutdown()
.cleanerHackEnable()
.transactionEnable() .transactionEnable()
.fileDeleteAfterClose() .fileDeleteAfterClose()
.make(); .make();
@ -123,7 +126,7 @@ public class MapDBContext implements DBContext {
doRecover(backupData); doRecover(backupData);
return true; return true;
} catch (IOException e) { } catch (IOException e) {
BotLogger.error(format("Could not recover DB data from file with String representation %s", backup), TAG, e); log.error(format("Could not recover DB data from file with String representation %s", backup), e);
// Attempt to fallback to data snapshot before recovery // Attempt to fallback to data snapshot before recovery
doRecover(snapshot); doRecover(snapshot);
return false; return false;
@ -204,7 +207,7 @@ public class MapDBContext implements DBContext {
List entryList = (List) value; List entryList = (List) value;
getList(name).addAll(entryList); getList(name).addAll(entryList);
} else { } else {
BotLogger.error(TAG, format("Unable to identify object type during DB recovery, entry name: %s", name)); log.error(format("Unable to identify object type during DB recovery, entry name: %s", name));
} }
}); });
commit(); commit();
@ -214,7 +217,7 @@ public class MapDBContext implements DBContext {
try { try {
return objectMapper.writeValueAsString(obj); return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
BotLogger.info(format("Failed to read the JSON representation of object: %s", obj), TAG, e); log.info(format("Failed to read the JSON representation of object: %s", obj), e);
return "Error reading required data..."; return "Error reading required data...";
} }
} }

View File

@ -2,8 +2,9 @@ package org.telegram.abilitybots.api.objects;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.logging.BotLogger;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -34,7 +35,7 @@ import static org.apache.commons.lang3.StringUtils.*;
* @author Abbas Abou Daya * @author Abbas Abou Daya
*/ */
public final class Ability { public final class Ability {
private static final String TAG = Ability.class.getSimpleName(); private static final Logger log = LogManager.getLogger(Ability.class);
private final String name; private final String name;
private final String info; private final String info;
@ -63,7 +64,7 @@ public final class Ability {
this.action = checkNotNull(action, "Method action can't be empty. Please assign a function by using .action() method"); this.action = checkNotNull(action, "Method action can't be empty. Please assign a function by using .action() method");
if (postAction == null) if (postAction == null)
BotLogger.info(TAG, format("No post action was detected for method with name [%s]", name)); log.info(format("No post action was detected for method with name [%s]", name));
this.flags = ofNullable(flags).map(Arrays::asList).orElse(newArrayList()); this.flags = ofNullable(flags).map(Arrays::asList).orElse(newArrayList());

View File

@ -1,11 +1,12 @@
package org.telegram.abilitybots.api.sender; package org.telegram.abilitybots.api.sender;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.telegram.telegrambots.meta.api.methods.BotApiMethod; import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.objects.Message; import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ForceReplyKeyboard; import org.telegram.telegrambots.meta.api.objects.replykeyboard.ForceReplyKeyboard;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.logging.BotLogger;
import java.io.Serializable; import java.io.Serializable;
import java.util.Optional; import java.util.Optional;
@ -17,7 +18,7 @@ import java.util.Optional;
* @author Abbas Abou Daya * @author Abbas Abou Daya
*/ */
public class SilentSender { public class SilentSender {
private static final String TAG = SilentSender.class.getSimpleName(); private static final Logger log = LogManager.getLogger(SilentSender.class);
private final MessageSender sender; private final MessageSender sender;
@ -46,7 +47,7 @@ public class SilentSender {
try { try {
return Optional.ofNullable(sender.execute(method)); return Optional.ofNullable(sender.execute(method));
} catch (TelegramApiException e) { } catch (TelegramApiException e) {
BotLogger.error("Could not execute bot API method", TAG, e); log.error("Could not execute bot API method", e);
return Optional.empty(); return Optional.empty();
} }
} }
@ -55,7 +56,7 @@ public class SilentSender {
try { try {
return Optional.ofNullable(sender.execute(method)); return Optional.ofNullable(sender.execute(method));
} catch (TelegramApiException e) { } catch (TelegramApiException e) {
BotLogger.error("Could not execute bot API method", TAG, e); log.error("Could not execute bot API method", e);
return Optional.empty(); return Optional.empty();
} }
} }

View File

@ -1,8 +1,8 @@
package org.telegram.abilitybots.api.bot; package org.telegram.abilitybots.api.bot;
import org.junit.After; import org.junit.jupiter.api.AfterEach;
import org.junit.Before; import org.junit.jupiter.api.BeforeEach;
import org.junit.Test; import org.junit.jupiter.api.Test;
import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.db.DBContext;
import org.telegram.abilitybots.api.objects.MessageContext; import org.telegram.abilitybots.api.objects.MessageContext;
import org.telegram.abilitybots.api.sender.MessageSender; import org.telegram.abilitybots.api.sender.MessageSender;
@ -18,7 +18,7 @@ import static org.mockito.internal.verification.VerificationModeFactory.times;
import static org.telegram.abilitybots.api.bot.AbilityBotTest.mockContext; import static org.telegram.abilitybots.api.bot.AbilityBotTest.mockContext;
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
public class AbilityBotI18nTest { class AbilityBotI18nTest {
private static final User NO_LANGUAGE_USER = new User(1, "first", false, "last", "username", null); private static final User NO_LANGUAGE_USER = new User(1, "first", false, "last", "username", null);
private static final User ITALIAN_USER = new User(2, "first", false, "last", "username", "it-IT"); private static final User ITALIAN_USER = new User(2, "first", false, "last", "username", "it-IT");
@ -28,8 +28,8 @@ public class AbilityBotI18nTest {
private MessageSender sender; private MessageSender sender;
private SilentSender silent; private SilentSender silent;
@Before @BeforeEach
public void setUp() { void setUp() {
db = offlineInstance("db"); db = offlineInstance("db");
bot = new NoPublicCommandsBot(EMPTY, EMPTY, db); bot = new NoPublicCommandsBot(EMPTY, EMPTY, db);
@ -38,11 +38,16 @@ public class AbilityBotI18nTest {
bot.sender = sender; bot.sender = sender;
bot.silent = silent; bot.silent = silent;
}
@AfterEach
void tearDown() throws IOException {
db.clear();
db.close();
} }
@Test @Test
public void missingPublicCommandsLocalizedInEnglishByDefault() { void missingPublicCommandsLocalizedInEnglishByDefault() {
MessageContext context = mockContext(NO_LANGUAGE_USER); MessageContext context = mockContext(NO_LANGUAGE_USER);
bot.reportCommands().action().accept(context); bot.reportCommands().action().accept(context);
@ -52,7 +57,7 @@ public class AbilityBotI18nTest {
} }
@Test @Test
public void missingPublicCommandsLocalizedInItalian() { void missingPublicCommandsLocalizedInItalian() {
MessageContext context = mockContext(ITALIAN_USER); MessageContext context = mockContext(ITALIAN_USER);
bot.reportCommands().action().accept(context); bot.reportCommands().action().accept(context);
@ -61,15 +66,9 @@ public class AbilityBotI18nTest {
.send("Non sono presenti comandi disponibile.", ITALIAN_USER.getId()); .send("Non sono presenti comandi disponibile.", ITALIAN_USER.getId());
} }
@After
public void tearDown() throws IOException {
db.clear();
db.close();
}
public static class NoPublicCommandsBot extends AbilityBot { public static class NoPublicCommandsBot extends AbilityBot {
protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { NoPublicCommandsBot(String botToken, String botUsername, DBContext db) {
super(botToken, botUsername, db); super(botToken, botUsername, db);
} }

View File

@ -3,9 +3,11 @@ package org.telegram.abilitybots.api.bot;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.io.Files; import com.google.common.io.Files;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.junit.After; import org.junit.jupiter.api.AfterEach;
import org.junit.Before; import org.junit.jupiter.api.Assertions;
import org.junit.Test; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.db.DBContext;
import org.telegram.abilitybots.api.objects.*; import org.telegram.abilitybots.api.objects.*;
import org.telegram.abilitybots.api.sender.MessageSender; import org.telegram.abilitybots.api.sender.MessageSender;
@ -13,7 +15,12 @@ import org.telegram.abilitybots.api.sender.SilentSender;
import org.telegram.abilitybots.api.util.Pair; import org.telegram.abilitybots.api.util.Pair;
import org.telegram.abilitybots.api.util.Trio; import org.telegram.abilitybots.api.util.Trio;
import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators; import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators;
import org.telegram.telegrambots.meta.api.objects.*; import org.telegram.telegrambots.meta.api.objects.ChatMember;
import org.telegram.telegrambots.meta.api.objects.Document;
import org.telegram.telegrambots.meta.api.objects.File;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.api.objects.User;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -32,9 +39,13 @@ import static java.util.Optional.empty;
import static org.apache.commons.io.FileUtils.deleteQuietly; import static org.apache.commons.io.FileUtils.deleteQuietly;
import static org.apache.commons.lang3.ArrayUtils.addAll; import static org.apache.commons.lang3.ArrayUtils.addAll;
import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.junit.Assert.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Matchers.any; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.mockito.internal.verification.VerificationModeFactory.times;
import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder; import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder;
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
@ -62,8 +73,8 @@ public class AbilityBotTest {
private MessageSender sender; private MessageSender sender;
private SilentSender silent; private SilentSender silent;
@Before @BeforeEach
public void setUp() { void setUp() {
db = offlineInstance("db"); db = offlineInstance("db");
bot = new DefaultBot(EMPTY, EMPTY, db); bot = new DefaultBot(EMPTY, EMPTY, db);
@ -74,8 +85,14 @@ public class AbilityBotTest {
bot.silent = silent; bot.silent = silent;
} }
@AfterEach
void tearDown() throws IOException {
db.clear();
db.close();
}
@Test @Test
public void sendsPrivacyViolation() { void sendsPrivacyViolation() {
Update update = mockFullUpdate(USER, "/admin"); Update update = mockFullUpdate(USER, "/admin");
bot.onUpdateReceived(update); bot.onUpdateReceived(update);
@ -84,7 +101,7 @@ public class AbilityBotTest {
} }
@Test @Test
public void sendsLocalityViolation() { void sendsLocalityViolation() {
Update update = mockFullUpdate(USER, "/group"); Update update = mockFullUpdate(USER, "/group");
bot.onUpdateReceived(update); bot.onUpdateReceived(update);
@ -94,7 +111,7 @@ public class AbilityBotTest {
} }
@Test @Test
public void sendsInputArgsViolation() { void sendsInputArgsViolation() {
Update update = mockFullUpdate(USER, "/count 1 2 3"); Update update = mockFullUpdate(USER, "/count 1 2 3");
bot.onUpdateReceived(update); bot.onUpdateReceived(update);
@ -103,7 +120,7 @@ public class AbilityBotTest {
} }
@Test @Test
public void canProcessRepliesIfSatisfyRequirements() { void canProcessRepliesIfSatisfyRequirements() {
Update update = mockFullUpdate(USER, "must reply"); Update update = mockFullUpdate(USER, "must reply");
// False means the update was not pushed down the stream since it has been consumed by the reply // False means the update was not pushed down the stream since it has been consumed by the reply
@ -112,7 +129,7 @@ public class AbilityBotTest {
} }
@Test @Test
public void canBackupDB() throws TelegramApiException { void canBackupDB() throws TelegramApiException {
MessageContext context = defaultContext(); MessageContext context = defaultContext();
bot.backupDB().action().accept(context); bot.backupDB().action().accept(context);
@ -122,21 +139,23 @@ public class AbilityBotTest {
} }
@Test @Test
public void canRecoverDB() throws TelegramApiException, IOException { void canRecoverDB() throws TelegramApiException, IOException {
Update update = mockBackupUpdate(); Update update = mockBackupUpdate();
Object backup = getDbBackup(); Object backup = getDbBackup();
java.io.File backupFile = createBackupFile(backup); java.io.File backupFile = createBackupFile(backup);
when(sender.downloadFile(any(File.class))).thenReturn(backupFile); // Support for null parameter matching since due to mocking API changes
when(sender.downloadFile(ArgumentMatchers.<File>isNull())).thenReturn(backupFile);
bot.recoverDB().replies().get(0).actOn(update); bot.recoverDB().replies().get(0).actOn(update);
verify(silent, times(1)).send(RECOVER_SUCCESS, GROUP_ID); verify(silent, times(1)).send(RECOVER_SUCCESS, GROUP_ID);
assertEquals("Bot recovered but the DB is still not in sync", db.getSet(TEST), newHashSet(TEST)); assertEquals(db.getSet(TEST), newHashSet(TEST), "Bot recovered but the DB is still not in sync");
assertTrue("Could not delete backup file", backupFile.delete()); assertTrue(backupFile.delete(), "Could not delete backup file");
} }
@Test @Test
public void canFilterOutReplies() { void canFilterOutReplies() {
Update update = mock(Update.class); Update update = mock(Update.class);
when(update.hasMessage()).thenReturn(false); when(update.hasMessage()).thenReturn(false);
@ -144,7 +163,7 @@ public class AbilityBotTest {
} }
@Test @Test
public void canDemote() { void canDemote() {
addUsers(USER); addUsers(USER);
bot.admins().add(USER.getId()); bot.admins().add(USER.getId());
@ -154,11 +173,11 @@ public class AbilityBotTest {
Set<Integer> actual = bot.admins(); Set<Integer> actual = bot.admins();
Set<Integer> expected = emptySet(); Set<Integer> expected = emptySet();
assertEquals("Could not sudont super-admin", expected, actual); assertEquals(expected, actual, "Could not sudont super-admin");
} }
@Test @Test
public void canPromote() { void canPromote() {
addUsers(USER); addUsers(USER);
MessageContext context = defaultContext(); MessageContext context = defaultContext();
@ -167,11 +186,11 @@ public class AbilityBotTest {
Set<Integer> actual = bot.admins(); Set<Integer> actual = bot.admins();
Set<Integer> expected = newHashSet(USER.getId()); Set<Integer> expected = newHashSet(USER.getId());
assertEquals("Could not sudo user", expected, actual); assertEquals(expected, actual, "Could not sudo user");
} }
@Test @Test
public void canBanUser() { void canBanUser() {
addUsers(USER); addUsers(USER);
MessageContext context = defaultContext(); MessageContext context = defaultContext();
@ -179,11 +198,11 @@ public class AbilityBotTest {
Set<Integer> actual = bot.blacklist(); Set<Integer> actual = bot.blacklist();
Set<Integer> expected = newHashSet(USER.getId()); Set<Integer> expected = newHashSet(USER.getId());
assertEquals("The ban was not emplaced", expected, actual); assertEquals(expected, actual, "The ban was not emplaced");
} }
@Test @Test
public void canUnbanUser() { void canUnbanUser() {
addUsers(USER); addUsers(USER);
bot.blacklist().add(USER.getId()); bot.blacklist().add(USER.getId());
@ -193,7 +212,7 @@ public class AbilityBotTest {
Set<Integer> actual = bot.blacklist(); Set<Integer> actual = bot.blacklist();
Set<Integer> expected = newHashSet(); Set<Integer> expected = newHashSet();
assertEquals("The ban was not lifted", expected, actual); assertEquals(expected, actual, "The ban was not lifted");
} }
@NotNull @NotNull
@ -202,7 +221,7 @@ public class AbilityBotTest {
} }
@Test @Test
public void cannotBanCreator() { void cannotBanCreator() {
addUsers(USER, CREATOR); addUsers(USER, CREATOR);
MessageContext context = mockContext(USER, GROUP_ID, CREATOR.getUserName()); MessageContext context = mockContext(USER, GROUP_ID, CREATOR.getUserName());
@ -210,7 +229,7 @@ public class AbilityBotTest {
Set<Integer> actual = bot.blacklist(); Set<Integer> actual = bot.blacklist();
Set<Integer> expected = newHashSet(USER.getId()); Set<Integer> expected = newHashSet(USER.getId());
assertEquals("Impostor was not added to the blacklist", expected, actual); assertEquals(expected, actual, "Impostor was not added to the blacklist");
} }
private void addUsers(User... users) { private void addUsers(User... users) {
@ -221,18 +240,18 @@ public class AbilityBotTest {
} }
@Test @Test
public void creatorCanClaimBot() { void creatorCanClaimBot() {
MessageContext context = mockContext(CREATOR, GROUP_ID); MessageContext context = mockContext(CREATOR, GROUP_ID);
bot.claimCreator().action().accept(context); bot.claimCreator().action().accept(context);
Set<Integer> actual = bot.admins(); Set<Integer> actual = bot.admins();
Set<Integer> expected = newHashSet(CREATOR.getId()); Set<Integer> expected = newHashSet(CREATOR.getId());
assertEquals("Creator was not properly added to the super admins set", expected, actual); assertEquals(expected, actual, "Creator was not properly added to the super admins set");
} }
@Test @Test
public void bannedCreatorPassesBlacklistCheck() { void bannedCreatorPassesBlacklistCheck() {
bot.blacklist().add(CREATOR.getId()); bot.blacklist().add(CREATOR.getId());
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -241,11 +260,11 @@ public class AbilityBotTest {
mockUser(update, message, user); mockUser(update, message, user);
boolean notBanned = bot.checkBlacklist(update); boolean notBanned = bot.checkBlacklist(update);
assertTrue("Creator is banned", notBanned); assertTrue(notBanned, "Creator is banned");
} }
@Test @Test
public void canAddUser() { void canAddUser() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -255,12 +274,12 @@ public class AbilityBotTest {
Map<String, Integer> expectedUserIds = ImmutableMap.of(USER.getUserName(), USER.getId()); Map<String, Integer> expectedUserIds = ImmutableMap.of(USER.getUserName(), USER.getId());
Map<Integer, User> expectedUsers = ImmutableMap.of(USER.getId(), USER); Map<Integer, User> expectedUsers = ImmutableMap.of(USER.getId(), USER);
assertEquals("User was not added", expectedUserIds, bot.userIds()); assertEquals(expectedUserIds, bot.userIds(), "User was not added");
assertEquals("User was not added", expectedUsers, bot.users()); assertEquals(expectedUsers, bot.users(), "User was not added");
} }
@Test @Test
public void canEditUser() { void canEditUser() {
addUsers(USER); addUsers(USER);
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -277,22 +296,22 @@ public class AbilityBotTest {
Map<String, Integer> expectedUserIds = ImmutableMap.of(changedUser.getUserName(), changedUser.getId()); Map<String, Integer> expectedUserIds = ImmutableMap.of(changedUser.getUserName(), changedUser.getId());
Map<Integer, User> expectedUsers = ImmutableMap.of(changedUser.getId(), changedUser); Map<Integer, User> expectedUsers = ImmutableMap.of(changedUser.getId(), changedUser);
assertEquals("User was not properly edited", bot.userIds(), expectedUserIds); assertEquals(bot.userIds(), expectedUserIds, "User was not properly edited");
assertEquals("User was not properly edited", expectedUsers, expectedUsers); assertEquals(expectedUsers, expectedUsers, "User was not properly edited");
} }
@Test @Test
public void canValidateAbility() { void canValidateAbility() {
Trio<Update, Ability, String[]> invalidPair = Trio.of(null, null, null); Trio<Update, Ability, String[]> invalidPair = Trio.of(null, null, null);
Ability validAbility = getDefaultBuilder().build(); Ability validAbility = getDefaultBuilder().build();
Trio<Update, Ability, String[]> validPair = Trio.of(null, validAbility, null); Trio<Update, Ability, String[]> validPair = Trio.of(null, validAbility, null);
assertFalse("Bot can't validate ability properly", bot.validateAbility(invalidPair)); assertFalse(bot.validateAbility(invalidPair), "Bot can't validate ability properly");
assertTrue("Bot can't validate ability properly", bot.validateAbility(validPair)); assertTrue(bot.validateAbility(validPair), "Bot can't validate ability properly");
} }
@Test @Test
public void canCheckInput() { void canCheckInput() {
Update update = mockFullUpdate(USER, "/something"); Update update = mockFullUpdate(USER, "/something");
Ability abilityWithOneInput = getDefaultBuilder() Ability abilityWithOneInput = getDefaultBuilder()
.build(); .build();
@ -303,19 +322,19 @@ public class AbilityBotTest {
Trio<Update, Ability, String[]> trioOneArg = Trio.of(update, abilityWithOneInput, TEXT); Trio<Update, Ability, String[]> trioOneArg = Trio.of(update, abilityWithOneInput, TEXT);
Trio<Update, Ability, String[]> trioZeroArg = Trio.of(update, abilityWithZeroInput, TEXT); Trio<Update, Ability, String[]> trioZeroArg = Trio.of(update, abilityWithZeroInput, TEXT);
assertTrue("Unexpected result when applying token filter", bot.checkInput(trioOneArg)); assertTrue(bot.checkInput(trioOneArg), "Unexpected result when applying token filter");
trioOneArg = Trio.of(update, abilityWithOneInput, addAll(TEXT, TEXT)); trioOneArg = Trio.of(update, abilityWithOneInput, addAll(TEXT, TEXT));
assertFalse("Unexpected result when applying token filter", bot.checkInput(trioOneArg)); assertFalse(bot.checkInput(trioOneArg), "Unexpected result when applying token filter");
assertTrue("Unexpected result when applying token filter", bot.checkInput(trioZeroArg)); assertTrue(bot.checkInput(trioZeroArg), "Unexpected result when applying token filter");
trioZeroArg = Trio.of(update, abilityWithZeroInput, EMPTY_ARRAY); trioZeroArg = Trio.of(update, abilityWithZeroInput, EMPTY_ARRAY);
assertTrue("Unexpected result when applying token filter", bot.checkInput(trioZeroArg)); assertTrue(bot.checkInput(trioZeroArg), "Unexpected result when applying token filter");
} }
@Test @Test
public void canCheckPrivacy() { void canCheckPrivacy() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
User user = mock(User.class); User user = mock(User.class);
@ -331,14 +350,14 @@ public class AbilityBotTest {
mockUser(update, message, user); mockUser(update, message, user);
assertTrue("Unexpected result when checking for privacy", bot.checkPrivacy(publicTrio)); assertTrue(bot.checkPrivacy(publicTrio), "Unexpected result when checking for privacy");
assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(groupAdminTrio)); assertFalse(bot.checkPrivacy(groupAdminTrio), "Unexpected result when checking for privacy");
assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(adminTrio)); assertFalse(bot.checkPrivacy(adminTrio), "Unexpected result when checking for privacy");
assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(creatorTrio)); assertFalse(bot.checkPrivacy(creatorTrio), "Unexpected result when checking for privacy");
} }
@Test @Test
public void canValidateGroupAdminPrivacy() { void canValidateGroupAdminPrivacy() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
User user = mock(User.class); User user = mock(User.class);
@ -355,11 +374,11 @@ public class AbilityBotTest {
when(silent.execute(any(GetChatAdministrators.class))).thenReturn(Optional.of(newArrayList(member))); when(silent.execute(any(GetChatAdministrators.class))).thenReturn(Optional.of(newArrayList(member)));
assertTrue("Unexpected result when checking for privacy", bot.checkPrivacy(groupAdminTrio)); assertTrue(bot.checkPrivacy(groupAdminTrio), "Unexpected result when checking for privacy");
} }
@Test @Test
public void canRestrictNormalUsersFromGroupAdminAbilities() { void canRestrictNormalUsersFromGroupAdminAbilities() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
User user = mock(User.class); User user = mock(User.class);
@ -372,11 +391,11 @@ public class AbilityBotTest {
when(silent.execute(any(GetChatAdministrators.class))).thenReturn(empty()); when(silent.execute(any(GetChatAdministrators.class))).thenReturn(empty());
assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(groupAdminTrio)); assertFalse(bot.checkPrivacy(groupAdminTrio), "Unexpected result when checking for privacy");
} }
@Test @Test
public void canBlockAdminsFromCreatorAbilities() { void canBlockAdminsFromCreatorAbilities() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
User user = mock(User.class); User user = mock(User.class);
@ -387,11 +406,11 @@ public class AbilityBotTest {
bot.admins().add(USER.getId()); bot.admins().add(USER.getId());
mockUser(update, message, user); mockUser(update, message, user);
assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(creatorTrio)); assertFalse(bot.checkPrivacy(creatorTrio), "Unexpected result when checking for privacy");
} }
@Test @Test
public void canCheckLocality() { void canCheckLocality() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
User user = mock(User.class); User user = mock(User.class);
@ -406,13 +425,13 @@ public class AbilityBotTest {
mockUser(update, message, user); mockUser(update, message, user);
when(message.isUserMessage()).thenReturn(true); when(message.isUserMessage()).thenReturn(true);
assertTrue("Unexpected result when checking for locality", bot.checkLocality(publicTrio)); assertTrue(bot.checkLocality(publicTrio), "Unexpected result when checking for locality");
assertTrue("Unexpected result when checking for locality", bot.checkLocality(userTrio)); assertTrue(bot.checkLocality(userTrio), "Unexpected result when checking for locality");
assertFalse("Unexpected result when checking for locality", bot.checkLocality(groupTrio)); assertFalse(bot.checkLocality(groupTrio), "Unexpected result when checking for locality");
} }
@Test @Test
public void canRetrieveContext() { void canRetrieveContext() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
Ability ability = getDefaultBuilder().build(); Ability ability = getDefaultBuilder().build();
@ -424,17 +443,17 @@ public class AbilityBotTest {
Pair<MessageContext, Ability> actualPair = bot.getContext(trio); Pair<MessageContext, Ability> actualPair = bot.getContext(trio);
Pair<MessageContext, Ability> expectedPair = Pair.of(newContext(update, USER, GROUP_ID, TEXT), ability); Pair<MessageContext, Ability> expectedPair = Pair.of(newContext(update, USER, GROUP_ID, TEXT), ability);
assertEquals("Unexpected result when fetching for context", expectedPair, actualPair); assertEquals(expectedPair, actualPair, "Unexpected result when fetching for context");
} }
@Test @Test
public void defaultGlobalFlagIsTrue() { void defaultGlobalFlagIsTrue() {
Update update = mock(Update.class); Update update = mock(Update.class);
assertTrue("Unexpected result when checking for the default global flags", bot.checkGlobalFlags(update)); assertTrue(bot.checkGlobalFlags(update), "Unexpected result when checking for the default global flags");
} }
@Test(expected = ArithmeticException.class) @Test
public void canConsumeUpdate() { void canConsumeUpdate() {
Ability ability = getDefaultBuilder() Ability ability = getDefaultBuilder()
.action((context) -> { .action((context) -> {
int x = 1 / 0; int x = 1 / 0;
@ -443,11 +462,11 @@ public class AbilityBotTest {
Pair<MessageContext, Ability> pair = Pair.of(context, ability); Pair<MessageContext, Ability> pair = Pair.of(context, ability);
bot.consumeUpdate(pair); Assertions.assertThrows(ArithmeticException.class, () -> bot.consumeUpdate(pair));
} }
@Test @Test
public void canFetchAbility() { void canFetchAbility() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -462,11 +481,11 @@ public class AbilityBotTest {
Ability expected = bot.testAbility(); Ability expected = bot.testAbility();
Ability actual = trio.b(); Ability actual = trio.b();
assertEquals("Wrong ability was fetched", expected, actual); assertEquals(expected, actual, "Wrong ability was fetched");
} }
@Test @Test
public void canFetchAbilityCaseInsensitive() { void canFetchAbilityCaseInsensitive() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -481,11 +500,11 @@ public class AbilityBotTest {
Ability expected = bot.testAbility(); Ability expected = bot.testAbility();
Ability actual = trio.b(); Ability actual = trio.b();
assertEquals("Wrong ability was fetched", expected, actual); assertEquals(expected, actual, "Wrong ability was fetched");
} }
@Test @Test
public void canFetchDefaultAbility() { void canFetchDefaultAbility() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -498,11 +517,11 @@ public class AbilityBotTest {
Ability expected = bot.defaultAbility(); Ability expected = bot.defaultAbility();
Ability actual = trio.b(); Ability actual = trio.b();
assertEquals("Wrong ability was fetched", expected, actual); assertEquals(expected, actual, "Wrong ability was fetched");
} }
@Test @Test
public void canCheckAbilityFlags() { void canCheckAbilityFlags() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -517,12 +536,12 @@ public class AbilityBotTest {
Trio<Update, Ability, String[]> docTrio = Trio.of(update, documentAbility, TEXT); Trio<Update, Ability, String[]> docTrio = Trio.of(update, documentAbility, TEXT);
Trio<Update, Ability, String[]> textTrio = Trio.of(update, textAbility, TEXT); Trio<Update, Ability, String[]> textTrio = Trio.of(update, textAbility, TEXT);
assertFalse("Unexpected result when checking for message flags", bot.checkMessageFlags(docTrio)); assertFalse(bot.checkMessageFlags(docTrio), "Unexpected result when checking for message flags");
assertTrue("Unexpected result when checking for message flags", bot.checkMessageFlags(textTrio)); assertTrue(bot.checkMessageFlags(textTrio), "Unexpected result when checking for message flags");
} }
@Test @Test
public void canReportCommands() { void canReportCommands() {
MessageContext context = mockContext(USER, GROUP_ID); MessageContext context = mockContext(USER, GROUP_ID);
bot.reportCommands().action().accept(context); bot.reportCommands().action().accept(context);
@ -531,12 +550,12 @@ public class AbilityBotTest {
} }
@NotNull @NotNull
public static MessageContext mockContext(User user) { static MessageContext mockContext(User user) {
return mockContext(user, user.getId()); return mockContext(user, user.getId());
} }
@NotNull @NotNull
public static MessageContext mockContext(User user, long groupId, String... args) { static MessageContext mockContext(User user, long groupId, String... args) {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -550,7 +569,7 @@ public class AbilityBotTest {
} }
@Test @Test
public void canPrintCommandsBasedOnPrivacy() { void canPrintCommandsBasedOnPrivacy() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -566,7 +585,7 @@ public class AbilityBotTest {
} }
@Test @Test
public void printsOnlyPublicCommandsForNormalUser() { void printsOnlyPublicCommandsForNormalUser() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
@ -582,12 +601,6 @@ public class AbilityBotTest {
verify(silent, times(1)).send(expected, GROUP_ID); verify(silent, times(1)).send(expected, GROUP_ID);
} }
@After
public void tearDown() throws IOException {
db.clear();
db.close();
}
@NotNull @NotNull
private Update mockFullUpdate(User user, String args) { private Update mockFullUpdate(User user, String args) {
bot.users().put(USER.getId(), USER); bot.users().put(USER.getId(), USER);

View File

@ -1,45 +1,45 @@
package org.telegram.abilitybots.api.bot; package org.telegram.abilitybots.api.bot;
import org.junit.After; import org.junit.jupiter.api.AfterEach;
import org.junit.Before; import org.junit.jupiter.api.BeforeEach;
import org.junit.Test; import org.junit.jupiter.api.Test;
import org.telegram.abilitybots.api.objects.Ability; import org.telegram.abilitybots.api.objects.Ability;
import org.telegram.abilitybots.api.util.AbilityExtension; import org.telegram.abilitybots.api.util.AbilityExtension;
import java.io.IOException; import java.io.IOException;
import static junit.framework.TestCase.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
import static org.telegram.abilitybots.api.objects.Locality.ALL; import static org.telegram.abilitybots.api.objects.Locality.ALL;
import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC; import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC;
public class ExtensionTest { class ExtensionTest {
private ExtensionUsingBot bot; private ExtensionUsingBot bot;
@Before @BeforeEach
public void setUp() { void setUp() {
bot = new ExtensionUsingBot(); bot = new ExtensionUsingBot();
} }
@Test @AfterEach
public void methodReturningAbilities() { void tearDown() throws IOException {
assertTrue("Failed to find Ability in directly declared in root extension/bot", hasAbilityNamed("direct"));
assertTrue("Failed to find Ability in directly declared in extension returned by method returning the AbilityExtension class", hasAbilityNamed("returningSuperClass0abc"));
assertTrue("Failed to find Ability in directly declared in extension returned by method returning the AbilityExtension subclass", hasAbilityNamed("returningSubClass0abc"));
}
@After
public void tearDown() throws IOException {
bot.db.clear(); bot.db.clear();
bot.db.close(); bot.db.close();
} }
@Test
void methodReturningAbilities() {
assertTrue(hasAbilityNamed("direct"), "Failed to find Ability in directly declared in root extension/bot");
assertTrue(hasAbilityNamed("returningSuperClass0abc"), "Failed to find Ability in directly declared in extension returned by method returning the AbilityExtension class");
assertTrue(hasAbilityNamed("returningSubClass0abc"), "Failed to find Ability in directly declared in extension returned by method returning the AbilityExtension subclass");
}
private boolean hasAbilityNamed(String name) { private boolean hasAbilityNamed(String name) {
return bot.abilities().values().stream().map(Ability::name).anyMatch(name::equals); return bot.abilities().values().stream().map(Ability::name).anyMatch(name::equals);
} }
public static class ExtensionUsingBot extends AbilityBot { public static class ExtensionUsingBot extends AbilityBot {
public ExtensionUsingBot() { ExtensionUsingBot() {
super("", "", offlineInstance("testing")); super("", "", offlineInstance("testing"));
} }
@ -71,7 +71,7 @@ public class ExtensionTest {
public static class AbilityBotExtension implements AbilityExtension { public static class AbilityBotExtension implements AbilityExtension {
private String name; private String name;
public AbilityBotExtension(String name) { AbilityBotExtension(String name) {
this.name = name; this.name = name;
} }

View File

@ -1,8 +1,9 @@
package org.telegram.abilitybots.api.db; package org.telegram.abilitybots.api.db;
import org.junit.After; import org.junit.jupiter.api.AfterEach;
import org.junit.Before; import org.junit.jupiter.api.Assertions;
import org.junit.Test; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.telegram.telegrambots.meta.api.objects.User; import org.telegram.telegrambots.meta.api.objects.User;
import java.io.IOException; import java.io.IOException;
@ -12,25 +13,33 @@ import java.util.Set;
import static com.google.common.collect.Maps.newHashMap; import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet; import static com.google.common.collect.Sets.newHashSet;
import static java.lang.String.format; import static java.lang.String.format;
import static org.junit.Assert.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.telegram.abilitybots.api.bot.AbilityBotTest.CREATOR; import static org.telegram.abilitybots.api.bot.AbilityBotTest.CREATOR;
import static org.telegram.abilitybots.api.bot.AbilityBotTest.USER; import static org.telegram.abilitybots.api.bot.AbilityBotTest.USER;
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
public class MapDBContextTest { class MapDBContextTest {
private static final String USERS = "USERS"; private static final String USERS = "USERS";
private static final String USER_ID = "USER_ID"; private static final String USER_ID = "USER_ID";
private static final String TEST = "TEST"; private static final String TEST = "TEST";
private DBContext db; private DBContext db;
@Before @BeforeEach
public void setUp() { void setUp() {
db = offlineInstance("db"); db = offlineInstance("db");
} }
@AfterEach
void tearDown() throws IOException {
db.clear();
db.close();
}
@Test @Test
public void canRecoverDB() { void canRecoverDB() {
Map<Integer, User> users = db.getMap(USERS); Map<Integer, User> users = db.getMap(USERS);
Map<String, Integer> userIds = db.getMap(USER_ID); Map<String, Integer> userIds = db.getMap(USER_ID);
users.put(CREATOR.getId(), CREATOR); users.put(CREATOR.getId(), CREATOR);
@ -49,30 +58,30 @@ public class MapDBContextTest {
Map<Integer, User> recoveredUsers = db.getMap(USERS); Map<Integer, User> recoveredUsers = db.getMap(USERS);
String afterRecoveryInfo = db.info(USERS); String afterRecoveryInfo = db.info(USERS);
assertTrue("Could not recover database successfully", recovered); assertTrue(recovered, "Could not recover database successfully");
assertEquals("Map info before and after recovery is different", beforeBackupInfo, afterRecoveryInfo); assertEquals(beforeBackupInfo, afterRecoveryInfo, "Map info before and after recovery is different");
assertEquals("Map before and after recovery are not equal", originalUsers, recoveredUsers); assertEquals(originalUsers, recoveredUsers, "Map before and after recovery are not equal");
} }
@Test @Test
public void canFallbackDBIfRecoveryFails() { void canFallbackDBIfRecoveryFails() {
Set<User> users = db.getSet(USERS); Set<User> users = db.getSet(USERS);
users.add(CREATOR); users.add(CREATOR);
users.add(USER); users.add(USER);
Set<User> originalSet = newHashSet(users); Set<User> originalSet = newHashSet(users);
Object jsonBackup = db.backup(); Object jsonBackup = db.backup();
String corruptBackup = "!@#$" + String.valueOf(jsonBackup); String corruptBackup = "!@#$" + jsonBackup;
boolean recovered = db.recover(corruptBackup); boolean recovered = db.recover(corruptBackup);
Set<User> recoveredSet = db.getSet(USERS); Set<User> recoveredSet = db.getSet(USERS);
assertFalse("Recovery was successful from a CORRUPT backup", recovered); assertFalse(recovered, "Recovery was successful from a CORRUPT backup");
assertEquals("Set before and after corrupt recovery are not equal", originalSet, recoveredSet); assertEquals(originalSet, recoveredSet, "Set before and after corrupt recovery are not equal");
} }
@Test @Test
public void canGetSummary() { void canGetSummary() {
String anotherTest = TEST + 1; String anotherTest = TEST + 1;
db.getSet(TEST).add(TEST); db.getSet(TEST).add(TEST);
db.getSet(anotherTest).add(anotherTest); db.getSet(anotherTest).add(anotherTest);
@ -81,27 +90,27 @@ public class MapDBContextTest {
// Name - Type - Number of "rows" // Name - Type - Number of "rows"
String expectedSummary = format("%s - Set - 1\n%s - Set - 1", TEST, anotherTest); String expectedSummary = format("%s - Set - 1\n%s - Set - 1", TEST, anotherTest);
assertEquals("Actual DB summary does not match that of the expected", expectedSummary, actualSummary); assertEquals(expectedSummary, actualSummary, "Actual DB summary does not match that of the expected");
} }
@Test @Test
public void canGetInfo() { void canGetInfo() {
db.getSet(TEST).add(TEST); db.getSet(TEST).add(TEST);
String actualInfo = db.info(TEST); String actualInfo = db.info(TEST);
// JSON // JSON
String expectedInfo = "TEST - Set - 1"; String expectedInfo = "TEST - Set - 1";
assertEquals("Actual DB structure info does not match that of the expected", expectedInfo, actualInfo); assertEquals(expectedInfo, actualInfo, "Actual DB structure info does not match that of the expected");
}
@Test(expected = IllegalStateException.class)
public void cantGetInfoFromNonexistentDBStructureName() {
db.info(TEST);
} }
@Test @Test
public void canGetAndSetVariables() { void cantGetInfoFromNonexistentDBStructureName() {
Assertions.assertThrows(IllegalStateException.class, () -> db.info(TEST));
}
@Test
void canGetAndSetVariables() {
String varName = "somevar"; String varName = "somevar";
Var<User> var = db.getVar(varName); Var<User> var = db.getVar(varName);
var.set(CREATOR); var.set(CREATOR);
@ -116,10 +125,4 @@ public class MapDBContextTest {
Var<User> changedVar = db.getVar(varName); Var<User> changedVar = db.getVar(varName);
assertEquals(changedVar.get(), USER); assertEquals(changedVar.get(), USER);
} }
@After
public void tearDown() throws IOException {
db.clear();
db.close();
}
} }

View File

@ -1,58 +1,59 @@
package org.telegram.abilitybots.api.objects; package org.telegram.abilitybots.api.objects;
import org.junit.Test; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.Assert.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder; import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder;
public class AbilityTest { class AbilityTest {
@Test(expected = IllegalArgumentException.class) @Test
public void argumentsCannotBeNegative() { void argumentsCannotBeNegative() {
getDefaultBuilder().input(-4).build(); Assertions.assertThrows(IllegalArgumentException.class, () -> getDefaultBuilder().input(-4).build());
}
@Test(expected = IllegalArgumentException.class)
public void nameCannotBeEmpty() {
getDefaultBuilder().name("").build();
}
@Test(expected = IllegalArgumentException.class)
public void nameCannotBeNull() {
getDefaultBuilder().name(null).build();
}
@Test(expected = NullPointerException.class)
public void consumerCannotBeNull() {
getDefaultBuilder().action(null).build();
}
@Test(expected = NullPointerException.class)
public void localityCannotBeNull() {
getDefaultBuilder().locality(null).build();
}
@Test(expected = NullPointerException.class)
public void privacyCannotBeNull() {
getDefaultBuilder().privacy(null).build();
}
@Test(expected = IllegalArgumentException.class)
public void nameCannotContainSpaces() {
getDefaultBuilder().name("test test").build();
} }
@Test @Test
public void abilityEqualsMethod() { void nameCannotBeEmpty() {
Assertions.assertThrows(IllegalArgumentException.class, () -> getDefaultBuilder().name("").build());
}
@Test
void nameCannotBeNull() {
Assertions.assertThrows(IllegalArgumentException.class, () -> getDefaultBuilder().name(null).build());
}
@Test
void consumerCannotBeNull() {
Assertions.assertThrows(NullPointerException.class, () -> getDefaultBuilder().action(null).build());
}
@Test
void localityCannotBeNull() {
Assertions.assertThrows(NullPointerException.class, () -> getDefaultBuilder().locality(null).build());
}
@Test
void privacyCannotBeNull() {
Assertions.assertThrows(NullPointerException.class, () -> getDefaultBuilder().privacy(null).build());
}
@Test
void nameCannotContainSpaces() {
Assertions.assertThrows(IllegalArgumentException.class, () -> getDefaultBuilder().name("test test").build());
}
@Test
void abilityEqualsMethod() {
Ability ability1 = getDefaultBuilder().build(); Ability ability1 = getDefaultBuilder().build();
Ability ability2 = getDefaultBuilder().build(); Ability ability2 = getDefaultBuilder().build();
Ability ability3 = getDefaultBuilder().name("anotherconsumer").build(); Ability ability3 = getDefaultBuilder().name("anotherconsumer").build();
Ability ability4 = getDefaultBuilder().action((context) -> { Ability ability4 = getDefaultBuilder().action((context) -> {
}).build(); }).build();
assertEquals("Abilities should not be equal", ability1, ability2); assertEquals(ability1, ability2, "Abilities should not be equal");
assertEquals("Abilities should not be equal", ability1, ability4); assertEquals(ability1, ability4, "Abilities should not be equal");
assertNotEquals("Abilities should be equal", ability1, ability3); assertNotEquals(ability1, ability3, "Abilities should be equal");
} }
} }

View File

@ -1,43 +1,43 @@
package org.telegram.abilitybots.api.sender; package org.telegram.abilitybots.api.sender;
import org.junit.Before; import org.junit.jupiter.api.BeforeEach;
import org.junit.Test; import org.junit.jupiter.api.Test;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.util.Optional; import java.util.Optional;
import static junit.framework.TestCase.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static junit.framework.TestCase.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.Matchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
public class SilentSenderTest { class SilentSenderTest {
private SilentSender silent; private SilentSender silent;
private MessageSender sender; private MessageSender sender;
@Before @BeforeEach
public void setUp() { void setUp() {
sender = mock(MessageSender.class); sender = mock(MessageSender.class);
silent = new SilentSender(sender); silent = new SilentSender(sender);
} }
@Test @Test
public void returnsEmptyOnError() throws TelegramApiException { void returnsEmptyOnError() throws TelegramApiException {
when(sender.execute(any())).thenThrow(TelegramApiException.class); when(sender.execute(any())).thenThrow(TelegramApiException.class);
Optional execute = silent.execute(null); Optional execute = silent.execute(null);
assertFalse("Execution of a bot API method with execption results in a nonempty optional", execute.isPresent()); assertFalse(execute.isPresent(), "Execution of a bot API method with execption results in a nonempty optional");
} }
@Test @Test
public void returnOptionalOnSuccess() throws TelegramApiException { void returnOptionalOnSuccess() throws TelegramApiException {
String data = "data"; String data = "data";
when(sender.execute(any())).thenReturn(data); when(sender.execute(any())).thenReturn(data);
Optional execute = silent.execute(null); Optional execute = silent.execute(null);
assertEquals("Silent execution resulted in a different object", data, execute.get()); assertEquals(data, execute.get(), "Silent execution resulted in a different object");
} }
} }

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.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
``` ```

View File

@ -3,9 +3,14 @@
xmlns="http://maven.apache.org/POM/4.0.0" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId>
<parent>
<groupId>org.telegram</groupId>
<artifactId>Bots</artifactId>
<version>4.4.0</version>
</parent>
<artifactId>telegrambots-chat-session-bot</artifactId> <artifactId>telegrambots-chat-session-bot</artifactId>
<version>4.3.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots Chat Session Bot</name> <name>Telegram Bots Chat Session Bot</name>
@ -63,9 +68,15 @@
</distributionManagement> </distributionManagement>
<properties> <properties>
<java.version>11</java.version>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<shiro.version>1.4.0</shiro.version>
<shiro.version>1.4.1</shiro.version>
</properties> </properties>
<dependencies> <dependencies>
@ -73,7 +84,7 @@
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core --> <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
@ -82,19 +93,6 @@
<artifactId>shiro-core</artifactId> <artifactId>shiro-core</artifactId>
<version>${shiro.version}</version> <version>${shiro.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -104,10 +102,15 @@
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version> <version>1.6</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@ -121,7 +124,7 @@
<plugin> <plugin>
<groupId>org.sonatype.plugins</groupId> <groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId> <artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version> <version>1.6.8</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<serverId>ossrh</serverId> <serverId>ossrh</serverId>
@ -131,7 +134,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<id>clean-project</id> <id>clean-project</id>
@ -144,7 +147,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version> <version>3.1.1</version>
<configuration> <configuration>
<descriptorRefs> <descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <descriptorRef>jar-with-dependencies</descriptorRef>
@ -163,7 +166,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -175,14 +178,14 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
<configuration> <configuration>
<additionalparam>-Xdoclint:none</additionalparam> <doclint>none</doclint>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@ -190,7 +193,7 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version> <version>0.8.4</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -209,7 +212,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version> <version>3.0.0-M2</version>
<executions> <executions>
<execution> <execution>
<id>enforce-versions</id> <id>enforce-versions</id>
@ -227,7 +230,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version> <version>3.1.1</version>
<executions> <executions>
<execution> <execution>
<id>copy</id> <id>copy</id>
@ -241,9 +244,10 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration> <configuration>
<source>1.8</source> <source>${java.version}</source>
<target>1.8</target> <target>${java.version}</target>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
</plugin> </plugin>

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.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
``` ```
2. Using Gradle: 2. Using Gradle:
```gradle ```gradle
compile "org.telegram:telegrambotsextensions:4.3.1" compile "org.telegram:telegrambotsextensions:4.4.0"
``` ```

View File

@ -3,9 +3,14 @@
xmlns="http://maven.apache.org/POM/4.0.0" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId>
<parent>
<groupId>org.telegram</groupId>
<artifactId>Bots</artifactId>
<version>4.4.0</version>
</parent>
<artifactId>telegrambotsextensions</artifactId> <artifactId>telegrambotsextensions</artifactId>
<version>4.3.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots Extensions</name> <name>Telegram Bots Extensions</name>
@ -57,6 +62,11 @@
</distributionManagement> </distributionManagement>
<properties> <properties>
<java.version>11</java.version>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties> </properties>
@ -65,7 +75,7 @@
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
@ -76,10 +86,15 @@
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version> <version>1.6</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@ -93,7 +108,7 @@
<plugin> <plugin>
<groupId>org.sonatype.plugins</groupId> <groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId> <artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version> <version>1.6.8</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<serverId>ossrh</serverId> <serverId>ossrh</serverId>
@ -103,7 +118,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<id>clean-project</id> <id>clean-project</id>
@ -116,7 +131,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version> <version>3.1.1</version>
<configuration> <configuration>
<descriptorRefs> <descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <descriptorRef>jar-with-dependencies</descriptorRef>
@ -135,7 +150,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -147,14 +162,14 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
<configuration> <configuration>
<additionalparam>-Xdoclint:none</additionalparam> <doclint>none</doclint>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@ -162,7 +177,7 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version> <version>0.8.4</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -181,7 +196,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version> <version>3.0.0-M2</version>
<executions> <executions>
<execution> <execution>
<id>enforce-versions</id> <id>enforce-versions</id>
@ -199,7 +214,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version> <version>3.1.1</version>
<executions> <executions>
<execution> <execution>
<id>copy</id> <id>copy</id>
@ -213,9 +228,10 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration> <configuration>
<source>1.8</source> <source>${java.version}</source>
<target>1.8</target> <target>${java.version}</target>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
</plugin> </plugin>

View File

@ -11,9 +11,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
* Created by Daniil Nikanov aka JetCoder * Created by Daniil Nikanov aka JetCoder
*/ */
@SuppressWarnings("unused")
public abstract class TimedSendLongPollingBot extends TelegramLongPollingBot public abstract class TimedSendLongPollingBot extends TelegramLongPollingBot
{ {
private static final long MANY_CHATS_SEND_INTERVAL = 33;
private static final long ONE_CHAT_SEND_INTERVAL = 1000; private static final long ONE_CHAT_SEND_INTERVAL = 1000;
private static final long CHAT_INACTIVE_INTERVAL = 1000 * 60 * 10; private static final long CHAT_INACTIVE_INTERVAL = 1000 * 60 * 10;
private final Timer mSendTimer = new Timer(true); private final Timer mSendTimer = new Timer(true);
@ -21,88 +21,29 @@ public abstract class TimedSendLongPollingBot extends TelegramLongPollingBot
private final ArrayList<MessageQueue> mSendQueues = new ArrayList<>(); private final ArrayList<MessageQueue> mSendQueues = new ArrayList<>();
private final AtomicBoolean mSendRequested = new AtomicBoolean(false); private final AtomicBoolean mSendRequested = new AtomicBoolean(false);
private final class MessageSenderTask extends TimerTask
{
@Override
public void run()
{
//mSendRequested used for optimisation to not traverse all mMessagesMap 30 times per second all the time
if (!mSendRequested.getAndSet(false))
return;
long currentTime = System.currentTimeMillis();
mSendQueues.clear();
boolean processNext = false;
//First step - find all chats in which already allowed to send message (passed more than 1000 ms from previuos send)
Iterator<Map.Entry<Long,MessageQueue>> it = mMessagesMap.entrySet().iterator();
while (it.hasNext())
{
MessageQueue queue = it.next().getValue();
int state = queue.getCurrentState(currentTime); //Actual check here
if (state == MessageQueue.GET_MESSAGE)
{
mSendQueues.add(queue);
processNext = true;
}
else if (state == MessageQueue.WAIT)
{
processNext = true;
}
else if (state == MessageQueue.DELETE)
{
it.remove();
}
}
//If any of chats are in state WAIT or GET_MESSAGE, request another iteration
if (processNext)
mSendRequested.set(true);
//Second step - find oldest waiting queue and peek it's message
MessageQueue sendQueue = null;
long oldestPutTime = Long.MAX_VALUE;
for (int i = 0; i < mSendQueues.size(); i++)
{
MessageQueue queue = mSendQueues.get(i);
long putTime = queue.getPutTime();
if (putTime < oldestPutTime)
{
oldestPutTime = putTime;
sendQueue = queue;
}
}
if (sendQueue == null) //Possible if on first step wasn't found any chats in state GET_MESSAGE
return;
//Invoke the send callback. ChatId is passed for possible additional processing
sendMessageCallback(sendQueue.getChatId(), sendQueue.getMessage(currentTime));
}
}
private static class MessageQueue private static class MessageQueue
{ {
public static final int EMPTY = 0; //Queue is empty static final int EMPTY = 0; //Queue is empty
public static final int WAIT = 1; //Queue has message(s) but not yet allowed to send static final int WAIT = 1; //Queue has message(s) but not yet allowed to send
public static final int DELETE = 2; //No one message of given queue was sent longer than CHAT_INACTIVE_INTERVAL, delete for optimisation static final int DELETE = 2; //No one message of given queue was sent longer than CHAT_INACTIVE_INTERVAL, delete for optimisation
public static final int GET_MESSAGE = 3; //Queue has message(s) and ready to send static final int GET_MESSAGE = 3; //Queue has message(s) and ready to send
private final ConcurrentLinkedQueue<Object> mQueue = new ConcurrentLinkedQueue<>(); private final ConcurrentLinkedQueue<Object> mQueue = new ConcurrentLinkedQueue<>();
private final Long mChatId; private final Long mChatId;
private long mLastSendTime; //Time of last peek from queue private long mLastSendTime; //Time of last peek from queue
private volatile long mLastPutTime; //Time of last put into queue private volatile long mLastPutTime; //Time of last put into queue
public MessageQueue(Long chatId) MessageQueue(Long chatId)
{ {
mChatId = chatId; mChatId = chatId;
} }
public synchronized void putMessage(Object msg) synchronized void putMessage(Object msg)
{ {
mQueue.add(msg); mQueue.add(msg);
mLastPutTime = System.currentTimeMillis(); mLastPutTime = System.currentTimeMillis();
} }
public synchronized int getCurrentState(long currentTime) synchronized int getCurrentState(long currentTime)
{ {
//currentTime is passed as parameter for optimisation to do not recall currentTimeMillis() many times //currentTime is passed as parameter for optimisation to do not recall currentTimeMillis() many times
long interval = currentTime - mLastSendTime; long interval = currentTime - mLastSendTime;
@ -117,29 +58,23 @@ public abstract class TimedSendLongPollingBot extends TelegramLongPollingBot
return WAIT; return WAIT;
} }
public synchronized Object getMessage(long currentTime) synchronized Object getMessage(long currentTime)
{ {
mLastSendTime = currentTime; mLastSendTime = currentTime;
return mQueue.poll(); return mQueue.poll();
} }
public long getPutTime() long getPutTime()
{ {
return mLastPutTime; return mLastPutTime;
} }
public Long getChatId() Long getChatId()
{ {
return mChatId; return mChatId;
} }
} }
//Constructor
protected TimedSendLongPollingBot()
{
mSendTimer.schedule(new MessageSenderTask(), MANY_CHATS_SEND_INTERVAL, MANY_CHATS_SEND_INTERVAL);
}
//Something like destructor //Something like destructor
public void finish() public void finish()
{ {
@ -214,5 +149,5 @@ public abstract class TimedSendLongPollingBot extends TelegramLongPollingBot
} }
} }
*/ */
public abstract void sendMessageCallback(Long chatId, Object messageRequest); abstract void sendMessageCallback(Long chatId, Object messageRequest);
} }

View File

@ -3,9 +3,14 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId>
<parent>
<groupId>org.telegram</groupId>
<artifactId>Bots</artifactId>
<version>4.4.0</version>
</parent>
<artifactId>telegrambots-meta</artifactId> <artifactId>telegrambots-meta</artifactId>
<version>4.3.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots Meta</name> <name>Telegram Bots Meta</name>
@ -57,14 +62,18 @@
</distributionManagement> </distributionManagement>
<properties> <properties>
<java.version>11</java.version>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<guice.version>4.2.2</guice.version> <guice.version>4.2.2</guice.version>
<jackson.version>2.9.9</jackson.version> <jackson.version>2.9.9</jackson.version>
<jacksonanotation.version>2.9.0</jacksonanotation.version> <jacksonanotation.version>2.9.9</jacksonanotation.version>
<json.version>20180813</json.version> <json.version>20180813</json.version>
<junit.version>4.12</junit.version> <guava.version>28.0-jre</guava.version>
<guava.version>25.1-jre</guava.version>
</properties> </properties>
<dependencies> <dependencies>
@ -105,12 +114,6 @@
<artifactId>json</artifactId> <artifactId>json</artifactId>
<version>${json.version}</version> <version>${json.version}</version>
</dependency> </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -123,7 +126,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version> <version>1.6</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@ -137,7 +140,7 @@
<plugin> <plugin>
<groupId>org.sonatype.plugins</groupId> <groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId> <artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version> <version>1.6.8</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<serverId>ossrh</serverId> <serverId>ossrh</serverId>
@ -147,7 +150,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<id>clean-project</id> <id>clean-project</id>
@ -160,7 +163,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version> <version>3.1.1</version>
<configuration> <configuration>
<descriptorRefs> <descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <descriptorRef>jar-with-dependencies</descriptorRef>
@ -179,7 +182,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -191,14 +194,14 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
<configuration> <configuration>
<additionalparam>-Xdoclint:none</additionalparam> <doclint>none</doclint>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@ -206,7 +209,7 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version> <version>0.8.4</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -225,7 +228,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version> <version>3.0.0-M2</version>
<executions> <executions>
<execution> <execution>
<id>enforce</id> <id>enforce</id>
@ -243,7 +246,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version> <version>3.1.1</version>
<executions> <executions>
<execution> <execution>
<id>copy</id> <id>copy</id>
@ -251,15 +254,21 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
</plugins> </plugins>
<pluginManagement> <pluginManagement>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration> <configuration>
<source>1.8</source> <source>${java.version}</source>
<target>1.8</target> <target>${java.version}</target>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
</plugin> </plugin>

View File

@ -4,8 +4,8 @@ import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import org.apache.logging.log4j.LogManager;
import org.telegram.telegrambots.meta.logging.BotLogger; import org.apache.logging.log4j.Logger;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.HashMap; import java.util.HashMap;
@ -16,6 +16,8 @@ import java.util.Map;
* @version 1.0 * @version 1.0
*/ */
public class ApiContext { public class ApiContext {
private static final Logger log = LogManager.getLogger(ApiContext.class);
private static final Object lock = new Object(); private static final Object lock = new Object();
private static Injector INJECTOR; private static Injector INJECTOR;
private static Map<Class, Class> bindings = new HashMap<>(); private static Map<Class, Class> bindings = new HashMap<>();
@ -27,14 +29,14 @@ public class ApiContext {
public static <T, S extends T> void register(Class<T> type, Class<S> implementation) { public static <T, S extends T> void register(Class<T> type, Class<S> implementation) {
if (bindings.containsKey(type)) { if (bindings.containsKey(type)) {
BotLogger.debug("ApiContext", MessageFormat.format("Class {0} already registered", type.getName())); log.debug(MessageFormat.format("Class {0} already registered", type.getName()));
} }
bindings.put(type, implementation); bindings.put(type, implementation);
} }
public static <T, S extends T> void registerSingleton(Class<T> type, Class<S> implementation) { public static <T, S extends T> void registerSingleton(Class<T> type, Class<S> implementation) {
if (singletonBindings.containsKey(type)) { if (singletonBindings.containsKey(type)) {
BotLogger.debug("ApiContext", MessageFormat.format("Class {0} already registered", type.getName())); log.debug(MessageFormat.format("Class {0} already registered", type.getName()));
} }
singletonBindings.put(type, implementation); singletonBindings.put(type, implementation);
} }

View File

@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import org.telegram.telegrambots.meta.api.methods.BotApiMethod; import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
import org.telegram.telegrambots.meta.api.objects.ApiResponse; import org.telegram.telegrambots.meta.api.objects.ApiResponse;
import org.telegram.telegrambots.meta.api.objects.ChatPermissions;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException; import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException; import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
@ -24,6 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Pass True for all boolean parameters to lift restrictions from a user. Returns True on success. * Pass True for all boolean parameters to lift restrictions from a user. Returns True on success.
* *
*/ */
@SuppressWarnings("WeakerAccess")
public class RestrictChatMember extends BotApiMethod<Boolean> { public class RestrictChatMember extends BotApiMethod<Boolean> {
public static final String PATH = "restrictchatmember"; public static final String PATH = "restrictchatmember";
@ -34,6 +36,7 @@ public class RestrictChatMember extends BotApiMethod<Boolean> {
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 PERMISSIONS_FIELD = "permissions";
@JsonProperty(CHATID_FIELD) @JsonProperty(CHATID_FIELD)
private String chatId; ///< Required. Unique identifier for the chat to send the message to (Or username for channels) private String chatId; ///< Required. Unique identifier for the chat to send the message to (Or username for channels)
@ -49,7 +52,14 @@ public class RestrictChatMember extends BotApiMethod<Boolean> {
private Boolean canSendOtherMessages; ///< Pass True, if the user can send animations, games, stickers and use inline bots, implies can_send_media_messages private Boolean canSendOtherMessages; ///< Pass 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; ///< Pass True, if the user may add web page previews to their messages, implies can_send_messages private Boolean canAddWebPagePreviews; ///< Pass True, if the user may add web page previews to their messages, implies can_send_messages
/**
* Optional
* Date when restrictions will be lifted for the user, unix time.
* If user is restricted for more than 366 days or less than 30 seconds
* from the current time, they are considered to be restricted forever
*/
@JsonProperty(PERMISSIONS_FIELD)
private ChatPermissions permissions;
public RestrictChatMember() { public RestrictChatMember() {
super(); super();
@ -108,46 +118,87 @@ public class RestrictChatMember extends BotApiMethod<Boolean> {
return setUntilDate(date.toInstant()); return setUntilDate(date.toInstant());
} }
@JsonIgnore
public RestrictChatMember forTimePeriod(Duration duration) { public RestrictChatMember forTimePeriod(Duration duration) {
return setUntilDate(Instant.now().plusMillis(duration.toMillis())); return setUntilDate(Instant.now().plusMillis(duration.toMillis()));
} }
/**
* @deprecated Use {@link #getPermissions()} instead
*/
@Deprecated
public Boolean getCanSendMessages() { public Boolean getCanSendMessages() {
return canSendMessages; return canSendMessages;
} }
/**
* @deprecated Use {@link #setPermissions(ChatPermissions)} instead
*/
@Deprecated
public RestrictChatMember setCanSendMessages(Boolean canSendMessages) { public RestrictChatMember setCanSendMessages(Boolean canSendMessages) {
this.canSendMessages = canSendMessages; this.canSendMessages = canSendMessages;
return this; return this;
} }
/**
* @deprecated Use {@link #getPermissions()} instead
*/
@Deprecated
public Boolean getCanSendMediaMessages() { public Boolean getCanSendMediaMessages() {
return canSendMediaMessages; return canSendMediaMessages;
} }
/**
* @deprecated Use {@link #setPermissions(ChatPermissions)} instead
*/
@Deprecated
public RestrictChatMember setCanSendMediaMessages(Boolean canSendMediaMessages) { public RestrictChatMember setCanSendMediaMessages(Boolean canSendMediaMessages) {
this.canSendMediaMessages = canSendMediaMessages; this.canSendMediaMessages = canSendMediaMessages;
return this; return this;
} }
/**
* @deprecated Use {@link #getPermissions()} instead
*/
@Deprecated
public Boolean getCanSendOtherMessages() { public Boolean getCanSendOtherMessages() {
return canSendOtherMessages; return canSendOtherMessages;
} }
/**
* @deprecated Use {@link #setPermissions(ChatPermissions)} instead
*/
@Deprecated
public RestrictChatMember setCanSendOtherMessages(Boolean canSendOtherMessages) { public RestrictChatMember setCanSendOtherMessages(Boolean canSendOtherMessages) {
this.canSendOtherMessages = canSendOtherMessages; this.canSendOtherMessages = canSendOtherMessages;
return this; return this;
} }
/**
* @deprecated Use {@link #getPermissions()} instead
*/
@Deprecated
public Boolean getCanAddWebPagePreviews() { public Boolean getCanAddWebPagePreviews() {
return canAddWebPagePreviews; return canAddWebPagePreviews;
} }
/**
* @deprecated Use {@link #setPermissions(ChatPermissions)} instead
*/
@Deprecated
public RestrictChatMember setCanAddWebPagePreviews(Boolean canAddWebPagePreviews) { public RestrictChatMember setCanAddWebPagePreviews(Boolean canAddWebPagePreviews) {
this.canAddWebPagePreviews = canAddWebPagePreviews; this.canAddWebPagePreviews = canAddWebPagePreviews;
return this; return this;
} }
public ChatPermissions getPermissions() {
return permissions;
}
public void setPermissions(ChatPermissions permissions) {
this.permissions = permissions;
}
@Override @Override
public String getMethod() { public String getMethod() {
return PATH; return PATH;
@ -176,6 +227,9 @@ public class RestrictChatMember extends BotApiMethod<Boolean> {
if (userId == null) { if (userId == null) {
throw new TelegramApiValidationException("UserId can't be empty", this); throw new TelegramApiValidationException("UserId can't be empty", this);
} }
if (permissions == null) {
throw new TelegramApiValidationException("Permissions can't be empty", this);
}
} }
@Override @Override
@ -188,6 +242,7 @@ public class RestrictChatMember extends BotApiMethod<Boolean> {
", canSendMediaMessages=" + canSendMediaMessages + ", canSendMediaMessages=" + canSendMediaMessages +
", canSendOtherMessages=" + canSendOtherMessages + ", canSendOtherMessages=" + canSendOtherMessages +
", canAddWebPagePreviews=" + canAddWebPagePreviews + ", canAddWebPagePreviews=" + canAddWebPagePreviews +
", permissions=" + permissions +
'}'; '}';
} }
} }

View File

@ -0,0 +1,112 @@
package org.telegram.telegrambots.meta.api.methods.groupadministration;
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.ApiResponse;
import org.telegram.telegrambots.meta.api.objects.ChatPermissions;
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 4.4
* Use this method to set default chat permissions for all members.
* The bot must be an administrator in the group or a supergroup
* for this to work and must have the can_restrict_members admin rights.
*/
public class SetChatPermissions extends BotApiMethod<Boolean> {
public static final String PATH = "setChatPermissions";
private static final String CHAT_ID_FIELD = "chat_id";
private static final String PERMISSIONS_FIELD = "permissions";
@JsonProperty(CHAT_ID_FIELD)
private String chatId; ///< Unique identifier for the target chat or username of the target supergroup (in the format @supergroupusername)
@JsonProperty(PERMISSIONS_FIELD)
private ChatPermissions permissions; ///< New default chat permissions
public SetChatPermissions() {
super();
}
public SetChatPermissions(String chatId, ChatPermissions permissions) {
super();
this.chatId = checkNotNull(chatId);
this.permissions = checkNotNull(permissions);
}
public SetChatPermissions(Long chatId, ChatPermissions permissions) {
super();
this.chatId = checkNotNull(chatId).toString();
this.permissions = checkNotNull(permissions);
}
public String getChatId() {
return chatId;
}
public SetChatPermissions setChatId(String chatId) {
this.chatId = chatId;
return this;
}
public SetChatPermissions setChatId(Long chatId) {
Objects.requireNonNull(chatId);
this.chatId = chatId.toString();
return this;
}
public ChatPermissions getPermissions() {
return permissions;
}
public SetChatPermissions setPermissions(ChatPermissions permissions) {
Objects.requireNonNull(permissions);
this.permissions = permissions;
return this;
}
@Override
public String getMethod() {
return PATH;
}
@Override
public Boolean deserializeResponse(String answer) throws TelegramApiRequestException {
try {
ApiResponse<Boolean> result = OBJECT_MAPPER.readValue(answer,
new TypeReference<ApiResponse<Boolean>>(){});
if (result.getOk()) {
return result.getResult();
} else {
throw new TelegramApiRequestException("Error setting chat description", result);
}
} catch (IOException e) {
throw new TelegramApiRequestException("Unable to deserialize response", e);
}
}
@Override
public void validate() throws TelegramApiValidationException {
if (chatId == null || chatId.isEmpty()) {
throw new TelegramApiValidationException("ChatId can't be empty", this);
}
if (permissions == null) {
throw new TelegramApiValidationException("Permissions can't be null", this);
}
}
@Override
public String toString() {
return "SetChatPermissions{" +
"chatId='" + chatId + '\'' +
", permissions=" + permissions +
'}';
}
}

View File

@ -25,6 +25,7 @@ public class Chat implements BotApiObject {
private static final String PINNEDMESSAGE_FIELD = "pinned_message"; private static final String PINNEDMESSAGE_FIELD = "pinned_message";
private static final String STICKERSETNAME_FIELD = "sticker_set_name"; private static final String STICKERSETNAME_FIELD = "sticker_set_name";
private static final String CANSETSTICKERSET_FIELD = "can_set_sticker_set"; private static final String CANSETSTICKERSET_FIELD = "can_set_sticker_set";
private static final String PERMISSIONS_FIELD = "permissions";
private static final String USERCHATTYPE = "private"; private static final String USERCHATTYPE = "private";
private static final String GROUPCHATTYPE = "group"; private static final String GROUPCHATTYPE = "group";
@ -57,15 +58,23 @@ public class Chat implements BotApiObject {
@JsonProperty(PHOTO_FIELD) @JsonProperty(PHOTO_FIELD)
private ChatPhoto photo; ///< Optional. Chat photo. Returned only in getChat. private ChatPhoto photo; ///< Optional. Chat photo. Returned only in getChat.
@JsonProperty(DESCRIPTION_FIELD) @JsonProperty(DESCRIPTION_FIELD)
private String description; ///< Optional. Description, for supergroups and channel chats. Returned only in getChat. private String description; ///< Optional. Description, for groups, supergroups and channel chats. Returned only in getChat.
/**
* Optional. Chat invite link, for groups, supergroups and channel chats.
* Each administrator in a chat generates their own invite links, so the bot must first generate the link using
* exportChatInviteLink.
* Each Returned only in getChat.
*/
@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;
@JsonProperty(PINNEDMESSAGE_FIELD) @JsonProperty(PINNEDMESSAGE_FIELD)
private Message pinnedMessage; ///< Optional. Pinned message, for groups, supergroups and channels. 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)
private Boolean canSetStickerSet; ///< Optional. True, if the bot can change group the sticker set. Returned only in getChat. private Boolean canSetStickerSet; ///< Optional. True, if the bot can change group the sticker set. Returned only in getChat.
@JsonProperty(PERMISSIONS_FIELD)
private ChatPermissions permissions; ///< Optional. Default chat member permissions, for groups and supergroups. Returned only in getChat.
public Chat() { public Chat() {
super(); super();
@ -107,6 +116,14 @@ public class Chat implements BotApiObject {
return userName; return userName;
} }
public ChatPermissions getPermissions() {
return permissions;
}
/**
* @deprecated Use {@link #getPermissions()} instead
*/
@Deprecated
public Boolean getAllMembersAreAdministrators() { public Boolean getAllMembersAreAdministrators() {
return allMembersAreAdministrators; return allMembersAreAdministrators;
} }
@ -151,6 +168,7 @@ public class Chat implements BotApiObject {
", pinnedMessage=" + pinnedMessage + ", pinnedMessage=" + pinnedMessage +
", stickerSetName='" + stickerSetName + '\'' + ", stickerSetName='" + stickerSetName + '\'' +
", canSetStickerSet=" + canSetStickerSet + ", canSetStickerSet=" + canSetStickerSet +
", permissions=" + permissions +
'}'; '}';
} }
} }

View File

@ -9,8 +9,7 @@ import java.time.Instant;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* @brief This object contains information about one member of the chat. * This object contains information about one member of the chat.
* @date 20 of May of 2016
*/ */
public class ChatMember implements BotApiObject { public class ChatMember implements BotApiObject {
private static final String USER_FIELD = "user"; private static final String USER_FIELD = "user";
@ -29,18 +28,19 @@ 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 CAN_SEND_POLLS_FIELD = "can_send_polls";
private static final String ISMEMBER_FIELD = "is_member"; 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
@JsonProperty(STATUS_FIELD) @JsonProperty(STATUS_FIELD)
private String status; ///< The member's status in the chat. Can be creator, administrator, member, restricted, left or kicked private String status; ///< The member's status in the chat. Can be creator, administrator, member, restricted, left or kicked
@JsonProperty(UNTILDATE_FIELD) @JsonProperty(UNTILDATE_FIELD)
private Integer untilDate; ///< Optional. Restricted and kicked only. Date when restrictions will be lifted for this user, unix time private Integer untilDate; ///< Optional. Restricted and kicked only. Date when restrictions will be lifted for this user, unix time
@JsonProperty(CANBEEDITED_FIELD) @JsonProperty(CANBEEDITED_FIELD)
private Boolean canBeEdited; ///< Optional. Administrators only. True, if the bot is allowed to edit administrator privileges of that user private Boolean canBeEdited; ///< Optional. Administrators only. True, if the bot is allowed to edit administrator privileges of that user
@JsonProperty(CANCHANGEINFORMATION_FIELD) @JsonProperty(CANCHANGEINFORMATION_FIELD)
private Boolean canChangeInformation; ///< Optional. Administrators only. True, if the administrator can change the chat title, photo and other settings private Boolean canChangeInformation; ///< Optional. Administrators and restricted only. True, if the administrator can change the chat title, photo and other settings
@JsonProperty(CANPOSTMESSAGES_FIELD) @JsonProperty(CANPOSTMESSAGES_FIELD)
private Boolean canPostMessages; ///< Optional. Administrators only. True, if the administrator can post in the channel, channels only private Boolean canPostMessages; ///< Optional. Administrators only. True, if the administrator can post in the channel, channels only
@JsonProperty(CANEDITMESSAGES_FIELD) @JsonProperty(CANEDITMESSAGES_FIELD)
@ -48,21 +48,23 @@ public class ChatMember implements BotApiObject {
@JsonProperty(CANDELETEMESSAGES_FIELD) @JsonProperty(CANDELETEMESSAGES_FIELD)
private Boolean canDeleteMessages; ///< Optional. Administrators only. True, if the administrator can delete messages of other users private Boolean canDeleteMessages; ///< Optional. Administrators only. True, if the administrator can delete messages of other users
@JsonProperty(CANINVITEUSERS_FIELD) @JsonProperty(CANINVITEUSERS_FIELD)
private Boolean canInviteUsers; ///< Optional. Administrators only. True, if the administrator can invite new users to the chat private Boolean canInviteUsers; ///< Optional. Administrators and restricted only. True, if the administrator can invite new users to the chat
@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, groups and supergroups only private Boolean canPinMessages; ///< Optional. Administrators and restricted 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)
private Boolean canSendMessages; ///< Optional. Restricted only. True, if the user can send text messages, contacts, locations and venues private Boolean canSendMessages; ///< Optional. Restricted only. True, if the user is allowed to send text messages, contacts, locations and venues
@JsonProperty(CANSENDMEDIAMESSAGES_FIELD) @JsonProperty(CANSENDMEDIAMESSAGES_FIELD)
private Boolean canSendMediaMessages; ///< Optional. Restricted only. True, if the user can send audios, documents, photos, videos, video notes and voice notes, implies can_send_messages private Boolean canSendMediaMessages; ///< Optional. Restricted only. True, if the user is allowed to send audios, documents, photos, videos, video notes and voice notes, implies can_send_messages
@JsonProperty(CANSENDOTHERMESSAGES_FIELD) @JsonProperty(CANSENDOTHERMESSAGES_FIELD)
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 is allowed to 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 the user is allowed to add web page previews to his messages
@JsonProperty(CAN_SEND_POLLS_FIELD)
private Boolean canSendPolls; ///< Optional. Restricted only. True, if the user is allowed to send polls.
@JsonProperty(ISMEMBER_FIELD) @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. 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.
@ -141,6 +143,14 @@ public class ChatMember implements BotApiObject {
return canAddWebPagePreviews; return canAddWebPagePreviews;
} }
public Boolean getCanSendPolls() {
return canSendPolls;
}
public Boolean getMemberField() {
return isMemberField;
}
@Override @Override
public String toString() { public String toString() {
return "ChatMember{" + return "ChatMember{" +
@ -160,6 +170,8 @@ public class ChatMember implements BotApiObject {
", canSendMediaMessages=" + canSendMediaMessages + ", canSendMediaMessages=" + canSendMediaMessages +
", canSendOtherMessages=" + canSendOtherMessages + ", canSendOtherMessages=" + canSendOtherMessages +
", canAddWebPagePreviews=" + canAddWebPagePreviews + ", canAddWebPagePreviews=" + canAddWebPagePreviews +
", canSendPolls=" + canSendPolls +
", isMemberField=" + isMemberField +
'}'; '}';
} }
} }

View File

@ -0,0 +1,89 @@
package org.telegram.telegrambots.meta.api.objects;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
/**
* @author Ruben Bermudez
* @version 4.4
* Use this method to change the description of a group, supergroup or channel.
* The bot must be an administrator in the chat for this to work and must have the appropriate admin rights.
* Returns True on success.
*/
public class ChatPermissions implements BotApiObject {
private static final String CAN_SEND_MESSAGES_FIELD = "can_send_messages";
private static final String CAN_SEND_MEDIA_MESSAGES_FIELD = "can_send_media_messages";
private static final String CAN_SEND_POLLS_FIELD = "can_send_polls";
private static final String CAN_SEND_OTHER_MESSAGES_FIELD = "can_send_other_messages";
private static final String CAN_ADD_WEB_PAGE_PREVIEWS_FIELD = "can_add_web_page_previews";
private static final String CAN_CHANGE_INFO_FIELD = "can_change_info";
private static final String CAN_INVITE_USERS_FIELD = "can_invite_users";
private static final String CAN_PIN_MESSAGES_FIELD = "can_pin_messages";
@JsonProperty(CAN_SEND_MESSAGES_FIELD)
private Boolean canSendMessages; ///< Optional. True, if the user is allowed to send text messages, contacts, locations and venues
@JsonProperty(CAN_SEND_MEDIA_MESSAGES_FIELD)
private Boolean getCanSendMediaMessages; ///< Optional. True, if the user is allowed to send audios, documents, photos, videos, video notes and voice notes, implies can_send_messages
@JsonProperty(CAN_SEND_POLLS_FIELD)
private Boolean canSendPolls; ///< Optional. True, if the user is allowed to send polls, implies can_send_messages
@JsonProperty(CAN_SEND_OTHER_MESSAGES_FIELD)
private Boolean canSendOtherMessages; ///< Optional. True, if the user is allowed to send animations, games, stickers and use inline bots, implies can_send_media_messages
@JsonProperty(CAN_ADD_WEB_PAGE_PREVIEWS_FIELD)
private Boolean canAddWebPagePreviews; ///< Optional. True, if the user is allowed to add web page previews to their messages, implies can_send_media_messages
@JsonProperty(CAN_CHANGE_INFO_FIELD)
private Boolean canChangeInfo; ///< Optional. True, if the user is allowed to change the chat title, photo and other settings. Ignored in public supergroups
@JsonProperty(CAN_INVITE_USERS_FIELD)
private Boolean canInviteUsers; ///< Optional. True, if the user is allowed to invite new users to the chat
@JsonProperty(CAN_PIN_MESSAGES_FIELD)
private Boolean canPinMessages; ///< Optional. True, if the user is allowed to pin messages. Ignored in public supergroups
public ChatPermissions() {
super();
}
public Boolean getCanSendMessages() {
return canSendMessages;
}
public Boolean getGetCanSendMediaMessages() {
return getCanSendMediaMessages;
}
public Boolean getCanSendPolls() {
return canSendPolls;
}
public Boolean getCanSendOtherMessages() {
return canSendOtherMessages;
}
public Boolean getCanAddWebPagePreviews() {
return canAddWebPagePreviews;
}
public Boolean getCanChangeInfo() {
return canChangeInfo;
}
public Boolean getCanInviteUsers() {
return canInviteUsers;
}
public Boolean getCanPinMessages() {
return canPinMessages;
}
@Override
public String toString() {
return "ChatPermissions{" +
"canSendMessages=" + canSendMessages +
", getCanSendMediaMessages=" + getCanSendMediaMessages +
", canSendPolls=" + canSendPolls +
", canSendOtherMessages=" + canSendOtherMessages +
", canAddWebPagePreviews=" + canAddWebPagePreviews +
", canChangeInfo=" + canChangeInfo +
", canInviteUsers=" + canInviteUsers +
", canPinMessages=" + canPinMessages +
'}';
}
}

View File

@ -6,16 +6,24 @@ import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* This object represents a chat photo. * This object represents a chat photo (profile picture of a user, group or channel)
*/ */
public class ChatPhoto implements BotApiObject { public class ChatPhoto implements BotApiObject {
private static final String SMALLFILEID_FIELD = "small_file_id"; private static final String SMALLFILEID_FIELD = "small_file_id";
private static final String BIGFILEID_FIELD = "big_file_id"; private static final String BIGFILEID_FIELD = "big_file_id";
/**
* Unique file identifier of a small chat photo (160x160).
* This file_id can be used only for photo download and only for as long as the photo is not changed.
*/
@JsonProperty(SMALLFILEID_FIELD) @JsonProperty(SMALLFILEID_FIELD)
private String smallFileId; ///< Unique file identifier of small (160x160) chat photo. This file_id can be used only for photo download. private String smallFileId;
/**
* Unique file identifier of a big chat photo (640x640).
* This file_id can be used only for photo download and only for as long as the photo is not changed.
*/
@JsonProperty(BIGFILEID_FIELD) @JsonProperty(BIGFILEID_FIELD)
private String bigFileId; ///< Unique file identifier of big (640x640) chat photo. This file_id can be used only for photo download. private String bigFileId;
public ChatPhoto() { public ChatPhoto() {
super(); super();

View File

@ -1,4 +0,0 @@
/**
* @deprecated Replaced by {@link org.telegram.telegrambots.meta.api.objects.inlinequery.result.cached}
*/
package org.telegram.telegrambots.meta.api.objects.inlinequery.result.chached;

View File

@ -8,7 +8,7 @@ import org.telegram.telegrambots.meta.api.objects.PhotoSize;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* @brief This object represents a sticker. * This object represents a sticker.
*/ */
public class Sticker implements BotApiObject { public class Sticker implements BotApiObject {
@ -20,6 +20,7 @@ public class Sticker implements BotApiObject {
private static final String EMOJI_FIELD = "emoji"; private static final String EMOJI_FIELD = "emoji";
private static final String SETNAME_FIELD = "set_name"; private static final String SETNAME_FIELD = "set_name";
private static final String MASKPOSITON_FIELD = "mask_position"; private static final String MASKPOSITON_FIELD = "mask_position";
private static final String ISANIMATED_FIELD = "is_animated";
@JsonProperty(FILEID_FIELD) @JsonProperty(FILEID_FIELD)
private String fileId; ///< Unique identifier for this file private String fileId; ///< Unique identifier for this file
@ -37,6 +38,8 @@ public class Sticker implements BotApiObject {
private String setName; ///< Optional. Name of the sticker set to which the sticker belongs private String setName; ///< Optional. Name of the sticker set to which the sticker belongs
@JsonProperty(MASKPOSITON_FIELD) @JsonProperty(MASKPOSITON_FIELD)
private MaskPosition maskPosition; ///< Optional. For mask stickers, the position where the mask should be placed private MaskPosition maskPosition; ///< Optional. For mask stickers, the position where the mask should be placed
@JsonProperty(ISANIMATED_FIELD)
private Boolean isAnimated; ///< True, if the sticker is animated
public Sticker() { public Sticker() {
super(); super();
@ -74,6 +77,10 @@ public class Sticker implements BotApiObject {
return maskPosition; return maskPosition;
} }
public Boolean getAnimated() {
return isAnimated;
}
@Override @Override
public String toString() { public String toString() {
return "Sticker{" + return "Sticker{" +
@ -85,6 +92,7 @@ public class Sticker implements BotApiObject {
", emoji='" + emoji + '\'' + ", emoji='" + emoji + '\'' +
", setName='" + setName + '\'' + ", setName='" + setName + '\'' +
", maskPosition=" + maskPosition + ", maskPosition=" + maskPosition +
", isAnimated=" + isAnimated +
'}'; '}';
} }
} }

View File

@ -15,6 +15,7 @@ public class StickerSet implements BotApiObject {
private static final String TITLE_FIELD = "title"; private static final String TITLE_FIELD = "title";
private static final String CONTAINSMASKS_FIELD = "contains_masks"; private static final String CONTAINSMASKS_FIELD = "contains_masks";
private static final String STICKERS_FIELD = "stickers"; private static final String STICKERS_FIELD = "stickers";
private static final String ISANIMATED_FIELD = "is_animated";
@JsonProperty(NAME_FIELD) @JsonProperty(NAME_FIELD)
private String name; private String name;
@ -24,6 +25,8 @@ public class StickerSet implements BotApiObject {
private Boolean containsMasks; private Boolean containsMasks;
@JsonProperty(STICKERS_FIELD) @JsonProperty(STICKERS_FIELD)
private List<Sticker> stickers; private List<Sticker> stickers;
@JsonProperty(ISANIMATED_FIELD)
private Boolean isAnimated;
public StickerSet() { public StickerSet() {
super(); super();
@ -45,6 +48,10 @@ public class StickerSet implements BotApiObject {
return stickers; return stickers;
} }
public Boolean getAnimated() {
return isAnimated;
}
@Override @Override
public String toString() { public String toString() {
return "StickerSet{" + return "StickerSet{" +
@ -52,6 +59,7 @@ public class StickerSet implements BotApiObject {
", title='" + title + '\'' + ", title='" + title + '\'' +
", containsMasks=" + containsMasks + ", containsMasks=" + containsMasks +
", stickers=" + stickers + ", stickers=" + stickers +
", isAnimated=" + isAnimated +
'}'; '}';
} }
} }

View File

@ -18,11 +18,11 @@
package org.telegram.telegrambots.meta.exceptions; package org.telegram.telegrambots.meta.exceptions;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject; import org.json.JSONObject;
import org.telegram.telegrambots.meta.api.objects.ResponseParameters;
import org.telegram.telegrambots.meta.api.objects.ApiResponse; import org.telegram.telegrambots.meta.api.objects.ApiResponse;
import org.telegram.telegrambots.meta.logging.BotLogger; import org.telegram.telegrambots.meta.api.objects.ResponseParameters;
import java.io.IOException; import java.io.IOException;
@ -33,6 +33,8 @@ import java.io.IOException;
* Exception thrown when something goes wrong in the api * Exception thrown when something goes wrong in the api
*/ */
public class TelegramApiRequestException extends TelegramApiException { public class TelegramApiRequestException extends TelegramApiException {
private static final Logger log = LogManager.getLogger(TelegramApiRequestException.class);
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final String ERRORDESCRIPTIONFIELD = "description"; private static final String ERRORDESCRIPTIONFIELD = "description";
private static final String ERRORCODEFIELD = "error_code"; private static final String ERRORCODEFIELD = "error_code";
@ -54,7 +56,7 @@ public class TelegramApiRequestException extends TelegramApiException {
try { try {
parameters = OBJECT_MAPPER.readValue(object.getJSONObject(PARAMETERSFIELD).toString(), ResponseParameters.class); parameters = OBJECT_MAPPER.readValue(object.getJSONObject(PARAMETERSFIELD).toString(), ResponseParameters.class);
} catch (IOException e) { } catch (IOException e) {
BotLogger.severe("APIEXCEPTION", e); log.fatal(e.getLocalizedMessage(), e);
} }
} }
} }

View File

@ -1,171 +0,0 @@
package org.telegram.telegrambots.meta.logging;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Ruben Bermudez
* @version 2.0
* @brief Logger to file
* @date 21/01/15
*/
public class BotLogger {
private static final Logger logger = Logger.getLogger("Telegram Bots Api");
public static void setLevel(Level level) {
logger.setLevel(level);
}
public static Level getLevel() {
return logger.getLevel();
}
public static void registerLogger(Handler handler) {
logger.addHandler(handler);
}
public static void log(Level level, String tag, String msg) {
logger.log(level, String.format("%s - %s", tag, msg));
}
public static void severe(String tag, String msg) {
logger.severe(String.format("%s - %s", tag, msg));
}
public static void warn(String tag, String msg) {
warning(tag, msg);
}
public static void debug(String tag, String msg) {
fine(tag, msg);
}
public static void error(String tag, String msg) {
severe(tag, msg);
}
public static void trace(String tag, String msg) {
finer(tag, msg);
}
public static void warning(String tag, String msg) {
logger.warning(String.format("%s - %s", tag, msg));
}
public static void info(String tag, String msg) {
logger.info(String.format("%s - %s", tag, msg));
}
public static void config(String tag, String msg) {
logger.config(String.format("%s - %s", tag, msg));
}
public static void fine(String tag, String msg) {
logger.fine(String.format("%s - %s", tag, msg));
}
public static void finer(String tag, String msg) {
logger.finer(String.format("%s - %s", tag, msg));
}
public static void finest(String tag, String msg) {
logger.finest(String.format("%s - %s", tag, msg));
}
public static void log(Level level, String tag, Throwable throwable) {
logger.log(level, tag, throwable);
}
public static void log(Level level, String tag, String msg, Throwable thrown) {
logger.log(level, String.format("%s - %s", tag, msg), thrown);
}
public static void severe(String tag, Throwable throwable) {
logger.log(Level.SEVERE, tag, throwable);
}
public static void warning(String tag, Throwable throwable) {
logger.log(Level.WARNING, tag, throwable);
}
public static void info(String tag, Throwable throwable) {
logger.log(Level.INFO, tag, throwable);
}
public static void config(String tag, Throwable throwable) {
logger.log(Level.CONFIG, tag, throwable);
}
public static void fine(String tag, Throwable throwable) {
logger.log(Level.FINE, tag, throwable);
}
public static void finer(String tag, Throwable throwable) {
logger.log(Level.FINER, tag, throwable);
}
public static void finest(String tag, Throwable throwable) {
logger.log(Level.FINEST, tag, throwable);
}
public static void warn(String tag, Throwable throwable) {
warning(tag, throwable);
}
public static void debug(String tag, Throwable throwable) {
fine(tag, throwable);
}
public static void error(String tag, Throwable throwable) {
severe(tag, throwable);
}
public static void trace(String tag, Throwable throwable) {
finer(tag, throwable);
}
public static void severe(String msg, String tag, Throwable throwable) {
log(Level.SEVERE, tag, msg, throwable);
}
public static void warning(String msg, String tag, Throwable throwable) {
log(Level.WARNING, tag, msg, throwable);
}
public static void info(String msg, String tag, Throwable throwable) {
log(Level.INFO, tag, msg, throwable);
}
public static void config(String msg, String tag, Throwable throwable) {
log(Level.CONFIG, tag, msg, throwable);
}
public static void fine(String msg, String tag, Throwable throwable) {
log(Level.FINE, tag, msg, throwable);
}
public static void finer(String msg, String tag, Throwable throwable) {
log(Level.FINER, tag, msg, throwable);
}
public static void finest(String msg, String tag, Throwable throwable) {
log(Level.FINEST, tag, msg, throwable);
}
public static void warn(String msg, String tag, Throwable throwable) {
log(Level.WARNING, tag, msg, throwable);
}
public static void debug(String msg, String tag, Throwable throwable) {
log(Level.FINE, tag, msg, throwable);
}
public static void error(String msg, String tag, Throwable throwable) {
log(Level.SEVERE, tag, msg, throwable);
}
public static void trace(String msg, String tag, Throwable throwable) {
log(Level.FINER, tag, msg, throwable);
}
}

View File

@ -1,45 +0,0 @@
package org.telegram.telegrambots.meta.logging;
import java.io.IOException;
import java.util.logging.FileHandler;
/**
* @author Ruben Bermudez
* @version 1.0
* @brief Handler to use a file as logs destination with {@link BotLogger}
* @date 19 of May of 2016
*/
public class BotsFileHandler extends FileHandler {
private static final String filePattern = "./TelegramBots%g.%u.log";
public BotsFileHandler() throws IOException, SecurityException {
super(filePattern, 1024 * 1024 * 10, 50, true);
setFormatter(new FileFormatter());
}
public BotsFileHandler(int limit, int count) throws IOException, SecurityException {
super(filePattern, limit, count);
setFormatter(new FileFormatter());
}
public BotsFileHandler(String pattern) throws IOException, SecurityException {
super(pattern);
setFormatter(new FileFormatter());
}
public BotsFileHandler(String pattern, boolean append) throws IOException, SecurityException {
super(pattern, append);
setFormatter(new FileFormatter());
}
public BotsFileHandler(String pattern, int limit, int count) throws IOException, SecurityException {
super(pattern, limit, count);
setFormatter(new FileFormatter());
}
public BotsFileHandler(String pattern, int limit, int count, boolean append) throws IOException, SecurityException {
super(pattern, limit, count, append);
setFormatter(new FileFormatter());
}
}

View File

@ -1,52 +0,0 @@
package org.telegram.telegrambots.meta.logging;
import java.time.LocalDateTime;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
/**
* @author Ruben Bermudez
* @version 1.0
* @brief Formatter for {@link BotsFileHandler}
* @date 19 of May of 2016
*/
class FileFormatter extends Formatter {
@Override
public String format(LogRecord record) {
final LocalDateTime currentDate = LocalDateTime.now();
final String dateForLog = dateFormatterForLogs(currentDate);
String result;
if (record.getThrown() == null) {
result = logMsgToFile(record.getLevel(), record.getMessage(), dateForLog);
} else {
result = logThrowableToFile(record.getLevel(), record.getMessage(), record.getThrown(), dateForLog);
}
return result;
}
private static String dateFormatterForLogs(LocalDateTime dateTime) {
String dateString = "[";
dateString += dateTime.getDayOfMonth() + "_";
dateString += dateTime.getMonthValue() + "_";
dateString += dateTime.getYear() + "_";
dateString += dateTime.getHour() + ":";
dateString += dateTime.getMinute() + ":";
dateString += dateTime.getSecond();
dateString += "] ";
return dateString;
}
private static String logMsgToFile(Level level, String msg, String dateForLog) {
return String.format("%s{%s} %s\n", dateForLog, level.toString(), msg);
}
private static String logThrowableToFile(Level level, String message, Throwable throwable, String dateForLog) {
String throwableLog = String.format("%s{%s} %s - %s\n", dateForLog, level.toString(), message, throwable.toString());
for (StackTraceElement element : throwable.getStackTrace()) {
throwableLog += "\tat " + element + "\n";
}
return throwableLog;
}
}

View File

@ -1,25 +1,26 @@
package org.telegram.telegrambots.meta.api.methods.send; package org.telegram.telegrambots.meta.api.methods.send;
import org.junit.Test; import org.junit.jupiter.api.Test;
import static org.junit.Assert.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
public class SendMessageTest { class SendMessageTest {
@Test @Test
public void comparison() throws Exception { void comparison() {
SendMessage sm1 = new SendMessage().setChatId(1L).setText("Hello World"); SendMessage sm1 = new SendMessage().setChatId(1L).setText("Hello World");
SendMessage sm2 = new SendMessage().setChatId(1L).setText("Hello World"); SendMessage sm2 = new SendMessage().setChatId(1L).setText("Hello World");
SendMessage noMessage = new SendMessage().setChatId(1L); SendMessage noMessage = new SendMessage().setChatId(1L);
SendMessage disabledNotification = new SendMessage().setChatId(1L).setText("Hello World").disableNotification(); SendMessage disabledNotification = new SendMessage().setChatId(1L).setText("Hello World").disableNotification();
assertTrue(sm1.equals(sm2)); assertEquals(sm1, sm2);
assertFalse(sm1.equals(noMessage)); assertNotEquals(sm1, noMessage);
assertFalse(sm1.equals(disabledNotification)); assertNotEquals(sm1, disabledNotification);
assertTrue(sm1.hashCode() == sm2.hashCode()); assertEquals(sm1.hashCode(), sm2.hashCode());
assertFalse(sm1.hashCode() == noMessage.hashCode()); assertNotEquals(sm1.hashCode(), noMessage.hashCode());
assertFalse(sm1.hashCode() == disabledNotification.hashCode()); assertNotEquals(sm1.hashCode(), disabledNotification.hashCode());
} }
} }

View File

@ -1,31 +1,30 @@
package org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons; package org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.hamcrest.core.Is.is; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.Assert.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.Assert.assertTrue;
public class KeyboardRowTest { class KeyboardRowTest {
private static final List<String> BUTTON_NAMES = asList("Carlotta Valdes", "Jimmy Stewart"); private static final List<String> BUTTON_NAMES = asList("Carlotta Valdes", "Jimmy Stewart");
@Test @Test
public void shouldAddAllButtons() { void shouldAddAllButtons() {
final KeyboardRow keyboardRow = new KeyboardRow(); final KeyboardRow keyboardRow = new KeyboardRow();
keyboardRow.addAll(BUTTON_NAMES); keyboardRow.addAll(BUTTON_NAMES);
assertThat(keyboardRow.size(), is(2)); assertEquals(2, keyboardRow.size());
assertThat(keyboardRow.get(0).getText(), is("Carlotta Valdes")); assertEquals("Carlotta Valdes", keyboardRow.get(0).getText());
assertThat(keyboardRow.get(1).getText(), is("Jimmy Stewart")); assertEquals("Jimmy Stewart", keyboardRow.get(1).getText());
} }
@Test @Test
public void shouldAddNoButtons() { void shouldAddNoButtons() {
final KeyboardRow keyboardRow = new KeyboardRow(); final KeyboardRow keyboardRow = new KeyboardRow();
keyboardRow.addAll(new ArrayList<String>()); keyboardRow.addAll(new ArrayList<String>());
assertTrue(keyboardRow.isEmpty()); assertTrue(keyboardRow.isEmpty());

View File

@ -3,9 +3,9 @@ package org.telegram.telegrambots.meta.test;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert; import org.junit.jupiter.api.BeforeEach;
import org.junit.Before; import org.junit.jupiter.api.Test;
import org.junit.Test; import org.telegram.telegrambots.meta.api.objects.ApiResponse;
import org.telegram.telegrambots.meta.api.objects.Audio; import org.telegram.telegrambots.meta.api.objects.Audio;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery; import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.Chat; import org.telegram.telegrambots.meta.api.objects.Chat;
@ -18,63 +18,67 @@ import org.telegram.telegrambots.meta.api.objects.User;
import org.telegram.telegrambots.meta.api.objects.Voice; import org.telegram.telegrambots.meta.api.objects.Voice;
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.ApiResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
*/ */
public class TestDeserialization { class TestDeserialization {
private ObjectMapper mapper; private ObjectMapper mapper;
@Before @BeforeEach
public void setUp() { void setUp() {
mapper = new ObjectMapper(); mapper = new ObjectMapper();
} }
@Test @Test
public void TestUpdateDeserialization() throws Exception { void TestUpdateDeserialization() throws Exception {
Update update = mapper.readValue(TelegramBotsHelper.GetUpdate(), Update.class); Update update = mapper.readValue(TelegramBotsHelper.GetUpdate(), Update.class);
assertUpdate(update); assertUpdate(update);
} }
@Test @Test
public void TestUpdateDeserializationWithInlineKeyboard() throws Exception { void TestUpdateDeserializationWithInlineKeyboard() throws Exception {
Update update = mapper.readValue(TelegramBotsHelper.GetUpdateWithMessageInCallbackQuery(), Update.class); Update update = mapper.readValue(TelegramBotsHelper.GetUpdateWithMessageInCallbackQuery(), Update.class);
Assert.assertNotNull(update); assertNotNull(update);
Assert.assertNotNull(update.getCallbackQuery()); assertNotNull(update.getCallbackQuery());
Assert.assertNotNull(update.getCallbackQuery().getMessage()); assertNotNull(update.getCallbackQuery().getMessage());
Assert.assertNotNull(update.getCallbackQuery().getMessage().getReplyMarkup()); assertNotNull(update.getCallbackQuery().getMessage().getReplyMarkup());
} }
@Test @Test
public void TestResponseWithoutErrorDeserialization() throws IOException { void TestResponseWithoutErrorDeserialization() throws IOException {
ApiResponse<ArrayList<Update>> result = mapper.readValue(TelegramBotsHelper.GetResponseWithoutError(), new TypeReference<ApiResponse<ArrayList<Update>>>(){}); ApiResponse<ArrayList<Update>> result = mapper.readValue(TelegramBotsHelper.GetResponseWithoutError(), new TypeReference<ApiResponse<ArrayList<Update>>>(){});
Assert.assertNotNull(result); assertNotNull(result);
Assert.assertTrue(result.getOk()); assertTrue(result.getOk());
Assert.assertEquals(1, result.getResult().size()); assertEquals(1, result.getResult().size());
assertUpdate(result.getResult().get(0)); assertUpdate(result.getResult().get(0));
} }
@Test @Test
public void TestResponseWithErrorDeserialization() throws IOException { void TestResponseWithErrorDeserialization() throws IOException {
ApiResponse<ArrayList<Update>> result = mapper.readValue(TelegramBotsHelper.GetResponseWithError(), new TypeReference<ApiResponse<ArrayList<Update>>>(){}); ApiResponse<ArrayList<Update>> result = mapper.readValue(TelegramBotsHelper.GetResponseWithError(), new TypeReference<ApiResponse<ArrayList<Update>>>(){});
Assert.assertNotNull(result); assertNotNull(result);
Assert.assertFalse(result.getOk()); assertFalse(result.getOk());
Assert.assertEquals(Integer.valueOf(400), result.getErrorCode()); assertEquals(Integer.valueOf(400), result.getErrorCode());
Assert.assertEquals("Error descriptions", result.getErrorDescription()); assertEquals("Error descriptions", result.getErrorDescription());
Assert.assertNotNull(result.getParameters()); assertNotNull(result.getParameters());
Assert.assertEquals(Long.valueOf(12345), result.getParameters().getMigrateToChatId()); assertEquals(Long.valueOf(12345), result.getParameters().getMigrateToChatId());
Assert.assertEquals(Integer.valueOf(12), result.getParameters().getRetryAfter()); assertEquals(Integer.valueOf(12), result.getParameters().getRetryAfter());
} }
private void assertUpdate(Update update) { private void assertUpdate(Update update) {
Assert.assertNotNull(update); assertNotNull(update);
Assert.assertEquals((Integer) 10000, update.getUpdateId()); assertEquals((Integer) 10000, update.getUpdateId());
assertEditedMessage(update.getEditedMessage()); assertEditedMessage(update.getEditedMessage());
assertCallbackQuery(update.getCallbackQuery()); assertCallbackQuery(update.getCallbackQuery());
assertInlineQuery(update.getInlineQuery()); assertInlineQuery(update.getInlineQuery());
@ -83,11 +87,11 @@ public class TestDeserialization {
} }
private void assertMessage(Message message) { private void assertMessage(Message message) {
Assert.assertNotNull(message); assertNotNull(message);
Assert.assertEquals(Integer.valueOf(1441645532), message.getDate()); assertEquals(Integer.valueOf(1441645532), message.getDate());
Assert.assertEquals(Integer.valueOf(1365), message.getMessageId()); assertEquals(Integer.valueOf(1365), message.getMessageId());
Assert.assertEquals(Integer.valueOf(1441645550), message.getForwardDate()); assertEquals(Integer.valueOf(1441645550), message.getForwardDate());
Assert.assertEquals("Bold and italics", message.getText()); assertEquals("Bold and italics", message.getText());
assertPrivateChat(message.getChat()); assertPrivateChat(message.getChat());
assertFromUser(message.getFrom()); assertFromUser(message.getFrom());
assertForwardFrom(message.getForwardFrom()); assertForwardFrom(message.getForwardFrom());
@ -99,119 +103,119 @@ public class TestDeserialization {
} }
private void assertDocument(Document document) { private void assertDocument(Document document) {
Assert.assertNotNull(document); assertNotNull(document);
Assert.assertEquals("AwADBAADbXXXXXXXXXXXGBdhD2l6_XX", document.getFileId()); assertEquals("AwADBAADbXXXXXXXXXXXGBdhD2l6_XX", document.getFileId());
Assert.assertEquals("Testfile.pdf", document.getFileName()); assertEquals("Testfile.pdf", document.getFileName());
Assert.assertEquals("application/pdf", document.getMimeType()); assertEquals("application/pdf", document.getMimeType());
Assert.assertEquals(Integer.valueOf(536392), document.getFileSize()); assertEquals(Integer.valueOf(536392), document.getFileSize());
} }
private void assertVoice(Voice voice) { private void assertVoice(Voice voice) {
Assert.assertNotNull(voice); assertNotNull(voice);
Assert.assertEquals("AwADBAADbXXXXXXXXXXXGBdhD2l6_XX", voice.getFileId()); assertEquals("AwADBAADbXXXXXXXXXXXGBdhD2l6_XX", voice.getFileId());
Assert.assertEquals(Integer.valueOf(5), voice.getDuration()); assertEquals(Integer.valueOf(5), voice.getDuration());
Assert.assertEquals("audio/ogg", voice.getMimeType()); assertEquals("audio/ogg", voice.getMimeType());
Assert.assertEquals(Integer.valueOf(23000), voice.getFileSize()); assertEquals(Integer.valueOf(23000), voice.getFileSize());
} }
private void assertAudio(Audio audio) { private void assertAudio(Audio audio) {
Assert.assertNotNull(audio); assertNotNull(audio);
Assert.assertEquals("AwADBAADbXXXXXXXXXXXGBdhD2l6_XX", audio.getFileId()); assertEquals("AwADBAADbXXXXXXXXXXXGBdhD2l6_XX", audio.getFileId());
Assert.assertEquals(Integer.valueOf(243), audio.getDuration()); assertEquals(Integer.valueOf(243), audio.getDuration());
Assert.assertEquals("audio/mpeg", audio.getMimeType()); assertEquals("audio/mpeg", audio.getMimeType());
Assert.assertEquals(Integer.valueOf(3897500), audio.getFileSize()); assertEquals(Integer.valueOf(3897500), audio.getFileSize());
Assert.assertEquals("Testmusicfile", audio.getTitle()); assertEquals("Testmusicfile", audio.getTitle());
} }
private void assertEntities(List<MessageEntity> entities) { private void assertEntities(List<MessageEntity> entities) {
Assert.assertNotNull(entities); assertNotNull(entities);
Assert.assertEquals(2, entities.size()); assertEquals(2, entities.size());
Assert.assertEquals(EntityType.ITALIC, entities.get(0).getType()); assertEquals(EntityType.ITALIC, entities.get(0).getType());
Assert.assertEquals(Integer.valueOf(9), entities.get(0).getOffset()); assertEquals(Integer.valueOf(9), entities.get(0).getOffset());
Assert.assertEquals(Integer.valueOf(7), entities.get(0).getLength()); assertEquals(Integer.valueOf(7), entities.get(0).getLength());
Assert.assertEquals("italics", entities.get(0).getText()); assertEquals("italics", entities.get(0).getText());
Assert.assertEquals(EntityType.BOLD, entities.get(1).getType()); assertEquals(EntityType.BOLD, entities.get(1).getType());
Assert.assertEquals(Integer.valueOf(0), entities.get(1).getOffset()); assertEquals(Integer.valueOf(0), entities.get(1).getOffset());
Assert.assertEquals(Integer.valueOf(4), entities.get(1).getLength()); assertEquals(Integer.valueOf(4), entities.get(1).getLength());
Assert.assertEquals("Bold", entities.get(1).getText()); assertEquals("Bold", entities.get(1).getText());
} }
private void assertReplyToMessage(Message replyToMessage) { private void assertReplyToMessage(Message replyToMessage) {
Assert.assertNotNull(replyToMessage); assertNotNull(replyToMessage);
Assert.assertEquals(Integer.valueOf(1441645000), replyToMessage.getDate()); assertEquals(Integer.valueOf(1441645000), replyToMessage.getDate());
Assert.assertEquals(Integer.valueOf(1334), replyToMessage.getMessageId()); assertEquals(Integer.valueOf(1334), replyToMessage.getMessageId());
Assert.assertEquals("Original", replyToMessage.getText()); assertEquals("Original", replyToMessage.getText());
Assert.assertNotNull(replyToMessage.getChat()); assertNotNull(replyToMessage.getChat());
Assert.assertEquals("ReplyLastname", replyToMessage.getChat().getLastName()); assertEquals("ReplyLastname", replyToMessage.getChat().getLastName());
Assert.assertEquals("ReplyFirstname", replyToMessage.getChat().getFirstName()); assertEquals("ReplyFirstname", replyToMessage.getChat().getFirstName());
Assert.assertEquals("Testusername", replyToMessage.getChat().getUserName()); assertEquals("Testusername", replyToMessage.getChat().getUserName());
Assert.assertEquals(Long.valueOf(1111112), replyToMessage.getChat().getId()); assertEquals(Long.valueOf(1111112), replyToMessage.getChat().getId());
} }
private void assertForwardFrom(User forwardFrom) { private void assertForwardFrom(User forwardFrom) {
Assert.assertNotNull(forwardFrom); assertNotNull(forwardFrom);
Assert.assertEquals("ForwardLastname", forwardFrom.getLastName()); assertEquals("ForwardLastname", forwardFrom.getLastName());
Assert.assertEquals("ForwardFirstname", forwardFrom.getFirstName()); assertEquals("ForwardFirstname", forwardFrom.getFirstName());
Assert.assertEquals(Integer.valueOf(222222), forwardFrom.getId()); assertEquals(Integer.valueOf(222222), forwardFrom.getId());
} }
private void assertPrivateChat(Chat chat) { private void assertPrivateChat(Chat chat) {
Assert.assertNotNull(chat); assertNotNull(chat);
Assert.assertEquals(Long.valueOf(1111111), chat.getId()); assertEquals(Long.valueOf(1111111), chat.getId());
Assert.assertTrue(chat.isUserChat()); assertTrue(chat.isUserChat());
Assert.assertEquals("Test Lastname", chat.getLastName()); assertEquals("Test Lastname", chat.getLastName());
Assert.assertEquals("Test Firstname", chat.getFirstName()); assertEquals("Test Firstname", chat.getFirstName());
Assert.assertEquals("Testusername", chat.getUserName()); assertEquals("Testusername", chat.getUserName());
} }
private void assertChosenInlineQuery(ChosenInlineQuery chosenInlineQuery) { private void assertChosenInlineQuery(ChosenInlineQuery chosenInlineQuery) {
Assert.assertNotNull(chosenInlineQuery); assertNotNull(chosenInlineQuery);
Assert.assertEquals("12", chosenInlineQuery.getResultId()); assertEquals("12", chosenInlineQuery.getResultId());
Assert.assertEquals("inline query", chosenInlineQuery.getQuery()); assertEquals("inline query", chosenInlineQuery.getQuery());
Assert.assertEquals("1234csdbsk4839", chosenInlineQuery.getInlineMessageId()); assertEquals("1234csdbsk4839", chosenInlineQuery.getInlineMessageId());
assertFromUser(chosenInlineQuery.getFrom()); assertFromUser(chosenInlineQuery.getFrom());
} }
private void assertInlineQuery(InlineQuery inlineQuery) { private void assertInlineQuery(InlineQuery inlineQuery) {
Assert.assertNotNull(inlineQuery); assertNotNull(inlineQuery);
Assert.assertEquals("134567890097", inlineQuery.getId()); assertEquals("134567890097", inlineQuery.getId());
Assert.assertEquals("inline query", inlineQuery.getQuery()); assertEquals("inline query", inlineQuery.getQuery());
Assert.assertEquals("offset", inlineQuery.getOffset()); assertEquals("offset", inlineQuery.getOffset());
assertFromUser(inlineQuery.getFrom()); assertFromUser(inlineQuery.getFrom());
Assert.assertNotNull(inlineQuery.getLocation()); assertNotNull(inlineQuery.getLocation());
Assert.assertEquals(Float.valueOf("0.234242534"), inlineQuery.getLocation().getLatitude()); assertEquals(Float.valueOf("0.234242534"), inlineQuery.getLocation().getLatitude());
Assert.assertEquals(Float.valueOf("0.234242534"), inlineQuery.getLocation().getLongitude()); assertEquals(Float.valueOf("0.234242534"), inlineQuery.getLocation().getLongitude());
} }
private void assertCallbackQuery(CallbackQuery callbackQuery) { private void assertCallbackQuery(CallbackQuery callbackQuery) {
Assert.assertNotNull(callbackQuery); assertNotNull(callbackQuery);
Assert.assertEquals("4382bfdwdsb323b2d9", callbackQuery.getId()); assertEquals("4382bfdwdsb323b2d9", callbackQuery.getId());
Assert.assertEquals("Data from button callback", callbackQuery.getData()); assertEquals("Data from button callback", callbackQuery.getData());
Assert.assertEquals("1234csdbsk4839", callbackQuery.getInlineMessageId()); assertEquals("1234csdbsk4839", callbackQuery.getInlineMessageId());
assertFromUser(callbackQuery.getFrom()); assertFromUser(callbackQuery.getFrom());
} }
private void assertEditedMessage(Message message) { private void assertEditedMessage(Message message) {
Assert.assertEquals((Integer) 1441645532, message.getDate()); assertEquals((Integer) 1441645532, message.getDate());
Assert.assertEquals((Integer) 1441646600, message.getEditDate()); assertEquals((Integer) 1441646600, message.getEditDate());
Assert.assertEquals((Integer) 1365, message.getMessageId()); assertEquals((Integer) 1365, message.getMessageId());
Assert.assertEquals("Edited text", message.getText()); assertEquals("Edited text", message.getText());
assertChannelChat(message.getChat()); assertChannelChat(message.getChat());
assertFromUser(message.getFrom()); assertFromUser(message.getFrom());
} }
private void assertFromUser(User from) { private void assertFromUser(User from) {
Assert.assertNotNull(from); assertNotNull(from);
Assert.assertEquals((Integer) 1111111, from.getId()); assertEquals((Integer) 1111111, from.getId());
Assert.assertEquals("Test Lastname", from.getLastName()); assertEquals("Test Lastname", from.getLastName());
Assert.assertEquals("Test Firstname", from.getFirstName()); assertEquals("Test Firstname", from.getFirstName());
Assert.assertEquals("Testusername", from.getUserName()); assertEquals("Testusername", from.getUserName());
} }
private void assertChannelChat(Chat chat) { private void assertChannelChat(Chat chat) {
Assert.assertNotNull(chat); assertNotNull(chat);
Assert.assertEquals(Long.valueOf(-10000000000L), chat.getId()); assertEquals(Long.valueOf(-10000000000L), chat.getId());
Assert.assertTrue(chat.isChannelChat()); assertTrue(chat.isChannelChat());
Assert.assertEquals("Test channel", chat.getTitle()); assertEquals("Test channel", chat.getTitle());
} }
} }

View File

@ -1,46 +1,47 @@
package org.telegram.telegrambots.meta.test; package org.telegram.telegrambots.meta.test;
import org.junit.Assert; import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.telegram.telegrambots.meta.TelegramBotsApi; import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.test.base.TestBase;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException; import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.test.base.TestBase;
import static org.junit.jupiter.api.Assertions.fail;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
*/ */
public class TestTelegramApi extends TestBase { class TestTelegramApi extends TestBase {
@Test @Test
public void TestTelegramApiMustBeInitializableForLongPolling() { void TestTelegramApiMustBeInitializableForLongPolling() {
new TelegramBotsApi(); new TelegramBotsApi();
} }
@Test @Test
public void TestTelegramApiMustBeInitializableForWebhookWithoutSecureSupport() { void TestTelegramApiMustBeInitializableForWebhookWithoutSecureSupport() {
try { try {
new TelegramBotsApi("externalUrl", "internalUrl"); new TelegramBotsApi("externalUrl", "internalUrl");
} catch (TelegramApiRequestException e) { } catch (TelegramApiRequestException e) {
Assert.fail(); fail();
} }
} }
@Test @Test
public void TestTelegramApiMustBeInitializableForWebhook() { void TestTelegramApiMustBeInitializableForWebhook() {
try { try {
new TelegramBotsApi("keyStore", "keyStorePassword", "externalUrl", "internalUrl"); new TelegramBotsApi("keyStore", "keyStorePassword", "externalUrl", "internalUrl");
} catch (TelegramApiRequestException e) { } catch (TelegramApiRequestException e) {
Assert.fail(); fail();
} }
} }
@Test @Test
public void TestTelegramApiMustBeInitializableForWebhookWithSelfSignedCertificate() { void TestTelegramApiMustBeInitializableForWebhookWithSelfSignedCertificate() {
try { try {
new TelegramBotsApi("keyStore", "keyStorePassword", "externalUrl", "internalUrl", "selfSignedPath"); new TelegramBotsApi("keyStore", "keyStorePassword", "externalUrl", "internalUrl", "selfSignedPath");
} catch (TelegramApiRequestException e) { } catch (TelegramApiRequestException e) {
Assert.fail(); fail();
} }
} }
} }

View File

@ -1,56 +1,57 @@
package org.telegram.telegrambots.meta.test.apimethods; package org.telegram.telegrambots.meta.test.apimethods;
import org.junit.Assert; import org.junit.jupiter.api.BeforeEach;
import org.junit.Before; import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.telegram.telegrambots.meta.api.methods.AnswerInlineQuery; import org.telegram.telegrambots.meta.api.methods.AnswerInlineQuery;
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException; import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
import java.util.ArrayList; import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
*/ */
public class TestAnswerInlineQuery { class TestAnswerInlineQuery {
private AnswerInlineQuery answerInlineQuery; private AnswerInlineQuery answerInlineQuery;
@Before @BeforeEach
public void setUp() throws Exception { void setUp() {
answerInlineQuery = new AnswerInlineQuery(); answerInlineQuery = new AnswerInlineQuery();
} }
@Test @Test
public void TestInlineQueryIdMustBePresent() throws Exception { void TestInlineQueryIdMustBePresent() {
try { try {
answerInlineQuery.validate(); answerInlineQuery.validate();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
Assert.assertEquals("InlineQueryId can't be empty", e.getMessage()); assertEquals("InlineQueryId can't be empty", e.getMessage());
} }
} }
@Test @Test
public void TestInlineQueryIdCanNotBeEmpty() throws Exception { void TestInlineQueryIdCanNotBeEmpty() {
answerInlineQuery.setInlineQueryId(""); answerInlineQuery.setInlineQueryId("");
try { try {
answerInlineQuery.validate(); answerInlineQuery.validate();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
Assert.assertEquals("InlineQueryId can't be empty", e.getMessage()); assertEquals("InlineQueryId can't be empty", e.getMessage());
} }
} }
@Test @Test
public void TestResultsMustBePresent() throws Exception { void TestResultsMustBePresent() {
answerInlineQuery.setInlineQueryId("RANDOMEID"); answerInlineQuery.setInlineQueryId("RANDOMEID");
try { try {
answerInlineQuery.validate(); answerInlineQuery.validate();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
Assert.assertEquals("Results array can't be null", e.getMessage()); assertEquals("Results array can't be null", e.getMessage());
} }
} }
@Test @Test
public void TestSwitchPmTextCanNotBeEmpty() throws Exception { void TestSwitchPmTextCanNotBeEmpty() {
answerInlineQuery.setInlineQueryId("RANDOMEID"); answerInlineQuery.setInlineQueryId("RANDOMEID");
answerInlineQuery.setResults(new ArrayList<>()); answerInlineQuery.setResults(new ArrayList<>());
answerInlineQuery.setSwitchPmText(""); answerInlineQuery.setSwitchPmText("");
@ -58,12 +59,12 @@ public class TestAnswerInlineQuery {
try { try {
answerInlineQuery.validate(); answerInlineQuery.validate();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
Assert.assertEquals("SwitchPmText can't be empty", e.getMessage()); assertEquals("SwitchPmText can't be empty", e.getMessage());
} }
} }
@Test @Test
public void TestSwitchPmParameterIsMandatoryIfSwitchPmTextIsPresent() throws Exception { void TestSwitchPmParameterIsMandatoryIfSwitchPmTextIsPresent() {
answerInlineQuery.setInlineQueryId("RANDOMEID"); answerInlineQuery.setInlineQueryId("RANDOMEID");
answerInlineQuery.setResults(new ArrayList<>()); answerInlineQuery.setResults(new ArrayList<>());
answerInlineQuery.setSwitchPmText("Test Text"); answerInlineQuery.setSwitchPmText("Test Text");
@ -71,12 +72,12 @@ public class TestAnswerInlineQuery {
try { try {
answerInlineQuery.validate(); answerInlineQuery.validate();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
Assert.assertEquals("SwitchPmParameter can't be empty if switchPmText is present", e.getMessage()); assertEquals("SwitchPmParameter can't be empty if switchPmText is present", e.getMessage());
} }
} }
@Test @Test
public void TestSwitchPmParameterCanNotBeEmptyIfSwitchPmTextIsPresent() throws Exception { void TestSwitchPmParameterCanNotBeEmptyIfSwitchPmTextIsPresent() {
answerInlineQuery.setInlineQueryId("RANDOMEID"); answerInlineQuery.setInlineQueryId("RANDOMEID");
answerInlineQuery.setResults(new ArrayList<>()); answerInlineQuery.setResults(new ArrayList<>());
answerInlineQuery.setSwitchPmText("Test Text"); answerInlineQuery.setSwitchPmText("Test Text");
@ -85,12 +86,12 @@ public class TestAnswerInlineQuery {
try { try {
answerInlineQuery.validate(); answerInlineQuery.validate();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
Assert.assertEquals("SwitchPmParameter can't be empty if switchPmText is present", e.getMessage()); assertEquals("SwitchPmParameter can't be empty if switchPmText is present", e.getMessage());
} }
} }
@Test @Test
public void TestSwitchPmParameterContainsUpTo64Chars() throws Exception { void TestSwitchPmParameterContainsUpTo64Chars() {
answerInlineQuery.setInlineQueryId("RANDOMEID"); answerInlineQuery.setInlineQueryId("RANDOMEID");
answerInlineQuery.setResults(new ArrayList<>()); answerInlineQuery.setResults(new ArrayList<>());
answerInlineQuery.setSwitchPmText("Test Text"); answerInlineQuery.setSwitchPmText("Test Text");
@ -99,12 +100,12 @@ public class TestAnswerInlineQuery {
try { try {
answerInlineQuery.validate(); answerInlineQuery.validate();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
Assert.assertEquals("SwitchPmParameter can't be longer than 64 chars", e.getMessage()); assertEquals("SwitchPmParameter can't be longer than 64 chars", e.getMessage());
} }
} }
@Test @Test
public void TestSwitchPmParameterOnlyContainsAcceptedCharacters() throws Exception { void TestSwitchPmParameterOnlyContainsAcceptedCharacters() {
answerInlineQuery.setInlineQueryId("RANDOMEID"); answerInlineQuery.setInlineQueryId("RANDOMEID");
answerInlineQuery.setResults(new ArrayList<>()); answerInlineQuery.setResults(new ArrayList<>());
answerInlineQuery.setSwitchPmText("Test Text"); answerInlineQuery.setSwitchPmText("Test Text");
@ -113,7 +114,7 @@ public class TestAnswerInlineQuery {
try { try {
answerInlineQuery.validate(); answerInlineQuery.validate();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
Assert.assertEquals("SwitchPmParameter only allows A-Z, a-z, 0-9, _ and - characters", e.getMessage()); assertEquals("SwitchPmParameter only allows A-Z, a-z, 0-9, _ and - characters", e.getMessage());
} }
} }
} }

View File

@ -2,27 +2,29 @@ package org.telegram.telegrambots.meta.test.apimethods;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert; import org.junit.jupiter.api.BeforeEach;
import org.junit.Before; import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.telegram.telegrambots.meta.test.TelegramBotsHelper;
import org.telegram.telegrambots.meta.api.methods.updates.GetUpdates; import org.telegram.telegrambots.meta.api.methods.updates.GetUpdates;
import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException; import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.test.TelegramBotsHelper;
import java.util.ArrayList; import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
*/ */
public class TestGetUpdates { class TestGetUpdates {
private GetUpdates getUpdates; private GetUpdates getUpdates;
private ObjectMapper mapper = new ObjectMapper(); private ObjectMapper mapper = new ObjectMapper();
@Before @BeforeEach
public void setUp() throws Exception { void setUp() {
getUpdates = new GetUpdates(); getUpdates = new GetUpdates();
getUpdates.setOffset(15); getUpdates.setOffset(15);
getUpdates.setTimeout(50); getUpdates.setTimeout(50);
@ -30,28 +32,28 @@ public class TestGetUpdates {
} }
@Test @Test
public void TestGetUpdatesMustBeSerializable() throws Exception { void TestGetUpdatesMustBeSerializable() throws Exception {
String json = mapper.writeValueAsString(getUpdates); String json = mapper.writeValueAsString(getUpdates);
Assert.assertNotNull(json); assertNotNull(json);
Assert.assertEquals("{\"offset\":15,\"limit\":100,\"timeout\":50,\"method\":\"getupdates\"}", json); assertEquals("{\"offset\":15,\"limit\":100,\"timeout\":50,\"method\":\"getupdates\"}", json);
} }
@Test @Test
public void TestGetUpdatesMustDeserializeCorrectResponse() throws Exception { void TestGetUpdatesMustDeserializeCorrectResponse() throws Exception {
ArrayList<Update> result = ArrayList<Update> result =
getUpdates.deserializeResponse(TelegramBotsHelper.GetResponseWithoutError()); getUpdates.deserializeResponse(TelegramBotsHelper.GetResponseWithoutError());
Assert.assertNotNull(result); assertNotNull(result);
Assert.assertEquals(1, result.size()); assertEquals(1, result.size());
} }
@Test @Test
public void TestGetUpdatesMustThrowAnExceptionForInCorrectResponse() { void TestGetUpdatesMustThrowAnExceptionForInCorrectResponse() {
try { try {
getUpdates.deserializeResponse(TelegramBotsHelper.GetResponseWithError()); getUpdates.deserializeResponse(TelegramBotsHelper.GetResponseWithError());
} catch (TelegramApiRequestException e) { } catch (TelegramApiRequestException e) {
Assert.assertNotNull(e.getParameters()); assertNotNull(e.getParameters());
Assert.assertEquals(Integer.valueOf(400), e.getErrorCode()); assertEquals(Integer.valueOf(400), e.getErrorCode());
Assert.assertEquals("Error descriptions", e.getApiResponse()); assertEquals("Error descriptions", e.getApiResponse());
} }
} }
} }

View File

@ -2,26 +2,29 @@ package org.telegram.telegrambots.meta.test.apimethods;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert; import org.junit.jupiter.api.BeforeEach;
import org.junit.Before; import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.telegram.telegrambots.meta.test.TelegramBotsHelper;
import org.telegram.telegrambots.meta.api.methods.games.SetGameScore; import org.telegram.telegrambots.meta.api.methods.games.SetGameScore;
import org.telegram.telegrambots.meta.api.objects.Message; import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.test.TelegramBotsHelper;
import java.io.Serializable; import java.io.Serializable;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
*/ */
public class TestSetGameScore { class TestSetGameScore {
private SetGameScore setGameScore; private SetGameScore setGameScore;
private ObjectMapper mapper = new ObjectMapper(); private ObjectMapper mapper = new ObjectMapper();
@Before @BeforeEach
public void setUp() throws Exception { void setUp() {
setGameScore = new SetGameScore(); setGameScore = new SetGameScore();
setGameScore.setChatId("12345"); setGameScore.setChatId("12345");
setGameScore.setDisableEditMessage(true); setGameScore.setDisableEditMessage(true);
@ -31,25 +34,25 @@ public class TestSetGameScore {
} }
@Test @Test
public void TestGetUpdatesMustBeSerializable() throws Exception { void TestGetUpdatesMustBeSerializable() throws Exception {
String json = mapper.writeValueAsString(setGameScore); String json = mapper.writeValueAsString(setGameScore);
Assert.assertNotNull(json); assertNotNull(json);
Assert.assertEquals("{\"chat_id\":\"12345\",\"message_id\":54321,\"disable_edit_message\":true,\"user_id\":98765,\"score\":12,\"method\":\"setGameScore\"}", json); assertEquals("{\"chat_id\":\"12345\",\"message_id\":54321,\"disable_edit_message\":true,\"user_id\":98765,\"score\":12,\"method\":\"setGameScore\"}", json);
} }
@Test @Test
public void TestGetUpdatesMustDeserializeCorrectResponse() throws Exception { void TestGetUpdatesMustDeserializeCorrectResponse() throws Exception {
Serializable result = Serializable result =
setGameScore.deserializeResponse(TelegramBotsHelper.GetSetGameScoreBooleanResponse()); setGameScore.deserializeResponse(TelegramBotsHelper.GetSetGameScoreBooleanResponse());
Assert.assertNotNull(result); assertNotNull(result);
Assert.assertTrue(result instanceof Boolean); assertTrue(result instanceof Boolean);
Assert.assertTrue((Boolean) result); assertTrue((Boolean) result);
} }
@Test @Test
public void TestGetUpdatesMustThrowAnExceptionForInCorrectResponse() throws Exception { void TestGetUpdatesMustThrowAnExceptionForInCorrectResponse() throws Exception {
Serializable result = setGameScore.deserializeResponse(TelegramBotsHelper.GetSetGameScoreMessageResponse()); Serializable result = setGameScore.deserializeResponse(TelegramBotsHelper.GetSetGameScoreMessageResponse());
Assert.assertNotNull(result); assertNotNull(result);
Assert.assertTrue(result instanceof Message); assertTrue(result instanceof Message);
} }
} }

View File

@ -1,11 +1,11 @@
package org.telegram.telegrambots.meta.test.base; package org.telegram.telegrambots.meta.test.base;
import org.junit.BeforeClass; import org.junit.jupiter.api.BeforeAll;
import org.telegram.telegrambots.meta.ApiContext; import org.telegram.telegrambots.meta.ApiContext;
import org.telegram.telegrambots.meta.test.fakes.FakeBotSession;
import org.telegram.telegrambots.meta.test.fakes.FakeWebhook;
import org.telegram.telegrambots.meta.generics.BotSession; import org.telegram.telegrambots.meta.generics.BotSession;
import org.telegram.telegrambots.meta.generics.Webhook; import org.telegram.telegrambots.meta.generics.Webhook;
import org.telegram.telegrambots.meta.test.fakes.FakeBotSession;
import org.telegram.telegrambots.meta.test.fakes.FakeWebhook;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
@ -13,7 +13,7 @@ import org.telegram.telegrambots.meta.generics.Webhook;
*/ */
public abstract class TestBase { public abstract class TestBase {
@BeforeClass @BeforeAll
public static void beforeClass() { public static void beforeClass() {
ApiContext.register(BotSession.class, FakeBotSession.class); ApiContext.register(BotSession.class, FakeBotSession.class);
ApiContext.register(Webhook.class, FakeWebhook.class); ApiContext.register(Webhook.class, FakeWebhook.class);

View File

@ -3,9 +3,14 @@
xmlns="http://maven.apache.org/POM/4.0.0" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId>
<parent>
<groupId>org.telegram</groupId>
<artifactId>Bots</artifactId>
<version>4.4.0</version>
</parent>
<artifactId>telegrambots-spring-boot-starter</artifactId> <artifactId>telegrambots-spring-boot-starter</artifactId>
<version>4.3.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots Spring Boot Starter</name> <name>Telegram Bots Spring Boot Starter</name>
@ -57,9 +62,15 @@
</distributionManagement> </distributionManagement>
<properties> <properties>
<java.version>11</java.version>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.0.2.RELEASE</spring-boot.version>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
</properties> </properties>
<dependencies> <dependencies>
@ -67,7 +78,7 @@
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -92,23 +103,8 @@
<groupId>org.assertj</groupId> <groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId> <artifactId>assertj-core</artifactId>
<scope>test</scope> <scope>test</scope>
<version>3.9.1</version> <version>3.13.1</version>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -121,7 +117,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version> <version>1.6</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@ -135,7 +131,7 @@
<plugin> <plugin>
<groupId>org.sonatype.plugins</groupId> <groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId> <artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version> <version>1.6.8</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<serverId>ossrh</serverId> <serverId>ossrh</serverId>
@ -145,7 +141,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<id>clean-project</id> <id>clean-project</id>
@ -158,7 +154,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version> <version>3.1.1</version>
<configuration> <configuration>
<descriptorRefs> <descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <descriptorRef>jar-with-dependencies</descriptorRef>
@ -177,7 +173,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -189,14 +185,14 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
<configuration> <configuration>
<additionalparam>-Xdoclint:none</additionalparam> <doclint>none</doclint>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@ -204,7 +200,7 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version> <version>0.8.4</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -223,7 +219,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version> <version>3.0.0-M2</version>
<executions> <executions>
<execution> <execution>
<id>enforce-versions</id> <id>enforce-versions</id>
@ -241,7 +237,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version> <version>3.1.1</version>
<executions> <executions>
<execution> <execution>
<id>copy</id> <id>copy</id>
@ -249,15 +245,21 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
</plugins> </plugins>
<pluginManagement> <pluginManagement>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration> <configuration>
<source>1.8</source> <source>${java.version}</source>
<target>1.8</target> <target>${java.version}</target>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
</plugin> </plugin>

View File

@ -1,12 +1,13 @@
package org.telegram.telegrambots.starter; package org.telegram.telegrambots.starter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.telegram.telegrambots.meta.TelegramBotsApi; import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.generics.BotSession; import org.telegram.telegrambots.meta.generics.BotSession;
import org.telegram.telegrambots.meta.generics.LongPollingBot; import org.telegram.telegrambots.meta.generics.LongPollingBot;
import org.telegram.telegrambots.meta.generics.WebhookBot; import org.telegram.telegrambots.meta.generics.WebhookBot;
import org.telegram.telegrambots.meta.logging.BotLogger;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -20,6 +21,7 @@ import static java.lang.String.format;
* Receives all beand which are #LongPollingBot and #WebhookBot and register them in #TelegramBotsApi. * Receives all beand which are #LongPollingBot and #WebhookBot and register them in #TelegramBotsApi.
*/ */
public class TelegramBotInitializer implements InitializingBean { public class TelegramBotInitializer implements InitializingBean {
private static final Logger log = LogManager.getLogger(TelegramBotInitializer.class);
private final TelegramBotsApi telegramBotsApi; private final TelegramBotsApi telegramBotsApi;
private final List<LongPollingBot> longPollingBots; private final List<LongPollingBot> longPollingBots;
@ -37,7 +39,7 @@ public class TelegramBotInitializer implements InitializingBean {
} }
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() {
try { try {
for (LongPollingBot bot : longPollingBots) { for (LongPollingBot bot : longPollingBots) {
BotSession session = telegramBotsApi.registerBot(bot); BotSession session = telegramBotsApi.registerBot(bot);
@ -54,12 +56,8 @@ public class TelegramBotInitializer implements InitializingBean {
private void handleAnnotatedMethod(Object bot, Method method, BotSession session) { private void handleAnnotatedMethod(Object bot, Method method, BotSession session) {
try { try {
if (method.getParameterCount() > 1) { if (method.getParameterCount() > 1) {
BotLogger.warn(this.getClass().getSimpleName(), log.warn(format("Method %s of Type %s has too many parameters",
format("Method %s of Type %s has too many parameters", method.getName(), method.getDeclaringClass().getCanonicalName()));
method.getName(),
method.getDeclaringClass().getCanonicalName()
)
);
return; return;
} }
if (method.getParameterCount() == 0) { if (method.getParameterCount() == 0) {
@ -70,18 +68,11 @@ public class TelegramBotInitializer implements InitializingBean {
method.invoke(bot, session); method.invoke(bot, session);
return; return;
} }
BotLogger.warn(this.getClass().getSimpleName(), log.warn(format("Method %s of Type %s has invalid parameter type",
format("Method %s of Type %s has invalid parameter type", method.getName(), method.getDeclaringClass().getCanonicalName()));
method.getName(),
method.getDeclaringClass().getCanonicalName()
)
);
} catch (InvocationTargetException | IllegalAccessException e) { } catch (InvocationTargetException | IllegalAccessException e) {
BotLogger.error(this.getClass().getSimpleName(), log.error(format("Couldn't invoke Method %s of Type %s",
format("Couldn't invoke Method %s of Type %s", method.getName(), method.getDeclaringClass().getCanonicalName()));
method.getName(), method.getDeclaringClass().getCanonicalName()
)
);
} }
} }

View File

@ -1,10 +1,6 @@
package org.telegram.telegrambots.starter; package org.telegram.telegrambots.starter;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import static org.mockito.Mockito.*;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -13,13 +9,19 @@ import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.generics.LongPollingBot; import org.telegram.telegrambots.meta.generics.LongPollingBot;
import org.telegram.telegrambots.meta.generics.WebhookBot; import org.telegram.telegrambots.meta.generics.WebhookBot;
public class TestTelegramBotStarterConfiguration { import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
class TestTelegramBotStarterConfiguration {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MockTelegramBotsApi.class, TelegramBotStarterConfiguration.class)); .withConfiguration(AutoConfigurations.of(MockTelegramBotsApi.class, TelegramBotStarterConfiguration.class));
@Test @Test
public void createMockTelegramBotsApiWithDefaultSettings() { void createMockTelegramBotsApiWithDefaultSettings() {
this.contextRunner.run((context) -> { this.contextRunner.run((context) -> {
assertThat(context).hasSingleBean(TelegramBotsApi.class); assertThat(context).hasSingleBean(TelegramBotsApi.class);
assertThat(context).hasSingleBean(TelegramBotInitializer.class); assertThat(context).hasSingleBean(TelegramBotInitializer.class);
@ -30,7 +32,7 @@ public class TestTelegramBotStarterConfiguration {
} }
@Test @Test
public void createOnlyLongPollingBot() { void createOnlyLongPollingBot() {
this.contextRunner.withUserConfiguration(LongPollingBotConfig.class) this.contextRunner.withUserConfiguration(LongPollingBotConfig.class)
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(LongPollingBot.class); assertThat(context).hasSingleBean(LongPollingBot.class);
@ -44,7 +46,7 @@ public class TestTelegramBotStarterConfiguration {
} }
@Test @Test
public void createOnlyWebhookBot() { void createOnlyWebhookBot() {
this.contextRunner.withUserConfiguration(WebhookBotConfig.class) this.contextRunner.withUserConfiguration(WebhookBotConfig.class)
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(WebhookBot.class); assertThat(context).hasSingleBean(WebhookBot.class);
@ -58,7 +60,7 @@ public class TestTelegramBotStarterConfiguration {
} }
@Test @Test
public void createLongPoolingBotAndWebhookBot() { void createLongPoolingBotAndWebhookBot() {
this.contextRunner.withUserConfiguration(LongPollingBotConfig.class, WebhookBotConfig.class) this.contextRunner.withUserConfiguration(LongPollingBotConfig.class, WebhookBotConfig.class)
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(LongPollingBot.class); assertThat(context).hasSingleBean(LongPollingBot.class);

View File

@ -1,7 +1,6 @@
package org.telegram.telegrambots.starter; package org.telegram.telegrambots.starter;
import org.junit.jupiter.api.Test;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -15,9 +14,14 @@ import org.telegram.telegrambots.meta.generics.LongPollingBot;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession; import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
public class TestTelegramBotStarterRegistrationHooks { class TestTelegramBotStarterRegistrationHooks {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MockTelegramBotsApi.class, TelegramBotStarterConfiguration.class)); .withConfiguration(AutoConfigurations.of(MockTelegramBotsApi.class, TelegramBotStarterConfiguration.class));
@ -30,7 +34,7 @@ public class TestTelegramBotStarterRegistrationHooks {
private static final TelegramBotsApi mockTelegramBotsApi = mock(TelegramBotsApi.class); private static final TelegramBotsApi mockTelegramBotsApi = mock(TelegramBotsApi.class);
@Test @Test
public void longPollingBotWithAnnotatedMethodshouldBeCalled() throws TelegramApiRequestException { void longPollingBotWithAnnotatedMethodshouldBeCalled() throws TelegramApiRequestException {
when(mockTelegramBotsApi.registerBot(any(LongPollingBot.class))).thenReturn(someBotSession); when(mockTelegramBotsApi.registerBot(any(LongPollingBot.class))).thenReturn(someBotSession);

View File

@ -3,9 +3,14 @@
xmlns="http://maven.apache.org/POM/4.0.0" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.telegram</groupId>
<parent>
<groupId>org.telegram</groupId>
<artifactId>Bots</artifactId>
<version>4.4.0</version>
</parent>
<artifactId>telegrambots</artifactId> <artifactId>telegrambots</artifactId>
<version>4.3.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Telegram Bots</name> <name>Telegram Bots</name>
@ -57,15 +62,21 @@
</distributionManagement> </distributionManagement>
<properties> <properties>
<java.version>11</java.version>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<glassfish.version>2.25.1</glassfish.version>
<glassfish.version>2.29</glassfish.version>
<jerseybundle.version>1.19.3</jerseybundle.version> <jerseybundle.version>1.19.3</jerseybundle.version>
<httpcompontents.version>4.5.3</httpcompontents.version> <httpcompontents.version>4.5.9</httpcompontents.version>
<json.version>20180813</json.version> <json.version>20180813</json.version>
<jackson.version>2.9.9</jackson.version> <jackson.version>2.9.9</jackson.version>
<jacksonanotation.version>2.9.0</jacksonanotation.version> <jacksonanotation.version>2.9.9</jacksonanotation.version>
<commonio.version>2.5</commonio.version> <commonio.version>2.6</commonio.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@ -84,7 +95,7 @@
<dependency> <dependency>
<groupId>org.telegram</groupId> <groupId>org.telegram</groupId>
<artifactId>telegrambots-meta</artifactId> <artifactId>telegrambots-meta</artifactId>
<version>4.3.1</version> <version>4.4.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
@ -96,26 +107,26 @@
<artifactId>jackson-jaxrs-json-provider</artifactId> <artifactId>jackson-jaxrs-json-provider</artifactId>
<version>${jackson.version}</version> <version>${jackson.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.9.9</version>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version> <version>${jackson.version}</version>
<exclusions> </dependency>
<exclusion> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jackson-annotations</artifactId> <artifactId>jersey-hk2</artifactId>
</exclusion> <version>${glassfish.version}</version>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.glassfish.jersey.media</groupId> <groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId> <artifactId>jersey-media-json-jackson</artifactId>
<version>${glassfish.version}</version> <version>${glassfish.version}</version>
<exclusions> <exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
<exclusion> <exclusion>
<groupId>com.fasterxml.jackson.jaxrs</groupId> <groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId> <artifactId>jackson-jaxrs-json-provider</artifactId>
@ -169,12 +180,6 @@
<version>${glassfish.version}</version> <version>${glassfish.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>2.0.2-beta</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -184,10 +189,15 @@
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId> <artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version> <version>1.6</version>
<executions> <executions>
<execution> <execution>
<id>sign-artifacts</id> <id>sign-artifacts</id>
@ -201,7 +211,7 @@
<plugin> <plugin>
<groupId>org.sonatype.plugins</groupId> <groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId> <artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version> <version>1.6.8</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<serverId>ossrh</serverId> <serverId>ossrh</serverId>
@ -211,7 +221,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-clean-plugin</artifactId> <artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<id>clean-project</id> <id>clean-project</id>
@ -224,7 +234,7 @@
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version> <version>3.1.1</version>
<configuration> <configuration>
<descriptorRefs> <descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef> <descriptorRef>jar-with-dependencies</descriptorRef>
@ -243,7 +253,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -255,14 +265,14 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version> <version>3.1.0</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
<configuration> <configuration>
<additionalparam>-Xdoclint:none</additionalparam> <doclint>none</doclint>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@ -270,7 +280,7 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</version> <version>0.8.4</version>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -289,7 +299,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version> <version>3.0.0-M2</version>
<executions> <executions>
<execution> <execution>
<id>enforce-versions</id> <id>enforce-versions</id>
@ -307,7 +317,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version> <version>3.1.1</version>
<executions> <executions>
<execution> <execution>
<id>copy</id> <id>copy</id>
@ -321,9 +331,10 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration> <configuration>
<source>1.8</source> <source>${java.version}</source>
<target>1.8</target> <target>${java.version}</target>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
</plugin> </plugin>

View File

@ -2,7 +2,6 @@ package org.telegram.telegrambots.bots;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
@ -14,6 +13,7 @@ import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.telegram.telegrambots.facilities.TelegramHttpClientBuilder; import org.telegram.telegrambots.facilities.TelegramHttpClientBuilder;
import org.telegram.telegrambots.facilities.filedownloader.TelegramFileDownloader;
import org.telegram.telegrambots.meta.api.methods.BotApiMethod; import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
import org.telegram.telegrambots.meta.api.methods.groupadministration.SetChatPhoto; import org.telegram.telegrambots.meta.api.methods.groupadministration.SetChatPhoto;
import org.telegram.telegrambots.meta.api.methods.send.*; import org.telegram.telegrambots.meta.api.methods.send.*;
@ -36,10 +36,9 @@ import org.telegram.telegrambots.meta.updateshandlers.DownloadFileCallback;
import org.telegram.telegrambots.meta.updateshandlers.SentCallback; import org.telegram.telegrambots.meta.updateshandlers.SentCallback;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -52,7 +51,7 @@ import static org.telegram.telegrambots.Constants.SOCKET_TIMEOUT;
* @version 1.0 * @version 1.0
* Implementation of all the methods needed to interact with Telegram Servers * Implementation of all the methods needed to interact with Telegram Servers
*/ */
@SuppressWarnings({"unused", "WeakerAccess"}) @SuppressWarnings({"unused"})
public abstract class DefaultAbsSender extends AbsSender { public abstract class DefaultAbsSender extends AbsSender {
private static final ContentType TEXT_PLAIN_CONTENT_TYPE = ContentType.create("text/plain", StandardCharsets.UTF_8); private static final ContentType TEXT_PLAIN_CONTENT_TYPE = ContentType.create("text/plain", StandardCharsets.UTF_8);
@ -61,6 +60,7 @@ public abstract class DefaultAbsSender extends AbsSender {
private final DefaultBotOptions options; private final DefaultBotOptions options;
private volatile CloseableHttpClient httpClient; private volatile CloseableHttpClient httpClient;
private volatile RequestConfig requestConfig; private volatile RequestConfig requestConfig;
private final TelegramFileDownloader telegramFileDownloader = new TelegramFileDownloader(this::getBotToken);
protected DefaultAbsSender(DefaultBotOptions options) { protected DefaultAbsSender(DefaultBotOptions options) {
super(); super();
@ -109,37 +109,35 @@ public abstract class DefaultAbsSender extends AbsSender {
// Send Requests // Send Requests
public final java.io.File downloadFile(String filePath) throws TelegramApiException { public final java.io.File downloadFile(String filePath) throws TelegramApiException {
if(filePath == null || filePath.isEmpty()){ return telegramFileDownloader.downloadFile(filePath);
throw new TelegramApiException("Parameter file can not be null");
}
String url = File.getFileUrl(getBotToken(), filePath);
String tempFileName = Long.toString(System.currentTimeMillis());
return downloadToTemporaryFileWrappingExceptions(url, tempFileName);
} }
public final java.io.File downloadFile(File file) throws TelegramApiException { public final java.io.File downloadFile(File file) throws TelegramApiException {
assertParamNotNull(file, "file"); return telegramFileDownloader.downloadFile(file);
String url = file.getFileUrl(getBotToken()); }
String tempFileName = file.getFileId();
return downloadToTemporaryFileWrappingExceptions(url, tempFileName); public final java.io.File downloadFile(File file, java.io.File outputFile) throws TelegramApiException {
return telegramFileDownloader.downloadFile(file, outputFile);
}
public final java.io.File downloadFile(String filePath, java.io.File outputFile) throws TelegramApiException {
return telegramFileDownloader.downloadFile(filePath, outputFile);
} }
public final void downloadFileAsync(String filePath, DownloadFileCallback<String> callback) throws TelegramApiException { public final void downloadFileAsync(String filePath, DownloadFileCallback<String> callback) throws TelegramApiException {
if(filePath == null || filePath.isEmpty()){ telegramFileDownloader.downloadFileAsync(filePath, callback);
throw new TelegramApiException("Parameter filePath can not be null");
}
assertParamNotNull(callback, "callback");
String url = File.getFileUrl(getBotToken(), filePath);
String tempFileName = Long.toString(System.currentTimeMillis());
exe.submit(getDownloadFileAsyncJob(filePath, callback, url, tempFileName));
} }
public final void downloadFileAsync(File file, DownloadFileCallback<File> callback) throws TelegramApiException { public final void downloadFileAsync(File file, DownloadFileCallback<File> callback) throws TelegramApiException {
assertParamNotNull(file, "file"); telegramFileDownloader.downloadFileAsync(file, callback);
assertParamNotNull(callback, "callback"); }
String url = file.getFileUrl(getBotToken());
String tempFileName = file.getFileId(); public final InputStream downloadFileAsStream(String filePath) throws TelegramApiException {
exe.submit(getDownloadFileAsyncJob(file, callback, url, tempFileName)); return telegramFileDownloader.downloadFileAsStream(filePath);
}
public final InputStream downloadFileAsStream(File file) throws TelegramApiException {
return telegramFileDownloader.downloadFileAsStream(file);
} }
// Specific Send Requests // Specific Send Requests
@ -720,38 +718,6 @@ public abstract class DefaultAbsSender extends AbsSender {
} }
} }
private <T> Runnable getDownloadFileAsyncJob(T fileIdentifier, DownloadFileCallback<T> callback, String url, String tempFileName) {
//noinspection Convert2Lambda
return new Runnable() {
@Override
public void run() {
try {
callback.onResult(fileIdentifier, downloadToTemporaryFile(url, tempFileName));
} catch (MalformedURLException e) {
callback.onException(fileIdentifier, new TelegramApiException("Wrong url for file: " + url));
} catch (IOException e) {
callback.onException(fileIdentifier, new TelegramApiRequestException("Error downloading the file", e));
}
}
};
}
private java.io.File downloadToTemporaryFileWrappingExceptions(String url, String tempFileName) throws TelegramApiException {
try {
return downloadToTemporaryFile(url, tempFileName);
} catch (MalformedURLException e) {
throw new TelegramApiException("Wrong url for file: " + url);
} catch (IOException e) {
throw new TelegramApiRequestException("Error downloading the file", e);
}
}
private java.io.File downloadToTemporaryFile(String url, String tempFileName) throws IOException {
java.io.File output = java.io.File.createTempFile(tempFileName, ".tmp");
FileUtils.copyURLToFile(new URL(url), output);
return output;
}
private <T extends Serializable, Method extends BotApiMethod<T>> String sendMethodRequest(Method method) throws TelegramApiValidationException, IOException { private <T extends Serializable, Method extends BotApiMethod<T>> String sendMethodRequest(Method method) throws TelegramApiValidationException, IOException {
method.validate(); method.validate();
String url = getBaseUrl() + method.getMethod(); String url = getBaseUrl() + method.getMethod();

View File

@ -0,0 +1,11 @@
package org.telegram.telegrambots.facilities.filedownloader;
/**
* Runtime Exception to wrap Exceptions thrown during file download
*/
@SuppressWarnings("WeakerAccess")
public class DownloadFileException extends RuntimeException {
public DownloadFileException(final String message, final Throwable e) {
super(message, e);
}
}

View File

@ -0,0 +1,172 @@
package org.telegram.telegrambots.facilities.filedownloader;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.telegram.telegrambots.meta.api.objects.File;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.updateshandlers.DownloadFileCallback;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;
import static org.apache.commons.io.FileUtils.copyInputStreamToFile;
import static org.apache.http.HttpStatus.SC_OK;
/**
* Wraps the file downloading code into one class.
* @author Chase22
* @version 1.0
*/
public class TelegramFileDownloader {
private final HttpClient httpClient;
private final Supplier<String> botTokenSupplier;
public TelegramFileDownloader(final Supplier<String> botTokenSupplier) {
this.botTokenSupplier = botTokenSupplier;
httpClient = HttpClients.createDefault();
}
public TelegramFileDownloader(final HttpClient httpClient, final Supplier<String> botTokenSupplier) {
this.httpClient = httpClient;
this.botTokenSupplier = botTokenSupplier;
}
public final java.io.File downloadFile(String filePath) throws TelegramApiException {
String tempFileName = Long.toString(System.currentTimeMillis());
return downloadFile(filePath, getTempFile(tempFileName));
}
public final java.io.File downloadFile(File file) throws TelegramApiException {
return downloadFile(file, getTempFile(file.getFileId()));
}
public final java.io.File downloadFile(File file, java.io.File outputFile) throws TelegramApiException {
if (file == null) {
throw new TelegramApiException("Parameter file can not be null");
}
String url = file.getFileUrl(botTokenSupplier.get());
return downloadToFile(url, outputFile);
}
public final java.io.File downloadFile(String filePath, java.io.File outputFile) throws TelegramApiException {
if (filePath == null || filePath.isEmpty()) {
throw new TelegramApiException("Parameter file can not be null");
}
String url = File.getFileUrl(botTokenSupplier.get(), filePath);
return downloadToFile(url, outputFile);
}
public final InputStream downloadFileAsStream(String filePath) throws TelegramApiException {
try {
return getFileDownloadStreamFuture(File.getFileUrl(botTokenSupplier.get(), filePath)).get();
} catch (InterruptedException e) {
throw new TelegramApiException("Error downloading file", e);
} catch (ExecutionException e) {
throw new TelegramApiException("Error downloading file", e.getCause());
}
}
public final InputStream downloadFileAsStream(File file) throws TelegramApiException {
try {
return getFileDownloadStreamFuture(file.getFileUrl(botTokenSupplier.get())).get();
} catch (InterruptedException e) {
throw new TelegramApiException("Error downloading file", e);
} catch (ExecutionException e) {
throw new TelegramApiException("Error downloading file", e.getCause());
}
}
public final void downloadFileAsync(String filePath, DownloadFileCallback<String> callback) throws TelegramApiException {
if (filePath == null || filePath.isEmpty()) {
throw new TelegramApiException("Parameter filePath can not be null");
}
if (callback == null) {
throw new TelegramApiException("Parameter callback can not be null");
}
String url = File.getFileUrl(botTokenSupplier.get(), filePath);
String tempFileName = Long.toString(System.currentTimeMillis());
getFileDownloadFuture(url, getTempFile(tempFileName))
.thenAccept(output -> callback.onResult(filePath, output))
.exceptionally(throwable -> {
// Unwrap java.util.concurrent.CompletionException
if (throwable instanceof CompletionException) {
callback.onException(filePath, new TelegramApiException("Error downloading file", throwable.getCause()));
} else {
callback.onException(filePath, new TelegramApiException("Error downloading file", throwable));
}
return null;
});
}
public final void downloadFileAsync(File file, DownloadFileCallback<File> callback) throws TelegramApiException {
if (file == null) {
throw new TelegramApiException("Parameter file can not be null");
}
if (callback == null) {
throw new TelegramApiException("Parameter callback can not be null");
}
String url = file.getFileUrl(botTokenSupplier.get());
String tempFileName = file.getFileId();
getFileDownloadFuture(url, getTempFile(tempFileName))
.thenAccept(output -> callback.onResult(file, output))
.exceptionally(throwable -> {
callback.onException(file, new TelegramApiException("Error downloading file", throwable));
return null;
});
}
private java.io.File getTempFile(String tempFileName) throws TelegramApiException {
try {
return java.io.File.createTempFile(tempFileName, ".tmp");
} catch (IOException e) {
throw new TelegramApiException("Error downloading file", e);
}
}
private java.io.File downloadToFile(String url, java.io.File output) throws TelegramApiException {
try {
return getFileDownloadFuture(url, output).get();
} catch (InterruptedException e) {
throw new TelegramApiException("File Download got interrupted", e);
} catch (ExecutionException e) {
throw new TelegramApiException("Error downloading file", e.getCause());
}
}
private CompletableFuture<java.io.File> getFileDownloadFuture(String url, java.io.File output) {
return getFileDownloadStreamFuture(url).thenApply(stream -> {
try {
copyInputStreamToFile(stream, output);
return output;
} catch (IOException e) {
throw new DownloadFileException("Error writing downloaded file", e);
}
});
}
private CompletableFuture<InputStream> getFileDownloadStreamFuture(final String url) {
return CompletableFuture.supplyAsync(() -> {
try {
HttpResponse response = httpClient.execute(new HttpGet(url));
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == SC_OK) {
return response.getEntity().getContent();
} else {
throw new TelegramApiException("Unexpected Status code while downloading file. Expected 200 got " + statusCode);
}
} catch (IOException | TelegramApiException e) {
throw new DownloadFileException("Error downloading file", e);
}
});
}
}

View File

@ -4,7 +4,6 @@ package org.telegram.telegrambots.facilities.proxysocketfactorys;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpContext;
import sun.net.SocksProxy;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -14,10 +13,9 @@ import java.net.Socket;
public class SocksConnectionSocketFactory extends PlainConnectionSocketFactory { public class SocksConnectionSocketFactory extends PlainConnectionSocketFactory {
@Override @Override
public Socket createSocket(final HttpContext context) throws IOException { public Socket createSocket(final HttpContext context) {
InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socketAddress"); InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socketAddress");
int socksVersion = (Integer) context.getAttribute("socksVersion"); Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
Proxy proxy = SocksProxy.create(socksaddr, socksVersion);
return new Socket(proxy); return new Socket(proxy);
} }

View File

@ -4,14 +4,14 @@ import org.apache.http.HttpHost;
import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpContext;
import sun.net.SocksProxy;
import javax.net.ssl.SSLContext;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Proxy; import java.net.Proxy;
import java.net.Socket; import java.net.Socket;
import javax.net.ssl.SSLContext;
public class SocksSSLConnectionSocketFactory extends SSLConnectionSocketFactory { public class SocksSSLConnectionSocketFactory extends SSLConnectionSocketFactory {
@ -20,10 +20,9 @@ public class SocksSSLConnectionSocketFactory extends SSLConnectionSocketFactory
} }
@Override @Override
public Socket createSocket(final HttpContext context) throws IOException { public Socket createSocket(final HttpContext context) {
InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socketAddress"); InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socketAddress");
int socksVersion = (Integer) context.getAttribute("socksVersion"); Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
Proxy proxy = SocksProxy.create(socksaddr, socksVersion);
return new Socket(proxy); return new Socket(proxy);
} }

View File

@ -11,6 +11,8 @@ import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONException; import org.json.JSONException;
import org.telegram.telegrambots.meta.ApiConstants; import org.telegram.telegrambots.meta.ApiConstants;
import org.telegram.telegrambots.meta.api.methods.updates.GetUpdates; import org.telegram.telegrambots.meta.api.methods.updates.GetUpdates;
@ -19,7 +21,6 @@ import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException; import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.facilities.TelegramHttpClientBuilder; import org.telegram.telegrambots.facilities.TelegramHttpClientBuilder;
import org.telegram.telegrambots.meta.generics.*; import org.telegram.telegrambots.meta.generics.*;
import org.telegram.telegrambots.meta.logging.BotLogger;
import java.io.IOException; import java.io.IOException;
import java.io.InvalidObjectException; import java.io.InvalidObjectException;
@ -39,7 +40,7 @@ import static org.telegram.telegrambots.Constants.SOCKET_TIMEOUT;
* Thread to request updates with active wait * Thread to request updates with active wait
*/ */
public class DefaultBotSession implements BotSession { public class DefaultBotSession implements BotSession {
private static final String LOGTAG = "BOTSESSION"; private static final Logger log = LogManager.getLogger(DefaultBotSession.class);
private AtomicBoolean running = new AtomicBoolean(false); private AtomicBoolean running = new AtomicBoolean(false);
@ -170,7 +171,7 @@ public class DefaultBotSession implements BotSession {
try { try {
httpclient.close(); httpclient.close();
} catch (IOException e) { } catch (IOException e) {
BotLogger.warn(LOGTAG, e); log.warn(e.getLocalizedMessage(), e);
} }
} }
super.interrupt(); super.interrupt();
@ -203,10 +204,10 @@ public class DefaultBotSession implements BotSession {
if (!running.get()) { if (!running.get()) {
receivedUpdates.clear(); receivedUpdates.clear();
} }
BotLogger.debug(LOGTAG, e); log.debug(e.getLocalizedMessage(), e);
interrupt(); interrupt();
} catch (Exception global) { } catch (Exception global) {
BotLogger.severe(LOGTAG, global); log.fatal(global.getLocalizedMessage(), global);
try { try {
synchronized (lock) { synchronized (lock) {
lock.wait(exponentialBackOff.nextBackOffMillis()); lock.wait(exponentialBackOff.nextBackOffMillis());
@ -215,14 +216,14 @@ public class DefaultBotSession implements BotSession {
if (!running.get()) { if (!running.get()) {
receivedUpdates.clear(); receivedUpdates.clear();
} }
BotLogger.debug(LOGTAG, e); log.debug(e.getLocalizedMessage(), e);
interrupt(); interrupt();
} }
} }
} }
} }
} }
BotLogger.debug(LOGTAG, "Reader thread has being closed"); log.debug("Reader thread has being closed");
} }
private List<Update> getUpdatesFromServer() throws IOException { private List<Update> getUpdatesFromServer() throws IOException {
@ -248,7 +249,7 @@ public class DefaultBotSession implements BotSession {
String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8); String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
if (response.getStatusLine().getStatusCode() >= 500) { if (response.getStatusLine().getStatusCode() >= 500) {
BotLogger.warn(LOGTAG, responseContent); log.warn(responseContent);
synchronized (lock) { synchronized (lock) {
lock.wait(500); lock.wait(500);
} }
@ -258,15 +259,15 @@ public class DefaultBotSession implements BotSession {
exponentialBackOff.reset(); exponentialBackOff.reset();
return updates; return updates;
} catch (JSONException e) { } catch (JSONException e) {
BotLogger.severe(responseContent, LOGTAG, e); log.error("Error deserializing update: " + responseContent, e);
} }
} }
} catch (SocketException | InvalidObjectException | TelegramApiRequestException e) { } catch (SocketException | InvalidObjectException | TelegramApiRequestException e) {
BotLogger.severe(LOGTAG, e); log.fatal(e.getLocalizedMessage(), e);
} catch (SocketTimeoutException e) { } catch (SocketTimeoutException e) {
BotLogger.fine(LOGTAG, e); log.info(e.getLocalizedMessage(), e);
} catch (InterruptedException e) { } catch (InterruptedException e) {
BotLogger.fine(LOGTAG, e); log.info(e.getLocalizedMessage(), e);
interrupt(); interrupt();
} }
return Collections.emptyList(); return Collections.emptyList();
@ -305,13 +306,13 @@ public class DefaultBotSession implements BotSession {
} }
callback.onUpdatesReceived(updates); callback.onUpdatesReceived(updates);
} catch (InterruptedException e) { } catch (InterruptedException e) {
BotLogger.debug(LOGTAG, e); log.debug(e.getLocalizedMessage(), e);
interrupt(); interrupt();
} catch (Exception e) { } catch (Exception e) {
BotLogger.severe(LOGTAG, e); log.fatal(e.getLocalizedMessage(), e);
} }
} }
BotLogger.debug(LOGTAG, "Handler thread has being closed"); log.debug("Handler thread has being closed");
} }
} }
} }

View File

@ -70,22 +70,22 @@ import com.google.common.base.Preconditions;
*/ */
public class ExponentialBackOff { public class ExponentialBackOff {
/** The default initial interval value in milliseconds (0.5 seconds). */ /** The default initial interval value in milliseconds (0.5 seconds). */
public static final int DEFAULT_INITIAL_INTERVAL_MILLIS = 500; private static final int DEFAULT_INITIAL_INTERVAL_MILLIS = 500;
/** /**
* The default randomization factor (0.5 which results in a random period ranging between 50% * The default randomization factor (0.5 which results in a random period ranging between 50%
* below and 50% above the retry interval). * below and 50% above the retry interval).
*/ */
public static final double DEFAULT_RANDOMIZATION_FACTOR = 0.5; private static final double DEFAULT_RANDOMIZATION_FACTOR = 0.5;
/** The default multiplier value (1.5 which is 50% increase per back off). */ /** The default multiplier value (1.5 which is 50% increase per back off). */
public static final double DEFAULT_MULTIPLIER = 1.5; private static final double DEFAULT_MULTIPLIER = 1.5;
/** The default maximum back off time in milliseconds (15 minutes). */ /** The default maximum back off time in milliseconds (15 minutes). */
public static final int DEFAULT_MAX_INTERVAL_MILLIS = 30000; private static final int DEFAULT_MAX_INTERVAL_MILLIS = 30000;
/** The default maximum elapsed time in milliseconds (60 minutes). */ /** The default maximum elapsed time in milliseconds (60 minutes). */
public static final int DEFAULT_MAX_ELAPSED_TIME_MILLIS = 3600000; private static final int DEFAULT_MAX_ELAPSED_TIME_MILLIS = 3600000;
/** The current retry interval in milliseconds. */ /** The current retry interval in milliseconds. */
private int currentIntervalMillis; private int currentIntervalMillis;
@ -116,7 +116,7 @@ public class ExponentialBackOff {
* The system time in nanoseconds. It is calculated when an ExponentialBackOffPolicy instance is * The system time in nanoseconds. It is calculated when an ExponentialBackOffPolicy instance is
* created and is reset when {@link #reset()} is called. * created and is reset when {@link #reset()} is called.
*/ */
long startTimeNanos; private long startTimeNanos;
/** /**
* The maximum elapsed time after instantiating {@link ExponentialBackOff} or calling * The maximum elapsed time after instantiating {@link ExponentialBackOff} or calling
@ -139,14 +139,14 @@ public class ExponentialBackOff {
* <li>{@code maxElapsedTimeMillis} defaults in {@link #DEFAULT_MAX_ELAPSED_TIME_MILLIS}</li> * <li>{@code maxElapsedTimeMillis} defaults in {@link #DEFAULT_MAX_ELAPSED_TIME_MILLIS}</li>
* </ul> * </ul>
*/ */
public ExponentialBackOff() { ExponentialBackOff() {
this(new Builder()); this(new Builder());
} }
/** /**
* @param builder builder * @param builder builder
*/ */
protected ExponentialBackOff(Builder builder) { private ExponentialBackOff(Builder builder) {
initialIntervalMillis = builder.initialIntervalMillis; initialIntervalMillis = builder.initialIntervalMillis;
randomizationFactor = builder.randomizationFactor; randomizationFactor = builder.randomizationFactor;
multiplier = builder.multiplier; multiplier = builder.multiplier;
@ -161,7 +161,7 @@ public class ExponentialBackOff {
} }
/** Sets the interval back to the initial retry interval and restarts the timer. */ /** Sets the interval back to the initial retry interval and restarts the timer. */
public final void reset() { final void reset() {
currentIntervalMillis = initialIntervalMillis; currentIntervalMillis = initialIntervalMillis;
startTimeNanos = nanoTime(); startTimeNanos = nanoTime();
} }
@ -178,7 +178,7 @@ public class ExponentialBackOff {
* Subclasses may override if a different algorithm is required. * Subclasses may override if a different algorithm is required.
* </p> * </p>
*/ */
public long nextBackOffMillis() { long nextBackOffMillis() {
// Make sure we have not gone over the maximum elapsed time. // Make sure we have not gone over the maximum elapsed time.
if (getElapsedTimeMillis() > maxElapsedTimeMillis) { if (getElapsedTimeMillis() > maxElapsedTimeMillis) {
return maxElapsedTimeMillis; return maxElapsedTimeMillis;
@ -193,7 +193,7 @@ public class ExponentialBackOff {
* Returns a random value from the interval [randomizationFactor * currentInterval, * Returns a random value from the interval [randomizationFactor * currentInterval,
* randomizationFactor * currentInterval]. * randomizationFactor * currentInterval].
*/ */
static int getRandomValueFromInterval( private static int getRandomValueFromInterval(
double randomizationFactor, double random, int currentIntervalMillis) { double randomizationFactor, double random, int currentIntervalMillis) {
double delta = randomizationFactor * currentIntervalMillis; double delta = randomizationFactor * currentIntervalMillis;
double minInterval = currentIntervalMillis - delta; double minInterval = currentIntervalMillis - delta;
@ -201,60 +201,7 @@ public class ExponentialBackOff {
// Get a random value from the range [minInterval, maxInterval]. // Get a random value from the range [minInterval, maxInterval].
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
// we want a 33% chance for selecting either 1, 2 or 3. // we want a 33% chance for selecting either 1, 2 or 3.
int randomValue = (int) (minInterval + (random * (maxInterval - minInterval + 1))); return (int) (minInterval + (random * (maxInterval - minInterval + 1)));
return randomValue;
}
/** Returns the initial retry interval in milliseconds. */
public final int getInitialIntervalMillis() {
return initialIntervalMillis;
}
/**
* Returns the randomization factor to use for creating a range around the retry interval.
*
* <p>
* A randomization factor of 0.5 results in a random period ranging between 50% below and 50%
* above the retry interval.
* </p>
*/
public final double getRandomizationFactor() {
return randomizationFactor;
}
/**
* Returns the current retry interval in milliseconds.
*/
public final int getCurrentIntervalMillis() {
return currentIntervalMillis;
}
/**
* Returns the value to multiply the current interval with for each retry attempt.
*/
public final double getMultiplier() {
return multiplier;
}
/**
* Returns the maximum value of the back off period in milliseconds. Once the current interval
* reaches this value it stops increasing.
*/
public final int getMaxIntervalMillis() {
return maxIntervalMillis;
}
/**
* Returns the maximum elapsed time in milliseconds.
*
* <p>
* If the time elapsed since an {@link ExponentialBackOff} instance is created goes past the
* max_elapsed_time then the method {@link #nextBackOffMillis()} starts returning
* this value. The elapsed time can be reset by calling {@link #reset()}.
* </p>
*/
public final int getMaxElapsedTimeMillis() {
return maxElapsedTimeMillis;
} }
/** /**
@ -265,7 +212,7 @@ public class ExponentialBackOff {
* The elapsed time is computed using {@link System#nanoTime()}. * The elapsed time is computed using {@link System#nanoTime()}.
* </p> * </p>
*/ */
public final long getElapsedTimeMillis() { private long getElapsedTimeMillis() {
return (nanoTime() - startTimeNanos) / 1000000; return (nanoTime() - startTimeNanos) / 1000000;
} }
@ -327,152 +274,12 @@ public class ExponentialBackOff {
*/ */
int maxElapsedTimeMillis = DEFAULT_MAX_ELAPSED_TIME_MILLIS; int maxElapsedTimeMillis = DEFAULT_MAX_ELAPSED_TIME_MILLIS;
public Builder() { Builder() {
} }
/** Builds a new instance of {@link ExponentialBackOff}. */ /** Builds a new instance of {@link ExponentialBackOff}. */
public ExponentialBackOff build() { public ExponentialBackOff build() {
return new ExponentialBackOff(this); return new ExponentialBackOff(this);
} }
/**
* Returns the initial retry interval in milliseconds. The default value is
* {@link #DEFAULT_INITIAL_INTERVAL_MILLIS}.
*/
public final int getInitialIntervalMillis() {
return initialIntervalMillis;
}
/**
* Sets the initial retry interval in milliseconds. The default value is
* {@link #DEFAULT_INITIAL_INTERVAL_MILLIS}. Must be {@code > 0}.
*
* <p>
* Overriding is only supported for the purpose of calling the super implementation and changing
* the return type, but nothing else.
* </p>
*/
public Builder setInitialIntervalMillis(int initialIntervalMillis) {
this.initialIntervalMillis = initialIntervalMillis;
return this;
}
/**
* Returns the randomization factor to use for creating a range around the retry interval. The
* default value is {@link #DEFAULT_RANDOMIZATION_FACTOR}.
*
* <p>
* A randomization factor of 0.5 results in a random period ranging between 50% below and 50%
* above the retry interval.
* </p>
*
* <p>
* Overriding is only supported for the purpose of calling the super implementation and changing
* the return type, but nothing else.
* </p>
*/
public final double getRandomizationFactor() {
return randomizationFactor;
}
/**
* Sets the randomization factor to use for creating a range around the retry interval. The
* default value is {@link #DEFAULT_RANDOMIZATION_FACTOR}. Must fall in the range
* {@code 0 <= randomizationFactor < 1}.
*
* <p>
* A randomization factor of 0.5 results in a random period ranging between 50% below and 50%
* above the retry interval.
* </p>
*
* <p>
* Overriding is only supported for the purpose of calling the super implementation and changing
* the return type, but nothing else.
* </p>
*/
public Builder setRandomizationFactor(double randomizationFactor) {
this.randomizationFactor = randomizationFactor;
return this;
}
/**
* Returns the value to multiply the current interval with for each retry attempt. The default
* value is {@link #DEFAULT_MULTIPLIER}.
*/
public final double getMultiplier() {
return multiplier;
}
/**
* Sets the value to multiply the current interval with for each retry attempt. The default
* value is {@link #DEFAULT_MULTIPLIER}. Must be {@code >= 1}.
*
* <p>
* Overriding is only supported for the purpose of calling the super implementation and changing
* the return type, but nothing else.
* </p>
*/
public Builder setMultiplier(double multiplier) {
this.multiplier = multiplier;
return this;
}
/**
* Returns the maximum value of the back off period in milliseconds. Once the current interval
* reaches this value it stops increasing. The default value is
* {@link #DEFAULT_MAX_INTERVAL_MILLIS}. Must be {@code >= initialInterval}.
*/
public final int getMaxIntervalMillis() {
return maxIntervalMillis;
}
/**
* Sets the maximum value of the back off period in milliseconds. Once the current interval
* reaches this value it stops increasing. The default value is
* {@link #DEFAULT_MAX_INTERVAL_MILLIS}.
*
* <p>
* Overriding is only supported for the purpose of calling the super implementation and changing
* the return type, but nothing else.
* </p>
*/
public Builder setMaxIntervalMillis(int maxIntervalMillis) {
this.maxIntervalMillis = maxIntervalMillis;
return this;
}
/**
* Returns the maximum elapsed time in milliseconds. The default value is
* {@link #DEFAULT_MAX_ELAPSED_TIME_MILLIS}.
*
* <p>
* If the time elapsed since an {@link ExponentialBackOff} instance is created goes past the
* max_elapsed_time then the method {@link #nextBackOffMillis()} starts returning
* this value. The elapsed time can be reset by calling {@link #reset()}.
* </p>
*/
public final int getMaxElapsedTimeMillis() {
return maxElapsedTimeMillis;
}
/**
* Sets the maximum elapsed time in milliseconds. The default value is
* {@link #DEFAULT_MAX_ELAPSED_TIME_MILLIS}. Must be {@code > 0}.
*
* <p>
* If the time elapsed since an {@link ExponentialBackOff} instance is created goes past the
* max_elapsed_time then the method {@link #nextBackOffMillis()} starts returning
* this value. The elapsed time can be reset by calling {@link #reset()}.
* </p>
*
* <p>
* Overriding is only supported for the purpose of calling the super implementation and changing
* the return type, but nothing else.
* </p>
*/
public Builder setMaxElapsedTimeMillis(int maxElapsedTimeMillis) {
this.maxElapsedTimeMillis = maxElapsedTimeMillis;
return this;
}
} }
} }

View File

@ -1,12 +1,11 @@
package org.telegram.telegrambots.updatesreceivers; package org.telegram.telegrambots.updatesreceivers;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.telegram.telegrambots.meta.api.methods.BotApiMethod; import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException; import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
import org.telegram.telegrambots.meta.generics.WebhookBot; import org.telegram.telegrambots.meta.generics.WebhookBot;
import org.telegram.telegrambots.meta.logging.BotLogger;
import java.util.concurrent.ConcurrentHashMap;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
@ -16,15 +15,16 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* @brief Rest api to for webhook callback function * Rest api to for webhook callback function
* @date 20 of June of 2015
*/ */
@Path("callback") @Path("callback")
public class RestApi { public class RestApi {
private static final Logger log = LogManager.getLogger(RestApi.class);
private final ConcurrentHashMap<String, WebhookBot> callbacks = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, WebhookBot> callbacks = new ConcurrentHashMap<>();
@ -50,7 +50,7 @@ public class RestApi {
} }
return Response.ok(response).build(); return Response.ok(response).build();
} catch (TelegramApiValidationException e) { } catch (TelegramApiValidationException e) {
BotLogger.severe("RESTAPI", e); log.error(e.getLocalizedMessage(), e);
return Response.serverError().build(); return Response.serverError().build();
} }
} }

View File

@ -43,7 +43,7 @@ public final class WebhookUtils {
builder.addTextBody(SetWebhook.MAXCONNECTIONS_FIELD, botOptions.getMaxWebhookConnections().toString()); builder.addTextBody(SetWebhook.MAXCONNECTIONS_FIELD, botOptions.getMaxWebhookConnections().toString());
} }
if (botOptions.getAllowedUpdates() != null) { if (botOptions.getAllowedUpdates() != null) {
builder.addTextBody(SetWebhook.ALLOWEDUPDATES_FIELD, new JSONArray(botOptions.getMaxWebhookConnections()).toString()); builder.addTextBody(SetWebhook.ALLOWEDUPDATES_FIELD, new JSONArray(botOptions.getAllowedUpdates()).toString());
} }
if (publicCertificatePath != null) { if (publicCertificatePath != null) {
File certificate = new File(publicCertificatePath); File certificate = new File(publicCertificatePath);

View File

@ -0,0 +1,115 @@
package org.telegram.telegrambots.test;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicStatusLine;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.telegram.telegrambots.facilities.filedownloader.TelegramFileDownloader;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.updateshandlers.DownloadFileCallback;
import java.io.File;
import java.io.IOException;
import java.util.function.Supplier;
import static java.nio.charset.Charset.defaultCharset;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.io.IOUtils.toInputStream;
import static org.apache.http.HttpVersion.HTTP_1_1;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class TelegramFileDownloaderTest {
private TelegramFileDownloader telegramFileDownloader;
@Mock
private DownloadFileCallback<String> downloadFileCallbackMock;
@Mock
private HttpClient httpClientMock;
@Mock
private HttpResponse httpResponseMock;
@Mock
private HttpEntity httpEntityMock;
private Supplier<String> tokenSupplierMock = () -> "someToken";
@BeforeEach
void setup() throws IOException {
when(httpResponseMock.getStatusLine()).thenReturn(new BasicStatusLine(HTTP_1_1, 200, "emptyString"));
when(httpResponseMock.getEntity()).thenReturn(httpEntityMock);
when(httpEntityMock.getContent()).thenReturn(toInputStream("Some File Content", defaultCharset()));
when(httpClientMock.execute(any(HttpUriRequest.class))).thenReturn(httpResponseMock);
telegramFileDownloader = new TelegramFileDownloader(httpClientMock, tokenSupplierMock);
}
@Test
void testFileDownload() throws TelegramApiException, IOException {
File returnFile = telegramFileDownloader.downloadFile("someFilePath");
String content = readFileToString(returnFile, defaultCharset());
assertEquals("Some File Content", content);
}
@Test
void testDownloadException() {
when(httpResponseMock.getStatusLine()).thenReturn(new BasicStatusLine(HTTP_1_1, 500, "emptyString"));
Assertions.assertThrows(TelegramApiException.class,
() -> telegramFileDownloader.downloadFile("someFilePath"));
}
@Test
void testAsyncDownload() throws TelegramApiException, IOException {
final ArgumentCaptor<File> fileArgumentCaptor = ArgumentCaptor.forClass(File.class);
telegramFileDownloader.downloadFileAsync("someFilePath", downloadFileCallbackMock);
verify(downloadFileCallbackMock, timeout(100)
.times(1))
.onResult(any(), fileArgumentCaptor.capture());
String content = readFileToString(fileArgumentCaptor.getValue(), defaultCharset());
assertEquals("Some File Content", content);
}
@Test
void testAsyncException() throws TelegramApiException {
final ArgumentCaptor<Exception> exceptionArgumentCaptor = ArgumentCaptor.forClass(Exception.class);
when(httpResponseMock.getStatusLine()).thenReturn(new BasicStatusLine(HTTP_1_1, 500, "emptyString"));
telegramFileDownloader.downloadFileAsync("someFilePath", downloadFileCallbackMock);
verify(downloadFileCallbackMock, timeout(100)
.times(1))
.onException(any(), exceptionArgumentCaptor.capture());
Exception e = exceptionArgumentCaptor.getValue();
assertThat(e, instanceOf(TelegramApiException.class));
assertEquals(e.getCause().getCause().getMessage(), "Unexpected Status code while downloading file. Expected 200 got 500");
}
}

View File

@ -2,23 +2,23 @@ package org.telegram.telegrambots.test;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.bots.DefaultBotOptions; import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.bots.TelegramLongPollingBot; import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession; import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
public class TelegramLongPollingBotTest { public class TelegramLongPollingBotTest {
@Test @Test
public void testOnUpdateReceived() throws Exception { public void testOnUpdateReceived() {
TelegramLongPollingBot bot = Mockito.mock(TelegramLongPollingBot.class); TelegramLongPollingBot bot = Mockito.mock(TelegramLongPollingBot.class);
Mockito.doCallRealMethod().when(bot).onUpdatesReceived(any()); Mockito.doCallRealMethod().when(bot).onUpdatesReceived(any());
Update update1 = new Update(); Update update1 = new Update();

View File

@ -11,10 +11,9 @@ import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.bots.DefaultBotOptions; import org.telegram.telegrambots.bots.DefaultBotOptions;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.generics.LongPollingBot; import org.telegram.telegrambots.meta.generics.LongPollingBot;
import org.telegram.telegrambots.test.Fakes.FakeLongPollingBot; import org.telegram.telegrambots.test.Fakes.FakeLongPollingBot;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession; import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
@ -22,17 +21,18 @@ import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import static org.mockito.ArgumentMatchers.any;
/** /**
* @author Ruben Bermudez * @author Ruben Bermudez
* @version 1.0 * @version 1.0
* @brief Test for DefaultBotSession * Test for DefaultBotSession
*/ */
public class TestDefaultBotSession { public class TestDefaultBotSession {
DefaultBotSession session; private DefaultBotSession session;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@ -40,14 +40,14 @@ public class TestDefaultBotSession {
} }
@After @After
public void tearDown() throws Exception { public void tearDown() {
if (session != null && session.isRunning()) { if (session != null && session.isRunning()) {
session.stop(); session.stop();
} }
} }
@Test @Test
public void TestDefaultBotSessionIsNotRunningWhenCreated() throws Exception { public void TestDefaultBotSessionIsNotRunningWhenCreated() {
Assert.assertFalse(session.isRunning()); Assert.assertFalse(session.isRunning());
} }
@ -96,7 +96,7 @@ public class TestDefaultBotSession {
session.setUpdatesSupplier(createFakeUpdatesSupplier(flag, updates)); session.setUpdatesSupplier(createFakeUpdatesSupplier(flag, updates));
session.start(); session.start();
Thread.sleep(1000); Thread.sleep(1000);
Mockito.verify(bot, Mockito.never()).onUpdateReceived(Matchers.any()); Mockito.verify(bot, Mockito.never()).onUpdateReceived(any());
flag.compareAndSet(0, 1); flag.compareAndSet(0, 1);
Thread.sleep(1000); Thread.sleep(1000);
Mockito.verify(bot).onUpdateReceived(updates[0]); Mockito.verify(bot).onUpdateReceived(updates[0]);
@ -124,7 +124,7 @@ public class TestDefaultBotSession {
session.setUpdatesSupplier(createFakeUpdatesSupplier(flag, updates)); session.setUpdatesSupplier(createFakeUpdatesSupplier(flag, updates));
session.start(); session.start();
Thread.sleep(1000); Thread.sleep(1000);
Mockito.verify(bot, Mockito.never()).onUpdateReceived(Matchers.any()); Mockito.verify(bot, Mockito.never()).onUpdateReceived(any());
flag.compareAndSet(0, 1); flag.compareAndSet(0, 1);
Thread.sleep(1000); Thread.sleep(1000);
Mockito.verify(bot).onUpdatesReceived(Arrays.asList(updates[0], updates[1])); Mockito.verify(bot).onUpdatesReceived(Arrays.asList(updates[0], updates[1]));
@ -146,18 +146,15 @@ public class TestDefaultBotSession {
} }
private DefaultBotSession.UpdatesSupplier createFakeUpdatesSupplier(AtomicInteger flag, Update[] updates) { private DefaultBotSession.UpdatesSupplier createFakeUpdatesSupplier(AtomicInteger flag, Update[] updates) {
return new DefaultBotSession.UpdatesSupplier() { return () -> {
@Override if (flag.compareAndSet(1, 2)) {
public List<Update> getUpdates() throws InterruptedException, Exception { return Arrays.asList(updates[0], updates[1]);
if (flag.compareAndSet(1, 2)) { } else if (flag.compareAndSet(3, 4)) {
return Arrays.asList(updates[0], updates[1]); return Arrays.asList(updates[2], updates[3], updates[4]);
} else if (flag.compareAndSet(3, 4)) { } else if (flag.compareAndSet(5, 6)) {
return Arrays.asList(updates[2], updates[3], updates[4]); return Arrays.asList(updates[5], updates[6], updates[7], updates[8]);
} else if (flag.compareAndSet(5, 6)) {
return Arrays.asList(updates[5], updates[6], updates[7], updates[8]);
}
return Collections.emptyList();
} }
return Collections.emptyList();
}; };
} }
@ -172,7 +169,7 @@ public class TestDefaultBotSession {
response.setEntity(new StringEntity("{}")); response.setEntity(new StringEntity("{}"));
HttpClient mockHttpClient = Mockito.mock(HttpClient.class); HttpClient mockHttpClient = Mockito.mock(HttpClient.class);
Mockito.when(mockHttpClient.execute(Mockito.any(HttpPost.class))) Mockito.when(mockHttpClient.execute(any(HttpPost.class)))
.thenReturn(response); .thenReturn(response);
DefaultBotSession session = new DefaultBotSession(); DefaultBotSession session = new DefaultBotSession();
session.setCallback(bot); session.setCallback(bot);