commit
c45e480d6d
128
Bots.ipr
128
Bots.ipr
@ -17,6 +17,7 @@
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="telegrambots" />
|
||||
<module name="telegrambots-abilities" />
|
||||
<module name="telegrambots-extensions" />
|
||||
<module name="telegrambots-meta" />
|
||||
</profile>
|
||||
@ -30,12 +31,14 @@
|
||||
<bytecodeTargetLevel>
|
||||
<module name="Bots" target="1.5" />
|
||||
<module name="telegrambots" target="1.8" />
|
||||
<module name="telegrambots-abilities" target="1.8" />
|
||||
<module name="telegrambots-extensions" target="1.8" />
|
||||
<module name="telegrambots-meta" target="1.8" />
|
||||
</bytecodeTargetLevel>
|
||||
</component>
|
||||
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
|
||||
<file url="file://$PROJECT_DIR$/telegrambots" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/telegrambots-abilities" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/telegrambots-extensions" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/telegrambots-meta" charset="UTF-8" />
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
@ -126,6 +129,9 @@
|
||||
<exe-path>/usr/local/bin/bower</exe-path>
|
||||
<config-path />
|
||||
</component>
|
||||
<component name="KotlinCommonCompilerArguments">
|
||||
<option name="coroutinesWarn" value="false" />
|
||||
</component>
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
@ -264,6 +270,7 @@
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Bots.iml" filepath="$PROJECT_DIR$/Bots.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/telegrambots/telegrambots.iml" filepath="$PROJECT_DIR$/telegrambots/telegrambots.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/telegrambots-abilities/telegrambots-abilities.iml" filepath="$PROJECT_DIR$/telegrambots-abilities/telegrambots-abilities.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/telegrambots-extensions/telegrambots-extensions.iml" filepath="$PROJECT_DIR$/telegrambots-extensions/telegrambots-extensions.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/telegrambots-meta/telegrambots-meta.iml" filepath="$PROJECT_DIR$/telegrambots-meta/telegrambots-meta.iml" />
|
||||
</modules>
|
||||
@ -497,6 +504,17 @@
|
||||
<root url="jar://$MAVEN_REPOSITORY$/javax/ws/rs/javax.ws.rs-api/2.0.1/javax.ws.rs-api-2.0.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: junit:junit:4.11">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.11/junit-4.11.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.11/junit-4.11-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.11/junit-4.11-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: junit:junit:4.12">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.12/junit-4.12.jar!/" />
|
||||
@ -508,6 +526,39 @@
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.12/junit-4.12-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: net.jcip:jcip-annotations:1.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/jcip/jcip-annotations/1.0/jcip-annotations-1.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/jcip/jcip-annotations/1.0/jcip-annotations-1.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/jcip/jcip-annotations/1.0/jcip-annotations-1.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: net.jpountz.lz4:lz4:1.3.0">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/jpountz/lz4/lz4/1.3.0/lz4-1.3.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/jpountz/lz4/lz4/1.3.0/lz4-1.3.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/net/jpountz/lz4/lz4/1.3.0/lz4-1.3.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.apache.commons:commons-lang3:3.5">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.apache.httpcomponents:httpclient:4.5.3">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpclient/4.5.3/httpclient-4.5.3.jar!/" />
|
||||
@ -541,6 +592,39 @@
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpmime/4.5.3/httpmime-4.5.3-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.eclipse.collections:eclipse-collections-api:7.1.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections-api/7.1.1/eclipse-collections-api-7.1.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections-api/7.1.1/eclipse-collections-api-7.1.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections-api/7.1.1/eclipse-collections-api-7.1.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.eclipse.collections:eclipse-collections-forkjoin:7.1.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections-forkjoin/7.1.1/eclipse-collections-forkjoin-7.1.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections-forkjoin/7.1.1/eclipse-collections-forkjoin-7.1.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections-forkjoin/7.1.1/eclipse-collections-forkjoin-7.1.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.eclipse.collections:eclipse-collections:7.1.1">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections/7.1.1/eclipse-collections-7.1.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections/7.1.1/eclipse-collections-7.1.1-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/eclipse/collections/eclipse-collections/7.1.1/eclipse-collections-7.1.1-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.glassfish.grizzly:grizzly-framework:2.3.28">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/glassfish/grizzly/grizzly-framework/2.3.28/grizzly-framework-2.3.28.jar!/" />
|
||||
@ -816,6 +900,28 @@
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/javassist/javassist/3.20.0-GA/javassist-3.20.0-GA-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.jetbrains.kotlin:kotlin-runtime:1.0.7">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-runtime/1.0.7/kotlin-runtime-1.0.7.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-runtime/1.0.7/kotlin-runtime-1.0.7-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-runtime/1.0.7/kotlin-runtime-1.0.7-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.0.7">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.0.7/kotlin-stdlib-1.0.7.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.0.7/kotlin-stdlib-1.0.7-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.0.7/kotlin-stdlib-1.0.7-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.json:json:20160810">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/json/json/20160810/json-20160810.jar!/" />
|
||||
@ -827,6 +933,28 @@
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/json/json/20160810/json-20160810-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.mapdb:elsa:3.0.0-M5">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mapdb/elsa/3.0.0-M5/elsa-3.0.0-M5.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mapdb/elsa/3.0.0-M5/elsa-3.0.0-M5-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mapdb/elsa/3.0.0-M5/elsa-3.0.0-M5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.mapdb:mapdb:3.0.4">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mapdb/mapdb/3.0.4/mapdb-3.0.4.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mapdb/mapdb/3.0.4/mapdb-3.0.4-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mapdb/mapdb/3.0.4/mapdb-3.0.4-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.mockito:mockito-all:2.0.2-beta">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/mockito/mockito-all/2.0.2-beta/mockito-all-2.0.2-beta.jar!/" />
|
||||
|
@ -27,16 +27,16 @@ Just import add the library to your project with one of these options:
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambots:3.1.2"
|
||||
compile "org.telegram:telegrambots:3.2"
|
||||
```
|
||||
|
||||
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/3.1.2)
|
||||
3. Download the jar(including all dependencies) from [here](https://github.com/rubenlagus/TelegramBots/releases/tag/v3.1.2)
|
||||
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/3.2)
|
||||
3. Download the jar(including all dependencies) from [here](https://github.com/rubenlagus/TelegramBots/releases/tag/v3.2)
|
||||
|
||||
In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`.
|
||||
|
||||
|
@ -83,3 +83,14 @@
|
||||
|
||||
### <a id="3.1.2"></a>3.1.2 ###
|
||||
1. Fix bug #266
|
||||
|
||||
### <a id="3.2"></a>3.2 ###
|
||||
1. Support for Api Version [3.2](https://core.telegram.org/bots/api-changelog#july-21-2017)
|
||||
2. Deprecated all redundant methods in AbsSender, will be removed in next major release
|
||||
3. New Abstract methods `addStickerToSet`, `createNewStickerSet` and `uploadStickerFile` in AbsSender.
|
||||
4. Abilities module
|
||||
5. Removed deprecated methods from previous versions
|
||||
6. Bug fixing: #257, #270
|
||||
7. Simplify code from DefaultAbsSender: #272
|
||||
|
||||
**[[How to update to version 3.2|How-To-Update#3.2]]**
|
@ -11,13 +11,13 @@ First you need ot get the library and add it to your project. There are few poss
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
```
|
||||
* With **Gradle**:
|
||||
|
||||
```groovy
|
||||
compile group: 'org.telegram', name: 'telegrambots', version: '3.1.2'
|
||||
compile group: 'org.telegram', name: 'telegrambots', version: '3.2'
|
||||
```
|
||||
|
||||
2. Don't like **Maven Central Repository**? It can also be taken from [Jitpack](https://jitpack.io/#rubenlagus/TelegramBots).
|
||||
|
@ -28,3 +28,8 @@
|
||||
### <a id="3.0.2"></a>To version 3.0.2 ###
|
||||
1. If you were using `TelegramLongPollingCommandBot`, add the new [extensions dependency](https://github.com/rubenlagus/TelegramBots/tree/master/telegrambots-extensions) to your maven and fix import statements in your project.
|
||||
2. If you were using `TelegramLongPollingCommandBot`, make sure you start using constructors with username and prevent overriding `getUsername` method.
|
||||
|
||||
|
||||
### <a id="3.2"></a>To version 3.2 ###
|
||||
1. Replace usage of all deprecated methods from AbsSender with methods `execute` or `executeAsync`.
|
||||
2. If you are extending AbsSender class, implement new added methods.
|
5
pom.xml
5
pom.xml
@ -7,12 +7,13 @@
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2</version>
|
||||
|
||||
<modules>
|
||||
<module>telegrambots</module>
|
||||
<module>telegrambots-meta</module>
|
||||
<module>telegrambots-extensions</module>
|
||||
<module>telegrambots-abilities</module>
|
||||
</modules>
|
||||
|
||||
<licenses>
|
||||
@ -25,6 +26,6 @@
|
||||
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
<bots.version>3.1.2</bots.version>
|
||||
<bots.version>3.2</bots.version>
|
||||
</properties>
|
||||
</project>
|
170
telegrambots-abilities/README.md
Normal file
170
telegrambots-abilities/README.md
Normal file
@ -0,0 +1,170 @@
|
||||
<div align="center">
|
||||
<img src="https://github.com/addo37/AbilityBots/blob/gh-pages/images/API%20BOT-03.png?raw=true" alt="abilitybots" width="200" height="200"/>
|
||||
|
||||
[![Build Status](https://travis-ci.org/rubenlagus/TelegramBots.svg?branch=master)](https://travis-ci.org/rubenlagus/TelegramBots)
|
||||
[![Jitpack](https://jitpack.io/v/rubenlagus/TelegramBots.svg)](https://jitpack.io/#rubenlagus/TelegramBots)
|
||||
[![JavaDoc](http://svgur.com/i/1Ex.svg)](https://addo37.github.io/AbilityBots/)
|
||||
[![Telegram](http://trellobot.doomdns.org/telegrambadge.svg)](https://telegram.me/JavaBotsApi)
|
||||
[![ghit.me](https://ghit.me/badge.svg?repo=rubenlagus/TelegramBots)](https://ghit.me/repo/rubenlagus/TelegramBots)
|
||||
|
||||
</div>
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
**Maven**
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-abilities</artifactId>
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Gradle**
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambots-abilities:3.2"
|
||||
```
|
||||
|
||||
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v3.2)
|
||||
|
||||
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v3.2)
|
||||
|
||||
Motivation
|
||||
----------
|
||||
Ever since I've started programming bots for Telegram, I've been using the Telegram Bot Java API. It's a basic and nicely done API that is a 1-to-1 translation of the HTTP API exposed by Telegram.
|
||||
|
||||
Dealing with a basic API has its advantages and disadvantages. Obviously, there's nothing hidden. If it's there on Telegram, it's here in the Java API.
|
||||
When you want to implement a feature in your bot, you start asking these questions:
|
||||
|
||||
* The **WHO**?
|
||||
* Who is going to use this feature? Should they be allowed to use all the features?
|
||||
* The **WHAT**?
|
||||
* Under what conditions should I allow this feature?
|
||||
* Should the message have a photo? A document? Oh, maybe a callback query?
|
||||
* The **HOW**?
|
||||
* If my bot crashes, how can I resume my operation?
|
||||
* Should I utilize a DB?
|
||||
* How can I separate logic execution of different features?
|
||||
* How can I unit-test my feature outside of Telegram?
|
||||
|
||||
Every time you write a command or a feature, you will need to answer these questions and ensure that your feature logic works.
|
||||
|
||||
Ability Bot Abstraction
|
||||
-----------------------
|
||||
After implementing my fifth bot using that API, I had had it with the amount of **boilerplate code** that was needed for every added feature. Methods were getting overly-complex and readability became subpar.
|
||||
That is where the notion of another layer of abstraction (AbilityBot) began taking shape.
|
||||
|
||||
The AbilityBot abstraction defines a new object, named **Ability**. An ability combines conditions, flags, action, post-action and replies.
|
||||
As an example, here is a code-snippet of an ability that creates a ***/hello*** command:
|
||||
|
||||
```java
|
||||
public Ability sayHelloWorld() {
|
||||
return Ability
|
||||
.builder()
|
||||
.name("hello")
|
||||
.info("says hello world!")
|
||||
.input(0)
|
||||
.locality(USER)
|
||||
.privacy(ADMIN)
|
||||
.action(ctx -> sender.send("Hello world!", ctx.chatId()))
|
||||
.post(ctx -> sender.send("Bye world!", ctx.chatId()))
|
||||
.build();
|
||||
}
|
||||
```
|
||||
Here is a breakdown of the above code snippet:
|
||||
* *.name()* - the name of the ability (essentially, this is the command)
|
||||
* *.info()* - provides information for the command
|
||||
* More on this later, but it basically centralizes command information in-code.
|
||||
* *.input()* - the number of input arguments needed, 0 is for do-not-care
|
||||
* *.locality()* - this answers where you want the ability to be available
|
||||
* In GROUP, USER private chats or ALL (both)
|
||||
* *.privacy()* - this answers who you want to access your ability
|
||||
* CREATOR, ADMIN, or everyone as PUBLIC
|
||||
* *.action()* - the feature logic resides here (a lambda function that takes a *MessageContext*)
|
||||
* *MessageContext* provides fast accessors for the **chatId**, **user** and the underlying **update**. It also conforms to the specifications of the basic API.
|
||||
* *.post()* - the logic executed **after** your main action finishes execution
|
||||
|
||||
The following is a snippet of how this would look like with the plain basic API.
|
||||
|
||||
```java
|
||||
@Override
|
||||
public void onUpdateReceived(Update update) {
|
||||
// Global checks...
|
||||
// Switch, if, logic to route to hello world method
|
||||
// Execute method
|
||||
}
|
||||
|
||||
public void sayHelloWorld(Update update) {
|
||||
if (!update.hasMessage() || !update.getMessage().isUserMessage() || !update.getMessage().hasText() || update.getMessage.getText().isEmpty())
|
||||
return;
|
||||
User maybeAdmin = update.getMessage().getFrom();
|
||||
/* Query DB for if the user is an admin, can be SQL, Reddis, Ignite, etc...
|
||||
If user is not an admin, then return here.
|
||||
*/
|
||||
|
||||
SendMessage snd = new SendMessage();
|
||||
snd.setChatId(update.getMessage().getChatId());
|
||||
snd.setText("Hello world!");
|
||||
|
||||
try {
|
||||
sendMessage(snd);
|
||||
} catch (TelegramApiException e) {
|
||||
BotLogger.error("Could not send message", TAG, e);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
I will leave you the choice to decide between the two snippets as to which is more **readable**, **writable** and **testable**.
|
||||
|
||||
***You can do so much more with abilities, besides plain commands. Head over to our [examples](#examples) to check out all of its features!***
|
||||
|
||||
Objective
|
||||
---------
|
||||
The AbilityBot abstraction intends to provide the following:
|
||||
* New feature is a new **Ability**, a new method - no fuss, zero overhead, no cross-code with other features
|
||||
* Argument length on a command is as easy as changing a single integer
|
||||
* Privacy settings per Ability - access levels to Abilities! User | Admin | Creator
|
||||
* Embedded database - available for every declared ability
|
||||
* Proxy sender interface - enhances testability; accurate results pre-release
|
||||
|
||||
Alongside these exciting core features of the AbilityBot, the following have been introduced:
|
||||
* The bot automatically maintains an up-to-date set of all the users who have contacted the bot
|
||||
* up-to-date: if a user changes their Username, First Name or Last Name, the bot updates the respective field in the embedded-DB
|
||||
* Backup and recovery for the DB
|
||||
* Default implementation relies on JSON/Jackson
|
||||
* Ban and unban users from accessing your bots
|
||||
* The bot will execute the shortest path to discard the update the next time they try to spam
|
||||
* Promote and demote users as bot administrators
|
||||
* Allows admins to execute admin abilities
|
||||
|
||||
What's next?
|
||||
------------
|
||||
I am looking forward to:
|
||||
* Provide a trigger to record metrics per ability
|
||||
* Implement AsyncAbility
|
||||
* Maintain integration with the latest updates on the basic API
|
||||
* Enrich the bot with features requested by the community
|
||||
|
||||
Examples
|
||||
-------------------
|
||||
* [Example Bots](https://github.com/addo37/ExampleBots)
|
||||
|
||||
Do you have a project that uses **AbilityBots**? Let us know!
|
||||
|
||||
Support
|
||||
-------
|
||||
For issues and features, please use GitHub's [issues](https://github.com/rubenlagus/TelegramBots/issues) tab.
|
||||
|
||||
For quick feedback, chatting or just having fun, please come and join us in our Telegram Supergroup.
|
||||
|
||||
[![Telegram](http://trellobot.doomdns.org/telegrambadge.svg)](https://telegram.me/JavaBotsApi)
|
||||
|
||||
Credits
|
||||
-------
|
||||
This project would not have been made possible had it not been for [Ruben](https://github.com/rubenlagus)'s work with the [Telegram Bot Java API](https://github.com/rubenlagus/TelegramBots).
|
||||
I strongly urge you to check out that project and implement a bot to have a sense of how the basic API feels like.
|
||||
Ruben has done a great job in supplying a clear and straightforward API that conforms to Telegram's HTTP API.
|
||||
There is also a chat for that API.
|
263
telegrambots-abilities/pom.xml
Normal file
263
telegrambots-abilities/pom.xml
Normal file
@ -0,0 +1,263 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-abilities</artifactId>
|
||||
<version>3.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Telegram Ability Bot</name>
|
||||
<url>https://github.com/rubenlagus/TelegramBots</url>
|
||||
<description>AbilityBot Extension and Abstraction</description>
|
||||
|
||||
<issueManagement>
|
||||
<url>https://github.com/rubenlagus/TelegramBots/issues</url>
|
||||
<system>GitHub Issues</system>
|
||||
</issueManagement>
|
||||
|
||||
<scm>
|
||||
<url>https://github.com/rubenlagus/TelegramBots</url>
|
||||
<connection>scm:git:git://github.com/rubenlagus/TelegramBots.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:rubenlagus/TelegramBots.git</developerConnection>
|
||||
</scm>
|
||||
|
||||
<ciManagement>
|
||||
<url>https://travis-ci.org/rubenlagus/TelegramBots</url>
|
||||
<system>Travis</system>
|
||||
</ciManagement>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<email>abbas.aboudayya@gmail.com</email>
|
||||
<name>Abbas Abou Daya</name>
|
||||
<url>https://github.com/addo37</url>
|
||||
<id>addo37</id>
|
||||
</developer>
|
||||
<developer>
|
||||
<email>rberlopez@gmail.com</email>
|
||||
<name>Ruben Bermudez</name>
|
||||
<url>https://github.com/rubenlagus</url>
|
||||
<id>rubenlagus</id>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>MIT License</name>
|
||||
<url>http://www.opensource.org/licenses/mit-license.php</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<bots.version>3.2</bots.version>
|
||||
<commonslang.version>3.5</commonslang.version>
|
||||
<mapdb.version>3.0.4</mapdb.version>
|
||||
<guava.version>19.0</guava.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>${bots.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commonslang.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapdb</groupId>
|
||||
<artifactId>mapdb</artifactId>
|
||||
<version>${mapdb.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</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>
|
||||
|
||||
<build>
|
||||
<directory>${project.basedir}/target</directory>
|
||||
<outputDirectory>${project.build.directory}/classes</outputDirectory>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
|
||||
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.3</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>clean-project</id>
|
||||
<phase>clean</phase>
|
||||
<goals>
|
||||
<goal>clean</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.10.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>0.7.7.201606060606</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>report</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>enforce-versions</id>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<rules>
|
||||
<DependencyConvergence />
|
||||
</rules>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,743 @@
|
||||
package org.telegram.abilitybots.api.bot;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
import org.telegram.abilitybots.api.objects.*;
|
||||
import org.telegram.abilitybots.api.sender.DefaultMessageSender;
|
||||
import org.telegram.abilitybots.api.sender.MessageSender;
|
||||
import org.telegram.abilitybots.api.util.AbilityUtils;
|
||||
import org.telegram.abilitybots.api.util.Pair;
|
||||
import org.telegram.abilitybots.api.util.Trio;
|
||||
import org.telegram.telegrambots.api.methods.GetFile;
|
||||
import org.telegram.telegrambots.api.methods.send.SendDocument;
|
||||
import org.telegram.telegrambots.api.objects.Message;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiException;
|
||||
import org.telegram.telegrambots.logging.BotLogger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.lang.String.format;
|
||||
import static java.time.ZonedDateTime.now;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.Objects.nonNull;
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static java.util.function.Function.identity;
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static java.util.regex.Pattern.compile;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static jersey.repackaged.com.google.common.base.Throwables.propagate;
|
||||
import static org.telegram.abilitybots.api.db.MapDBContext.onlineInstance;
|
||||
import static org.telegram.abilitybots.api.objects.Ability.builder;
|
||||
import static org.telegram.abilitybots.api.objects.EndUser.fromUser;
|
||||
import static org.telegram.abilitybots.api.objects.Flag.*;
|
||||
import static org.telegram.abilitybots.api.objects.Locality.*;
|
||||
import static org.telegram.abilitybots.api.objects.MessageContext.newContext;
|
||||
import static org.telegram.abilitybots.api.objects.Privacy.*;
|
||||
import static org.telegram.abilitybots.api.util.AbilityUtils.*;
|
||||
|
||||
/**
|
||||
* The <b>father</b> of all ability bots. Bots that need to utilize abilities need to extend this bot.
|
||||
* <p>
|
||||
* It's important to note that this bot strictly extends {@link TelegramLongPollingBot}.
|
||||
* <p>
|
||||
* All bots extending the {@link AbilityBot} get implicit abilities:
|
||||
* <ul>
|
||||
* <li>/claim - Claims this bot</li>
|
||||
* <ul>
|
||||
* <li>Sets the user as the {@link Privacy#CREATOR} of the bot</li>
|
||||
* <li>Only the user with the ID returned by {@link AbilityBot#creatorId()} can genuinely claim the bot</li>
|
||||
* </ul>
|
||||
* <li>/commands - reports all user-defined commands (abilities)</li>
|
||||
* <ul>
|
||||
* <li>The same format acceptable by BotFather</li>
|
||||
* </ul>
|
||||
* <li>/backup - returns a backup of the bot database</li>
|
||||
* <li>/recover - recovers the database</li>
|
||||
* <li>/promote <code>@username</code> - promotes user to bot admin</li>
|
||||
* <li>/demote <code>@username</code> - demotes bot admin to user</li>
|
||||
* <li>/ban <code>@username</code> - bans the user from accessing your bot commands and features</li>
|
||||
* <li>/unban <code>@username</code> - lifts the ban from the user</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Additional information of the implicit abilities are present in the methods that declare them.
|
||||
* <p>
|
||||
* The two most important handles in the AbilityBot are the {@link DBContext} <b><code>db</code></b> and the {@link MessageSender} <b><code>sender</code></b>.
|
||||
* All bots extending AbilityBot can use both handles in their update consumers.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
private static final String TAG = AbilityBot.class.getSimpleName();
|
||||
|
||||
// DB objects
|
||||
public static final String ADMINS = "ADMINS";
|
||||
public static final String USERS = "USERS";
|
||||
public static final String USER_ID = "USER_ID";
|
||||
public static final String BLACKLIST = "BLACKLIST";
|
||||
|
||||
// Factory commands
|
||||
protected static final String DEFAULT = "default";
|
||||
protected static final String CLAIM = "claim";
|
||||
protected static final String BAN = "ban";
|
||||
protected static final String PROMOTE = "promote";
|
||||
protected static final String DEMOTE = "demote";
|
||||
protected static final String UNBAN = "unban";
|
||||
protected static final String BACKUP = "backup";
|
||||
protected static final String RECOVER = "recover";
|
||||
protected static final String COMMANDS = "commands";
|
||||
|
||||
// Messages
|
||||
protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached.";
|
||||
protected static final String RECOVER_SUCCESS = "I have successfully recovered.";
|
||||
|
||||
// DB and sender
|
||||
protected final DBContext db;
|
||||
protected MessageSender sender;
|
||||
|
||||
// Bot token and username
|
||||
private final String botToken;
|
||||
private final String botUsername;
|
||||
|
||||
// Ability registry
|
||||
private Map<String, Ability> abilities;
|
||||
|
||||
// Reply registry
|
||||
private List<Reply> replies;
|
||||
|
||||
protected AbilityBot(String botToken, String botUsername, DBContext db, DefaultBotOptions botOptions) {
|
||||
super(botOptions);
|
||||
|
||||
this.botToken = botToken;
|
||||
this.botUsername = botUsername;
|
||||
this.db = db;
|
||||
this.sender = new DefaultMessageSender(this);
|
||||
|
||||
registerAbilities();
|
||||
}
|
||||
|
||||
protected AbilityBot(String botToken, String botUsername, DBContext db) {
|
||||
this(botToken, botUsername, db, new DefaultBotOptions());
|
||||
}
|
||||
|
||||
protected AbilityBot(String botToken, String botUsername, DefaultBotOptions botOptions) {
|
||||
this(botToken, botUsername, onlineInstance(botUsername), botOptions);
|
||||
}
|
||||
|
||||
protected AbilityBot(String botToken, String botUsername) {
|
||||
this(botToken, botUsername, onlineInstance(botUsername));
|
||||
}
|
||||
|
||||
public abstract int creatorId();
|
||||
|
||||
/**
|
||||
* @return the map of ID -> EndUser
|
||||
*/
|
||||
protected Map<Integer, EndUser> users() {
|
||||
return db.getMap(USERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the map of Username -> ID
|
||||
*/
|
||||
protected Map<String, Integer> userIds() {
|
||||
return db.getMap(USER_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a blacklist containing all the IDs of the banned users
|
||||
*/
|
||||
protected Set<Integer> blacklist() {
|
||||
return db.getSet(BLACKLIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an admin set of all the IDs of bot administrators
|
||||
*/
|
||||
protected Set<Integer> admins() {
|
||||
return db.getSet(ADMINS);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method contains the stream of actions that are applied on any update.
|
||||
* <p>
|
||||
* It will correctly handle addition of users into the DB and the execution of abilities and replies.
|
||||
*
|
||||
* @param update the update received by Telegram's API
|
||||
*/
|
||||
@Override
|
||||
public void onUpdateReceived(Update update) {
|
||||
BotLogger.info(format("New update [%s] received at %s", update.getUpdateId(), now()), format("%s - %s", TAG, botUsername));
|
||||
BotLogger.info(update.toString(), TAG);
|
||||
long millisStarted = System.currentTimeMillis();
|
||||
|
||||
Stream.of(update)
|
||||
.filter(this::checkGlobalFlags)
|
||||
.filter(this::checkBlacklist)
|
||||
.map(this::addUser)
|
||||
.filter(this::filterReply)
|
||||
.map(this::getAbility)
|
||||
.filter(this::validateAbility)
|
||||
.filter(this::checkPrivacy)
|
||||
.filter(this::checkLocality)
|
||||
.filter(this::checkInput)
|
||||
.filter(this::checkMessageFlags)
|
||||
.map(this::getContext)
|
||||
.map(this::consumeUpdate)
|
||||
.forEach(this::postConsumption);
|
||||
|
||||
long processingTime = System.currentTimeMillis() - millisStarted;
|
||||
BotLogger.info(format("Processing of update [%s] ended at %s%n---> Processing time: [%d ms] <---%n", update.getUpdateId(), now(), processingTime), format("%s - %s", TAG, botUsername));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBotToken() {
|
||||
return botToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBotUsername() {
|
||||
return botUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the update against the provided global flags. The default implementation requires a {@link Flag#MESSAGE}.
|
||||
* <p>
|
||||
* This method should be <b>overridden</b> if the user wants updates that don't require a MESSAGE to pass through.
|
||||
*
|
||||
* @param update a Telegram {@link Update}
|
||||
* @return <tt>true</tt> if the update satisfies the global flags
|
||||
*/
|
||||
protected boolean checkGlobalFlags(Update update) {
|
||||
return MESSAGE.test(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user with the specified username.
|
||||
*
|
||||
* @param username the username of the required user
|
||||
* @return the user
|
||||
*/
|
||||
protected EndUser getUser(String username) {
|
||||
Integer id = userIds().get(username.toLowerCase());
|
||||
if (id == null) {
|
||||
throw new IllegalStateException(format("Could not find ID corresponding to username [%s]", username));
|
||||
}
|
||||
|
||||
return getUser(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user with the specified ID.
|
||||
*
|
||||
* @param id the id of the required user
|
||||
* @return the user
|
||||
*/
|
||||
protected EndUser getUser(int id) {
|
||||
EndUser endUser = users().get(id);
|
||||
if (endUser == null) {
|
||||
throw new IllegalStateException(format("Could not find user corresponding to id [%d]", id));
|
||||
}
|
||||
|
||||
return endUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user with the specified username. If user was not found, the bot will send a message on Telegram.
|
||||
*
|
||||
* @param username the username of the required user
|
||||
* @return the id of the user
|
||||
*/
|
||||
protected int getUserIdSendError(String username, long chatId) {
|
||||
try {
|
||||
return getUser(username).id();
|
||||
} catch (IllegalStateException ex) {
|
||||
sender.send(format("Sorry, I could not find the user [%s].", username), chatId);
|
||||
throw propagate(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Format of the report:
|
||||
* <p>
|
||||
* [command1] - [description1]
|
||||
* <p>
|
||||
* [command2] - [description2]
|
||||
* <p>
|
||||
* ...
|
||||
* <p>
|
||||
* Once you invoke it, the bot will send the available commands to the chat. This is a public ability so anyone can invoke it.
|
||||
* <p>
|
||||
* Usage: <code>/commands</code>
|
||||
*
|
||||
* @return the ability to report commands defined by the child bot.
|
||||
*/
|
||||
public Ability reportCommands() {
|
||||
return builder()
|
||||
.name(COMMANDS)
|
||||
.locality(ALL)
|
||||
.privacy(PUBLIC)
|
||||
.input(0)
|
||||
.action(ctx -> {
|
||||
String commands = abilities.entrySet().stream()
|
||||
.filter(entry -> nonNull(entry.getValue().info()))
|
||||
.map(entry -> {
|
||||
String name = entry.getValue().name();
|
||||
String info = entry.getValue().info();
|
||||
return format("%s - %s", name, info);
|
||||
})
|
||||
.sorted()
|
||||
.reduce((a, b) -> format("%s%n%s", a, b))
|
||||
.orElse("No public commands found.");
|
||||
|
||||
sender.send(commands, ctx.chatId());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* This backup ability returns the object defined by {@link DBContext#backup()} as a message document.
|
||||
* <p>
|
||||
* This is a high-profile ability and is restricted to the CREATOR only.
|
||||
* <p>
|
||||
* Usage: <code>/backup</code>
|
||||
*
|
||||
* @return the ability to back-up the database of the bot
|
||||
*/
|
||||
public Ability backupDB() {
|
||||
return builder()
|
||||
.name(BACKUP)
|
||||
.locality(USER)
|
||||
.privacy(CREATOR)
|
||||
.input(0)
|
||||
.action(ctx -> {
|
||||
File backup = new File("backup.json");
|
||||
|
||||
try (PrintStream printStream = new PrintStream(backup)) {
|
||||
printStream.print(db.backup());
|
||||
sender.sendDocument(new SendDocument()
|
||||
.setNewDocument(backup)
|
||||
.setChatId(ctx.chatId())
|
||||
);
|
||||
} catch (FileNotFoundException e) {
|
||||
BotLogger.error("Error while fetching backup", TAG, e);
|
||||
} catch (TelegramApiException e) {
|
||||
BotLogger.error("Error while sending document/backup file", TAG, e);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recovers the bot database using {@link DBContext#recover(Object)}.
|
||||
* <p>
|
||||
* The bot recovery process hugely depends on the implementation of the recovery method of {@link DBContext}.
|
||||
* <p>
|
||||
* Usage: <code>/recover</code>
|
||||
*
|
||||
* @return the ability to recover the database of the bot
|
||||
*/
|
||||
public Ability recoverDB() {
|
||||
return builder()
|
||||
.name(RECOVER)
|
||||
.locality(USER)
|
||||
.privacy(CREATOR)
|
||||
.input(0)
|
||||
.action(ctx -> sender.forceReply(RECOVERY_MESSAGE, ctx.chatId()))
|
||||
.reply(update -> {
|
||||
Long chatId = update.getMessage().getChatId();
|
||||
String fileId = update.getMessage().getDocument().getFileId();
|
||||
|
||||
try (FileReader reader = new FileReader(downloadFileWithId(fileId))) {
|
||||
String backupData = IOUtils.toString(reader);
|
||||
if (db.recover(backupData)) {
|
||||
sender.send(RECOVER_SUCCESS, chatId);
|
||||
} else {
|
||||
sender.send("Oops, something went wrong during recovery.", chatId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
BotLogger.error("Could not recover DB from backup", TAG, e);
|
||||
sender.send("I have failed to recover.", chatId);
|
||||
}
|
||||
}, MESSAGE, DOCUMENT, REPLY, isReplyTo(RECOVERY_MESSAGE))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Banned users are accumulated in the blacklist. Use {@link DBContext#getSet(String)} with name specified by {@link AbilityBot#BLACKLIST}.
|
||||
* <p>
|
||||
* Usage: <code>/ban @username</code>
|
||||
* <p>
|
||||
* <u>Note that admins who try to ban the creator, get banned.</u>
|
||||
*
|
||||
* @return the ability to ban the user from any kind of <b>bot interaction</b>
|
||||
*/
|
||||
public Ability banUser() {
|
||||
return builder()
|
||||
.name(BAN)
|
||||
.locality(ALL)
|
||||
.privacy(ADMIN)
|
||||
.input(1)
|
||||
.action(ctx -> {
|
||||
String username = stripTag(ctx.firstArg());
|
||||
int userId = getUserIdSendError(username, ctx.chatId());
|
||||
String bannedUser;
|
||||
|
||||
// Protection from abuse
|
||||
if (userId == creatorId()) {
|
||||
userId = ctx.user().id();
|
||||
bannedUser = isNullOrEmpty(ctx.user().username()) ? addTag(ctx.user().username()) : ctx.user().shortName();
|
||||
} else {
|
||||
bannedUser = addTag(username);
|
||||
}
|
||||
|
||||
Set<Integer> blacklist = blacklist();
|
||||
if (blacklist.contains(userId))
|
||||
sender.sendMd(format("%s is already *banned*.", bannedUser), ctx.chatId());
|
||||
else {
|
||||
blacklist.add(userId);
|
||||
sender.sendMd(format("%s is now *banned*.", bannedUser), ctx.chatId());
|
||||
}
|
||||
})
|
||||
.post(commitTo(db))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage: <code>/unban @username</code>
|
||||
*
|
||||
* @return the ability to unban a user
|
||||
*/
|
||||
public Ability unbanUser() {
|
||||
return builder()
|
||||
.name(UNBAN)
|
||||
.locality(ALL)
|
||||
.privacy(ADMIN)
|
||||
.input(1)
|
||||
.action(ctx -> {
|
||||
String username = stripTag(ctx.firstArg());
|
||||
Integer userId = getUserIdSendError(username, ctx.chatId());
|
||||
|
||||
Set<Integer> blacklist = blacklist();
|
||||
|
||||
if (!blacklist.remove(userId))
|
||||
sender.sendMd(format("@%s is *not* on the *blacklist*.", username), ctx.chatId());
|
||||
else {
|
||||
sender.sendMd(format("@%s, your ban has been *lifted*.", username), ctx.chatId());
|
||||
}
|
||||
})
|
||||
.post(commitTo(db))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ability to promote a user to a bot admin
|
||||
*/
|
||||
public Ability promoteAdmin() {
|
||||
return builder()
|
||||
.name(PROMOTE)
|
||||
.locality(ALL)
|
||||
.privacy(ADMIN)
|
||||
.input(1)
|
||||
.action(ctx -> {
|
||||
String username = stripTag(ctx.firstArg());
|
||||
Integer userId = getUserIdSendError(username, ctx.chatId());
|
||||
|
||||
Set<Integer> admins = admins();
|
||||
if (admins.contains(userId))
|
||||
sender.sendMd(format("@%s is already an *admin*.", username), ctx.chatId());
|
||||
else {
|
||||
admins.add(userId);
|
||||
sender.sendMd(format("@%s has been *promoted*.", username), ctx.chatId());
|
||||
}
|
||||
}).post(commitTo(db))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ability to demote an admin to a user
|
||||
*/
|
||||
public Ability demoteAdmin() {
|
||||
return builder()
|
||||
.name(DEMOTE)
|
||||
.locality(ALL)
|
||||
.privacy(ADMIN)
|
||||
.input(1)
|
||||
.action(ctx -> {
|
||||
String username = stripTag(ctx.firstArg());
|
||||
Integer userId = getUserIdSendError(username, ctx.chatId());
|
||||
|
||||
Set<Integer> admins = admins();
|
||||
if (admins.remove(userId)) {
|
||||
sender.sendMd(format("@%s has been *demoted*.", username), ctx.chatId());
|
||||
} else {
|
||||
sender.sendMd(format("@%s is *not* an *admin*.", username), ctx.chatId());
|
||||
}
|
||||
})
|
||||
.post(commitTo(db))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Regular users and admins who try to claim the bot will get <b>banned</b>.
|
||||
*
|
||||
* @return the ability to claim yourself as the master and creator of the bot
|
||||
*/
|
||||
public Ability claimCreator() {
|
||||
return builder()
|
||||
.name(CLAIM)
|
||||
.locality(ALL)
|
||||
.privacy(PUBLIC)
|
||||
.input(0)
|
||||
.action(ctx -> {
|
||||
if (ctx.user().id() == creatorId()) {
|
||||
Set<Integer> admins = admins();
|
||||
int id = creatorId();
|
||||
long chatId = ctx.chatId();
|
||||
|
||||
if (admins.contains(id))
|
||||
sender.send("You're already my master.", chatId);
|
||||
else {
|
||||
admins.add(id);
|
||||
sender.send("You're now my master.", chatId);
|
||||
}
|
||||
} else {
|
||||
// This is not a joke
|
||||
abilities.get(BAN).action().accept(newContext(ctx.update(), ctx.user(), ctx.chatId(), ctx.user().username()));
|
||||
}
|
||||
})
|
||||
.post(commitTo(db))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the declared abilities using method reflection. Also, replies are accumulated using the built abilities and standalone methods that return a Reply.
|
||||
* <p>
|
||||
* <b>Only abilities and replies with the <u>public</u> accessor are registered!</b>
|
||||
*/
|
||||
private void registerAbilities() {
|
||||
try {
|
||||
abilities = stream(this.getClass().getMethods())
|
||||
.filter(method -> method.getReturnType().equals(Ability.class))
|
||||
.map(this::returnAbility)
|
||||
.collect(toMap(Ability::name, identity()));
|
||||
|
||||
Stream<Reply> methodReplies = stream(this.getClass().getMethods())
|
||||
.filter(method -> method.getReturnType().equals(Reply.class))
|
||||
.map(this::returnReply);
|
||||
|
||||
Stream<Reply> abilityReplies = abilities.values().stream()
|
||||
.flatMap(ability -> ability.replies().stream());
|
||||
|
||||
replies = Stream.concat(methodReplies, abilityReplies).collect(toList());
|
||||
} catch (IllegalStateException e) {
|
||||
BotLogger.error(TAG, "Duplicate names found while registering abilities. Make sure that the abilities declared don't clash with the reserved ones.", e);
|
||||
throw propagate(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the method and retrieves its return {@link Ability}.
|
||||
*
|
||||
* @param method a method that returns an ability
|
||||
* @return the ability returned by the method
|
||||
*/
|
||||
private Ability returnAbility(Method method) {
|
||||
try {
|
||||
return (Ability) method.invoke(this);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
BotLogger.error("Could not add ability", TAG, e);
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the method and retrieves its returned Reply.
|
||||
*
|
||||
* @param method a method that returns a reply
|
||||
* @return the reply returned by the method
|
||||
*/
|
||||
private Reply returnReply(Method method) {
|
||||
try {
|
||||
return (Reply) method.invoke(this);
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
BotLogger.error("Could not add reply", TAG, e);
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void postConsumption(Pair<MessageContext, Ability> pair) {
|
||||
ofNullable(pair.b().postAction())
|
||||
.ifPresent(consumer -> consumer.accept(pair.a()));
|
||||
}
|
||||
|
||||
Pair<MessageContext, Ability> consumeUpdate(Pair<MessageContext, Ability> pair) {
|
||||
pair.b().action().accept(pair.a());
|
||||
return pair;
|
||||
}
|
||||
|
||||
Pair<MessageContext, Ability> getContext(Trio<Update, Ability, String[]> trio) {
|
||||
Update update = trio.a();
|
||||
EndUser user = fromUser(AbilityUtils.getUser(update));
|
||||
|
||||
return Pair.of(newContext(update, user, getChatId(update), trio.c()), trio.b());
|
||||
}
|
||||
|
||||
boolean checkBlacklist(Update update) {
|
||||
Integer id = AbilityUtils.getUser(update).getId();
|
||||
|
||||
return id == creatorId() || !blacklist().contains(id);
|
||||
}
|
||||
|
||||
boolean checkInput(Trio<Update, Ability, String[]> trio) {
|
||||
String[] tokens = trio.c();
|
||||
int abilityTokens = trio.b().tokens();
|
||||
|
||||
boolean isOk = abilityTokens == 0 || (tokens.length > 0 && tokens.length == abilityTokens);
|
||||
|
||||
if (!isOk)
|
||||
sender.send(String.format("Sorry, this feature requires %d additional %s.", abilityTokens, abilityTokens == 1 ? "input" : "inputs"), getChatId(trio.a()));
|
||||
return isOk;
|
||||
}
|
||||
|
||||
boolean checkLocality(Trio<Update, Ability, String[]> trio) {
|
||||
Update update = trio.a();
|
||||
Locality locality = isUserMessage(update) ? USER : GROUP;
|
||||
Locality abilityLocality = trio.b().locality();
|
||||
|
||||
boolean isOk = abilityLocality == ALL || locality == abilityLocality;
|
||||
|
||||
if (!isOk)
|
||||
sender.send(String.format("Sorry, %s-only feature.", abilityLocality.toString().toLowerCase()), getChatId(trio.a()));
|
||||
return isOk;
|
||||
}
|
||||
|
||||
boolean checkPrivacy(Trio<Update, Ability, String[]> trio) {
|
||||
Update update = trio.a();
|
||||
EndUser user = fromUser(AbilityUtils.getUser(update));
|
||||
Privacy privacy;
|
||||
int id = user.id();
|
||||
|
||||
privacy = isCreator(id) ? CREATOR : isAdmin(id) ? ADMIN : PUBLIC;
|
||||
|
||||
boolean isOk = privacy.compareTo(trio.b().privacy()) >= 0;
|
||||
|
||||
if (!isOk)
|
||||
sender.send(String.format("Sorry, %s-only feature.", trio.b().privacy().toString().toLowerCase()), getChatId(trio.a()));
|
||||
return isOk;
|
||||
}
|
||||
|
||||
private boolean isCreator(int id) {
|
||||
return id == creatorId();
|
||||
}
|
||||
|
||||
private boolean isAdmin(Integer id) {
|
||||
return admins().contains(id);
|
||||
}
|
||||
|
||||
boolean validateAbility(Trio<Update, Ability, String[]> trio) {
|
||||
return trio.b() != null;
|
||||
}
|
||||
|
||||
Trio<Update, Ability, String[]> getAbility(Update update) {
|
||||
// Handle updates without messages
|
||||
// Passing through this function means that the global flags have passed
|
||||
Message msg = update.getMessage();
|
||||
if (!update.hasMessage() || !msg.hasText())
|
||||
return Trio.of(update, abilities.get(DEFAULT), new String[]{});
|
||||
|
||||
// Priority goes to text before captions
|
||||
String[] tokens = msg.getText().split(" ");
|
||||
|
||||
if (tokens[0].startsWith("/")) {
|
||||
String abilityToken = stripBotUsername(tokens[0].substring(1));
|
||||
Ability ability = abilities.get(abilityToken);
|
||||
tokens = Arrays.copyOfRange(tokens, 1, tokens.length);
|
||||
return Trio.of(update, ability, tokens);
|
||||
} else {
|
||||
Ability ability = abilities.get(DEFAULT);
|
||||
return Trio.of(update, ability, tokens);
|
||||
}
|
||||
}
|
||||
|
||||
private String stripBotUsername(String token) {
|
||||
return compile(format("@%s", botUsername), CASE_INSENSITIVE)
|
||||
.matcher(token)
|
||||
.replaceAll("");
|
||||
}
|
||||
|
||||
Update addUser(Update update) {
|
||||
EndUser endUser = fromUser(AbilityUtils.getUser(update));
|
||||
|
||||
users().compute(endUser.id(), (id, user) -> {
|
||||
if (user == null) {
|
||||
updateUserId(user, endUser);
|
||||
return endUser;
|
||||
}
|
||||
|
||||
if (!user.equals(endUser)) {
|
||||
updateUserId(user, endUser);
|
||||
return endUser;
|
||||
}
|
||||
|
||||
return user;
|
||||
});
|
||||
|
||||
db.commit();
|
||||
return update;
|
||||
}
|
||||
|
||||
private void updateUserId(EndUser oldUser, EndUser newUser) {
|
||||
if (oldUser != null && oldUser.username() != null) {
|
||||
// Remove old username -> ID
|
||||
userIds().remove(oldUser.username());
|
||||
}
|
||||
|
||||
if (newUser.username() != null) {
|
||||
// Add new mapping with the new username
|
||||
userIds().put(newUser.username().toLowerCase(), newUser.id());
|
||||
}
|
||||
}
|
||||
|
||||
boolean filterReply(Update update) {
|
||||
return replies.stream()
|
||||
.filter(reply -> reply.isOkFor(update))
|
||||
.map(reply -> {
|
||||
reply.actOn(update);
|
||||
return false;
|
||||
})
|
||||
.reduce(true, Boolean::logicalAnd);
|
||||
}
|
||||
|
||||
boolean checkMessageFlags(Trio<Update, Ability, String[]> trio) {
|
||||
Ability ability = trio.b();
|
||||
Update update = trio.a();
|
||||
|
||||
// The following variable is required to avoid bug #JDK-8044546
|
||||
BiFunction<Boolean, Predicate<Update>, Boolean> flagAnd = (flag, nextFlag) -> flag && nextFlag.test(update);
|
||||
return ability.flags().stream()
|
||||
.reduce(true, flagAnd, Boolean::logicalAnd);
|
||||
}
|
||||
|
||||
private File downloadFileWithId(String fileId) throws TelegramApiException {
|
||||
return sender.downloadFile(sender.getFile(new GetFile().setFileId(fileId)));
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package org.telegram.abilitybots.api.db;
|
||||
|
||||
import org.telegram.abilitybots.api.bot.AbilityBot;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This interface represents the high-level methods exposed to the user when handling an {@link Update}.
|
||||
* Example usage:
|
||||
* <p><code>Ability.builder().action(ctx -> {db.getSet(USERS); doSomething();})* </code></p>
|
||||
* {@link AbilityBot} contains a handle on the <code>db</code> that the user can use inside his declared abilities.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public interface DBContext extends Closeable {
|
||||
/**
|
||||
* @param name the unique name of the {@link List}
|
||||
* @param <T> the type that the List holds
|
||||
* @return the List with the specified name
|
||||
*/
|
||||
<T> List<T> getList(String name);
|
||||
|
||||
/**
|
||||
* @param name the unique name of the {@link Map}
|
||||
* @param <K> the type of the Map keys
|
||||
* @param <V> the type of the Map values
|
||||
* @return the Map with the specified name
|
||||
*/
|
||||
<K, V> Map<K, V> getMap(String name);
|
||||
|
||||
/**
|
||||
* @param name the unique name of the {@link Set}
|
||||
* @param <T> the type that the Set holds
|
||||
* @return the Set with the specified name
|
||||
*/
|
||||
<T> Set<T> getSet(String name);
|
||||
|
||||
/**
|
||||
* @return a high-level summary of the database structures (Sets, Lists, Maps, ...) present.
|
||||
*/
|
||||
String summary();
|
||||
|
||||
/**
|
||||
* Implementations of this method are free to return any object such as XML, JSON, etc...
|
||||
*
|
||||
* @return a backup of the DB
|
||||
*/
|
||||
Object backup();
|
||||
|
||||
/**
|
||||
* The object passed to this method need to conform to the implementation of the {@link DBContext#backup()} method.
|
||||
*
|
||||
* @param backup the backup of the database containing all the structures
|
||||
* @return <tt>true</tt> if the database successfully recovered
|
||||
*/
|
||||
boolean recover(Object backup);
|
||||
|
||||
/**
|
||||
* @param name the name of the data structure
|
||||
* @return the high-level information of the structure
|
||||
*/
|
||||
String info(String name);
|
||||
|
||||
/**
|
||||
* Commits the database to its persistent layer. Implementations are free to not implement this method as it is not compulsory.
|
||||
*/
|
||||
void commit();
|
||||
|
||||
/**
|
||||
* Clears the data structures present in the database.
|
||||
* <p>
|
||||
* This method does not delete the data-structure themselves, but leaves them empty.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* @param name the name of the data structure
|
||||
* @return <tt>true</tt> if this database contains the specified structure name
|
||||
*/
|
||||
boolean contains(String name);
|
||||
}
|
@ -0,0 +1,224 @@
|
||||
package org.telegram.abilitybots.api.db;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.mapdb.DB;
|
||||
import org.mapdb.DBMaker;
|
||||
import org.mapdb.Serializer;
|
||||
import org.telegram.abilitybots.api.util.Pair;
|
||||
import org.telegram.telegrambots.logging.BotLogger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
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 java.lang.String.format;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static java.util.stream.StreamSupport.stream;
|
||||
import static org.mapdb.Serializer.JAVA;
|
||||
import static org.telegram.abilitybots.api.bot.AbilityBot.USERS;
|
||||
|
||||
/**
|
||||
* An implementation of {@link DBContext} that relies on a {@link DB}.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
* @see <a href="https://github.com/jankotek/mapdb">MapDB project</a>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MapDBContext implements DBContext {
|
||||
private static final String TAG = DBContext.class.getSimpleName();
|
||||
|
||||
private final DB db;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public MapDBContext(DB db) {
|
||||
this.db = db;
|
||||
|
||||
objectMapper = new ObjectMapper();
|
||||
objectMapper.enableDefaultTyping();
|
||||
}
|
||||
|
||||
/**
|
||||
* This DB returned by this method does not trigger deletion on JVM shutdown.
|
||||
*
|
||||
* @param name name of the DB file
|
||||
* @return an online instance of {@link MapDBContext}
|
||||
*/
|
||||
public static DBContext onlineInstance(String name) {
|
||||
DB db = DBMaker
|
||||
.fileDB(name)
|
||||
.fileMmapEnableIfSupported()
|
||||
.closeOnJvmShutdown()
|
||||
.transactionEnable()
|
||||
.make();
|
||||
|
||||
return new MapDBContext(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* This DB returned by this method gets deleted on JVM shutdown.
|
||||
*
|
||||
* @param name name of the DB file
|
||||
* @return an offline instance of {@link MapDBContext}
|
||||
*/
|
||||
public static DBContext offlineInstance(String name) {
|
||||
DB db = DBMaker
|
||||
.fileDB(name)
|
||||
.fileMmapEnableIfSupported()
|
||||
.closeOnJvmShutdown()
|
||||
.cleanerHackEnable()
|
||||
.transactionEnable()
|
||||
.fileDeleteAfterClose()
|
||||
.make();
|
||||
|
||||
return new MapDBContext(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> getList(String name) {
|
||||
return (List<T>) db.<T>indexTreeList(name, Serializer.JAVA).createOrOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> Map<K, V> getMap(String name) {
|
||||
return db.<K, V>hashMap(name, JAVA, JAVA).createOrOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Set<T> getSet(String name) {
|
||||
return (Set<T>) db.<T>hashSet(name, JAVA).createOrOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String summary() {
|
||||
return stream(db.getAllNames().spliterator(), false)
|
||||
.map(this::info)
|
||||
.reduce(new StringJoiner("\n"), StringJoiner::add, StringJoiner::merge)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object backup() {
|
||||
Map<String, Object> collectedMap = localCopy();
|
||||
return writeAsString(collectedMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean recover(Object backup) {
|
||||
Map<String, Object> snapshot = localCopy();
|
||||
|
||||
try {
|
||||
Map<String, Object> backupData = objectMapper.readValue(backup.toString(), new TypeReference<HashMap<String, Object>>() {
|
||||
});
|
||||
doRecover(backupData);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
BotLogger.error(format("Could not recover DB data from file with String representation %s", backup), TAG, e);
|
||||
// Attempt to fallback to data snapshot before recovery
|
||||
doRecover(snapshot);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String info(String name) {
|
||||
Object struct = db.get(name);
|
||||
if (isNull(struct))
|
||||
throw new IllegalStateException(format("DB structure with name [%s] does not exist", name));
|
||||
|
||||
if (struct instanceof Set)
|
||||
return format("%s - Set - %d", name, ((Set) struct).size());
|
||||
else if (struct instanceof List)
|
||||
return format("%s - List - %d", name, ((List) struct).size());
|
||||
else if (struct instanceof Map)
|
||||
return format("%s - Map - %d", name, ((Map) struct).size());
|
||||
else
|
||||
return format("%s - %s", name, struct.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
db.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
db.getAllNames().forEach(name -> {
|
||||
Object struct = db.get(name);
|
||||
if (struct instanceof Collection)
|
||||
((Collection) struct).clear();
|
||||
else if (struct instanceof Map)
|
||||
((Map) struct).clear();
|
||||
});
|
||||
commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String name) {
|
||||
return db.exists(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
db.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a local non-thread safe copy of the database
|
||||
*/
|
||||
private Map<String, Object> localCopy() {
|
||||
return db.getAll().entrySet().stream().map(entry -> {
|
||||
Object struct = entry.getValue();
|
||||
if (struct instanceof Set)
|
||||
return Pair.of(entry.getKey(), newHashSet((Set) struct));
|
||||
else if (struct instanceof List)
|
||||
return Pair.of(entry.getKey(), newArrayList((List) struct));
|
||||
else if (struct instanceof Map)
|
||||
return Pair.of(entry.getKey(), newHashMap((Map) struct));
|
||||
else
|
||||
return Pair.of(entry.getKey(), struct);
|
||||
}).collect(toMap(pair -> (String) pair.a(), Pair::b));
|
||||
}
|
||||
|
||||
private void doRecover(Map<String, Object> backupData) {
|
||||
clear();
|
||||
backupData.forEach((name, value) -> {
|
||||
|
||||
if (value instanceof Set) {
|
||||
Set entrySet = (Set) value;
|
||||
getSet(name).addAll(entrySet);
|
||||
} else if (value instanceof Map) {
|
||||
Map<Object, Object> entryMap = (Map) value;
|
||||
|
||||
// TODO: This is ugly
|
||||
// Special handling of USERS since the key is an integer. JSON by default considers a map a JSONObject.
|
||||
// Keys are serialized and deserialized as String
|
||||
if (name.equals(USERS))
|
||||
entryMap = entryMap.entrySet().stream()
|
||||
.map(entry -> Pair.of(Integer.parseInt(entry.getKey().toString()), entry.getValue()))
|
||||
.collect(toMap(Pair::a, Pair::b));
|
||||
|
||||
getMap(name).putAll(entryMap);
|
||||
} else if (value instanceof List) {
|
||||
List entryList = (List) value;
|
||||
getList(name).addAll(entryList);
|
||||
} else {
|
||||
BotLogger.error(TAG, format("Unable to identify object type during DB recovery, entry name: %s", name));
|
||||
}
|
||||
});
|
||||
commit();
|
||||
}
|
||||
|
||||
private String writeAsString(Object obj) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
BotLogger.info(format("Failed to read the JSON representation of object: %s", obj), TAG, e);
|
||||
return "Error reading required data...";
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
import org.telegram.telegrambots.logging.BotLogger;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Objects.hash;
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
|
||||
/**
|
||||
* An ability is a fully-fledged bot action that contains all the necessary information to process:
|
||||
* <ol>
|
||||
* <li>A response to a command</li>
|
||||
* <li>A post-response to a command</li>
|
||||
* <li>A reply to a sequence of actions</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* In-order to instantiate an ability, you can call {@link Ability#builder()} to get the {@link AbilityBuilder}.
|
||||
* Once you're done setting your ability, you'll call {@link AbilityBuilder#build()} to get your constructed ability.
|
||||
* <p>
|
||||
* The only optional fields in an ability are {@link Ability#info}, {@link Ability#postAction}, {@link Ability#flags} and {@link Ability#replies}.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public final class Ability {
|
||||
private static final String TAG = Ability.class.getSimpleName();
|
||||
|
||||
private final String name;
|
||||
private final String info;
|
||||
private final Locality locality;
|
||||
private final Privacy privacy;
|
||||
private final int argNum;
|
||||
private final Consumer<MessageContext> action;
|
||||
private final Consumer<MessageContext> postAction;
|
||||
private final List<Reply> replies;
|
||||
private final List<Predicate<Update>> flags;
|
||||
|
||||
@SafeVarargs
|
||||
private Ability(String name, String info, Locality locality, Privacy privacy, int argNum, Consumer<MessageContext> action, Consumer<MessageContext> postAction, List<Reply> replies, Predicate<Update>... flags) {
|
||||
checkArgument(!isEmpty(name), "Method name cannot be empty");
|
||||
checkArgument(!containsWhitespace(name), "Method name cannot contain spaces");
|
||||
checkArgument(isAlphanumeric(name), "Method name can only be alpha-numeric", name);
|
||||
this.name = name;
|
||||
this.info = info;
|
||||
|
||||
this.locality = checkNotNull(locality, "Please specify a valid locality setting. Use the Locality enum class");
|
||||
this.privacy = checkNotNull(privacy, "Please specify a valid privacy setting. Use the Privacy enum class");
|
||||
|
||||
checkArgument(argNum >= 0, "The number of arguments the method can handle CANNOT be negative. " +
|
||||
"Use the number 0 if the method ignores the arguments OR uses as many as appended");
|
||||
this.argNum = argNum;
|
||||
|
||||
this.action = checkNotNull(action, "Method action can't be empty. Please assign a function by using .action() method");
|
||||
if (postAction == null)
|
||||
BotLogger.info(TAG, format("No post action was detected for method with name [%s]", name));
|
||||
|
||||
this.flags = ofNullable(flags).map(Arrays::asList).orElse(newArrayList());
|
||||
|
||||
this.postAction = postAction;
|
||||
this.replies = replies;
|
||||
}
|
||||
|
||||
public static AbilityBuilder builder() {
|
||||
return new AbilityBuilder();
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String info() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public Locality locality() {
|
||||
return locality;
|
||||
}
|
||||
|
||||
public Privacy privacy() {
|
||||
return privacy;
|
||||
}
|
||||
|
||||
public int tokens() {
|
||||
return argNum;
|
||||
}
|
||||
|
||||
public Consumer<MessageContext> action() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public Consumer<MessageContext> postAction() {
|
||||
return postAction;
|
||||
}
|
||||
|
||||
public List<Reply> replies() {
|
||||
return replies;
|
||||
}
|
||||
|
||||
public List<Predicate<Update>> flags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("name", name)
|
||||
.add("locality", locality)
|
||||
.add("privacy", privacy)
|
||||
.add("argNum", argNum)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Ability ability = (Ability) o;
|
||||
return argNum == ability.argNum &&
|
||||
Objects.equal(name, ability.name) &&
|
||||
locality == ability.locality &&
|
||||
privacy == ability.privacy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash(name, info, locality, privacy, argNum, action, postAction, replies, flags);
|
||||
}
|
||||
|
||||
public static class AbilityBuilder {
|
||||
private String name;
|
||||
private String info;
|
||||
private Privacy privacy;
|
||||
private Locality locality;
|
||||
private int argNum;
|
||||
private Consumer<MessageContext> consumer;
|
||||
private Consumer<MessageContext> postConsumer;
|
||||
private List<Reply> replies;
|
||||
private Flag[] flags;
|
||||
|
||||
private AbilityBuilder() {
|
||||
replies = newArrayList();
|
||||
}
|
||||
|
||||
public AbilityBuilder action(Consumer<MessageContext> consumer) {
|
||||
this.consumer = consumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbilityBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbilityBuilder info(String info) {
|
||||
this.info = info;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbilityBuilder flag(Flag... flags) {
|
||||
this.flags = flags;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbilityBuilder locality(Locality type) {
|
||||
this.locality = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbilityBuilder input(int argNum) {
|
||||
this.argNum = argNum;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbilityBuilder privacy(Privacy privacy) {
|
||||
this.privacy = privacy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AbilityBuilder post(Consumer<MessageContext> postConsumer) {
|
||||
this.postConsumer = postConsumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final AbilityBuilder reply(Consumer<Update> action, Predicate<Update>... conditions) {
|
||||
replies.add(Reply.of(action, conditions));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Ability build() {
|
||||
return new Ability(name, info, locality, privacy, argNum, consumer, postConsumer, replies, flags);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.telegram.telegrambots.api.objects.User;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
||||
|
||||
/**
|
||||
* This class serves the purpose of separating the basic Telegram {@link User} and the augmented {@link EndUser}.
|
||||
* <p>
|
||||
* It adds proper hashCode, equals, toString as well as useful utility methods such as {@link EndUser#shortName} and {@link EndUser#fullName}.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public final class EndUser implements Serializable {
|
||||
@JsonProperty("id")
|
||||
private final Integer id;
|
||||
@JsonProperty("firstName")
|
||||
private final String firstName;
|
||||
@JsonProperty("lastName")
|
||||
private final String lastName;
|
||||
@JsonProperty("username")
|
||||
private final String username;
|
||||
|
||||
private EndUser(Integer id, String firstName, String lastName, String username) {
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static EndUser endUser(@JsonProperty("id") Integer id,
|
||||
@JsonProperty("firstName") String firstName,
|
||||
@JsonProperty("lastName") String lastName,
|
||||
@JsonProperty("username") String username) {
|
||||
return new EndUser(id, firstName, lastName, username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@link EndUser} from a {@link User}.
|
||||
*
|
||||
* @param user the Telegram user
|
||||
* @return an augmented end-user
|
||||
*/
|
||||
public static EndUser fromUser(User user) {
|
||||
return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName());
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String firstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public String lastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public String username() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* The full name is identified as the concatenation of the first and last name, separated by a space.
|
||||
* This method can return an empty name if both first and last name are empty.
|
||||
*
|
||||
* @return the full name of the user
|
||||
*/
|
||||
public String fullName() {
|
||||
StringJoiner name = new StringJoiner(" ");
|
||||
|
||||
if (!isEmpty(firstName))
|
||||
name.add(firstName);
|
||||
if (!isEmpty(lastName))
|
||||
name.add(lastName);
|
||||
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* The short name is one of the following:
|
||||
* <ol>
|
||||
* <li>First name</li>
|
||||
* <li>Last name</li>
|
||||
* <li>Username</li>
|
||||
* </ol>
|
||||
* The method will try to return the first valid name in the specified order.
|
||||
*
|
||||
* @return the short name of the user
|
||||
*/
|
||||
public String shortName() {
|
||||
if (!isEmpty(firstName))
|
||||
return firstName;
|
||||
|
||||
if (!isEmpty(lastName))
|
||||
return lastName;
|
||||
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
EndUser endUser = (EndUser) o;
|
||||
return Objects.equals(id, endUser.id) &&
|
||||
Objects.equals(firstName, endUser.firstName) &&
|
||||
Objects.equals(lastName, endUser.lastName) &&
|
||||
Objects.equals(username, endUser.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, firstName, lastName, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("id", id)
|
||||
.add("firstName", firstName)
|
||||
.add("lastName", lastName)
|
||||
.add("username", username)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
import org.telegram.abilitybots.api.objects.Ability.AbilityBuilder;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
/**
|
||||
* Flags are an conditions that are applied on an {@link Update}.
|
||||
* <p>
|
||||
* They can be used on {@link AbilityBuilder#flag(Flag...)} and on the post conditions in {@link AbilityBuilder#reply(Consumer, Predicate[])}.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public enum Flag implements Predicate<Update> {
|
||||
// Update Flags
|
||||
NONE(update -> true),
|
||||
MESSAGE(Update::hasMessage),
|
||||
CALLBACK_QUERY(Update::hasCallbackQuery),
|
||||
CHANNEL_POST(Update::hasChannelPost),
|
||||
EDITED_CHANNEL_POST(Update::hasEditedChannelPost),
|
||||
EDITED_MESSAGE(Update::hasEditedMessage),
|
||||
INLINE_QUERY(Update::hasInlineQuery),
|
||||
CHOSEN_INLINE_QUERY(Update::hasChosenInlineQuery),
|
||||
|
||||
// Message Flags
|
||||
REPLY(update -> update.getMessage().isReply()),
|
||||
DOCUMENT(upd -> upd.getMessage().hasDocument()),
|
||||
TEXT(upd -> upd.getMessage().hasText()),
|
||||
PHOTO(upd -> upd.getMessage().hasPhoto()),
|
||||
LOCATION(upd -> upd.getMessage().hasLocation()),
|
||||
CAPTION(upd -> nonNull(upd.getMessage().getCaption()));
|
||||
|
||||
private final Predicate<Update> predicate;
|
||||
|
||||
Flag(Predicate<Update> predicate) {
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
public boolean test(Update update) {
|
||||
return nonNull(update) && predicate.test(update);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
/**
|
||||
* Locality identifies the location in which you want your message to be accessed.
|
||||
* <p>
|
||||
* If locality of your message is set to <code>USER</code>, then the ability will only be executed if its being called in a user private chat.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public enum Locality {
|
||||
/**
|
||||
* Ability would be valid for groups and private user chats
|
||||
*/
|
||||
ALL,
|
||||
/**
|
||||
* Only user chats
|
||||
*/
|
||||
USER,
|
||||
/**
|
||||
* Only group chats
|
||||
*/
|
||||
GROUP
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* MessageContext is a wrapper class to the {@link Update}, originating end-user and the arguments present in its message (if any).
|
||||
* <p>
|
||||
* A user is not bound to the usage of this higher level context as it's possible to fetch the underlying {@link Update} using {@link MessageContext#update()}.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public class MessageContext {
|
||||
private final EndUser user;
|
||||
private final Long chatId;
|
||||
private final String[] arguments;
|
||||
private final Update update;
|
||||
|
||||
private MessageContext(Update update, EndUser user, Long chatId, String[] arguments) {
|
||||
this.user = user;
|
||||
this.chatId = chatId;
|
||||
this.update = update;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public static MessageContext newContext(Update update, EndUser user, Long chatId, String... arguments) {
|
||||
return new MessageContext(update, user, chatId, arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the originating Telegram user of this update
|
||||
*/
|
||||
public EndUser user() {
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the originating chatId, maps correctly to both group and user-private chats
|
||||
*/
|
||||
public Long chatId() {
|
||||
return chatId;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there's no message in the update, then this will an empty array.
|
||||
*
|
||||
* @return the text sent by the user message.
|
||||
*/
|
||||
public String[] arguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the first argument directly after the command
|
||||
* @throws IllegalStateException if message has no arguments
|
||||
*/
|
||||
public String firstArg() {
|
||||
checkLength();
|
||||
return arguments[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the second argument directly after the command
|
||||
* @throws IllegalStateException if message has no arguments
|
||||
*/
|
||||
public String secondArg() {
|
||||
checkLength();
|
||||
return arguments[1 % arguments.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the third argument directly after the command
|
||||
* @throws IllegalStateException if message has no arguments
|
||||
*/
|
||||
public String thirdArg() {
|
||||
checkLength();
|
||||
return arguments[2 % arguments.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the actual update behind this context
|
||||
*/
|
||||
public Update update() {
|
||||
return update;
|
||||
}
|
||||
|
||||
private void checkLength() {
|
||||
if (arguments.length == 0)
|
||||
throw new IllegalStateException("This message has no arguments");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("user", user)
|
||||
.add("chatId", chatId)
|
||||
.add("arguments", arguments)
|
||||
.add("update", update)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
MessageContext that = (MessageContext) o;
|
||||
return Objects.equal(user, that.user) &&
|
||||
Objects.equal(chatId, that.chatId) &&
|
||||
Arrays.equals(arguments, that.arguments) &&
|
||||
Objects.equal(update, that.update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(user, chatId, Arrays.hashCode(arguments), update);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
/**
|
||||
* Privacy represents a restriction on <b>who</b> can use the ability.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public enum Privacy {
|
||||
/**
|
||||
* Anybody who is not a bot admin or its creator will be considered as a public user.
|
||||
*/
|
||||
PUBLIC,
|
||||
/**
|
||||
* A global admin of the bot, regardless of the group the bot is in.
|
||||
*/
|
||||
ADMIN,
|
||||
/**
|
||||
* The creator of the bot.
|
||||
*/
|
||||
CREATOR
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
* A reply consists of update conditionals and an action to be applied on the update.
|
||||
* <p>
|
||||
* If an update satisfies the {@link Reply#conditions}set by the reply, then it's safe to {@link Reply#actOn(Update)}.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public final class Reply {
|
||||
public final List<Predicate<Update>> conditions;
|
||||
public final Consumer<Update> action;
|
||||
|
||||
private Reply(List<Predicate<Update>> conditions, Consumer<Update> action) {
|
||||
this.conditions = conditions;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static Reply of(Consumer<Update> action, Predicate<Update>... conditions) {
|
||||
return new Reply(asList(conditions), action);
|
||||
}
|
||||
|
||||
public boolean isOkFor(Update update) {
|
||||
// The following variable is required to avoid bug #JDK-8044546
|
||||
BiFunction<Boolean, Predicate<Update>, Boolean> stateAnd = (state, cond) -> state && cond.test(update);
|
||||
return conditions.stream().reduce(true, stateAnd, Boolean::logicalAnd);
|
||||
}
|
||||
|
||||
public void actOn(Update update) {
|
||||
action.accept(update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Reply reply = (Reply) o;
|
||||
return Objects.equals(conditions, reply.conditions) &&
|
||||
Objects.equals(action, reply.action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(conditions, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("conditions", conditions)
|
||||
.add("action", action)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,493 @@
|
||||
package org.telegram.abilitybots.api.sender;
|
||||
|
||||
import org.telegram.telegrambots.api.methods.*;
|
||||
import org.telegram.telegrambots.api.methods.games.GetGameHighScores;
|
||||
import org.telegram.telegrambots.api.methods.games.SetGameScore;
|
||||
import org.telegram.telegrambots.api.methods.groupadministration.*;
|
||||
import org.telegram.telegrambots.api.methods.pinnedmessages.PinChatMessage;
|
||||
import org.telegram.telegrambots.api.methods.pinnedmessages.UnpinChatMessage;
|
||||
import org.telegram.telegrambots.api.methods.send.*;
|
||||
import org.telegram.telegrambots.api.methods.updates.DeleteWebhook;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.DeleteMessage;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageCaption;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageReplyMarkup;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageText;
|
||||
import org.telegram.telegrambots.api.objects.*;
|
||||
import org.telegram.telegrambots.api.objects.games.GameHighScore;
|
||||
import org.telegram.telegrambots.api.objects.replykeyboard.ForceReplyKeyboard;
|
||||
import org.telegram.telegrambots.bots.DefaultAbsSender;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiException;
|
||||
import org.telegram.telegrambots.logging.BotLogger;
|
||||
import org.telegram.telegrambots.updateshandlers.DownloadFileCallback;
|
||||
import org.telegram.telegrambots.updateshandlers.SentCallback;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Optional.empty;
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
/**
|
||||
* The default implementation of the {@link MessageSender}. This serves as a proxy to the {@link DefaultAbsSender} methods.
|
||||
* <p>Most of the methods below will be directly calling the bot's similar functions. However, there are some methods introduced to ease sending messages such as:</p>
|
||||
* <ol>
|
||||
* <li>{@link DefaultMessageSender#sendMd(String, long)} - with markdown</li>
|
||||
* <li>{@link DefaultMessageSender#send(String, long)} - without markdown</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public class DefaultMessageSender implements MessageSender {
|
||||
private static final String TAG = MessageSender.class.getName();
|
||||
|
||||
private DefaultAbsSender bot;
|
||||
|
||||
public DefaultMessageSender(DefaultAbsSender bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Message> send(String message, long id) {
|
||||
return doSendMessage(message, id, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Message> sendMd(String message, long id) {
|
||||
return doSendMessage(message, id, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Message> forceReply(String message, long id) {
|
||||
SendMessage msg = new SendMessage();
|
||||
msg.setText(message);
|
||||
msg.setChatId(id);
|
||||
msg.setReplyMarkup(new ForceReplyKeyboard());
|
||||
|
||||
return optionalSendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean answerInlineQuery(AnswerInlineQuery answerInlineQuery) throws TelegramApiException {
|
||||
return bot.execute(answerInlineQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean sendChatAction(SendChatAction sendChatAction) throws TelegramApiException {
|
||||
return bot.execute(sendChatAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message forwardMessage(ForwardMessage forwardMessage) throws TelegramApiException {
|
||||
return bot.execute(forwardMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendLocation(SendLocation sendLocation) throws TelegramApiException {
|
||||
return bot.execute(sendLocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendVenue(SendVenue sendVenue) throws TelegramApiException {
|
||||
return bot.execute(sendVenue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendContact(SendContact sendContact) throws TelegramApiException {
|
||||
return bot.execute(sendContact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean kickMember(KickChatMember kickChatMember) throws TelegramApiException {
|
||||
return bot.execute(kickChatMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean unbanMember(UnbanChatMember unbanChatMember) throws TelegramApiException {
|
||||
return bot.execute(unbanChatMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean leaveChat(LeaveChat leaveChat) throws TelegramApiException {
|
||||
return bot.execute(leaveChat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chat getChat(GetChat getChat) throws TelegramApiException {
|
||||
return bot.execute(getChat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChatMember> getChatAdministrators(GetChatAdministrators getChatAdministrators) throws TelegramApiException {
|
||||
return bot.execute(getChatAdministrators);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatMember getChatMember(GetChatMember getChatMember) throws TelegramApiException {
|
||||
return bot.execute(getChatMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getChatMemberCount(GetChatMemberCount getChatMemberCount) throws TelegramApiException {
|
||||
return bot.execute(getChatMemberCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean setChatPhoto(SetChatPhoto setChatPhoto) throws TelegramApiException {
|
||||
return bot.setChatPhoto(setChatPhoto);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteChatPhoto(DeleteChatPhoto deleteChatPhoto) throws TelegramApiException {
|
||||
return bot.execute(deleteChatPhoto);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteChatPhoto(DeleteChatPhoto deleteChatPhoto, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(deleteChatPhoto, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean pinChatMessage(PinChatMessage pinChatMessage) throws TelegramApiException {
|
||||
return bot.execute(pinChatMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pinChatMessage(PinChatMessage pinChatMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(pinChatMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean unpinChatMessage(UnpinChatMessage unpinChatMessage) throws TelegramApiException {
|
||||
return bot.execute(unpinChatMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unpinChatMessage(UnpinChatMessage unpinChatMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(unpinChatMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean promoteChatMember(PromoteChatMember promoteChatMember) throws TelegramApiException {
|
||||
return bot.execute(promoteChatMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void promoteChatMember(PromoteChatMember promoteChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(promoteChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean restrictChatMember(RestrictChatMember restrictChatMember) throws TelegramApiException {
|
||||
return bot.execute(restrictChatMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restrictChatMember(RestrictChatMember restrictChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(restrictChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean setChatDescription(SetChatDescription setChatDescription) throws TelegramApiException {
|
||||
return bot.execute(setChatDescription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChatDescription(SetChatDescription setChatDescription, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(setChatDescription, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean setChatTite(SetChatTitle setChatTitle) throws TelegramApiException {
|
||||
return bot.execute(setChatTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChatTite(SetChatTitle setChatTitle, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(setChatTitle, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String exportChatInviteLink(ExportChatInviteLink exportChatInviteLink) throws TelegramApiException {
|
||||
return bot.execute(exportChatInviteLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportChatInviteLinkAsync(ExportChatInviteLink exportChatInviteLink, SentCallback<String> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(exportChatInviteLink, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteMessage(DeleteMessage deleteMessage) throws TelegramApiException {
|
||||
return bot.execute(deleteMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMessageAsync(DeleteMessage deleteMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(deleteMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable editMessageText(EditMessageText editMessageText) throws TelegramApiException {
|
||||
return bot.execute(editMessageText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable editMessageCaption(EditMessageCaption editMessageCaption) throws TelegramApiException {
|
||||
return bot.execute(editMessageCaption);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable editMessageReplyMarkup(EditMessageReplyMarkup editMessageReplyMarkup) throws TelegramApiException {
|
||||
return bot.execute(editMessageReplyMarkup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean answerCallbackQuery(AnswerCallbackQuery answerCallbackQuery) throws TelegramApiException {
|
||||
return bot.execute(answerCallbackQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserProfilePhotos getUserProfilePhotos(GetUserProfilePhotos getUserProfilePhotos) throws TelegramApiException {
|
||||
return bot.execute(getUserProfilePhotos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.io.File downloadFile(String path) throws TelegramApiException {
|
||||
return bot.downloadFile(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadFileAsync(String path, DownloadFileCallback<String> callback) throws TelegramApiException {
|
||||
bot.downloadFileAsync(path, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.io.File downloadFile(File file) throws TelegramApiException {
|
||||
return bot.downloadFile(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadFileAsync(File file, DownloadFileCallback<File> callback) throws TelegramApiException {
|
||||
bot.downloadFileAsync(file, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFile(GetFile getFile) throws TelegramApiException {
|
||||
return bot.execute(getFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getMe() throws TelegramApiException {
|
||||
return bot.getMe();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebhookInfo getWebhookInfo() throws TelegramApiException {
|
||||
return bot.getWebhookInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable setGameScore(SetGameScore setGameScore) throws TelegramApiException {
|
||||
return bot.execute(setGameScore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getGameHighScores(GetGameHighScores getGameHighScores) throws TelegramApiException {
|
||||
return bot.execute(getGameHighScores);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendGame(SendGame sendGame) throws TelegramApiException {
|
||||
return bot.execute(sendGame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean deleteWebhook(DeleteWebhook deleteWebhook) throws TelegramApiException {
|
||||
return bot.execute(deleteWebhook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendMessage(SendMessage sendMessage) throws TelegramApiException {
|
||||
return bot.execute(sendMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessageAsync(SendMessage sendMessage, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(sendMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void answerInlineQueryAsync(AnswerInlineQuery answerInlineQuery, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(answerInlineQuery, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChatActionAsync(SendChatAction sendChatAction, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(sendChatAction, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forwardMessageAsync(ForwardMessage forwardMessage, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(forwardMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendLocationAsync(SendLocation sendLocation, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(sendLocation, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendVenueAsync(SendVenue sendVenue, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(sendVenue, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendContactAsync(SendContact sendContact, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(sendContact, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kickMemberAsync(KickChatMember kickChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(kickChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbanMemberAsync(UnbanChatMember unbanChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(unbanChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leaveChatAsync(LeaveChat leaveChat, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(leaveChat, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getChatAsync(GetChat getChat, SentCallback<Chat> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(getChat, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getChatAdministratorsAsync(GetChatAdministrators getChatAdministrators, SentCallback<ArrayList<ChatMember>> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(getChatAdministrators, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getChatMemberAsync(GetChatMember getChatMember, SentCallback<ChatMember> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(getChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getChatMemberCountAsync(GetChatMemberCount getChatMemberCount, SentCallback<Integer> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(getChatMemberCount, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editMessageTextAsync(EditMessageText editMessageText, SentCallback<Serializable> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(editMessageText, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editMessageCaptionAsync(EditMessageCaption editMessageCaption, SentCallback<Serializable> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(editMessageCaption, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editMessageReplyMarkup(EditMessageReplyMarkup editMessageReplyMarkup, SentCallback<Serializable> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(editMessageReplyMarkup, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void answerCallbackQueryAsync(AnswerCallbackQuery answerCallbackQuery, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(answerCallbackQuery, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getUserProfilePhotosAsync(GetUserProfilePhotos getUserProfilePhotos, SentCallback<UserProfilePhotos> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(getUserProfilePhotos, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getFileAsync(GetFile getFile, SentCallback<File> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(getFile, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getMeAsync(SentCallback<User> sentCallback) throws TelegramApiException {
|
||||
bot.getMeAsync(sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getWebhookInfoAsync(SentCallback<WebhookInfo> sentCallback) throws TelegramApiException {
|
||||
bot.getWebhookInfoAsync(sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGameScoreAsync(SetGameScore setGameScore, SentCallback<Serializable> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(setGameScore, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getGameHighScoresAsync(GetGameHighScores getGameHighScores, SentCallback<ArrayList<GameHighScore>> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(getGameHighScores, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendGameAsync(SendGame sendGame, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(sendGame, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteWebhook(DeleteWebhook deleteWebhook, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
bot.executeAsync(deleteWebhook, sentCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendDocument(SendDocument sendDocument) throws TelegramApiException {
|
||||
return bot.sendDocument(sendDocument);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendPhoto(SendPhoto sendPhoto) throws TelegramApiException {
|
||||
return bot.sendPhoto(sendPhoto);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendVideo(SendVideo sendVideo) throws TelegramApiException {
|
||||
return bot.sendVideo(sendVideo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendSticker(SendSticker sendSticker) throws TelegramApiException {
|
||||
return bot.sendSticker(sendSticker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendAudio(SendAudio sendAudio) throws TelegramApiException {
|
||||
return bot.sendAudio(sendAudio);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message sendVoice(SendVoice sendVoice) throws TelegramApiException {
|
||||
return bot.sendVoice(sendVoice);
|
||||
}
|
||||
|
||||
private Optional<Message> doSendMessage(String txt, long groupId, boolean format) {
|
||||
SendMessage smsg = new SendMessage();
|
||||
smsg.setChatId(groupId);
|
||||
smsg.setText(txt);
|
||||
smsg.enableMarkdown(format);
|
||||
|
||||
return optionalSendMessage(smsg);
|
||||
}
|
||||
|
||||
private Optional<Message> optionalSendMessage(SendMessage smsg) {
|
||||
try {
|
||||
return ofNullable(sendMessage(smsg));
|
||||
} catch (TelegramApiException e) {
|
||||
BotLogger.error("Could not send message", TAG, e);
|
||||
return empty();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
package org.telegram.abilitybots.api.sender;
|
||||
|
||||
import org.telegram.telegrambots.api.methods.*;
|
||||
import org.telegram.telegrambots.api.methods.games.GetGameHighScores;
|
||||
import org.telegram.telegrambots.api.methods.games.SetGameScore;
|
||||
import org.telegram.telegrambots.api.methods.groupadministration.*;
|
||||
import org.telegram.telegrambots.api.methods.pinnedmessages.PinChatMessage;
|
||||
import org.telegram.telegrambots.api.methods.pinnedmessages.UnpinChatMessage;
|
||||
import org.telegram.telegrambots.api.methods.send.*;
|
||||
import org.telegram.telegrambots.api.methods.updates.DeleteWebhook;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.DeleteMessage;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageCaption;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageReplyMarkup;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.EditMessageText;
|
||||
import org.telegram.telegrambots.api.objects.*;
|
||||
import org.telegram.telegrambots.api.objects.games.GameHighScore;
|
||||
import org.telegram.telegrambots.bots.DefaultAbsSender;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiException;
|
||||
import org.telegram.telegrambots.updateshandlers.DownloadFileCallback;
|
||||
import org.telegram.telegrambots.updateshandlers.SentCallback;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A sender interface that replicates {@link DefaultAbsSender} methods.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
public interface MessageSender {
|
||||
Optional<Message> send(String message, long id);
|
||||
|
||||
Optional<Message> sendMd(String message, long id);
|
||||
|
||||
Optional<Message> forceReply(String message, long id);
|
||||
|
||||
Boolean answerInlineQuery(AnswerInlineQuery answerInlineQuery) throws TelegramApiException;
|
||||
|
||||
Boolean sendChatAction(SendChatAction sendChatAction) throws TelegramApiException;
|
||||
|
||||
Message forwardMessage(ForwardMessage forwardMessage) throws TelegramApiException;
|
||||
|
||||
Message sendLocation(SendLocation sendLocation) throws TelegramApiException;
|
||||
|
||||
Message sendVenue(SendVenue sendVenue) throws TelegramApiException;
|
||||
|
||||
Message sendContact(SendContact sendContact) throws TelegramApiException;
|
||||
|
||||
Boolean kickMember(KickChatMember kickChatMember) throws TelegramApiException;
|
||||
|
||||
Boolean unbanMember(UnbanChatMember unbanChatMember) throws TelegramApiException;
|
||||
|
||||
Boolean leaveChat(LeaveChat leaveChat) throws TelegramApiException;
|
||||
|
||||
Chat getChat(GetChat getChat) throws TelegramApiException;
|
||||
|
||||
List<ChatMember> getChatAdministrators(GetChatAdministrators getChatAdministrators) throws TelegramApiException;
|
||||
|
||||
ChatMember getChatMember(GetChatMember getChatMember) throws TelegramApiException;
|
||||
|
||||
Integer getChatMemberCount(GetChatMemberCount getChatMemberCount) throws TelegramApiException;
|
||||
|
||||
Boolean setChatPhoto(SetChatPhoto setChatPhoto) throws TelegramApiException;
|
||||
|
||||
Boolean deleteChatPhoto(DeleteChatPhoto deleteChatPhoto) throws TelegramApiException;
|
||||
|
||||
void deleteChatPhoto(DeleteChatPhoto deleteChatPhoto, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
Boolean pinChatMessage(PinChatMessage pinChatMessage) throws TelegramApiException;
|
||||
|
||||
void pinChatMessage(PinChatMessage pinChatMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
Boolean unpinChatMessage(UnpinChatMessage unpinChatMessage) throws TelegramApiException;
|
||||
|
||||
void unpinChatMessage(UnpinChatMessage unpinChatMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
Boolean promoteChatMember(PromoteChatMember promoteChatMember) throws TelegramApiException;
|
||||
|
||||
void promoteChatMember(PromoteChatMember promoteChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
Boolean restrictChatMember(RestrictChatMember restrictChatMember) throws TelegramApiException;
|
||||
|
||||
void restrictChatMember(RestrictChatMember restrictChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
Boolean setChatDescription(SetChatDescription setChatDescription) throws TelegramApiException;
|
||||
|
||||
void setChatDescription(SetChatDescription setChatDescription, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
Boolean setChatTite(SetChatTitle setChatTitle) throws TelegramApiException;
|
||||
|
||||
void setChatTite(SetChatTitle setChatTitle, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
String exportChatInviteLink(ExportChatInviteLink exportChatInviteLink) throws TelegramApiException;
|
||||
|
||||
void exportChatInviteLinkAsync(ExportChatInviteLink exportChatInviteLink, SentCallback<String> sentCallback) throws TelegramApiException;
|
||||
|
||||
Boolean deleteMessage(DeleteMessage deleteMessage) throws TelegramApiException;
|
||||
|
||||
void deleteMessageAsync(DeleteMessage deleteMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
Serializable editMessageText(EditMessageText editMessageText) throws TelegramApiException;
|
||||
|
||||
Serializable editMessageCaption(EditMessageCaption editMessageCaption) throws TelegramApiException;
|
||||
|
||||
Serializable editMessageReplyMarkup(EditMessageReplyMarkup editMessageReplyMarkup) throws TelegramApiException;
|
||||
|
||||
Boolean answerCallbackQuery(AnswerCallbackQuery answerCallbackQuery) throws TelegramApiException;
|
||||
|
||||
UserProfilePhotos getUserProfilePhotos(GetUserProfilePhotos getUserProfilePhotos) throws TelegramApiException;
|
||||
|
||||
java.io.File downloadFile(String path) throws TelegramApiException;
|
||||
|
||||
void downloadFileAsync(String path, DownloadFileCallback<String> callback) throws TelegramApiException;
|
||||
|
||||
java.io.File downloadFile(File file) throws TelegramApiException;
|
||||
|
||||
void downloadFileAsync(File file, DownloadFileCallback<File> callback) throws TelegramApiException;
|
||||
|
||||
File getFile(GetFile getFile) throws TelegramApiException;
|
||||
|
||||
User getMe() throws TelegramApiException;
|
||||
|
||||
WebhookInfo getWebhookInfo() throws TelegramApiException;
|
||||
|
||||
Serializable setGameScore(SetGameScore setGameScore) throws TelegramApiException;
|
||||
|
||||
Serializable getGameHighScores(GetGameHighScores getGameHighScores) throws TelegramApiException;
|
||||
|
||||
Message sendGame(SendGame sendGame) throws TelegramApiException;
|
||||
|
||||
Boolean deleteWebhook(DeleteWebhook deleteWebhook) throws TelegramApiException;
|
||||
|
||||
Message sendMessage(SendMessage sendMessage) throws TelegramApiException;
|
||||
|
||||
void sendMessageAsync(SendMessage sendMessage, SentCallback<Message> sentCallback) throws TelegramApiException;
|
||||
|
||||
void answerInlineQueryAsync(AnswerInlineQuery answerInlineQuery, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
void sendChatActionAsync(SendChatAction sendChatAction, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
void forwardMessageAsync(ForwardMessage forwardMessage, SentCallback<Message> sentCallback) throws TelegramApiException;
|
||||
|
||||
void sendLocationAsync(SendLocation sendLocation, SentCallback<Message> sentCallback) throws TelegramApiException;
|
||||
|
||||
void sendVenueAsync(SendVenue sendVenue, SentCallback<Message> sentCallback) throws TelegramApiException;
|
||||
|
||||
void sendContactAsync(SendContact sendContact, SentCallback<Message> sentCallback) throws TelegramApiException;
|
||||
|
||||
void kickMemberAsync(KickChatMember kickChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
void unbanMemberAsync(UnbanChatMember unbanChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
void leaveChatAsync(LeaveChat leaveChat, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getChatAsync(GetChat getChat, SentCallback<Chat> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getChatAdministratorsAsync(GetChatAdministrators getChatAdministrators, SentCallback<ArrayList<ChatMember>> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getChatMemberAsync(GetChatMember getChatMember, SentCallback<ChatMember> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getChatMemberCountAsync(GetChatMemberCount getChatMemberCount, SentCallback<Integer> sentCallback) throws TelegramApiException;
|
||||
|
||||
void editMessageTextAsync(EditMessageText editMessageText, SentCallback<Serializable> sentCallback) throws TelegramApiException;
|
||||
|
||||
void editMessageCaptionAsync(EditMessageCaption editMessageCaption, SentCallback<Serializable> sentCallback) throws TelegramApiException;
|
||||
|
||||
void editMessageReplyMarkup(EditMessageReplyMarkup editMessageReplyMarkup, SentCallback<Serializable> sentCallback) throws TelegramApiException;
|
||||
|
||||
void answerCallbackQueryAsync(AnswerCallbackQuery answerCallbackQuery, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getUserProfilePhotosAsync(GetUserProfilePhotos getUserProfilePhotos, SentCallback<UserProfilePhotos> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getFileAsync(GetFile getFile, SentCallback<File> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getMeAsync(SentCallback<User> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getWebhookInfoAsync(SentCallback<WebhookInfo> sentCallback) throws TelegramApiException;
|
||||
|
||||
void setGameScoreAsync(SetGameScore setGameScore, SentCallback<Serializable> sentCallback) throws TelegramApiException;
|
||||
|
||||
void getGameHighScoresAsync(GetGameHighScores getGameHighScores, SentCallback<ArrayList<GameHighScore>> sentCallback) throws TelegramApiException;
|
||||
|
||||
void sendGameAsync(SendGame sendGame, SentCallback<Message> sentCallback) throws TelegramApiException;
|
||||
|
||||
void deleteWebhook(DeleteWebhook deleteWebhook, SentCallback<Boolean> sentCallback) throws TelegramApiException;
|
||||
|
||||
Message sendDocument(SendDocument sendDocument) throws TelegramApiException;
|
||||
|
||||
Message sendPhoto(SendPhoto sendPhoto) throws TelegramApiException;
|
||||
|
||||
Message sendVideo(SendVideo sendVideo) throws TelegramApiException;
|
||||
|
||||
Message sendSticker(SendSticker sendSticker) throws TelegramApiException;
|
||||
|
||||
Message sendAudio(SendAudio sendAudio) throws TelegramApiException;
|
||||
|
||||
Message sendVoice(SendVoice sendVoice) throws TelegramApiException;
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
package org.telegram.abilitybots.api.util;
|
||||
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
import org.telegram.abilitybots.api.objects.MessageContext;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
import org.telegram.telegrambots.api.objects.User;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static org.telegram.abilitybots.api.objects.Flag.*;
|
||||
|
||||
/**
|
||||
* Helper and utility methods
|
||||
*/
|
||||
public final class AbilityUtils {
|
||||
private AbilityUtils() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param username any username
|
||||
* @return the username with the preceding "@" stripped off
|
||||
*/
|
||||
public static String stripTag(String username) {
|
||||
String lowerCase = username.toLowerCase();
|
||||
return lowerCase.startsWith("@") ? lowerCase.substring(1, lowerCase.length()) : lowerCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits to DB.
|
||||
*
|
||||
* @param db the database to commit on
|
||||
* @return a lambda consumer that takes in a {@link MessageContext}, used in post actions for abilities
|
||||
*/
|
||||
public static Consumer<MessageContext> commitTo(DBContext db) {
|
||||
return ctx -> db.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the user who caused the update.
|
||||
*
|
||||
* @param update a Telegram {@link Update}
|
||||
* @return the originating user
|
||||
* @throws IllegalStateException if the user could not be found
|
||||
*/
|
||||
public static User getUser(Update update) {
|
||||
if (MESSAGE.test(update)) {
|
||||
return update.getMessage().getFrom();
|
||||
} else if (CALLBACK_QUERY.test(update)) {
|
||||
return update.getCallbackQuery().getFrom();
|
||||
} else if (INLINE_QUERY.test(update)) {
|
||||
return update.getInlineQuery().getFrom();
|
||||
} else if (CHANNEL_POST.test(update)) {
|
||||
return update.getChannelPost().getFrom();
|
||||
} else if (EDITED_CHANNEL_POST.test(update)) {
|
||||
return update.getEditedChannelPost().getFrom();
|
||||
} else if (EDITED_MESSAGE.test(update)) {
|
||||
return update.getEditedMessage().getFrom();
|
||||
} else if (CHOSEN_INLINE_QUERY.test(update)) {
|
||||
return update.getChosenInlineQuery().getFrom();
|
||||
} else {
|
||||
throw new IllegalStateException("Could not retrieve originating user from update");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the direct chat ID of the specified update.
|
||||
*
|
||||
* @param update a Telegram {@link Update}
|
||||
* @return the originating chat ID
|
||||
* @throws IllegalStateException if the chat ID could not be found
|
||||
*/
|
||||
public static Long getChatId(Update update) {
|
||||
if (MESSAGE.test(update)) {
|
||||
return update.getMessage().getChatId();
|
||||
} else if (CALLBACK_QUERY.test(update)) {
|
||||
return update.getCallbackQuery().getMessage().getChatId();
|
||||
} else if (INLINE_QUERY.test(update)) {
|
||||
return (long) update.getInlineQuery().getFrom().getId();
|
||||
} else if (CHANNEL_POST.test(update)) {
|
||||
return update.getChannelPost().getChatId();
|
||||
} else if (EDITED_CHANNEL_POST.test(update)) {
|
||||
return update.getEditedChannelPost().getChatId();
|
||||
} else if (EDITED_MESSAGE.test(update)) {
|
||||
return update.getEditedMessage().getChatId();
|
||||
} else if (CHOSEN_INLINE_QUERY.test(update)) {
|
||||
return (long) update.getChosenInlineQuery().getFrom().getId();
|
||||
} else {
|
||||
throw new IllegalStateException("Could not retrieve originating chat ID from update");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param update a Telegram {@link Update}
|
||||
* @return <tt>true</tt> if the update contains contains a private user message
|
||||
*/
|
||||
public static boolean isUserMessage(Update update) {
|
||||
if (MESSAGE.test(update)) {
|
||||
return update.getMessage().isUserMessage();
|
||||
} else if (CALLBACK_QUERY.test(update)) {
|
||||
return update.getCallbackQuery().getMessage().isUserMessage();
|
||||
} else if (CHANNEL_POST.test(update)) {
|
||||
return update.getChannelPost().isUserMessage();
|
||||
} else if (EDITED_CHANNEL_POST.test(update)) {
|
||||
return update.getEditedChannelPost().isUserMessage();
|
||||
} else if (EDITED_MESSAGE.test(update)) {
|
||||
return update.getEditedMessage().isUserMessage();
|
||||
} else if (CHOSEN_INLINE_QUERY.test(update) || INLINE_QUERY.test(update)) {
|
||||
return true;
|
||||
} else {
|
||||
throw new IllegalStateException("Could not retrieve update context origin (user/group)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param username the username to add the tag to
|
||||
* @return the username prefixed with the "@" tag.
|
||||
*/
|
||||
public static String addTag(String username) {
|
||||
return "@" + username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param msg the message to be replied to
|
||||
* @return a predicate that asserts that the update is a reply to the specified message.
|
||||
*/
|
||||
public static Predicate<Update> isReplyTo(String msg) {
|
||||
return update -> update.getMessage().getReplyToMessage().getText().equals(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package org.telegram.abilitybots.api.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class Pair<A, B> {
|
||||
@JsonProperty("a")
|
||||
private final A a;
|
||||
@JsonProperty("b")
|
||||
private final B b;
|
||||
|
||||
private Pair(A a, B b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static <A, B> Pair<A, B> of(@JsonProperty("a") A a, @JsonProperty("b") B b) {
|
||||
return new Pair<>(a, b);
|
||||
}
|
||||
|
||||
public A a() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public B b() {
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Pair<?, ?> pair = (Pair<?, ?>) o;
|
||||
return Objects.equals(a, pair.a) &&
|
||||
Objects.equals(b, pair.b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(a, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("a", a)
|
||||
.add("b", b)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package org.telegram.abilitybots.api.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Trio<A, B, C> {
|
||||
@JsonProperty("a")
|
||||
private final A a;
|
||||
@JsonProperty("b")
|
||||
private final B b;
|
||||
@JsonProperty("c")
|
||||
private final C c;
|
||||
|
||||
private Trio(A a, B b, C c) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public static <A, B, C> Trio<A, B, C> of(@JsonProperty("a") A a, @JsonProperty("b") B b, @JsonProperty("c") C c) {
|
||||
return new Trio<>(a, b, c);
|
||||
}
|
||||
|
||||
public A a() {
|
||||
return a;
|
||||
}
|
||||
|
||||
public B b() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public C c() {
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Trio<?, ?, ?> trio = (Trio<?, ?, ?>) o;
|
||||
return Objects.equals(a, trio.a) &&
|
||||
Objects.equals(b, trio.b) &&
|
||||
Objects.equals(c, trio.c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(a, b, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("a", a)
|
||||
.add("b", b)
|
||||
.add("c", c)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,588 @@
|
||||
package org.telegram.abilitybots.api.bot;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.Files;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Matchers;
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
import org.telegram.abilitybots.api.objects.*;
|
||||
import org.telegram.abilitybots.api.sender.MessageSender;
|
||||
import org.telegram.abilitybots.api.util.Pair;
|
||||
import org.telegram.abilitybots.api.util.Trio;
|
||||
import org.telegram.telegrambots.api.objects.*;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiException;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.apache.commons.lang3.ArrayUtils.addAll;
|
||||
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
import static org.telegram.abilitybots.api.bot.AbilityBot.RECOVERY_MESSAGE;
|
||||
import static org.telegram.abilitybots.api.bot.AbilityBot.RECOVER_SUCCESS;
|
||||
import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder;
|
||||
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
|
||||
import static org.telegram.abilitybots.api.objects.EndUser.endUser;
|
||||
import static org.telegram.abilitybots.api.objects.Flag.DOCUMENT;
|
||||
import static org.telegram.abilitybots.api.objects.Flag.MESSAGE;
|
||||
import static org.telegram.abilitybots.api.objects.Locality.ALL;
|
||||
import static org.telegram.abilitybots.api.objects.Locality.GROUP;
|
||||
import static org.telegram.abilitybots.api.objects.MessageContext.newContext;
|
||||
import static org.telegram.abilitybots.api.objects.Privacy.ADMIN;
|
||||
import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC;
|
||||
|
||||
public class AbilityBotTest {
|
||||
private static final String[] EMPTY_ARRAY = {};
|
||||
private static final long GROUP_ID = 10L;
|
||||
private static final String TEST = "test";
|
||||
private static final String[] TEXT = {TEST};
|
||||
public static final EndUser MUSER = endUser(1, "first", "last", "username");
|
||||
public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername");
|
||||
|
||||
private DefaultBot bot;
|
||||
private DBContext db;
|
||||
private MessageSender sender;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
db = offlineInstance("db");
|
||||
bot = new DefaultBot(EMPTY, EMPTY, db);
|
||||
sender = mock(MessageSender.class);
|
||||
bot.setSender(sender);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendsPrivacyViolation() {
|
||||
Update update = mockFullUpdate(MUSER, "/admin");
|
||||
|
||||
bot.onUpdateReceived(update);
|
||||
|
||||
verify(sender, times(1)).send(format("Sorry, %s-only feature.", "admin"), MUSER.id());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendsLocalityViolation() {
|
||||
Update update = mockFullUpdate(MUSER, "/group");
|
||||
|
||||
bot.onUpdateReceived(update);
|
||||
|
||||
verify(sender, times(1)).send(format("Sorry, %s-only feature.", "group"), MUSER.id());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendsInputArgsViolation() {
|
||||
Update update = mockFullUpdate(MUSER, "/count 1 2 3");
|
||||
|
||||
bot.onUpdateReceived(update);
|
||||
|
||||
verify(sender, times(1)).send(format("Sorry, this feature requires %d additional inputs.", 4), MUSER.id());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canProcessRepliesIfSatisfyRequirements() {
|
||||
Update update = mockFullUpdate(MUSER, "must reply");
|
||||
|
||||
// False means the update was not pushed down the stream since it has been consumed by the reply
|
||||
assertFalse(bot.filterReply(update));
|
||||
verify(sender, times(1)).send("reply", MUSER.id());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canBackupDB() throws TelegramApiException {
|
||||
MessageContext context = defaultContext();
|
||||
|
||||
bot.backupDB().action().accept(context);
|
||||
|
||||
verify(sender, times(1)).sendDocument(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canRecoverDB() throws TelegramApiException, IOException {
|
||||
Update update = mockBackupUpdate();
|
||||
Object backup = getDbBackup();
|
||||
java.io.File backupFile = createBackupFile(backup);
|
||||
|
||||
when(sender.downloadFile(Matchers.any(File.class))).thenReturn(backupFile);
|
||||
bot.recoverDB().replies().get(0).actOn(update);
|
||||
|
||||
verify(sender, times(1)).send(RECOVER_SUCCESS, GROUP_ID);
|
||||
assertEquals("Bot recovered but the DB is still not in sync", db.getSet(TEST), newHashSet(TEST));
|
||||
assertTrue("Could not delete backup file", backupFile.delete());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canFilterOutReplies() {
|
||||
Update update = mock(Update.class);
|
||||
when(update.hasMessage()).thenReturn(false);
|
||||
|
||||
assertTrue(bot.filterReply(update));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canDemote() {
|
||||
addUsers(MUSER);
|
||||
bot.admins().add(MUSER.id());
|
||||
|
||||
MessageContext context = defaultContext();
|
||||
|
||||
bot.demoteAdmin().action().accept(context);
|
||||
|
||||
Set<Integer> actual = bot.admins();
|
||||
Set<Integer> expected = emptySet();
|
||||
assertEquals("Could not sudont super-admin", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canPromote() {
|
||||
addUsers(MUSER);
|
||||
|
||||
MessageContext context = defaultContext();
|
||||
|
||||
bot.promoteAdmin().action().accept(context);
|
||||
|
||||
Set<Integer> actual = bot.admins();
|
||||
Set<Integer> expected = newHashSet(MUSER.id());
|
||||
assertEquals("Could not sudo user", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canBanUser() {
|
||||
addUsers(MUSER);
|
||||
MessageContext context = defaultContext();
|
||||
|
||||
bot.banUser().action().accept(context);
|
||||
|
||||
Set<Integer> actual = bot.blacklist();
|
||||
Set<Integer> expected = newHashSet(MUSER.id());
|
||||
assertEquals("The ban was not emplaced", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canUnbanUser() {
|
||||
addUsers(MUSER);
|
||||
bot.blacklist().add(MUSER.id());
|
||||
|
||||
MessageContext context = defaultContext();
|
||||
|
||||
bot.unbanUser().action().accept(context);
|
||||
|
||||
Set<Integer> actual = bot.blacklist();
|
||||
Set<Integer> expected = newHashSet();
|
||||
assertEquals("The ban was not lifted", expected, actual);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private MessageContext defaultContext() {
|
||||
MessageContext context = mock(MessageContext.class);
|
||||
when(context.user()).thenReturn(CREATOR);
|
||||
when(context.firstArg()).thenReturn(MUSER.username());
|
||||
return context;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cannotBanCreator() {
|
||||
addUsers(MUSER, CREATOR);
|
||||
MessageContext context = mock(MessageContext.class);
|
||||
when(context.user()).thenReturn(MUSER);
|
||||
when(context.firstArg()).thenReturn(CREATOR.username());
|
||||
|
||||
bot.banUser().action().accept(context);
|
||||
|
||||
Set<Integer> actual = bot.blacklist();
|
||||
Set<Integer> expected = newHashSet(MUSER.id());
|
||||
assertEquals("Impostor was not added to the blacklist", expected, actual);
|
||||
}
|
||||
|
||||
private void addUsers(EndUser... users) {
|
||||
Arrays.stream(users).forEach(user -> {
|
||||
bot.users().put(user.id(), user);
|
||||
bot.userIds().put(user.username().toLowerCase(), user.id());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void creatorCanClaimBot() {
|
||||
MessageContext context = mock(MessageContext.class);
|
||||
when(context.user()).thenReturn(CREATOR);
|
||||
|
||||
bot.claimCreator().action().accept(context);
|
||||
|
||||
Set<Integer> actual = bot.admins();
|
||||
Set<Integer> expected = newHashSet(CREATOR.id());
|
||||
assertEquals("Creator was not properly added to the super admins set", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userGetsBannedIfClaimsBot() {
|
||||
addUsers(MUSER);
|
||||
MessageContext context = mock(MessageContext.class);
|
||||
when(context.user()).thenReturn(MUSER);
|
||||
|
||||
bot.claimCreator().action().accept(context);
|
||||
|
||||
Set<Integer> actual = bot.blacklist();
|
||||
Set<Integer> expected = newHashSet(MUSER.id());
|
||||
assertEquals("Could not find user on the blacklist", expected, actual);
|
||||
|
||||
actual = bot.admins();
|
||||
expected = emptySet();
|
||||
assertEquals("Admins set is not empty", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bannedCreatorPassesBlacklistCheck() {
|
||||
bot.blacklist().add(CREATOR.id());
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
User user = mock(User.class);
|
||||
|
||||
mockUser(update, message, user);
|
||||
|
||||
boolean notBanned = bot.checkBlacklist(update);
|
||||
assertTrue("Creator is banned", notBanned);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canAddUser() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
User user = mock(User.class);
|
||||
|
||||
mockAlternateUser(update, message, user, MUSER);
|
||||
|
||||
bot.addUser(update);
|
||||
|
||||
Map<String, Integer> expectedUserIds = ImmutableMap.of(MUSER.username(), MUSER.id());
|
||||
Map<Integer, EndUser> expectedUsers = ImmutableMap.of(MUSER.id(), MUSER);
|
||||
assertEquals("User was not added", expectedUserIds, bot.userIds());
|
||||
assertEquals("User was not added", expectedUsers, bot.users());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canEditUser() {
|
||||
addUsers(MUSER);
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
User user = mock(User.class);
|
||||
|
||||
String newUsername = MUSER.username() + "-test";
|
||||
String newFirstName = MUSER.firstName() + "-test";
|
||||
String newLastName = MUSER.lastName() + "-test";
|
||||
int sameId = MUSER.id();
|
||||
EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername);
|
||||
|
||||
mockAlternateUser(update, message, user, changedUser);
|
||||
|
||||
bot.addUser(update);
|
||||
|
||||
Map<String, Integer> expectedUserIds = ImmutableMap.of(changedUser.username(), changedUser.id());
|
||||
Map<Integer, EndUser> expectedUsers = ImmutableMap.of(changedUser.id(), changedUser);
|
||||
assertEquals("User was not properly edited", bot.userIds(), expectedUserIds);
|
||||
assertEquals("User was not properly edited", expectedUsers, expectedUsers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canValidateAbility() {
|
||||
Trio<Update, Ability, String[]> invalidPair = Trio.of(null, null, null);
|
||||
Ability validAbility = getDefaultBuilder().build();
|
||||
Trio<Update, Ability, String[]> validPair = Trio.of(null, validAbility, null);
|
||||
|
||||
assertEquals("Bot can't validate ability properly", false, bot.validateAbility(invalidPair));
|
||||
assertEquals("Bot can't validate ability properly", true, bot.validateAbility(validPair));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCheckInput() {
|
||||
Update update = mockFullUpdate(MUSER, "/something");
|
||||
Ability abilityWithOneInput = getDefaultBuilder()
|
||||
.build();
|
||||
Ability abilityWithZeroInput = getDefaultBuilder()
|
||||
.input(0)
|
||||
.build();
|
||||
|
||||
Trio<Update, Ability, String[]> trioOneArg = Trio.of(update, abilityWithOneInput, TEXT);
|
||||
Trio<Update, Ability, String[]> trioZeroArg = Trio.of(update, abilityWithZeroInput, TEXT);
|
||||
|
||||
assertEquals("Unexpected result when applying token filter", true, bot.checkInput(trioOneArg));
|
||||
|
||||
trioOneArg = Trio.of(update, abilityWithOneInput, addAll(TEXT, TEXT));
|
||||
assertEquals("Unexpected result when applying token filter", false, bot.checkInput(trioOneArg));
|
||||
|
||||
assertEquals("Unexpected result when applying token filter", true, bot.checkInput(trioZeroArg));
|
||||
|
||||
trioZeroArg = Trio.of(update, abilityWithZeroInput, EMPTY_ARRAY);
|
||||
assertEquals("Unexpected result when applying token filter", true, bot.checkInput(trioZeroArg));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCheckPrivacy() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
org.telegram.telegrambots.api.objects.User user = mock(User.class);
|
||||
Ability publicAbility = getDefaultBuilder().privacy(PUBLIC).build();
|
||||
Ability adminAbility = getDefaultBuilder().privacy(ADMIN).build();
|
||||
Ability creatorAbility = getDefaultBuilder().privacy(Privacy.CREATOR).build();
|
||||
|
||||
Trio<Update, Ability, String[]> publicTrio = Trio.of(update, publicAbility, TEXT);
|
||||
Trio<Update, Ability, String[]> adminTrio = Trio.of(update, adminAbility, TEXT);
|
||||
Trio<Update, Ability, String[]> creatorTrio = Trio.of(update, creatorAbility, TEXT);
|
||||
|
||||
mockUser(update, message, user);
|
||||
|
||||
assertEquals("Unexpected result when checking for privacy", true, bot.checkPrivacy(publicTrio));
|
||||
assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(adminTrio));
|
||||
assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(creatorTrio));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canBlockAdminsFromCreatorAbilities() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
org.telegram.telegrambots.api.objects.User user = mock(User.class);
|
||||
Ability creatorAbility = getDefaultBuilder().privacy(Privacy.CREATOR).build();
|
||||
|
||||
Trio<Update, Ability, String[]> creatorTrio = Trio.of(update, creatorAbility, TEXT);
|
||||
|
||||
bot.admins().add(MUSER.id());
|
||||
mockUser(update, message, user);
|
||||
|
||||
assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(creatorTrio));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCheckLocality() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
User user = mock(User.class);
|
||||
Ability allAbility = getDefaultBuilder().locality(ALL).build();
|
||||
Ability userAbility = getDefaultBuilder().locality(Locality.USER).build();
|
||||
Ability groupAbility = getDefaultBuilder().locality(GROUP).build();
|
||||
|
||||
Trio<Update, Ability, String[]> publicTrio = Trio.of(update, allAbility, TEXT);
|
||||
Trio<Update, Ability, String[]> userTrio = Trio.of(update, userAbility, TEXT);
|
||||
Trio<Update, Ability, String[]> groupTrio = Trio.of(update, groupAbility, TEXT);
|
||||
|
||||
mockUser(update, message, user);
|
||||
when(message.isUserMessage()).thenReturn(true);
|
||||
|
||||
assertEquals("Unexpected result when checking for locality", true, bot.checkLocality(publicTrio));
|
||||
assertEquals("Unexpected result when checking for locality", true, bot.checkLocality(userTrio));
|
||||
assertEquals("Unexpected result when checking for locality", false, bot.checkLocality(groupTrio));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canRetrieveContext() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
User user = mock(User.class);
|
||||
Ability ability = getDefaultBuilder().build();
|
||||
Trio<Update, Ability, String[]> trio = Trio.of(update, ability, TEXT);
|
||||
|
||||
when(message.getChatId()).thenReturn(GROUP_ID);
|
||||
mockUser(update, message, user);
|
||||
|
||||
Pair<MessageContext, Ability> actualPair = bot.getContext(trio);
|
||||
Pair<MessageContext, Ability> expectedPair = Pair.of(newContext(update, MUSER, GROUP_ID, TEXT), ability);
|
||||
|
||||
assertEquals("Unexpected result when fetching for context", expectedPair, actualPair);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCheckGlobalFlags() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
|
||||
when(update.hasMessage()).thenReturn(true);
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
assertEquals("Unexpected result when checking for locality", true, bot.checkGlobalFlags(update));
|
||||
}
|
||||
|
||||
@Test(expected = ArithmeticException.class)
|
||||
public void canConsumeUpdate() {
|
||||
Ability ability = getDefaultBuilder()
|
||||
.action((context) -> {
|
||||
int x = 1 / 0;
|
||||
}).build();
|
||||
MessageContext context = mock(MessageContext.class);
|
||||
|
||||
Pair<MessageContext, Ability> pair = Pair.of(context, ability);
|
||||
|
||||
bot.consumeUpdate(pair);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canFetchAbility() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
|
||||
String text = "/test";
|
||||
when(update.hasMessage()).thenReturn(true);
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
when(update.getMessage().hasText()).thenReturn(true);
|
||||
when(message.getText()).thenReturn(text);
|
||||
|
||||
Trio<Update, Ability, String[]> trio = bot.getAbility(update);
|
||||
|
||||
Ability expected = bot.testAbility();
|
||||
Ability actual = trio.b();
|
||||
|
||||
assertEquals("Wrong ability was fetched", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canFetchDefaultAbility() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
|
||||
String text = "test tags";
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
when(message.getText()).thenReturn(text);
|
||||
|
||||
Trio<Update, Ability, String[]> trio = bot.getAbility(update);
|
||||
|
||||
Ability expected = bot.defaultAbility();
|
||||
Ability actual = trio.b();
|
||||
|
||||
assertEquals("Wrong ability was fetched", expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canCheckAbilityFlags() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
|
||||
when(update.hasMessage()).thenReturn(true);
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
when(message.hasDocument()).thenReturn(false);
|
||||
when(message.hasText()).thenReturn(true);
|
||||
|
||||
Ability documentAbility = getDefaultBuilder().flag(DOCUMENT, MESSAGE).build();
|
||||
Ability textAbility = getDefaultBuilder().flag(Flag.TEXT, MESSAGE).build();
|
||||
|
||||
Trio<Update, Ability, String[]> docTrio = Trio.of(update, documentAbility, TEXT);
|
||||
Trio<Update, Ability, String[]> textTrio = Trio.of(update, textAbility, TEXT);
|
||||
|
||||
assertEquals("Unexpected result when checking for message flags", false, bot.checkMessageFlags(docTrio));
|
||||
assertEquals("Unexpected result when checking for message flags", true, bot.checkMessageFlags(textTrio));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canReportCommands() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
|
||||
when(update.hasMessage()).thenReturn(true);
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
when(message.hasText()).thenReturn(true);
|
||||
MessageContext context = mock(MessageContext.class);
|
||||
when(context.chatId()).thenReturn(GROUP_ID);
|
||||
|
||||
bot.reportCommands().action().accept(context);
|
||||
|
||||
verify(sender, times(1)).send("default - dis iz default command", GROUP_ID);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws IOException {
|
||||
db.clear();
|
||||
db.close();
|
||||
}
|
||||
|
||||
private User mockUser(EndUser fromUser) {
|
||||
User user = mock(User.class);
|
||||
when(user.getId()).thenReturn(fromUser.id());
|
||||
when(user.getUserName()).thenReturn(fromUser.username());
|
||||
when(user.getFirstName()).thenReturn(fromUser.firstName());
|
||||
when(user.getLastName()).thenReturn(fromUser.lastName());
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Update mockFullUpdate(EndUser fromUser, String args) {
|
||||
bot.users().put(MUSER.id(), MUSER);
|
||||
bot.users().put(CREATOR.id(), CREATOR);
|
||||
bot.userIds().put(CREATOR.username(), CREATOR.id());
|
||||
bot.userIds().put(MUSER.username(), MUSER.id());
|
||||
|
||||
bot.admins().add(CREATOR.id());
|
||||
|
||||
User user = mockUser(fromUser);
|
||||
|
||||
Update update = mock(Update.class);
|
||||
when(update.hasMessage()).thenReturn(true);
|
||||
Message message = mock(Message.class);
|
||||
when(message.getFrom()).thenReturn(user);
|
||||
when(message.getText()).thenReturn(args);
|
||||
when(message.hasText()).thenReturn(true);
|
||||
when(message.isUserMessage()).thenReturn(true);
|
||||
when(message.getChatId()).thenReturn((long) fromUser.id());
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
return update;
|
||||
}
|
||||
|
||||
private void mockUser(Update update, Message message, User user) {
|
||||
when(update.hasMessage()).thenReturn(true);
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
when(message.getFrom()).thenReturn(user);
|
||||
when(user.getFirstName()).thenReturn(MUSER.firstName());
|
||||
when(user.getLastName()).thenReturn(MUSER.lastName());
|
||||
when(user.getId()).thenReturn(MUSER.id());
|
||||
when(user.getUserName()).thenReturn(MUSER.username());
|
||||
}
|
||||
|
||||
private void mockAlternateUser(Update update, Message message, User user, EndUser changedUser) {
|
||||
when(user.getId()).thenReturn(changedUser.id());
|
||||
when(user.getFirstName()).thenReturn(changedUser.firstName());
|
||||
when(user.getLastName()).thenReturn(changedUser.lastName());
|
||||
when(user.getUserName()).thenReturn(changedUser.username());
|
||||
when(message.getFrom()).thenReturn(user);
|
||||
when(update.hasMessage()).thenReturn(true);
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
}
|
||||
|
||||
private Update mockBackupUpdate() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
Message botMessage = mock(Message.class);
|
||||
Document document = mock(Document.class);
|
||||
|
||||
when(update.getMessage()).thenReturn(message);
|
||||
when(message.getDocument()).thenReturn(document);
|
||||
when(botMessage.getText()).thenReturn(RECOVERY_MESSAGE);
|
||||
when(message.isReply()).thenReturn(true);
|
||||
when(message.hasDocument()).thenReturn(true);
|
||||
when(message.getReplyToMessage()).thenReturn(botMessage);
|
||||
when(message.getChatId()).thenReturn(GROUP_ID);
|
||||
return update;
|
||||
}
|
||||
|
||||
private Object getDbBackup() {
|
||||
db.getSet(TEST).add(TEST);
|
||||
Object backup = db.backup();
|
||||
db.clear();
|
||||
return backup;
|
||||
}
|
||||
|
||||
private java.io.File createBackupFile(Object backup) throws IOException {
|
||||
java.io.File backupFile = new java.io.File(TEST);
|
||||
BufferedWriter writer = Files.newWriter(backupFile, Charset.defaultCharset());
|
||||
writer.write(backup.toString());
|
||||
writer.flush();
|
||||
writer.close();
|
||||
return backupFile;
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package org.telegram.abilitybots.api.bot;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
import org.telegram.abilitybots.api.objects.Ability;
|
||||
import org.telegram.abilitybots.api.objects.Ability.AbilityBuilder;
|
||||
import org.telegram.abilitybots.api.sender.MessageSender;
|
||||
|
||||
import static org.telegram.abilitybots.api.objects.Ability.builder;
|
||||
import static org.telegram.abilitybots.api.objects.Flag.CALLBACK_QUERY;
|
||||
import static org.telegram.abilitybots.api.objects.Flag.MESSAGE;
|
||||
import static org.telegram.abilitybots.api.objects.Locality.*;
|
||||
import static org.telegram.abilitybots.api.objects.Privacy.ADMIN;
|
||||
import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC;
|
||||
|
||||
public class DefaultBot extends AbilityBot {
|
||||
|
||||
public DefaultBot(String token, String username, DBContext db) {
|
||||
super(token, username, db);
|
||||
}
|
||||
|
||||
public static AbilityBuilder getDefaultBuilder() {
|
||||
return builder()
|
||||
.name("test")
|
||||
.privacy(PUBLIC)
|
||||
.locality(ALL)
|
||||
.input(1)
|
||||
.action(ctx -> {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int creatorId() {
|
||||
return 1337;
|
||||
}
|
||||
|
||||
public Ability defaultAbility() {
|
||||
return getDefaultBuilder()
|
||||
.name(DEFAULT)
|
||||
.info("dis iz default command")
|
||||
.reply(upd -> sender.send("reply", upd.getMessage().getChatId()), MESSAGE, update -> update.getMessage().getText().equals("must reply"))
|
||||
.reply(upd -> sender.send("reply", upd.getCallbackQuery().getMessage().getChatId()), CALLBACK_QUERY)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Ability adminAbility() {
|
||||
return getDefaultBuilder()
|
||||
.name("admin")
|
||||
.privacy(ADMIN)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Ability groupAbility() {
|
||||
return getDefaultBuilder()
|
||||
.name("group")
|
||||
.privacy(PUBLIC)
|
||||
.locality(GROUP)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Ability multipleInputAbility() {
|
||||
return getDefaultBuilder()
|
||||
.name("count")
|
||||
.privacy(PUBLIC)
|
||||
.locality(USER)
|
||||
.input(4)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Ability testAbility() {
|
||||
return getDefaultBuilder().build();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setSender(MessageSender sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
package org.telegram.abilitybots.api.db;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.telegram.abilitybots.api.objects.EndUser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.collect.Maps.newHashMap;
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static java.lang.String.format;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.telegram.abilitybots.api.bot.AbilityBot.USERS;
|
||||
import static org.telegram.abilitybots.api.bot.AbilityBot.USER_ID;
|
||||
import static org.telegram.abilitybots.api.bot.AbilityBotTest.CREATOR;
|
||||
import static org.telegram.abilitybots.api.bot.AbilityBotTest.MUSER;
|
||||
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
|
||||
|
||||
public class MapDBContextTest {
|
||||
|
||||
private static final String TEST = "TEST";
|
||||
private DBContext db;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
db = offlineInstance("db");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canRecoverDB() throws IOException {
|
||||
Map<Integer, EndUser> users = db.getMap(USERS);
|
||||
Map<String, Integer> userIds = db.getMap(USER_ID);
|
||||
users.put(CREATOR.id(), CREATOR);
|
||||
users.put(MUSER.id(), MUSER);
|
||||
userIds.put(CREATOR.username(), CREATOR.id());
|
||||
userIds.put(MUSER.username(), MUSER.id());
|
||||
|
||||
db.getSet("AYRE").add(123123);
|
||||
Map<Integer, EndUser> originalUsers = newHashMap(users);
|
||||
String beforeBackupInfo = db.info(USERS);
|
||||
|
||||
Object jsonBackup = db.backup();
|
||||
db.clear();
|
||||
boolean recovered = db.recover(jsonBackup);
|
||||
|
||||
Map<Integer, EndUser> recoveredUsers = db.getMap(USERS);
|
||||
String afterRecoveryInfo = db.info(USERS);
|
||||
|
||||
assertTrue("Could not recover database successfully", recovered);
|
||||
assertEquals("Map info before and after recovery is different", beforeBackupInfo, afterRecoveryInfo);
|
||||
assertEquals("Map before and after recovery are not equal", originalUsers, recoveredUsers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canFallbackDBIfRecoveryFails() throws IOException {
|
||||
Set<EndUser> users = db.getSet(USERS);
|
||||
users.add(CREATOR);
|
||||
users.add(MUSER);
|
||||
|
||||
Set<EndUser> originalSet = newHashSet(users);
|
||||
Object jsonBackup = db.backup();
|
||||
String corruptBackup = "!@#$" + String.valueOf(jsonBackup);
|
||||
boolean recovered = db.recover(corruptBackup);
|
||||
|
||||
Set<EndUser> recoveredSet = db.getSet(USERS);
|
||||
|
||||
assertEquals("Recovery was successful from a CORRUPT backup", false, recovered);
|
||||
assertEquals("Set before and after corrupt recovery are not equal", originalSet, recoveredSet);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetSummary() throws IOException {
|
||||
String anotherTest = TEST + 1;
|
||||
db.getSet(TEST).add(TEST);
|
||||
db.getSet(anotherTest).add(anotherTest);
|
||||
|
||||
String actualSummary = db.summary();
|
||||
// Name - Type - Number of "rows"
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetInfo() throws IOException {
|
||||
db.getSet(TEST).add(TEST);
|
||||
|
||||
String actualInfo = db.info(TEST);
|
||||
// JSON
|
||||
String expectedInfo = "TEST - Set - 1";
|
||||
|
||||
assertEquals("Actual DB structure info does not match that of the expected", expectedInfo, actualInfo);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void cantGetInfoFromNonexistentDBStructureName() throws IOException {
|
||||
db.info(TEST);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws IOException {
|
||||
db.clear();
|
||||
db.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder;
|
||||
|
||||
public class AbilityTest {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void argumentsCannotBeNegative() {
|
||||
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
|
||||
public void abilityEqualsMethod() {
|
||||
Ability ability1 = getDefaultBuilder().build();
|
||||
Ability ability2 = getDefaultBuilder().build();
|
||||
Ability ability3 = getDefaultBuilder().name("anotherconsumer").build();
|
||||
Ability ability4 = getDefaultBuilder().action((context) -> {
|
||||
}).build();
|
||||
|
||||
assertEquals("Abilities should not be equal", ability1, ability2);
|
||||
assertEquals("Abilities should not be equal", ability1, ability4);
|
||||
assertNotEquals("Abilities should be equal", ability1, ability3);
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,12 @@ Just import add the library to your project with one of these options:
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambotsextensions</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
2. Using Gradle:
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambotsextensions:3.1.2"
|
||||
compile "org.telegram:telegrambotsextensions:3.2"
|
||||
```
|
@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambotsextensions</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Telegram Bots Extensions</name>
|
||||
@ -59,7 +59,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<bots.version>3.1.2</bots.version>
|
||||
<bots.version>3.2</bots.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -24,17 +24,6 @@ public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingB
|
||||
private final CommandRegistry commandRegistry;
|
||||
private String botUsername;
|
||||
|
||||
/**
|
||||
* Creates a TelegramLongPollingCommandBot using default options
|
||||
* Use ICommandRegistry's methods on this bot to register commands
|
||||
*
|
||||
* @deprecated Uses {@link #TelegramLongPollingCommandBot(String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public TelegramLongPollingCommandBot() {
|
||||
this(ApiContext.getInstance(DefaultBotOptions.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TelegramLongPollingCommandBot using default options
|
||||
* Use ICommandRegistry's methods on this bot to register commands
|
||||
@ -45,19 +34,6 @@ public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingB
|
||||
this(ApiContext.getInstance(DefaultBotOptions.class), botUsername);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TelegramLongPollingCommandBot with custom options and allowing commands with
|
||||
* usernames
|
||||
* Use ICommandRegistry's methods on this bot to register commands
|
||||
* @param options Bot options
|
||||
*
|
||||
* @deprecated Use {@link #TelegramLongPollingCommandBot(DefaultBotOptions, String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public TelegramLongPollingCommandBot(DefaultBotOptions options) {
|
||||
this(options, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TelegramLongPollingCommandBot with custom options and allowing commands with
|
||||
* usernames
|
||||
@ -69,21 +45,6 @@ public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingB
|
||||
this(options, true, botUsername);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TelegramLongPollingCommandBot
|
||||
* Use ICommandRegistry's methods on this bot to register commands
|
||||
* @param options Bot options
|
||||
* @param allowCommandsWithUsername true to allow commands with parameters (default),
|
||||
* false otherwise
|
||||
*
|
||||
* @deprecated Use {@link #TelegramLongPollingCommandBot(DefaultBotOptions, boolean, String)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public TelegramLongPollingCommandBot(DefaultBotOptions options, boolean allowCommandsWithUsername) {
|
||||
super(options);
|
||||
this.commandRegistry = new CommandRegistry(allowCommandsWithUsername, getBotUsername());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TelegramLongPollingCommandBot
|
||||
* Use ICommandRegistry's methods on this bot to register commands
|
||||
@ -164,11 +125,10 @@ public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingB
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO This method will become final in next mayor release, avoid overriding it
|
||||
* @return Bot username
|
||||
*/
|
||||
@Override
|
||||
public String getBotUsername() {
|
||||
public final String getBotUsername() {
|
||||
return botUsername;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-meta</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Telegram Bots Meta</name>
|
||||
|
@ -50,6 +50,7 @@ public class ApiContext {
|
||||
return INJECTOR;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static class ApiModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
|
@ -0,0 +1,190 @@
|
||||
package org.telegram.telegrambots.api.methods.stickers;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.telegram.telegrambots.api.methods.PartialBotApiMethod;
|
||||
import org.telegram.telegrambots.api.objects.replykeyboard.ApiResponse;
|
||||
import org.telegram.telegrambots.api.objects.stickers.MaskPosition;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiValidationException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* Use this method to add a new sticker to a set created by the bot. Returns True on success.
|
||||
*/
|
||||
public class AddStickerToSet extends PartialBotApiMethod<Boolean> {
|
||||
public static final String PATH = "addStickerToSet";
|
||||
|
||||
public static final String USERID_FIELD = "user_id";
|
||||
public static final String NAME_FIELD = "name";
|
||||
public static final String PNGSTICKER_FIELD = "png_sticker";
|
||||
public static final String EMOJIS_FIELD = "emojis";
|
||||
public static final String MASKPOSITION_FIELD = "mask_position";
|
||||
|
||||
private Integer userId; ///< User identifier of sticker set owner
|
||||
private String name; ///< Sticker set name
|
||||
private String emojis; ///< One or more emoji corresponding to the sticker
|
||||
private MaskPosition maskPosition; ///< Position where the mask should be placed on faces
|
||||
/**
|
||||
* Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px,
|
||||
* and either width or height must be exactly 512px. Pass a file_id as a String to send a file
|
||||
* that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram
|
||||
* to get a file from the Internet, or upload a new one using multipart/form-data.
|
||||
*/
|
||||
private Boolean isNewPngSticker;
|
||||
private String pngSticker;
|
||||
private File pngStickerFile; ///< New sticker file
|
||||
private InputStream pngStickerStream; ///< New sticker stream
|
||||
private String pngStickerName; ///< New sticker stream name
|
||||
|
||||
public AddStickerToSet() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AddStickerToSet(Integer userId, String name, String emojis) {
|
||||
this.userId = checkNotNull(userId);
|
||||
this.name = checkNotNull(name);
|
||||
this.emojis = checkNotNull(emojis);
|
||||
}
|
||||
|
||||
public Integer getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public AddStickerToSet setUserId(Integer userId) {
|
||||
this.userId = userId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPngSticker() {
|
||||
return pngSticker;
|
||||
}
|
||||
|
||||
public AddStickerToSet setPngSticker(String pngSticker) {
|
||||
this.pngSticker = pngSticker;
|
||||
this.isNewPngSticker = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public File getPngStickerFile() {
|
||||
return pngStickerFile;
|
||||
}
|
||||
|
||||
public AddStickerToSet setPngStickerFile(File pngStickerFile) {
|
||||
Objects.requireNonNull(pngStickerFile, "pngStickerFile cannot be null!");
|
||||
this.pngStickerFile = pngStickerFile;
|
||||
this.isNewPngSticker = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputStream getPngStickerStream() {
|
||||
return pngStickerStream;
|
||||
}
|
||||
|
||||
public AddStickerToSet setPngStickerStream(String pngStickerName, InputStream pngStickerStream) {
|
||||
Objects.requireNonNull(pngStickerName, "pngStickerName cannot be null!");
|
||||
Objects.requireNonNull(pngStickerStream, "pngStickerStream cannot be null!");
|
||||
this.pngStickerStream = pngStickerStream;
|
||||
this.pngStickerName = pngStickerName;
|
||||
this.isNewPngSticker = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPngStickerName() {
|
||||
return pngStickerName;
|
||||
}
|
||||
|
||||
public Boolean isNewPngSticker() {
|
||||
return isNewPngSticker;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public AddStickerToSet setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getEmojis() {
|
||||
return emojis;
|
||||
}
|
||||
|
||||
public AddStickerToSet setEmojis(String emojis) {
|
||||
this.emojis = emojis;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MaskPosition getMaskPosition() {
|
||||
return maskPosition;
|
||||
}
|
||||
|
||||
public AddStickerToSet setMaskPosition(MaskPosition maskPosition) {
|
||||
this.maskPosition = maskPosition;
|
||||
return this;
|
||||
}
|
||||
|
||||
@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 creating new sticker set", result);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiRequestException("Unable to deserialize response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (userId == null || userId <= 0) {
|
||||
throw new TelegramApiValidationException("userId can't be empty", this);
|
||||
}
|
||||
if (name == null || name.isEmpty()) {
|
||||
throw new TelegramApiValidationException("name can't be empty", this);
|
||||
}
|
||||
if (emojis == null || emojis.isEmpty()) {
|
||||
throw new TelegramApiValidationException("emojis can't be empty", this);
|
||||
}
|
||||
if (isNewPngSticker) {
|
||||
if (pngStickerFile == null && pngStickerStream == null) {
|
||||
throw new TelegramApiValidationException("PngSticker can't be empty", this);
|
||||
}
|
||||
if (pngStickerStream != null && (pngStickerName == null || pngStickerName.isEmpty())) {
|
||||
throw new TelegramApiValidationException("PngSticker name can't be empty", this);
|
||||
}
|
||||
} else if (pngSticker == null) {
|
||||
throw new TelegramApiValidationException("PngSticker can't be empty", this);
|
||||
}
|
||||
if (maskPosition != null) {
|
||||
maskPosition.validate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AddStickerToSet{" +
|
||||
"userId=" + userId +
|
||||
", name='" + name + '\'' +
|
||||
", emojis='" + emojis + '\'' +
|
||||
", maskPosition=" + maskPosition +
|
||||
", isNewPngSticker=" + isNewPngSticker +
|
||||
", pngSticker='" + pngSticker + '\'' +
|
||||
", pngStickerFile=" + pngStickerFile +
|
||||
", pngStickerStream=" + pngStickerStream +
|
||||
", pngStickerName='" + pngStickerName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,220 @@
|
||||
package org.telegram.telegrambots.api.methods.stickers;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.telegram.telegrambots.api.methods.PartialBotApiMethod;
|
||||
import org.telegram.telegrambots.api.objects.replykeyboard.ApiResponse;
|
||||
import org.telegram.telegrambots.api.objects.stickers.MaskPosition;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiValidationException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* Use this method to create new sticker set owned by a user. The bot will be able to edit the created sticker set.
|
||||
* Returns True on success.
|
||||
*/
|
||||
public class CreateNewStickerSet extends PartialBotApiMethod<Boolean> {
|
||||
public static final String PATH = "createNewStickerSet";
|
||||
|
||||
public static final String USERID_FIELD = "user_id";
|
||||
public static final String NAME_FIELD = "name";
|
||||
public static final String TITLE_FIELD = "title";
|
||||
public static final String PNGSTICKER_FIELD = "png_sticker";
|
||||
public static final String EMOJIS_FIELD = "emojis";
|
||||
public static final String CONTAINSMASKS_FIELD = "contains_masks";
|
||||
public static final String MASKPOSITION_FIELD = "mask_position";
|
||||
|
||||
private Integer userId; ///< User identifier of created sticker set owner
|
||||
/**
|
||||
* Name of sticker set, to be used in t.me/addstickers/<name> URLs.
|
||||
* Can contain only english letters, digits and underscores.
|
||||
* Must begin with a letter, can't contain consecutive underscores and must end in “_by_<bot username>”.
|
||||
* <bot_username> is case insensitive. 7-64 characters.
|
||||
*/
|
||||
private String name; ///< Sticker set title, 1-64 characters
|
||||
private String title; ///< User identifier of created sticker set owner
|
||||
private String emojis; ///< One or more emoji corresponding to the sticker
|
||||
private Boolean containsMasks; ///< Pass True, if a set of mask stickers should be created
|
||||
private MaskPosition maskPosition; ///< Position where the mask should be placed on faces
|
||||
/**
|
||||
* Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px,
|
||||
* and either width or height must be exactly 512px.
|
||||
* Pass a file_id as a String to send a file that already exists on the Telegram servers,
|
||||
* pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one
|
||||
* using multipart/form-data. More info on Sending Files »
|
||||
*/
|
||||
private Boolean isNewPngSticker;
|
||||
private String pngSticker;
|
||||
private java.io.File pngStickerFile; ///< New sticker file
|
||||
private InputStream pngStickerStream; ///< New sticker stream
|
||||
private String pngStickerName; ///< New sticker stream name
|
||||
|
||||
public CreateNewStickerSet() {
|
||||
super();
|
||||
}
|
||||
|
||||
public CreateNewStickerSet(Integer userId, String name, String title, String emojis) {
|
||||
this.userId = checkNotNull(userId);
|
||||
this.name = checkNotNull(name);
|
||||
this.title = checkNotNull(title);
|
||||
this.emojis = checkNotNull(emojis);
|
||||
}
|
||||
|
||||
public Integer getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Integer userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getPngSticker() {
|
||||
return pngSticker;
|
||||
}
|
||||
|
||||
public CreateNewStickerSet setPngSticker(String pngSticker) {
|
||||
this.pngSticker = pngSticker;
|
||||
this.isNewPngSticker = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public File getPngStickerFile() {
|
||||
return pngStickerFile;
|
||||
}
|
||||
|
||||
public CreateNewStickerSet setPngStickerFile(File pngStickerFile) {
|
||||
Objects.requireNonNull(pngStickerFile, "pngStickerFile cannot be null!");
|
||||
this.pngStickerFile = pngStickerFile;
|
||||
this.isNewPngSticker = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputStream getPngStickerStream() {
|
||||
return pngStickerStream;
|
||||
}
|
||||
|
||||
public CreateNewStickerSet setPngStickerStream(String pngStickerName, InputStream pngStickerStream) {
|
||||
Objects.requireNonNull(pngStickerName, "pngStickerName cannot be null!");
|
||||
Objects.requireNonNull(pngStickerStream, "pngStickerStream cannot be null!");
|
||||
this.pngStickerStream = pngStickerStream;
|
||||
this.pngStickerName = pngStickerName;
|
||||
this.isNewPngSticker = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPngStickerName() {
|
||||
return pngStickerName;
|
||||
}
|
||||
|
||||
public Boolean isNewPngSticker() {
|
||||
return isNewPngSticker;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getEmojis() {
|
||||
return emojis;
|
||||
}
|
||||
|
||||
public void setEmojis(String emojis) {
|
||||
this.emojis = emojis;
|
||||
}
|
||||
|
||||
public Boolean getContainsMasks() {
|
||||
return containsMasks;
|
||||
}
|
||||
|
||||
public void setContainsMasks(Boolean containsMasks) {
|
||||
this.containsMasks = containsMasks;
|
||||
}
|
||||
|
||||
public MaskPosition getMaskPosition() {
|
||||
return maskPosition;
|
||||
}
|
||||
|
||||
public void setMaskPosition(MaskPosition maskPosition) {
|
||||
this.maskPosition = maskPosition;
|
||||
}
|
||||
|
||||
@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 creating new sticker set", result);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiRequestException("Unable to deserialize response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (userId == null || userId <= 0) {
|
||||
throw new TelegramApiValidationException("userId can't be empty", this);
|
||||
}
|
||||
if (name == null || name.isEmpty()) {
|
||||
throw new TelegramApiValidationException("name can't be empty", this);
|
||||
}
|
||||
if (title == null || title.isEmpty()) {
|
||||
throw new TelegramApiValidationException("userId can't be empty", this);
|
||||
}
|
||||
if (emojis == null || emojis.isEmpty()) {
|
||||
throw new TelegramApiValidationException("emojis can't be empty", this);
|
||||
}
|
||||
if (isNewPngSticker) {
|
||||
if (pngStickerFile == null && pngStickerStream == null) {
|
||||
throw new TelegramApiValidationException("PngSticker can't be empty", this);
|
||||
}
|
||||
if (pngStickerStream != null && (pngStickerName == null || pngStickerName.isEmpty())) {
|
||||
throw new TelegramApiValidationException("PngSticker name can't be empty", this);
|
||||
}
|
||||
} else if (pngSticker == null) {
|
||||
throw new TelegramApiValidationException("PngSticker can't be empty", this);
|
||||
}
|
||||
if (maskPosition != null) {
|
||||
maskPosition.validate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CreateNewStickerSet{" +
|
||||
"userId=" + userId +
|
||||
", name='" + name + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", emojis='" + emojis + '\'' +
|
||||
", containsMasks=" + containsMasks +
|
||||
", maskPosition=" + maskPosition +
|
||||
", isNewPngSticker=" + isNewPngSticker +
|
||||
", pngSticker='" + pngSticker + '\'' +
|
||||
", pngStickerFile=" + pngStickerFile +
|
||||
", pngStickerStream=" + pngStickerStream +
|
||||
", pngStickerName='" + pngStickerName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package org.telegram.telegrambots.api.methods.stickers;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.telegram.telegrambots.api.methods.BotApiMethod;
|
||||
import org.telegram.telegrambots.api.objects.replykeyboard.ApiResponse;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiValidationException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* Use this method to delete a sticker from a set created by the bot. Returns True on success.
|
||||
*/
|
||||
public class DeleteStickerFromSet extends BotApiMethod<Boolean> {
|
||||
private static final String PATH = "deleteStickerFromSet";
|
||||
|
||||
private static final String STICKER_FIELD = "sticker";
|
||||
|
||||
@JsonProperty(STICKER_FIELD)
|
||||
private String sticker; ///< File identifier of the sticker
|
||||
|
||||
public DeleteStickerFromSet() {
|
||||
super();
|
||||
}
|
||||
|
||||
public DeleteStickerFromSet(String sticker) {
|
||||
super();
|
||||
this.sticker = checkNotNull(sticker);
|
||||
}
|
||||
|
||||
@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 deleting sticker from set", result);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiRequestException("Unable to deserialize response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (sticker == null || sticker.isEmpty()) {
|
||||
throw new TelegramApiValidationException("sticker can't be null", this);
|
||||
}
|
||||
}
|
||||
|
||||
public String getSticker() {
|
||||
return sticker;
|
||||
}
|
||||
|
||||
public DeleteStickerFromSet setSticker(String sticker) {
|
||||
this.sticker = sticker;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeleteStickerFromSet{" +
|
||||
"sticker='" + sticker + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package org.telegram.telegrambots.api.methods.stickers;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.telegram.telegrambots.api.methods.BotApiMethod;
|
||||
import org.telegram.telegrambots.api.objects.replykeyboard.ApiResponse;
|
||||
import org.telegram.telegrambots.api.objects.stickers.StickerSet;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiValidationException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* Use this method to get a sticker set. On success, a StickerSet object is returned.
|
||||
*/
|
||||
public class GetStickerSet extends BotApiMethod<StickerSet> {
|
||||
private static final String PATH = "getStickerSet";
|
||||
|
||||
private static final String NAME_FIELD = "name";
|
||||
|
||||
@JsonProperty(NAME_FIELD)
|
||||
private String name; ///< Name of the sticker set
|
||||
|
||||
public GetStickerSet(String name) {
|
||||
super();
|
||||
this.name = checkNotNull(name);
|
||||
}
|
||||
|
||||
public GetStickerSet() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return PATH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StickerSet deserializeResponse(String answer) throws TelegramApiRequestException {
|
||||
try {
|
||||
ApiResponse<StickerSet> result = OBJECT_MAPPER.readValue(answer,
|
||||
new TypeReference<ApiResponse<StickerSet>>(){});
|
||||
if (result.getOk()) {
|
||||
return result.getResult();
|
||||
} else {
|
||||
throw new TelegramApiRequestException("Error getting sticker set", result);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiRequestException("Unable to deserialize response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (name == null || name.isEmpty()) {
|
||||
throw new TelegramApiValidationException("Name can't be null", this);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public GetStickerSet setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GetStickerSet{" +
|
||||
"name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package org.telegram.telegrambots.api.methods.stickers;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.telegram.telegrambots.api.methods.BotApiMethod;
|
||||
import org.telegram.telegrambots.api.objects.replykeyboard.ApiResponse;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiValidationException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* Use this method to move a sticker in a set created by the bot to a specific position. Returns True on success.
|
||||
*/
|
||||
public class SetStickerPositionInSet extends BotApiMethod<Boolean> {
|
||||
private static final String PATH = "getStickerSet";
|
||||
|
||||
private static final String STICKER_FIELD = "sticker";
|
||||
private static final String POSITION_FIELD = "position";
|
||||
|
||||
@JsonProperty(STICKER_FIELD)
|
||||
private String sticker; ///< File identifier of the sticker
|
||||
@JsonProperty(STICKER_FIELD)
|
||||
private Integer position; ///< New sticker position in the set, zero-based
|
||||
|
||||
public SetStickerPositionInSet(String sticker, Integer position) {
|
||||
this.sticker = checkNotNull(sticker);
|
||||
this.position = checkNotNull(position);
|
||||
}
|
||||
|
||||
public SetStickerPositionInSet() {
|
||||
super();
|
||||
}
|
||||
|
||||
@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 sticker position in set", result);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiRequestException("Unable to deserialize response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (sticker == null || sticker.isEmpty()) {
|
||||
throw new TelegramApiValidationException("sticker can't be null", this);
|
||||
}
|
||||
if (position == null || position > 0) {
|
||||
throw new TelegramApiValidationException("position can't be null", this);
|
||||
}
|
||||
}
|
||||
|
||||
public String getSticker() {
|
||||
return sticker;
|
||||
}
|
||||
|
||||
public SetStickerPositionInSet setSticker(String sticker) {
|
||||
this.sticker = sticker;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Integer getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public SetStickerPositionInSet setPosition(Integer position) {
|
||||
this.position = position;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SetStickerPositionInSet{" +
|
||||
"sticker='" + sticker + '\'' +
|
||||
", position=" + position +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package org.telegram.telegrambots.api.methods.stickers;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.telegram.telegrambots.api.methods.PartialBotApiMethod;
|
||||
import org.telegram.telegrambots.api.objects.File;
|
||||
import org.telegram.telegrambots.api.objects.replykeyboard.ApiResponse;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiValidationException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* Use this method to upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet
|
||||
* methods (can be used multiple times). Returns the uploaded File on success.
|
||||
*/
|
||||
public class UploadStickerFile extends PartialBotApiMethod<File> {
|
||||
public static final String PATH = "uploadStickerFile";
|
||||
|
||||
public static final String USERID_FIELD = "name";
|
||||
public static final String PNGSTICKER_FIELD = "png_sticker";
|
||||
|
||||
private Integer userId; ///< User identifier of sticker file owner
|
||||
/**
|
||||
* Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px,
|
||||
* and either width or height must be exactly 512px. More info on Sending Files »
|
||||
*/
|
||||
private java.io.File newPngStickerFile; ///< New sticker file
|
||||
private InputStream newPngStickerStream; ///< New sticker stream
|
||||
private String newPngStickerName; ///< New sticker stream name
|
||||
|
||||
public UploadStickerFile() {
|
||||
super();
|
||||
}
|
||||
|
||||
public UploadStickerFile(Integer userId) {
|
||||
super();
|
||||
this.userId = checkNotNull(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File deserializeResponse(String answer) throws TelegramApiRequestException {
|
||||
try {
|
||||
ApiResponse<File> result = OBJECT_MAPPER.readValue(answer,
|
||||
new TypeReference<ApiResponse<File>>(){});
|
||||
if (result.getOk()) {
|
||||
return result.getResult();
|
||||
} else {
|
||||
throw new TelegramApiRequestException("Error uploading sticker set", result);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiRequestException("Unable to deserialize response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (userId == null || userId <= 0) {
|
||||
throw new TelegramApiValidationException("userId can't be empty", this);
|
||||
}
|
||||
if (newPngStickerFile == null && newPngStickerStream == null) {
|
||||
throw new TelegramApiValidationException("file or stream must be present", this);
|
||||
}
|
||||
if (newPngStickerStream != null && (newPngStickerName == null || newPngStickerName.isEmpty())) {
|
||||
throw new TelegramApiValidationException("Stream name must be present", this);
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public UploadStickerFile setUserId(Integer userId) {
|
||||
this.userId = userId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public java.io.File getNewPngStickerFile() {
|
||||
return newPngStickerFile;
|
||||
}
|
||||
|
||||
public UploadStickerFile setNewPngSticker(java.io.File newPngStickerFile) {
|
||||
this.newPngStickerFile = newPngStickerFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputStream getNewPngStickerStream() {
|
||||
return newPngStickerStream;
|
||||
}
|
||||
|
||||
public UploadStickerFile setNewPngSticker(String newPngStickerName, InputStream newPngStickerStream) {
|
||||
this.newPngStickerName = newPngStickerName;
|
||||
this.newPngStickerStream = newPngStickerStream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getNewPngStickerName() {
|
||||
return newPngStickerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UploadStickerFile{" +
|
||||
"userId=" + userId +
|
||||
", newPngStickerFile=" + newPngStickerFile +
|
||||
", newPngStickerStream=" + newPngStickerStream +
|
||||
", newPngStickerName='" + newPngStickerName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import org.telegram.telegrambots.api.interfaces.BotApiObject;
|
||||
import org.telegram.telegrambots.api.objects.games.Game;
|
||||
import org.telegram.telegrambots.api.objects.payments.Invoice;
|
||||
import org.telegram.telegrambots.api.objects.payments.SuccessfulPayment;
|
||||
import org.telegram.telegrambots.api.objects.stickers.Sticker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -0,0 +1,89 @@
|
||||
package org.telegram.telegrambots.api.objects.stickers;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.telegram.telegrambots.api.interfaces.InputBotApiObject;
|
||||
import org.telegram.telegrambots.api.interfaces.Validable;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiValidationException;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 3.2
|
||||
* This object describes the position on faces where a mask should be placed by default.
|
||||
*/
|
||||
public class MaskPosition implements InputBotApiObject, Validable {
|
||||
private static final String POINT_FIELD = "point";
|
||||
private static final String XSHIFT_FIELD = "x_shift";
|
||||
private static final String YSHIFT_FIELD = "y_shift";
|
||||
private static final String SCALE_FIELD = "scale";
|
||||
|
||||
@JsonProperty(POINT_FIELD)
|
||||
private String point; ///< The part of the face relative to which the mask should be placed. One of “forehead”, “eyes”, “mouth”, or “chin”.
|
||||
@JsonProperty(XSHIFT_FIELD)
|
||||
private Float xShift; ///< Shift by X-axis measured in widths of the mask scaled to the face size, from left to right. For example, choosing -1.0 will place mask just to the left of the default mask position.
|
||||
@JsonProperty(YSHIFT_FIELD)
|
||||
private Float yShift; ///< Shift by Y-axis measured in heights of the mask scaled to the face size, from top to bottom. For example, 1.0 will place the mask just below the default mask position.
|
||||
@JsonProperty(SCALE_FIELD)
|
||||
private Float scale; ///< Mask scaling coefficient. For example, 2.0 means double size.
|
||||
|
||||
public MaskPosition() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getPoint() {
|
||||
return point;
|
||||
}
|
||||
|
||||
public Float getxShift() {
|
||||
return xShift;
|
||||
}
|
||||
|
||||
public Float getyShift() {
|
||||
return yShift;
|
||||
}
|
||||
|
||||
public Float getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public void setPoint(String point) {
|
||||
this.point = point;
|
||||
}
|
||||
|
||||
public void setxShift(Float xShift) {
|
||||
this.xShift = xShift;
|
||||
}
|
||||
|
||||
public void setyShift(Float yShift) {
|
||||
this.yShift = yShift;
|
||||
}
|
||||
|
||||
public void setScale(Float scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MaskPosition{" +
|
||||
"point='" + point + '\'' +
|
||||
", xShift=" + xShift +
|
||||
", yShift=" + yShift +
|
||||
", scale=" + scale +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (point == null || point.isEmpty()) {
|
||||
throw new TelegramApiValidationException("point can't be empty", this);
|
||||
}
|
||||
if (xShift == null) {
|
||||
throw new TelegramApiValidationException("xShift can't be empty", this);
|
||||
}
|
||||
if (yShift == null) {
|
||||
throw new TelegramApiValidationException("yShift can't be empty", this);
|
||||
}
|
||||
if (scale == null) {
|
||||
throw new TelegramApiValidationException("scale can't be empty", this);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
package org.telegram.telegrambots.api.objects;
|
||||
package org.telegram.telegrambots.api.objects.stickers;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.telegram.telegrambots.api.interfaces.BotApiObject;
|
||||
import org.telegram.telegrambots.api.objects.PhotoSize;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* @brief This object represents a sticker.
|
||||
* @date 20 of June of 2015
|
||||
*/
|
||||
public class Sticker implements BotApiObject {
|
||||
|
||||
@ -18,6 +18,8 @@ public class Sticker implements BotApiObject {
|
||||
private static final String THUMB_FIELD = "thumb";
|
||||
private static final String FILESIZE_FIELD = "file_size";
|
||||
private static final String EMOJI_FIELD = "emoji";
|
||||
private static final String SETNAME_FIELD = "set_name";
|
||||
private static final String MASKPOSITON_FIELD = "mask_position";
|
||||
|
||||
@JsonProperty(FILEID_FIELD)
|
||||
private String fileId; ///< Unique identifier for this file
|
||||
@ -31,6 +33,10 @@ public class Sticker implements BotApiObject {
|
||||
private Integer fileSize; ///< Optional. File size
|
||||
@JsonProperty(EMOJI_FIELD)
|
||||
private String emoji; ///< Optional. Emoji associated with the sticker
|
||||
@JsonProperty(SETNAME_FIELD)
|
||||
private String setName; ///< Optional. Name of the sticker set to which the sticker belongs
|
||||
@JsonProperty(MASKPOSITON_FIELD)
|
||||
private String maskPosition; ///< Optional. For mask stickers, the position where the mask should be placed
|
||||
|
||||
public Sticker() {
|
||||
super();
|
||||
@ -60,6 +66,14 @@ public class Sticker implements BotApiObject {
|
||||
return emoji;
|
||||
}
|
||||
|
||||
public String getSetName() {
|
||||
return setName;
|
||||
}
|
||||
|
||||
public String getMaskPosition() {
|
||||
return maskPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Sticker{" +
|
||||
@ -68,7 +82,9 @@ public class Sticker implements BotApiObject {
|
||||
", height=" + height +
|
||||
", thumb=" + thumb +
|
||||
", fileSize=" + fileSize +
|
||||
", emoji=" + emoji +
|
||||
", emoji='" + emoji + '\'' +
|
||||
", setName='" + setName + '\'' +
|
||||
", maskPosition='" + maskPosition + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package org.telegram.telegrambots.api.objects.stickers;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.telegram.telegrambots.api.interfaces.BotApiObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* This object represents a sticker set.
|
||||
*/
|
||||
public class StickerSet implements BotApiObject {
|
||||
private static final String NAME_FIELD = "name";
|
||||
private static final String TITLE_FIELD = "title";
|
||||
private static final String CONTAINSMASKS_FIELD = "contains_masks";
|
||||
private static final String STICKERS_FIELD = "stickers";
|
||||
|
||||
@JsonProperty(NAME_FIELD)
|
||||
private String name;
|
||||
@JsonProperty(TITLE_FIELD)
|
||||
private String title;
|
||||
@JsonProperty(CONTAINSMASKS_FIELD)
|
||||
private Boolean containsMasks;
|
||||
@JsonProperty(STICKERS_FIELD)
|
||||
private List<Sticker> stickers;
|
||||
|
||||
public StickerSet() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public Boolean getContainsMasks() {
|
||||
return containsMasks;
|
||||
}
|
||||
|
||||
public List<Sticker> getStickers() {
|
||||
return stickers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StickerSet{" +
|
||||
"name='" + name + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", containsMasks=" + containsMasks +
|
||||
", stickers=" + stickers +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -7,6 +7,9 @@ import org.telegram.telegrambots.api.methods.groupadministration.*;
|
||||
import org.telegram.telegrambots.api.methods.pinnedmessages.PinChatMessage;
|
||||
import org.telegram.telegrambots.api.methods.pinnedmessages.UnpinChatMessage;
|
||||
import org.telegram.telegrambots.api.methods.send.*;
|
||||
import org.telegram.telegrambots.api.methods.stickers.AddStickerToSet;
|
||||
import org.telegram.telegrambots.api.methods.stickers.CreateNewStickerSet;
|
||||
import org.telegram.telegrambots.api.methods.stickers.UploadStickerFile;
|
||||
import org.telegram.telegrambots.api.methods.updates.DeleteWebhook;
|
||||
import org.telegram.telegrambots.api.methods.updates.GetWebhookInfo;
|
||||
import org.telegram.telegrambots.api.methods.updatingmessages.DeleteMessage;
|
||||
@ -52,6 +55,7 @@ public abstract class AbsSender {
|
||||
|
||||
// Send Requests
|
||||
|
||||
@Deprecated
|
||||
public final Message sendMessage(SendMessage sendMessage) throws TelegramApiException {
|
||||
if (sendMessage == null) {
|
||||
throw new TelegramApiException("Parameter sendMessage can not be null");
|
||||
@ -60,6 +64,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(sendMessage);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean answerInlineQuery(AnswerInlineQuery answerInlineQuery) throws TelegramApiException {
|
||||
if (answerInlineQuery == null) {
|
||||
throw new TelegramApiException("Parameter answerInlineQuery can not be null");
|
||||
@ -68,6 +73,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(answerInlineQuery);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean sendChatAction(SendChatAction sendChatAction) throws TelegramApiException {
|
||||
if (sendChatAction == null) {
|
||||
throw new TelegramApiException("Parameter sendChatAction can not be null");
|
||||
@ -76,6 +82,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(sendChatAction);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Message forwardMessage(ForwardMessage forwardMessage) throws TelegramApiException {
|
||||
if (forwardMessage == null) {
|
||||
throw new TelegramApiException("Parameter forwardMessage can not be null");
|
||||
@ -84,6 +91,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(forwardMessage);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Message sendLocation(SendLocation sendLocation) throws TelegramApiException {
|
||||
if (sendLocation == null) {
|
||||
throw new TelegramApiException("Parameter sendLocation can not be null");
|
||||
@ -92,6 +100,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(sendLocation);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Message sendVenue(SendVenue sendVenue) throws TelegramApiException {
|
||||
if (sendVenue == null) {
|
||||
throw new TelegramApiException("Parameter sendVenue can not be null");
|
||||
@ -100,6 +109,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(sendVenue);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Message sendContact(SendContact sendContact) throws TelegramApiException {
|
||||
if (sendContact == null) {
|
||||
throw new TelegramApiException("Parameter sendContact can not be null");
|
||||
@ -108,6 +118,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(sendContact);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean kickMember(KickChatMember kickChatMember) throws TelegramApiException {
|
||||
if (kickChatMember == null) {
|
||||
throw new TelegramApiException("Parameter kickChatMember can not be null");
|
||||
@ -115,6 +126,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(kickChatMember);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean unbanMember(UnbanChatMember unbanChatMember) throws TelegramApiException {
|
||||
if (unbanChatMember == null) {
|
||||
throw new TelegramApiException("Parameter unbanChatMember can not be null");
|
||||
@ -122,6 +134,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(unbanChatMember);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean leaveChat(LeaveChat leaveChat) throws TelegramApiException {
|
||||
if (leaveChat == null) {
|
||||
throw new TelegramApiException("Parameter leaveChat can not be null");
|
||||
@ -129,6 +142,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(leaveChat);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Chat getChat(GetChat getChat) throws TelegramApiException {
|
||||
if (getChat == null) {
|
||||
throw new TelegramApiException("Parameter getChat can not be null");
|
||||
@ -136,6 +150,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(getChat);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final String exportChatInviteLink(ExportChatInviteLink exportChatInviteLink) throws TelegramApiException {
|
||||
if (exportChatInviteLink == null) {
|
||||
throw new TelegramApiException("Parameter exportChatInviteLink can not be null");
|
||||
@ -143,6 +158,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(exportChatInviteLink);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final List<ChatMember> getChatAdministrators(GetChatAdministrators getChatAdministrators) throws TelegramApiException {
|
||||
if (getChatAdministrators == null) {
|
||||
throw new TelegramApiException("Parameter getChatAdministrators can not be null");
|
||||
@ -150,6 +166,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(getChatAdministrators);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final ChatMember getChatMember(GetChatMember getChatMember) throws TelegramApiException {
|
||||
if (getChatMember == null) {
|
||||
throw new TelegramApiException("Parameter getChatMember can not be null");
|
||||
@ -157,6 +174,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(getChatMember);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Integer getChatMemberCount(GetChatMemberCount getChatMemberCount) throws TelegramApiException {
|
||||
if (getChatMemberCount == null) {
|
||||
throw new TelegramApiException("Parameter getChatMemberCount can not be null");
|
||||
@ -164,6 +182,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(getChatMemberCount);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Serializable editMessageText(EditMessageText editMessageText) throws TelegramApiException {
|
||||
if (editMessageText == null) {
|
||||
throw new TelegramApiException("Parameter editMessageText can not be null");
|
||||
@ -171,6 +190,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(editMessageText);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Serializable editMessageCaption(EditMessageCaption editMessageCaption) throws TelegramApiException {
|
||||
if (editMessageCaption == null) {
|
||||
throw new TelegramApiException("Parameter editMessageCaption can not be null");
|
||||
@ -178,6 +198,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(editMessageCaption);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Serializable editMessageReplyMarkup(EditMessageReplyMarkup editMessageReplyMarkup) throws TelegramApiException {
|
||||
if (editMessageReplyMarkup == null) {
|
||||
throw new TelegramApiException("Parameter editMessageReplyMarkup can not be null");
|
||||
@ -185,6 +206,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(editMessageReplyMarkup);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean answerCallbackQuery(AnswerCallbackQuery answerCallbackQuery) throws TelegramApiException {
|
||||
if (answerCallbackQuery == null) {
|
||||
throw new TelegramApiException("Parameter answerCallbackQuery can not be null");
|
||||
@ -192,6 +214,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(answerCallbackQuery);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final UserProfilePhotos getUserProfilePhotos(GetUserProfilePhotos getUserProfilePhotos) throws TelegramApiException {
|
||||
if (getUserProfilePhotos == null) {
|
||||
throw new TelegramApiException("Parameter getUserProfilePhotos can not be null");
|
||||
@ -200,6 +223,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(getUserProfilePhotos);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final File getFile(GetFile getFile) throws TelegramApiException {
|
||||
if(getFile == null){
|
||||
throw new TelegramApiException("Parameter getFile can not be null");
|
||||
@ -211,9 +235,7 @@ public abstract class AbsSender {
|
||||
}
|
||||
|
||||
public final User getMe() throws TelegramApiException {
|
||||
GetMe getMe = new GetMe();
|
||||
|
||||
return sendApiMethod(getMe);
|
||||
return sendApiMethod(new GetMe());
|
||||
}
|
||||
|
||||
public final WebhookInfo getWebhookInfo() throws TelegramApiException {
|
||||
@ -221,6 +243,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(getWebhookInfo);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Serializable setGameScore(SetGameScore setGameScore) throws TelegramApiException {
|
||||
if(setGameScore == null){
|
||||
throw new TelegramApiException("Parameter setGameScore can not be null");
|
||||
@ -228,6 +251,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(setGameScore);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Serializable getGameHighScores(GetGameHighScores getGameHighScores) throws TelegramApiException {
|
||||
if(getGameHighScores == null){
|
||||
throw new TelegramApiException("Parameter getGameHighScores can not be null");
|
||||
@ -235,6 +259,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(getGameHighScores);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Message sendGame(SendGame sendGame) throws TelegramApiException {
|
||||
if(sendGame == null){
|
||||
throw new TelegramApiException("Parameter sendGame can not be null");
|
||||
@ -242,6 +267,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(sendGame);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean deleteWebhook(DeleteWebhook deleteWebhook) throws TelegramApiException {
|
||||
if(deleteWebhook == null){
|
||||
throw new TelegramApiException("Parameter deleteWebhook can not be null");
|
||||
@ -249,6 +275,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(deleteWebhook);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Message sendInvoice(SendInvoice sendInvoice) throws TelegramApiException {
|
||||
if(sendInvoice == null){
|
||||
throw new TelegramApiException("Parameter sendInvoice can not be null");
|
||||
@ -256,6 +283,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(sendInvoice);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean answerShippingQuery(AnswerShippingQuery answerShippingQuery) throws TelegramApiException {
|
||||
if(answerShippingQuery == null){
|
||||
throw new TelegramApiException("Parameter answerShippingQuery can not be null");
|
||||
@ -263,6 +291,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(answerShippingQuery);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean answerPreCheckoutQuery(AnswerPreCheckoutQuery answerPreCheckoutQuery) throws TelegramApiException {
|
||||
if(answerPreCheckoutQuery == null){
|
||||
throw new TelegramApiException("Parameter answerPreCheckoutQuery can not be null");
|
||||
@ -270,6 +299,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(answerPreCheckoutQuery);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean deleteMessage(DeleteMessage deleteMessage) throws TelegramApiException {
|
||||
if(deleteMessage == null){
|
||||
throw new TelegramApiException("Parameter deleteMessage can not be null");
|
||||
@ -277,6 +307,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(deleteMessage);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean deleteChatPhoto(DeleteChatPhoto deleteChatPhoto) throws TelegramApiException {
|
||||
if(deleteChatPhoto == null){
|
||||
throw new TelegramApiException("Parameter deleteChatPhoto can not be null");
|
||||
@ -284,6 +315,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(deleteChatPhoto);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean pinChatMessage(PinChatMessage pinChatMessage) throws TelegramApiException {
|
||||
if(pinChatMessage == null){
|
||||
throw new TelegramApiException("Parameter pinChatMessage can not be null");
|
||||
@ -291,6 +323,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(pinChatMessage);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean unpinChatMessage(UnpinChatMessage unpinChatMessage) throws TelegramApiException {
|
||||
if(unpinChatMessage == null){
|
||||
throw new TelegramApiException("Parameter unpinChatMessage can not be null");
|
||||
@ -298,6 +331,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(unpinChatMessage);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean promoteChatMember(PromoteChatMember promoteChatMember) throws TelegramApiException {
|
||||
if(promoteChatMember == null){
|
||||
throw new TelegramApiException("Parameter promoteChatMember can not be null");
|
||||
@ -305,6 +339,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(promoteChatMember);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean restrictChatMember(RestrictChatMember restrictChatMember) throws TelegramApiException {
|
||||
if(restrictChatMember == null){
|
||||
throw new TelegramApiException("Parameter restrictChatMember can not be null");
|
||||
@ -312,6 +347,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(restrictChatMember);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean setChatDescription(SetChatDescription setChatDescription) throws TelegramApiException {
|
||||
if(setChatDescription == null){
|
||||
throw new TelegramApiException("Parameter setChatDescription can not be null");
|
||||
@ -319,6 +355,7 @@ public abstract class AbsSender {
|
||||
return sendApiMethod(setChatDescription);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final Boolean setChatTitle(SetChatTitle setChatTitle) throws TelegramApiException {
|
||||
if(setChatTitle == null){
|
||||
throw new TelegramApiException("Parameter setChatTitle can not be null");
|
||||
@ -328,6 +365,7 @@ public abstract class AbsSender {
|
||||
|
||||
// Send Requests Async
|
||||
|
||||
@Deprecated
|
||||
public final void sendMessageAsync(SendMessage sendMessage, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
if (sendMessage == null) {
|
||||
throw new TelegramApiException("Parameter sendMessage can not be null");
|
||||
@ -340,6 +378,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(sendMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void answerInlineQueryAsync(AnswerInlineQuery answerInlineQuery, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (answerInlineQuery == null) {
|
||||
throw new TelegramApiException("Parameter answerInlineQuery can not be null");
|
||||
@ -352,6 +391,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(answerInlineQuery, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void sendChatActionAsync(SendChatAction sendChatAction, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (sendChatAction == null) {
|
||||
throw new TelegramApiException("Parameter sendChatAction can not be null");
|
||||
@ -364,6 +404,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(sendChatAction, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void forwardMessageAsync(ForwardMessage forwardMessage, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
if (forwardMessage == null) {
|
||||
throw new TelegramApiException("Parameter forwardMessage can not be null");
|
||||
@ -376,6 +417,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(forwardMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void sendLocationAsync(SendLocation sendLocation, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
if (sendLocation == null) {
|
||||
throw new TelegramApiException("Parameter sendLocation can not be null");
|
||||
@ -388,6 +430,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(sendLocation, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void sendVenueAsync(SendVenue sendVenue, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
if (sendVenue == null) {
|
||||
throw new TelegramApiException("Parameter sendVenue can not be null");
|
||||
@ -400,6 +443,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(sendVenue, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void sendContactAsync(SendContact sendContact, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
if (sendContact == null) {
|
||||
throw new TelegramApiException("Parameter sendContact can not be null");
|
||||
@ -411,6 +455,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(sendContact, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void kickMemberAsync(KickChatMember kickChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (kickChatMember == null) {
|
||||
throw new TelegramApiException("Parameter kickChatMember can not be null");
|
||||
@ -422,6 +467,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(kickChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void unbanMemberAsync(UnbanChatMember unbanChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (unbanChatMember == null) {
|
||||
throw new TelegramApiException("Parameter unbanChatMember can not be null");
|
||||
@ -433,6 +479,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(unbanChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void leaveChatAsync(LeaveChat leaveChat, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (leaveChat == null) {
|
||||
throw new TelegramApiException("Parameter leaveChat can not be null");
|
||||
@ -443,6 +490,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(leaveChat, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void getChatAsync(GetChat getChat, SentCallback<Chat> sentCallback) throws TelegramApiException {
|
||||
if (getChat == null) {
|
||||
throw new TelegramApiException("Parameter getChat can not be null");
|
||||
@ -453,6 +501,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(getChat, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void exportChatInviteLinkAsync(ExportChatInviteLink exportChatInviteLink, SentCallback<String> sentCallback) throws TelegramApiException {
|
||||
if (exportChatInviteLink == null) {
|
||||
throw new TelegramApiException("Parameter exportChatInviteLink can not be null");
|
||||
@ -463,6 +512,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(exportChatInviteLink, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void getChatAdministratorsAsync(GetChatAdministrators getChatAdministrators, SentCallback<ArrayList<ChatMember>> sentCallback) throws TelegramApiException {
|
||||
if (getChatAdministrators == null) {
|
||||
throw new TelegramApiException("Parameter getChatAdministrators can not be null");
|
||||
@ -473,6 +523,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(getChatAdministrators, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void getChatMemberAsync(GetChatMember getChatMember, SentCallback<ChatMember> sentCallback) throws TelegramApiException {
|
||||
if (getChatMember == null) {
|
||||
throw new TelegramApiException("Parameter getChatMember can not be null");
|
||||
@ -483,6 +534,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(getChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void getChatMemberCountAsync(GetChatMemberCount getChatMemberCount, SentCallback<Integer> sentCallback) throws TelegramApiException {
|
||||
if (getChatMemberCount == null) {
|
||||
throw new TelegramApiException("Parameter getChatMemberCount can not be null");
|
||||
@ -494,6 +546,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(getChatMemberCount, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void editMessageTextAsync(EditMessageText editMessageText, SentCallback<Serializable> sentCallback) throws TelegramApiException {
|
||||
if (editMessageText == null) {
|
||||
throw new TelegramApiException("Parameter editMessageText can not be null");
|
||||
@ -505,6 +558,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(editMessageText, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void editMessageCaptionAsync(EditMessageCaption editMessageCaption, SentCallback<Serializable> sentCallback) throws TelegramApiException {
|
||||
if (editMessageCaption == null) {
|
||||
throw new TelegramApiException("Parameter editMessageCaption can not be null");
|
||||
@ -516,6 +570,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(editMessageCaption, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void editMessageReplyMarkup(EditMessageReplyMarkup editMessageReplyMarkup, SentCallback<Serializable> sentCallback) throws TelegramApiException {
|
||||
if (editMessageReplyMarkup == null) {
|
||||
throw new TelegramApiException("Parameter editMessageReplyMarkup can not be null");
|
||||
@ -527,6 +582,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(editMessageReplyMarkup, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void answerCallbackQueryAsync(AnswerCallbackQuery answerCallbackQuery, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (answerCallbackQuery == null) {
|
||||
throw new TelegramApiException("Parameter answerCallbackQuery can not be null");
|
||||
@ -538,6 +594,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(answerCallbackQuery, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void getUserProfilePhotosAsync(GetUserProfilePhotos getUserProfilePhotos, SentCallback<UserProfilePhotos> sentCallback) throws TelegramApiException {
|
||||
if (getUserProfilePhotos == null) {
|
||||
throw new TelegramApiException("Parameter getUserProfilePhotos can not be null");
|
||||
@ -549,6 +606,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(getUserProfilePhotos, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void getFileAsync(GetFile getFile, SentCallback<File> sentCallback) throws TelegramApiException {
|
||||
if (getFile == null) {
|
||||
throw new TelegramApiException("Parameter getFile can not be null");
|
||||
@ -564,19 +622,17 @@ public abstract class AbsSender {
|
||||
if (sentCallback == null) {
|
||||
throw new TelegramApiException("Parameter sentCallback can not be null");
|
||||
}
|
||||
GetMe getMe = new GetMe();
|
||||
sendApiMethodAsync(getMe, sentCallback);
|
||||
sendApiMethodAsync(new GetMe(), sentCallback);
|
||||
}
|
||||
|
||||
public final void getWebhookInfoAsync(SentCallback<WebhookInfo> sentCallback) throws TelegramApiException {
|
||||
if (sentCallback == null) {
|
||||
throw new TelegramApiException("Parameter sentCallback can not be null");
|
||||
}
|
||||
|
||||
GetWebhookInfo getWebhookInfo = new GetWebhookInfo();
|
||||
sendApiMethodAsync(getWebhookInfo, sentCallback);
|
||||
sendApiMethodAsync(new GetWebhookInfo(), sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void setGameScoreAsync(SetGameScore setGameScore, SentCallback<Serializable> sentCallback) throws TelegramApiException {
|
||||
if (setGameScore == null) {
|
||||
throw new TelegramApiException("Parameter setGameScore can not be null");
|
||||
@ -587,6 +643,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(setGameScore, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void getGameHighScoresAsync(GetGameHighScores getGameHighScores, SentCallback<ArrayList<GameHighScore>> sentCallback) throws TelegramApiException {
|
||||
if (getGameHighScores == null) {
|
||||
throw new TelegramApiException("Parameter getGameHighScores can not be null");
|
||||
@ -597,6 +654,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(getGameHighScores, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void sendGameAsync(SendGame sendGame, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
if (sendGame == null) {
|
||||
throw new TelegramApiException("Parameter sendGame can not be null");
|
||||
@ -607,6 +665,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(sendGame, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void deleteWebhook(DeleteWebhook deleteWebhook, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (deleteWebhook == null) {
|
||||
throw new TelegramApiException("Parameter deleteWebhook can not be null");
|
||||
@ -617,6 +676,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(deleteWebhook, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void sendInvoice(SendInvoice sendInvoice, SentCallback<Message> sentCallback) throws TelegramApiException {
|
||||
if (sendInvoice == null) {
|
||||
throw new TelegramApiException("Parameter sendInvoice can not be null");
|
||||
@ -627,6 +687,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(sendInvoice, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void answerShippingQuery(AnswerShippingQuery answerShippingQuery, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (answerShippingQuery == null) {
|
||||
throw new TelegramApiException("Parameter answerShippingQuery can not be null");
|
||||
@ -637,6 +698,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(answerShippingQuery, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void answerPreCheckoutQuery(AnswerPreCheckoutQuery answerPreCheckoutQuery, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (answerPreCheckoutQuery == null) {
|
||||
throw new TelegramApiException("Parameter answerPreCheckoutQuery can not be null");
|
||||
@ -647,6 +709,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(answerPreCheckoutQuery, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void deleteMessage(DeleteMessage deleteMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (deleteMessage == null) {
|
||||
throw new TelegramApiException("Parameter deleteMessage can not be null");
|
||||
@ -657,6 +720,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(deleteMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void deleteChatPhoto(DeleteChatPhoto deleteChatPhoto, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (deleteChatPhoto == null) {
|
||||
throw new TelegramApiException("Parameter deleteChatPhoto can not be null");
|
||||
@ -667,6 +731,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(deleteChatPhoto, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void pinChatMessage(PinChatMessage pinChatMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (pinChatMessage == null) {
|
||||
throw new TelegramApiException("Parameter pinChatMessage can not be null");
|
||||
@ -677,6 +742,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(pinChatMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void unpinChatMessage(UnpinChatMessage unpinChatMessage, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (unpinChatMessage == null) {
|
||||
throw new TelegramApiException("Parameter unpinChatMessage can not be null");
|
||||
@ -687,6 +753,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(unpinChatMessage, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void promoteChatMember(PromoteChatMember promoteChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (promoteChatMember == null) {
|
||||
throw new TelegramApiException("Parameter promoteChatMember can not be null");
|
||||
@ -697,6 +764,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(promoteChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void restrictChatMember(RestrictChatMember restrictChatMember, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (restrictChatMember == null) {
|
||||
throw new TelegramApiException("Parameter restrictChatMember can not be null");
|
||||
@ -707,6 +775,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(restrictChatMember, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void setChatDescription(SetChatDescription setChatDescription, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (setChatDescription == null) {
|
||||
throw new TelegramApiException("Parameter setChatDescription can not be null");
|
||||
@ -717,6 +786,7 @@ public abstract class AbsSender {
|
||||
sendApiMethodAsync(setChatDescription, sentCallback);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public final void setChatTitle(SetChatTitle setChatTitle, SentCallback<Boolean> sentCallback) throws TelegramApiException {
|
||||
if (setChatTitle == null) {
|
||||
throw new TelegramApiException("Parameter setChatTitle can not be null");
|
||||
@ -763,6 +833,30 @@ public abstract class AbsSender {
|
||||
*/
|
||||
public abstract Boolean setChatPhoto(SetChatPhoto setChatPhoto) throws TelegramApiException;
|
||||
|
||||
/**
|
||||
* Adds a new sticker to a set (https://core.telegram.org/bots/api#addStickerToSet)
|
||||
* @param addStickerToSet Information of the sticker to set
|
||||
* @return If success, true is returned
|
||||
* @throws TelegramApiException If there is any error adding the sticker to the set
|
||||
*/
|
||||
public abstract Boolean addStickerToSet(AddStickerToSet addStickerToSet) throws TelegramApiException;
|
||||
|
||||
/**
|
||||
* Creates a new sticker set (https://core.telegram.org/bots/api#createNewStickerSet)
|
||||
* @param createNewStickerSet Information of the sticker set to create
|
||||
* @return If success, true is returned
|
||||
* @throws TelegramApiException If there is any error creating the new sticker set
|
||||
*/
|
||||
public abstract Boolean createNewStickerSet(CreateNewStickerSet createNewStickerSet) throws TelegramApiException;
|
||||
|
||||
/**
|
||||
* Upload a new file as sticker (https://core.telegram.org/bots/api#uploadStickerFile)
|
||||
* @param uploadStickerFile Information of the file to upload as sticker
|
||||
* @return If success, true is returned
|
||||
* @throws TelegramApiException If there is any error uploading the new file
|
||||
*/
|
||||
public abstract File uploadStickerFile(UploadStickerFile uploadStickerFile) throws TelegramApiException;
|
||||
|
||||
// Simplified methods
|
||||
|
||||
protected abstract <T extends Serializable, Method extends BotApiMethod<T>, Callback extends SentCallback<T>> void sendApiMethodAsync(Method method, Callback callback);
|
||||
|
@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>3.1.2</version>
|
||||
<version>3.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Telegram Bots</name>
|
||||
@ -66,7 +66,7 @@
|
||||
<jackson.version>2.8.7</jackson.version>
|
||||
<jacksonanotation.version>2.8.0</jacksonanotation.version>
|
||||
<commonio.version>2.5</commonio.version>
|
||||
<bots.version>3.1.2</bots.version>
|
||||
<bots.version>3.2</bots.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -17,6 +17,9 @@ import org.apache.http.util.EntityUtils;
|
||||
import org.telegram.telegrambots.api.methods.BotApiMethod;
|
||||
import org.telegram.telegrambots.api.methods.groupadministration.SetChatPhoto;
|
||||
import org.telegram.telegrambots.api.methods.send.*;
|
||||
import org.telegram.telegrambots.api.methods.stickers.AddStickerToSet;
|
||||
import org.telegram.telegrambots.api.methods.stickers.CreateNewStickerSet;
|
||||
import org.telegram.telegrambots.api.methods.stickers.UploadStickerFile;
|
||||
import org.telegram.telegrambots.api.objects.File;
|
||||
import org.telegram.telegrambots.api.objects.Message;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiException;
|
||||
@ -89,105 +92,48 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
throw new TelegramApiException("Parameter file can not be null");
|
||||
}
|
||||
String url = File.getFileUrl(getBotToken(), filePath);
|
||||
java.io.File output;
|
||||
try {
|
||||
output = java.io.File.createTempFile(Long.toString(System.currentTimeMillis()), ".tmp");
|
||||
FileUtils.copyURLToFile(new URL(url), output);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new TelegramApiException("Wrong url for file: " + url);
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiRequestException("Error downloading the file", e);
|
||||
}
|
||||
|
||||
return output;
|
||||
String tempFileName = Long.toString(System.currentTimeMillis());
|
||||
return downloadToTemporaryFileWrappingExceptions(url, tempFileName);
|
||||
}
|
||||
|
||||
public final java.io.File downloadFile(File file) throws TelegramApiException {
|
||||
if(file == null){
|
||||
throw new TelegramApiException("Parameter file can not be null");
|
||||
}
|
||||
assertParamNotNull(file, "file");
|
||||
String url = file.getFileUrl(getBotToken());
|
||||
java.io.File output;
|
||||
try {
|
||||
output = java.io.File.createTempFile(file.getFileId(), ".tmp");
|
||||
FileUtils.copyURLToFile(new URL(url), output);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new TelegramApiException("Wrong url for file: " + url);
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiRequestException("Error downloading the file", e);
|
||||
}
|
||||
|
||||
return output;
|
||||
String tempFileName = file.getFileId();
|
||||
return downloadToTemporaryFileWrappingExceptions(url, tempFileName);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
exe.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String url = File.getFileUrl(getBotToken(), filePath);
|
||||
try {
|
||||
java.io.File output = java.io.File.createTempFile(Long.toString(System.currentTimeMillis()), ".tmp");
|
||||
FileUtils.copyURLToFile(new URL(url), output);
|
||||
callback.onResult(filePath, output);
|
||||
} catch (MalformedURLException e) {
|
||||
callback.onException(filePath, new TelegramApiException("Wrong url for file: " + url));
|
||||
} catch (IOException e) {
|
||||
callback.onException(filePath, new TelegramApiRequestException("Error downloading the file", e));
|
||||
}
|
||||
}
|
||||
});
|
||||
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 {
|
||||
if(file == null){
|
||||
throw new TelegramApiException("Parameter file can not be null");
|
||||
}
|
||||
if (callback == null) {
|
||||
throw new TelegramApiException("Parameter callback can not be null");
|
||||
}
|
||||
|
||||
exe.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String url = file.getFileUrl(getBotToken());
|
||||
try {
|
||||
java.io.File output = java.io.File.createTempFile(file.getFileId(), ".tmp");
|
||||
FileUtils.copyURLToFile(new URL(url), output);
|
||||
callback.onResult(file, output);
|
||||
} catch (MalformedURLException e) {
|
||||
callback.onException(file, new TelegramApiException("Wrong url for file: " + url));
|
||||
} catch (IOException e) {
|
||||
callback.onException(file, new TelegramApiRequestException("Error downloading the file", e));
|
||||
}
|
||||
}
|
||||
});
|
||||
assertParamNotNull(file, "file");
|
||||
assertParamNotNull(callback, "callback");
|
||||
String url = file.getFileUrl(getBotToken());
|
||||
String tempFileName = file.getFileId();
|
||||
exe.submit(getDownloadFileAsyncJob(file, callback, url, tempFileName));
|
||||
}
|
||||
|
||||
// Specific Send Requests
|
||||
|
||||
@Override
|
||||
public final Message sendDocument(SendDocument sendDocument) throws TelegramApiException {
|
||||
if(sendDocument == null){
|
||||
throw new TelegramApiException("Parameter sendDocument can not be null");
|
||||
}
|
||||
assertParamNotNull(sendDocument, "sendDocument");
|
||||
|
||||
sendDocument.validate();
|
||||
String responseContent;
|
||||
|
||||
try {
|
||||
String url = getBaseUrl() + SendDocument.PATH;
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(SendDocument.CHATID_FIELD, sendDocument.getChatId());
|
||||
builder.addTextBody(SendDocument.CHATID_FIELD, sendDocument.getChatId(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
if (sendDocument.isNewDocument()) {
|
||||
if (sendDocument.getNewDocumentFile() != null) {
|
||||
builder.addBinaryBody(SendDocument.DOCUMENT_FIELD, sendDocument.getNewDocumentFile());
|
||||
@ -197,47 +143,37 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
builder.addBinaryBody(SendDocument.DOCUMENT_FIELD, new java.io.File(sendDocument.getDocument()), ContentType.APPLICATION_OCTET_STREAM, sendDocument.getDocumentName());
|
||||
}
|
||||
} else {
|
||||
builder.addTextBody(SendDocument.DOCUMENT_FIELD, sendDocument.getDocument());
|
||||
builder.addTextBody(SendDocument.DOCUMENT_FIELD, sendDocument.getDocument(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
}
|
||||
if (sendDocument.getReplyMarkup() != null) {
|
||||
builder.addTextBody(SendDocument.REPLYMARKUP_FIELD, objectMapper.writeValueAsString(sendDocument.getReplyMarkup()), TEXT_PLAIN_CONTENT_TYPE);
|
||||
}
|
||||
if (sendDocument.getReplyToMessageId() != null) {
|
||||
builder.addTextBody(SendDocument.REPLYTOMESSAGEID_FIELD, sendDocument.getReplyToMessageId().toString());
|
||||
builder.addTextBody(SendDocument.REPLYTOMESSAGEID_FIELD, sendDocument.getReplyToMessageId().toString(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
}
|
||||
if (sendDocument.getCaption() != null) {
|
||||
builder.addTextBody(SendDocument.CAPTION_FIELD, sendDocument.getCaption(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
}
|
||||
if (sendDocument.getDisableNotification() != null) {
|
||||
builder.addTextBody(SendDocument.DISABLENOTIFICATION_FIELD, sendDocument.getDisableNotification().toString());
|
||||
builder.addTextBody(SendDocument.DISABLENOTIFICATION_FIELD, sendDocument.getDisableNotification().toString(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
}
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return sendDocument.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to send document", e);
|
||||
}
|
||||
|
||||
return sendDocument.deserializeResponse(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Message sendPhoto(SendPhoto sendPhoto) throws TelegramApiException {
|
||||
if(sendPhoto == null){
|
||||
throw new TelegramApiException("Parameter sendPhoto can not be null");
|
||||
}
|
||||
assertParamNotNull(sendPhoto, "sendPhoto");
|
||||
|
||||
sendPhoto.validate();
|
||||
String responseContent;
|
||||
try {
|
||||
String url = getBaseUrl() + SendPhoto.PATH;
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(SendPhoto.CHATID_FIELD, sendPhoto.getChatId());
|
||||
@ -267,30 +203,20 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return sendPhoto.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to send photo", e);
|
||||
}
|
||||
|
||||
return sendPhoto.deserializeResponse(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Message sendVideo(SendVideo sendVideo) throws TelegramApiException {
|
||||
if(sendVideo == null){
|
||||
throw new TelegramApiException("Parameter sendVideo can not be null");
|
||||
}
|
||||
assertParamNotNull(sendVideo, "sendVideo");
|
||||
|
||||
sendVideo.validate();
|
||||
String responseContent;
|
||||
try {
|
||||
String url = getBaseUrl() + SendVideo.PATH;
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(SendVideo.CHATID_FIELD, sendVideo.getChatId());
|
||||
@ -329,30 +255,20 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return sendVideo.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to send video", e);
|
||||
}
|
||||
|
||||
return sendVideo.deserializeResponse(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Message sendVideoNote(SendVideoNote sendVideoNote) throws TelegramApiException {
|
||||
if(sendVideoNote == null){
|
||||
throw new TelegramApiException("Parameter sendVideoNote can not be null");
|
||||
}
|
||||
assertParamNotNull(sendVideoNote, "sendVideoNote");
|
||||
|
||||
sendVideoNote.validate();
|
||||
String responseContent;
|
||||
try {
|
||||
String url = getBaseUrl() + SendVideoNote.PATH;
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(SendVideoNote.CHATID_FIELD, sendVideoNote.getChatId());
|
||||
@ -386,30 +302,20 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return sendVideoNote.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to send video note", e);
|
||||
}
|
||||
|
||||
return sendVideoNote.deserializeResponse(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Message sendSticker(SendSticker sendSticker) throws TelegramApiException {
|
||||
if(sendSticker == null){
|
||||
throw new TelegramApiException("Parameter sendSticker can not be null");
|
||||
}
|
||||
assertParamNotNull(sendSticker, "sendSticker");
|
||||
|
||||
sendSticker.validate();
|
||||
String responseContent;
|
||||
try {
|
||||
String url = getBaseUrl() + SendSticker.PATH;
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(SendSticker.CHATID_FIELD, sendSticker.getChatId());
|
||||
@ -436,16 +342,10 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return sendSticker.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to send sticker", e);
|
||||
}
|
||||
|
||||
return sendSticker.deserializeResponse(responseContent);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -456,16 +356,11 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
*/
|
||||
@Override
|
||||
public final Message sendAudio(SendAudio sendAudio) throws TelegramApiException {
|
||||
if(sendAudio == null){
|
||||
throw new TelegramApiException("Parameter sendAudio can not be null");
|
||||
}
|
||||
assertParamNotNull(sendAudio, "sendAudio");
|
||||
sendAudio.validate();
|
||||
String responseContent;
|
||||
|
||||
try {
|
||||
String url = getBaseUrl() + SendAudio.PATH;
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(SendAudio.CHATID_FIELD, sendAudio.getChatId());
|
||||
if (sendAudio.isNewAudio()) {
|
||||
@ -504,16 +399,10 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return sendAudio.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to send sticker", e);
|
||||
}
|
||||
|
||||
return sendAudio.deserializeResponse(responseContent);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -525,16 +414,11 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
*/
|
||||
@Override
|
||||
public final Message sendVoice(SendVoice sendVoice) throws TelegramApiException {
|
||||
if(sendVoice == null){
|
||||
throw new TelegramApiException("Parameter sendVoice can not be null");
|
||||
}
|
||||
assertParamNotNull(sendVoice, "sendVoice");
|
||||
sendVoice.validate();
|
||||
String responseContent;
|
||||
|
||||
try {
|
||||
String url = getBaseUrl() + SendVoice.PATH;
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(SendVoice.CHATID_FIELD, sendVoice.getChatId());
|
||||
if (sendVoice.isNewVoice()) {
|
||||
@ -566,30 +450,20 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return sendVoice.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to send voice", e);
|
||||
}
|
||||
|
||||
return sendVoice.deserializeResponse(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean setChatPhoto(SetChatPhoto setChatPhoto) throws TelegramApiException {
|
||||
if(setChatPhoto == null){
|
||||
throw new TelegramApiException("Parameter setChatPhoto can not be null");
|
||||
}
|
||||
assertParamNotNull(setChatPhoto, "setChatPhoto");
|
||||
setChatPhoto.validate();
|
||||
String responseContent;
|
||||
|
||||
try {
|
||||
String url = getBaseUrl() + SetChatPhoto.PATH;
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(SetChatPhoto.CHATID_FIELD, setChatPhoto.getChatId());
|
||||
@ -601,16 +475,104 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return setChatPhoto.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to set chat photo", e);
|
||||
}
|
||||
}
|
||||
|
||||
return setChatPhoto.deserializeResponse(responseContent);
|
||||
|
||||
@Override
|
||||
public Boolean addStickerToSet(AddStickerToSet addStickerToSet) throws TelegramApiException {
|
||||
assertParamNotNull(addStickerToSet, "addStickerToSet");
|
||||
addStickerToSet.validate();
|
||||
try {
|
||||
String url = getBaseUrl() + AddStickerToSet.PATH;
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(AddStickerToSet.USERID_FIELD, addStickerToSet.getUserId().toString(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
builder.addTextBody(AddStickerToSet.NAME_FIELD, addStickerToSet.getName(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
builder.addTextBody(AddStickerToSet.EMOJIS_FIELD, addStickerToSet.getEmojis(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
if (addStickerToSet.isNewPngSticker()) {
|
||||
if (addStickerToSet.getPngStickerFile() != null) {
|
||||
builder.addBinaryBody(AddStickerToSet.PNGSTICKER_FIELD, addStickerToSet.getPngStickerFile());
|
||||
} else if (addStickerToSet.getPngStickerStream() != null) {
|
||||
builder.addBinaryBody(AddStickerToSet.PNGSTICKER_FIELD, addStickerToSet.getPngStickerStream(), ContentType.APPLICATION_OCTET_STREAM, addStickerToSet.getPngStickerName());
|
||||
} else {
|
||||
builder.addBinaryBody(AddStickerToSet.PNGSTICKER_FIELD, new java.io.File(addStickerToSet.getPngSticker()), ContentType.create("image/png"), addStickerToSet.getPngStickerName());
|
||||
}
|
||||
} else {
|
||||
builder.addTextBody(AddStickerToSet.PNGSTICKER_FIELD, addStickerToSet.getPngSticker());
|
||||
}
|
||||
if (addStickerToSet.getMaskPosition() != null) {
|
||||
builder.addTextBody(AddStickerToSet.MASKPOSITION_FIELD, objectMapper.writeValueAsString(addStickerToSet.getMaskPosition()), TEXT_PLAIN_CONTENT_TYPE);
|
||||
}
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
return addStickerToSet.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to add sticker to set", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean createNewStickerSet(CreateNewStickerSet createNewStickerSet) throws TelegramApiException {
|
||||
assertParamNotNull(createNewStickerSet, "createNewStickerSet");
|
||||
createNewStickerSet.validate();
|
||||
try {
|
||||
String url = getBaseUrl() + CreateNewStickerSet.PATH;
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(CreateNewStickerSet.USERID_FIELD, createNewStickerSet.getUserId().toString(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
builder.addTextBody(CreateNewStickerSet.NAME_FIELD, createNewStickerSet.getName(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
builder.addTextBody(CreateNewStickerSet.TITLE_FIELD, createNewStickerSet.getTitle(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
builder.addTextBody(CreateNewStickerSet.EMOJIS_FIELD, createNewStickerSet.getEmojis(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
builder.addTextBody(CreateNewStickerSet.CONTAINSMASKS_FIELD, createNewStickerSet.getContainsMasks().toString());
|
||||
if (createNewStickerSet.isNewPngSticker()) {
|
||||
if (createNewStickerSet.getPngStickerFile() != null) {
|
||||
builder.addBinaryBody(CreateNewStickerSet.PNGSTICKER_FIELD, createNewStickerSet.getPngStickerFile());
|
||||
} else if (createNewStickerSet.getPngStickerStream() != null) {
|
||||
builder.addBinaryBody(CreateNewStickerSet.PNGSTICKER_FIELD, createNewStickerSet.getPngStickerStream(), ContentType.APPLICATION_OCTET_STREAM, createNewStickerSet.getPngStickerName());
|
||||
} else {
|
||||
builder.addBinaryBody(CreateNewStickerSet.PNGSTICKER_FIELD, new java.io.File(createNewStickerSet.getPngSticker()), ContentType.create("image/png"), createNewStickerSet.getPngStickerName());
|
||||
}
|
||||
} else {
|
||||
builder.addTextBody(CreateNewStickerSet.PNGSTICKER_FIELD, createNewStickerSet.getPngSticker());
|
||||
}
|
||||
if (createNewStickerSet.getMaskPosition() != null) {
|
||||
builder.addTextBody(CreateNewStickerSet.MASKPOSITION_FIELD, objectMapper.writeValueAsString(createNewStickerSet.getMaskPosition()), TEXT_PLAIN_CONTENT_TYPE);
|
||||
}
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
return createNewStickerSet.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to create new sticker set", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File uploadStickerFile(UploadStickerFile uploadStickerFile) throws TelegramApiException {
|
||||
assertParamNotNull(uploadStickerFile, "uploadStickerFile");
|
||||
uploadStickerFile.validate();
|
||||
try {
|
||||
String url = getBaseUrl() + UploadStickerFile.PATH;
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.addTextBody(UploadStickerFile.USERID_FIELD, uploadStickerFile.getUserId().toString(), TEXT_PLAIN_CONTENT_TYPE);
|
||||
if (uploadStickerFile.getNewPngStickerFile() != null) {
|
||||
builder.addBinaryBody(UploadStickerFile.PNGSTICKER_FIELD, uploadStickerFile.getNewPngStickerFile());
|
||||
} else if (uploadStickerFile.getNewPngStickerStream() != null) {
|
||||
builder.addBinaryBody(UploadStickerFile.PNGSTICKER_FIELD, uploadStickerFile.getNewPngStickerStream(), ContentType.APPLICATION_OCTET_STREAM, uploadStickerFile.getNewPngStickerName());
|
||||
}
|
||||
HttpEntity multipart = builder.build();
|
||||
httppost.setEntity(multipart);
|
||||
|
||||
return uploadStickerFile.deserializeResponse(sendHttpPostRequest(httppost));
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to upload new sticker file", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Simplified methods
|
||||
@ -622,21 +584,11 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
method.validate();
|
||||
String url = getBaseUrl() + method.getMethod();
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
httppost.addHeader("charset", StandardCharsets.UTF_8.name());
|
||||
httppost.setEntity(new StringEntity(objectMapper.writeValueAsString(method), ContentType.APPLICATION_JSON));
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
String responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
try {
|
||||
callback.onResult(method, method.deserializeResponse(responseContent));
|
||||
} catch (TelegramApiRequestException e) {
|
||||
callback.onError(method, e);
|
||||
}
|
||||
String responseContent = sendMethodRequest(method);
|
||||
try {
|
||||
callback.onResult(method, method.deserializeResponse(responseContent));
|
||||
} catch (TelegramApiRequestException e) {
|
||||
callback.onError(method, e);
|
||||
}
|
||||
} catch (IOException | TelegramApiValidationException e) {
|
||||
callback.onException(method, e);
|
||||
@ -648,27 +600,76 @@ public abstract class DefaultAbsSender extends AbsSender {
|
||||
|
||||
@Override
|
||||
protected final <T extends Serializable, Method extends BotApiMethod<T>> T sendApiMethod(Method method) throws TelegramApiException {
|
||||
method.validate();
|
||||
String responseContent;
|
||||
try {
|
||||
String url = getBaseUrl() + method.getMethod();
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
httppost.addHeader("charset", StandardCharsets.UTF_8.name());
|
||||
httppost.setEntity(new StringEntity(objectMapper.writeValueAsString(method), ContentType.APPLICATION_JSON));
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
responseContent = EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
String responseContent = sendMethodRequest(method);
|
||||
return method.deserializeResponse(responseContent);
|
||||
} catch (IOException e) {
|
||||
throw new TelegramApiException("Unable to execute " + method.getMethod() + " method", e);
|
||||
}
|
||||
}
|
||||
|
||||
return method.deserializeResponse(responseContent);
|
||||
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 {
|
||||
method.validate();
|
||||
String url = getBaseUrl() + method.getMethod();
|
||||
HttpPost httppost = configuredHttpPost(url);
|
||||
httppost.addHeader("charset", StandardCharsets.UTF_8.name());
|
||||
httppost.setEntity(new StringEntity(objectMapper.writeValueAsString(method), ContentType.APPLICATION_JSON));
|
||||
return sendHttpPostRequest(httppost);
|
||||
}
|
||||
|
||||
private String sendHttpPostRequest(HttpPost httppost) throws IOException {
|
||||
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
|
||||
HttpEntity ht = response.getEntity();
|
||||
BufferedHttpEntity buf = new BufferedHttpEntity(ht);
|
||||
return EntityUtils.toString(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
private HttpPost configuredHttpPost(String url) {
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setConfig(requestConfig);
|
||||
return httppost;
|
||||
}
|
||||
|
||||
protected String getBaseUrl() {
|
||||
return options.getBaseUrl() + getBotToken() + "/";
|
||||
}
|
||||
|
||||
private void assertParamNotNull(Object param, String paramName) throws TelegramApiException {
|
||||
if (param == null) {
|
||||
throw new TelegramApiException("Parameter " + paramName + " can not be null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
package org.telegram.telegrambots.updatesreceivers;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
@ -21,15 +19,12 @@ import org.telegram.telegrambots.api.methods.updates.GetUpdates;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||
import org.telegram.telegrambots.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.generics.BotOptions;
|
||||
import org.telegram.telegrambots.generics.BotSession;
|
||||
import org.telegram.telegrambots.generics.LongPollingBot;
|
||||
import org.telegram.telegrambots.generics.UpdatesHandler;
|
||||
import org.telegram.telegrambots.generics.UpdatesReader;
|
||||
import org.telegram.telegrambots.generics.*;
|
||||
import org.telegram.telegrambots.logging.BotLogger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.List;
|
||||
@ -229,6 +224,8 @@ public class DefaultBotSession implements BotSession {
|
||||
BotLogger.severe(responseContent, LOGTAG, e);
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
BotLogger.fine(LOGTAG, e);
|
||||
} catch (InvalidObjectException | TelegramApiRequestException e) {
|
||||
BotLogger.severe(LOGTAG, e);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user