Merge commit '203b26587f771f9b9bf0f97f8df04e18612a5fe5'
This commit is contained in:
commit
73b8f90ee2
@ -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>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambots:4.9"
|
||||
compile "org.telegram:telegrambots:4.9.1"
|
||||
```
|
||||
|
||||
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.9)
|
||||
3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.9)
|
||||
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.9.1)
|
||||
3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.9.1)
|
||||
|
||||
In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`.
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
### <a id="4.9.1"></a>4.9.1 ###
|
||||
1. Bug fixing: #767, #766, #761, #763, #776, #772, #771, #780
|
||||
|
||||
### <a id="4.9"></a>4.9 ###
|
||||
1. Update Api version [4.9](https://core.telegram.org/bots/api-changelog#june-4-2020)
|
||||
2. Bug fixing: #731, #749, #752 and #753
|
||||
|
@ -243,16 +243,16 @@ This is just one way, how you can compile it (here with maven). The example belo
|
||||
Please use ```execute()``` instead.
|
||||
Example:
|
||||
```java
|
||||
SendMessage sn = new SendMessage();
|
||||
SendMessage message = new SendMessage();
|
||||
//add chat id and text
|
||||
execute(sn);
|
||||
execute(message);
|
||||
```
|
||||
|
||||
If you extend ```TelegramLongPollingCommandBot```, then use ```AbsSender.execute()``` instead.
|
||||
|
||||
|
||||
## <a id="example_webhook"></a>Is there any example for WebHook? ##
|
||||
Please see the example Bot for https://telegram.me/SnowcrashBot in the [TelegramBotsExample]() repo and also an [example bot for Sping Boot](https://github.com/UnAfraid/SpringTelegramBot) from [UnAfraid](https://github.com/UnAfraid) [here](https://github.com/UnAfraid/SpringTelegramBot/blob/master/src/main/java/com/github/unafraid/spring/bot/TelegramWebhookBot.java)
|
||||
Please see the example Bot for https://telegram.me/SnowcrashBot in the [TelegramBotsExample]() repo and also an [example bot for Sping Boot](https://github.com/UnAfraid/SpringTelegramBot) from [UnAfraid](https://github.com/UnAfraid) [here](https://github.com/UnAfraid/SpringTelegramBot/blob/master/src/main/java/com/github/unafraid/spring/bot/TelegramWebHookBot.java)
|
||||
|
||||
|
||||
|
||||
@ -268,7 +268,7 @@ public class YourApplicationMainClass {
|
||||
//Add this line to initialize bots context
|
||||
ApiContextInitializer.init();
|
||||
|
||||
SpringApplication.run(MusicUploaderApplication.class, args);
|
||||
SpringApplication.run(YourApplicationMainClass.class, args);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -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>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
* With **Gradle**:
|
||||
|
||||
```groovy
|
||||
compile group: 'org.telegram', name: 'telegrambots', version: '4.9'
|
||||
compile group: 'org.telegram', name: 'telegrambots', version: '4.9.1'
|
||||
```
|
||||
|
||||
2. Don't like **Maven Central Repository**? It can also be taken from [Jitpack](https://jitpack.io/#rubenlagus/TelegramBots).
|
||||
|
@ -33,5 +33,35 @@ As an example, if you want to restrict the updates to photos only, then you may
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Command Processing
|
||||
### Command Prefix
|
||||
Customizing the command prefix is as simple as overriding the `getCommandPrefix` method as shown below.
|
||||
```java
|
||||
@Override
|
||||
protected String getCommandPrefix() {
|
||||
return "!";
|
||||
}
|
||||
```
|
||||
|
||||
### Command Regex Split
|
||||
The method that the bot uses to capture command tokens is through the regex splitters. By default, it's set to `" "`. However, this can be customized. For example,
|
||||
if you'd like to split on digits and whitespaces, then you may do the following:
|
||||
```java
|
||||
@Override
|
||||
protected String getCommandRegexSplit() {
|
||||
return "\\s\\d";
|
||||
}
|
||||
```
|
||||
### Commands with Continuous Text
|
||||
Feeling ambitious? You may allow your bot to process tokens that are technically attached to your command. Imagine you have a command
|
||||
`/do` and you'd like users to send commands as `/do1` and still trigger the `do` ability. In order to do that, override the `allowContinuousText` function.
|
||||
```java
|
||||
@Override
|
||||
protected boolean allowContinuousText() {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
Please note that this may cause ability overlap. If multiple abilities can match the same command, the longest match will be taken. For example,
|
||||
if you have two abilities `do` and `do1`, the command `/do1` will trigger the `do1` ability.
|
||||
## Statistics
|
||||
AbilityBot can accrue basic statistics about the usage of your abilities and replies. Simply `enableStats()` on an Ability builder or `enableStats(<name>)` on replies to activate this feature. Once activated, you may call `/stats` and the bot will print a basic list of statistics. At the moment, AbilityBot only tracks hits. In the future, this will be enhanced to track more stats.
|
@ -9,12 +9,12 @@ As with any Java project, you will need to set your dependencies.
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-abilities</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
* **Gradle**
|
||||
```groovy
|
||||
implementation group: 'org.telegram', name: 'telegrambots-abilities', version: '4.9'
|
||||
implementation group: 'org.telegram', name: 'telegrambots-abilities', version: '4.9.1'
|
||||
```
|
||||
* [JitPack](https://jitpack.io/#rubenlagus/TelegramBots)
|
||||
|
||||
|
2
pom.xml
2
pom.xml
@ -7,7 +7,7 @@
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
|
||||
<modules>
|
||||
<module>telegrambots</module>
|
||||
|
@ -18,19 +18,19 @@ Usage
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-abilities</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Gradle**
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambots-abilities:4.9"
|
||||
compile "org.telegram:telegrambots-abilities:4.9.1"
|
||||
```
|
||||
|
||||
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.9)
|
||||
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.9.1)
|
||||
|
||||
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.9)
|
||||
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.9.1)
|
||||
|
||||
Motivation
|
||||
----------
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots-abilities</artifactId>
|
||||
@ -84,7 +84,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
@ -3,9 +3,9 @@ package org.telegram.abilitybots.api.bot;
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
import org.telegram.abilitybots.api.toggle.AbilityToggle;
|
||||
import org.telegram.abilitybots.api.toggle.DefaultToggle;
|
||||
import org.telegram.telegrambots.bots.DefaultAbsSender;
|
||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.meta.generics.LongPollingBot;
|
||||
import org.telegram.telegrambots.util.WebhookUtils;
|
||||
@ -13,7 +13,7 @@ import org.telegram.telegrambots.util.WebhookUtils;
|
||||
import static org.telegram.abilitybots.api.db.MapDBContext.onlineInstance;
|
||||
|
||||
/**
|
||||
* The default AbilityBot class implements {@link LongPollingBot}. It delegates all updates to a {@link TelegramLongPollingBot} instance.
|
||||
* The default AbilityBot class implements {@link LongPollingBot}. It delegates all updates to a {@link DefaultAbsSender} instance.
|
||||
*
|
||||
* @author Abbas Abou Daya
|
||||
*/
|
||||
|
@ -3,7 +3,6 @@ package org.telegram.abilitybots.api.bot;
|
||||
import com.google.common.collect.*;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
@ -18,7 +17,6 @@ import org.telegram.abilitybots.api.util.Pair;
|
||||
import org.telegram.abilitybots.api.util.Trio;
|
||||
import org.telegram.telegrambots.bots.DefaultAbsSender;
|
||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
||||
import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators;
|
||||
import org.telegram.telegrambots.meta.api.objects.Message;
|
||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||
@ -27,6 +25,7 @@ import org.telegram.telegrambots.meta.api.objects.User;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
@ -37,6 +36,8 @@ import static com.google.common.collect.Sets.difference;
|
||||
import static java.lang.String.format;
|
||||
import static java.time.ZonedDateTime.now;
|
||||
import static java.util.Arrays.stream;
|
||||
import static java.util.Comparator.comparingInt;
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Optional.ofNullable;
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static java.util.regex.Pattern.compile;
|
||||
@ -51,7 +52,7 @@ 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}.
|
||||
* It's important to note that this bot strictly extends {@link DefaultAbsSender}.
|
||||
* <p>
|
||||
* All bots extending the {@link BaseAbilityBot} get implicit abilities:
|
||||
* <ul>
|
||||
@ -130,35 +131,35 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
||||
/**
|
||||
* @return the map of <ID,User>
|
||||
*/
|
||||
protected Map<Integer, User> users() {
|
||||
public Map<Integer, User> users() {
|
||||
return db.getMap(USERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the map of <Username,ID>
|
||||
*/
|
||||
protected Map<String, Integer> userIds() {
|
||||
public Map<String, Integer> userIds() {
|
||||
return db.getMap(USER_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a blacklist containing all the IDs of the banned users
|
||||
*/
|
||||
protected Set<Integer> blacklist() {
|
||||
public Set<Integer> blacklist() {
|
||||
return db.getSet(BLACKLIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an admin set of all the IDs of bot administrators
|
||||
*/
|
||||
protected Set<Integer> admins() {
|
||||
public Set<Integer> admins() {
|
||||
return db.getSet(ADMINS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a mapping of ability and reply names to their corresponding statistics
|
||||
*/
|
||||
protected Map<String, Stats> stats() {
|
||||
public Map<String, Stats> stats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
@ -221,6 +222,32 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
||||
return botUsername;
|
||||
}
|
||||
|
||||
public Privacy getPrivacy(Update update, int id) {
|
||||
return isCreator(id) ?
|
||||
CREATOR : isAdmin(id) ?
|
||||
ADMIN : (isGroupUpdate(update) || isSuperGroupUpdate(update)) && isGroupAdmin(update, id) ?
|
||||
GROUP_ADMIN : PUBLIC;
|
||||
}
|
||||
|
||||
public boolean isGroupAdmin(Update update, int id) {
|
||||
return isGroupAdmin(getChatId(update), id);
|
||||
}
|
||||
|
||||
public boolean isGroupAdmin(long chatId, int id) {
|
||||
GetChatAdministrators admins = new GetChatAdministrators().setChatId(chatId);
|
||||
return silent.execute(admins)
|
||||
.orElse(new ArrayList<>()).stream()
|
||||
.anyMatch(member -> member.getUser().getId() == id);
|
||||
}
|
||||
|
||||
public boolean isCreator(int id) {
|
||||
return id == creatorId();
|
||||
}
|
||||
|
||||
public boolean isAdmin(Integer id) {
|
||||
return admins().contains(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the update against the provided global flags. The default implementation is a passthrough to all updates.
|
||||
* <p>
|
||||
@ -233,6 +260,18 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
||||
return true;
|
||||
}
|
||||
|
||||
protected String getCommandPrefix() {
|
||||
return "/";
|
||||
}
|
||||
|
||||
protected String getCommandRegexSplit() {
|
||||
return " ";
|
||||
}
|
||||
|
||||
protected boolean allowContinuousText() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the declared abilities using method reflection. Also, replies are accumulated using the built abilities and standalone methods that return a Reply.
|
||||
* <p>
|
||||
@ -277,7 +316,8 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
||||
|
||||
// Replies can be standalone or attached to abilities, fetch those too
|
||||
Stream<Reply> abilityReplies = abilities.values().stream()
|
||||
.flatMap(ability -> ability.replies().stream());
|
||||
.flatMap(ability -> ability.replies().stream())
|
||||
.flatMap(Reply::stream);
|
||||
|
||||
// Now create the replies registry (list)
|
||||
replies = Stream.concat(abilityReplies, extensionReplies).collect(
|
||||
@ -401,8 +441,12 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
||||
}
|
||||
|
||||
boolean checkBlacklist(Update update) {
|
||||
Integer id = AbilityUtils.getUser(update).getId();
|
||||
User user = getUser(update);
|
||||
if (isNull(user)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int id = user.getId();
|
||||
return id == creatorId() || !blacklist().contains(id);
|
||||
}
|
||||
|
||||
@ -458,30 +502,6 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
||||
return isOk;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Privacy getPrivacy(Update update, int id) {
|
||||
return isCreator(id) ?
|
||||
CREATOR : isAdmin(id) ?
|
||||
ADMIN : (isGroupUpdate(update) || isSuperGroupUpdate(update)) && isGroupAdmin(update, id) ?
|
||||
GROUP_ADMIN : PUBLIC;
|
||||
}
|
||||
|
||||
private boolean isGroupAdmin(Update update, int id) {
|
||||
GetChatAdministrators admins = new GetChatAdministrators().setChatId(getChatId(update));
|
||||
|
||||
return silent.execute(admins)
|
||||
.orElse(new ArrayList<>()).stream()
|
||||
.anyMatch(member -> member.getUser().getId() == id);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -493,17 +513,28 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
||||
if (!update.hasMessage() || !msg.hasText())
|
||||
return Trio.of(update, abilities.get(DEFAULT), new String[]{});
|
||||
|
||||
String[] tokens = msg.getText().split(" ");
|
||||
|
||||
if (tokens[0].startsWith("/")) {
|
||||
String abilityToken = stripBotUsername(tokens[0].substring(1)).toLowerCase();
|
||||
Ability ability = abilities.get(abilityToken);
|
||||
tokens = Arrays.copyOfRange(tokens, 1, tokens.length);
|
||||
return Trio.of(update, ability, tokens);
|
||||
Ability ability;
|
||||
String[] tokens;
|
||||
if (allowContinuousText()) {
|
||||
String abName = abilities.keySet().stream()
|
||||
.filter(name -> msg.getText().startsWith(format("%s%s", getCommandPrefix(), name)))
|
||||
.max(comparingInt(String::length))
|
||||
.orElse(DEFAULT);
|
||||
tokens = msg.getText()
|
||||
.replaceFirst(getCommandPrefix() + abName, "")
|
||||
.split(getCommandRegexSplit());
|
||||
ability = abilities.get(abName);
|
||||
} else {
|
||||
Ability ability = abilities.get(DEFAULT);
|
||||
return Trio.of(update, ability, tokens);
|
||||
tokens = msg.getText().split(getCommandRegexSplit());
|
||||
if (tokens[0].startsWith(getCommandPrefix())) {
|
||||
String abilityToken = stripBotUsername(tokens[0].substring(1)).toLowerCase();
|
||||
ability = abilities.get(abilityToken);
|
||||
tokens = Arrays.copyOfRange(tokens, 1, tokens.length);
|
||||
} else {
|
||||
ability = abilities.get(DEFAULT);
|
||||
}
|
||||
}
|
||||
return Trio.of(update, ability, tokens);
|
||||
}
|
||||
|
||||
private String stripBotUsername(String token) {
|
||||
@ -556,15 +587,25 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
||||
|
||||
boolean filterReply(Update update) {
|
||||
return replies.stream()
|
||||
.filter(reply -> reply.isOkFor(update))
|
||||
.map(reply -> {
|
||||
.filter(reply -> runSilently(() -> reply.isOkFor(update), reply.name()))
|
||||
.map(reply -> runSilently(() -> {
|
||||
reply.actOn(update);
|
||||
updateReplyStats(reply);
|
||||
return false;
|
||||
})
|
||||
}, reply.name()))
|
||||
.reduce(true, Boolean::logicalAnd);
|
||||
}
|
||||
|
||||
boolean runSilently(Callable<Boolean> callable, String name) {
|
||||
try {
|
||||
return callable.call();
|
||||
} catch(Exception ex) {
|
||||
log.error(format("Reply [%s] failed to check for conditions. " +
|
||||
"Make sure you're safeguarding against all possible updates.", name));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean checkMessageFlags(Trio<Update, Ability, String[]> trio) {
|
||||
Ability ability = trio.b();
|
||||
Update update = trio.a();
|
||||
|
@ -2,10 +2,8 @@ package org.telegram.abilitybots.api.objects;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
@ -14,7 +12,6 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
/**
|
||||
* A reply consists of update conditionals and an action to be applied on the update.
|
||||
@ -37,6 +34,13 @@ public class Reply {
|
||||
statsEnabled = false;
|
||||
}
|
||||
|
||||
Reply(List<Predicate<Update>> conditions, Consumer<Update> action, String name) {
|
||||
this(conditions, action);
|
||||
if (Objects.nonNull(name)) {
|
||||
enableStats(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static Reply of(Consumer<Update> action, List<Predicate<Update>> conditions) {
|
||||
return new Reply(conditions, action);
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ public class ReplyFlow extends Reply {
|
||||
|
||||
private final Set<Reply> nextReplies;
|
||||
|
||||
private ReplyFlow(List<Predicate<Update>> conditions, Consumer<Update> action, Set<Reply> nextReplies) {
|
||||
super(conditions, action);
|
||||
private ReplyFlow(List<Predicate<Update>> conditions, Consumer<Update> action, Set<Reply> nextReplies, String name) {
|
||||
super(conditions, action, name);
|
||||
this.nextReplies = nextReplies;
|
||||
}
|
||||
|
||||
@ -50,6 +50,7 @@ public class ReplyFlow extends Reply {
|
||||
private List<Predicate<Update>> conds;
|
||||
private Consumer<Update> action;
|
||||
private Set<Reply> nextReplies;
|
||||
private String name;
|
||||
|
||||
private ReplyFlowBuilder(DBContext db, int id) {
|
||||
conds = new ArrayList<>();
|
||||
@ -67,6 +68,11 @@ public class ReplyFlow extends Reply {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplyFlowBuilder enableStats(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReplyFlowBuilder onlyIf(Predicate<Update> pred) {
|
||||
conds.add(pred);
|
||||
return this;
|
||||
@ -79,7 +85,7 @@ public class ReplyFlow extends Reply {
|
||||
db.<Long, Integer>getMap(STATES).remove(chatId);
|
||||
});
|
||||
|
||||
Reply statefulReply = Reply.of(statefulAction, statefulConditions);
|
||||
Reply statefulReply = new Reply(statefulConditions, statefulAction, nextReply.name());
|
||||
nextReplies.add(statefulReply);
|
||||
return this;
|
||||
}
|
||||
@ -87,7 +93,7 @@ public class ReplyFlow extends Reply {
|
||||
public ReplyFlowBuilder next(ReplyFlow nextReplyFlow) {
|
||||
List<Predicate<Update>> statefulConditions = toStateful(nextReplyFlow.conditions());
|
||||
|
||||
ReplyFlow statefulReplyFlow = new ReplyFlow(statefulConditions, nextReplyFlow.action(), nextReplyFlow.nextReplies());
|
||||
ReplyFlow statefulReplyFlow = new ReplyFlow(statefulConditions, nextReplyFlow.action(), nextReplyFlow.nextReplies(), nextReplyFlow.name());
|
||||
nextReplies.add(statefulReplyFlow);
|
||||
return this;
|
||||
}
|
||||
@ -95,12 +101,21 @@ public class ReplyFlow extends Reply {
|
||||
public ReplyFlow build() {
|
||||
if (action == null)
|
||||
action = upd -> {};
|
||||
Consumer<Update> statefulAction = action.andThen(upd -> {
|
||||
Long chatId = AbilityUtils.getChatId(upd);
|
||||
db.<Long, Integer>getMap(STATES).put(chatId, id);
|
||||
});
|
||||
|
||||
return new ReplyFlow(conds, statefulAction, nextReplies);
|
||||
Consumer<Update> statefulAction;
|
||||
if (nextReplies.size() > 0) {
|
||||
statefulAction = action.andThen(upd -> {
|
||||
Long chatId = AbilityUtils.getChatId(upd);
|
||||
db.<Long, Integer>getMap(STATES).put(chatId, id);
|
||||
});
|
||||
} else {
|
||||
statefulAction = action.andThen(upd -> {
|
||||
Long chatId = AbilityUtils.getChatId(upd);
|
||||
db.<Long, Integer>getMap(STATES).remove(chatId);
|
||||
});
|
||||
}
|
||||
|
||||
return new ReplyFlow(conds, statefulAction, nextReplies, name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -17,6 +17,7 @@ import java.util.function.Predicate;
|
||||
import static java.util.ResourceBundle.Control.FORMAT_PROPERTIES;
|
||||
import static java.util.ResourceBundle.Control.getNoFallbackControl;
|
||||
import static java.util.ResourceBundle.getBundle;
|
||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
||||
import static org.telegram.abilitybots.api.objects.Flag.*;
|
||||
|
||||
@ -57,6 +58,10 @@ public final class AbilityUtils {
|
||||
* @throws IllegalStateException if the user could not be found
|
||||
*/
|
||||
public static User getUser(Update update) {
|
||||
return defaultIfNull(getUserElseThrow(update), EMPTY_USER);
|
||||
}
|
||||
|
||||
private static User getUserElseThrow(Update update) {
|
||||
if (MESSAGE.test(update)) {
|
||||
return update.getMessage().getFrom();
|
||||
} else if (CALLBACK_QUERY.test(update)) {
|
||||
@ -199,16 +204,16 @@ public final class AbilityUtils {
|
||||
return update -> update.getMessage().getReplyToMessage().getText().equals(msg);
|
||||
}
|
||||
|
||||
public static String getLocalizedMessage(String messageCode, Locale locale, Object...arguments) {
|
||||
public static String getLocalizedMessage(String messageCode, Locale locale, Object... arguments) {
|
||||
ResourceBundle bundle;
|
||||
if (locale == null) {
|
||||
bundle = getBundle("messages", Locale.ROOT);
|
||||
} else {
|
||||
try {
|
||||
bundle = getBundle(
|
||||
"messages",
|
||||
locale,
|
||||
getNoFallbackControl(FORMAT_PROPERTIES));
|
||||
"messages",
|
||||
locale,
|
||||
getNoFallbackControl(FORMAT_PROPERTIES));
|
||||
} catch (MissingResourceException e) {
|
||||
bundle = getBundle("messages", Locale.ROOT);
|
||||
}
|
||||
@ -217,7 +222,7 @@ public final class AbilityUtils {
|
||||
return MessageFormat.format(message, arguments);
|
||||
}
|
||||
|
||||
public static String getLocalizedMessage(String messageCode, String languageCode, Object...arguments){
|
||||
public static String getLocalizedMessage(String messageCode, String languageCode, Object... arguments) {
|
||||
Locale locale = Strings.isNullOrEmpty(languageCode) ? null : Locale.forLanguageTag(languageCode);
|
||||
return getLocalizedMessage(messageCode, locale, arguments);
|
||||
}
|
||||
@ -247,8 +252,8 @@ public final class AbilityUtils {
|
||||
* 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
|
||||
* @param user
|
||||
* @return the full name of the user
|
||||
*/
|
||||
public static String fullName(User user) {
|
||||
StringJoiner name = new StringJoiner(" ");
|
||||
@ -262,6 +267,6 @@ public final class AbilityUtils {
|
||||
}
|
||||
|
||||
public static String escape(String username) {
|
||||
return username.replace("_", "\\_");
|
||||
return username.replace("_", "\\_");
|
||||
}
|
||||
}
|
@ -644,6 +644,21 @@ public class AbilityBotTest {
|
||||
verify(silent, times(1)).send(expected, GROUP_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
void canProcessChannelPosts() {
|
||||
Update update = mock(Update.class);
|
||||
Message message = mock(Message.class);
|
||||
when(message.getChatId()).thenReturn(1L);
|
||||
|
||||
when(update.getChannelPost()).thenReturn(message);
|
||||
when(update.hasChannelPost()).thenReturn(true);
|
||||
|
||||
bot.onUpdateReceived(update);
|
||||
|
||||
String expected = "test channel post";
|
||||
verify(silent, times(1)).send(expected, 1);
|
||||
}
|
||||
|
||||
private void handlesAllUpdates(Consumer<Update> utilMethod) {
|
||||
Arrays.stream(Update.class.getMethods())
|
||||
// filter to all these methods of hasXXX (hasPoll, hasMessage, etc...)
|
||||
|
@ -0,0 +1,102 @@
|
||||
package org.telegram.abilitybots.api.bot;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
import org.telegram.abilitybots.api.objects.Ability;
|
||||
import org.telegram.abilitybots.api.sender.SilentSender;
|
||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||
import org.telegram.telegrambots.meta.api.objects.User;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
import static org.telegram.abilitybots.api.bot.TestUtils.mockFullUpdate;
|
||||
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
|
||||
import static org.telegram.abilitybots.api.objects.Ability.builder;
|
||||
import static org.telegram.abilitybots.api.objects.Locality.ALL;
|
||||
import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC;
|
||||
|
||||
public class ContinuousTextTest {
|
||||
private static final User USER = new User(1, "first", false, "last", "username", null);
|
||||
|
||||
private DBContext db;
|
||||
|
||||
private SilentSender silent;
|
||||
private ContinuousTextBot bot;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
db = offlineInstance("db");
|
||||
bot = new ContinuousTextBot(EMPTY, EMPTY, db);
|
||||
silent = mock(SilentSender.class);
|
||||
bot.silent = silent;
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() throws IOException {
|
||||
db.clear();
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void processesContinuousText() {
|
||||
Update update = mockFullUpdate(bot, USER, "/do2");
|
||||
|
||||
bot.onUpdateReceived(update);
|
||||
|
||||
verify(silent, times(1))
|
||||
.send("2", USER.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesLongestAbilityName() {
|
||||
Update update = mockFullUpdate(bot, USER, "/do1");
|
||||
|
||||
bot.onUpdateReceived(update);
|
||||
|
||||
verify(silent, times(1))
|
||||
.send("longer ability name", USER.getId());
|
||||
}
|
||||
|
||||
public static class ContinuousTextBot extends AbilityBot {
|
||||
|
||||
public ContinuousTextBot(String token, String username, DBContext db) {
|
||||
super(token, username, db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int creatorId() {
|
||||
return 1337;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean allowContinuousText() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Ability continuousTextAbility() {
|
||||
return builder()
|
||||
.name("do")
|
||||
.privacy(PUBLIC)
|
||||
.locality(ALL)
|
||||
.input(0)
|
||||
.action(ctx -> silent.send(ctx.firstArg(), ctx.chatId()))
|
||||
.build();
|
||||
}
|
||||
|
||||
public Ability continuousTextSimilarAbility() {
|
||||
return builder()
|
||||
.name("do1")
|
||||
.privacy(PUBLIC)
|
||||
.locality(ALL)
|
||||
.input(0)
|
||||
.action(ctx -> silent.send("longer ability name", ctx.chatId()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package org.telegram.abilitybots.api.bot;
|
||||
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.objects.Flag;
|
||||
import org.telegram.abilitybots.api.objects.Reply;
|
||||
import org.telegram.abilitybots.api.toggle.AbilityToggle;
|
||||
|
||||
@ -72,6 +73,12 @@ public class DefaultBot extends AbilityBot {
|
||||
.build();
|
||||
}
|
||||
|
||||
public Reply channelPostReply() {
|
||||
return Reply.of(
|
||||
upd -> silent.send("test channel post", upd.getChannelPost().getChatId()), Flag.CHANNEL_POST
|
||||
);
|
||||
}
|
||||
|
||||
public Ability testAbility() {
|
||||
return getDefaultBuilder().build();
|
||||
}
|
||||
|
@ -5,17 +5,18 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
import org.telegram.abilitybots.api.objects.Flag;
|
||||
import org.telegram.abilitybots.api.objects.Reply;
|
||||
import org.telegram.abilitybots.api.objects.ReplyFlow;
|
||||
import org.telegram.abilitybots.api.objects.*;
|
||||
import org.telegram.abilitybots.api.sender.MessageSender;
|
||||
import org.telegram.abilitybots.api.sender.SilentSender;
|
||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||
import org.telegram.telegrambots.meta.api.objects.polls.Poll;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
@ -122,6 +123,33 @@ public class ReplyFlowTest {
|
||||
assertTrue(bot.filterReply(update));
|
||||
}
|
||||
|
||||
@Test
|
||||
void replyFlowsAreWorkingWhenDefinedInAbilities() {
|
||||
Update update1 = mockFullUpdate(bot, USER, "one");
|
||||
Update update2 = mockFullUpdate(bot, USER, "two");
|
||||
long chatId = getChatId(update1);
|
||||
|
||||
// Trigger and verify first reply stage
|
||||
assertFalse(bot.filterReply(update1));
|
||||
|
||||
verify(silent, only()).send("First reply", chatId);
|
||||
assertTrue(db.<Long, Integer>getMap(STATES).containsKey(chatId), "User is not in initial state");
|
||||
// Resetting the mock now helps with verification later
|
||||
reset(silent);
|
||||
|
||||
// Trigger and verify second reply stage
|
||||
assertFalse(bot.filterReply(update2));
|
||||
|
||||
verify(silent, only()).send("Second reply", chatId);
|
||||
assertFalse(db.<Long, Integer>getMap(STATES).containsKey(chatId), "User is still in a state");
|
||||
}
|
||||
|
||||
@Test
|
||||
void replyFlowsPertainNames() {
|
||||
Set<String> replyNames = bot.replies().stream().map(Reply::name).collect(Collectors.toSet());
|
||||
assertTrue(replyNames.containsAll(newHashSet("FIRST", "SECOND")));
|
||||
}
|
||||
|
||||
public static class ReplyFlowBot extends AbilityBot {
|
||||
|
||||
private ReplyFlowBot(String botToken, String botUsername, DBContext db) {
|
||||
@ -153,6 +181,43 @@ public class ReplyFlowTest {
|
||||
.build();
|
||||
}
|
||||
|
||||
public Reply errantReply() {
|
||||
return Reply.of(
|
||||
upd -> {
|
||||
throw new RuntimeException("Throwing an exception inside the update consumer");
|
||||
},
|
||||
upd -> {
|
||||
throw new RuntimeException("Throwing an exception inside the reply conditions (flags)");
|
||||
});
|
||||
}
|
||||
|
||||
public Ability replyFlowsWithAbility() {
|
||||
Reply replyWithVk = ReplyFlow.builder(db, 2)
|
||||
.enableStats("SECOND")
|
||||
.action(upd -> {
|
||||
silent.send("Second reply", upd.getMessage().getChatId());
|
||||
})
|
||||
.onlyIf(hasMessageWith("two"))
|
||||
.build();
|
||||
|
||||
Reply replyWithNickname = ReplyFlow.builder(db, 1)
|
||||
.enableStats("FIRST")
|
||||
.action(upd -> {
|
||||
silent.send("First reply", upd.getMessage().getChatId());
|
||||
})
|
||||
.onlyIf(hasMessageWith("one"))
|
||||
.next(replyWithVk)
|
||||
.build();
|
||||
|
||||
return Ability.builder()
|
||||
.name("trigger")
|
||||
.privacy(Privacy.PUBLIC)
|
||||
.locality(Locality.ALL)
|
||||
.action(ctx -> silent.send("I'm in an ability", ctx.chatId()))
|
||||
.reply(replyWithNickname)
|
||||
.build();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Predicate<Update> hasMessageWith(String msg) {
|
||||
return upd -> Flag.MESSAGE.test(upd) && upd.getMessage().getText().equalsIgnoreCase(msg);
|
||||
|
@ -15,7 +15,7 @@ Usage
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-chat-session-bot</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots-chat-session-bot</artifactId>
|
||||
@ -84,7 +84,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
|
||||
|
@ -5,6 +5,8 @@ import org.apache.shiro.session.UnknownSessionException;
|
||||
import org.apache.shiro.session.mgt.DefaultSessionManager;
|
||||
import org.apache.shiro.session.mgt.SessionContext;
|
||||
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
|
||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||
import org.telegram.telegrambots.meta.ApiContext;
|
||||
import org.telegram.telegrambots.meta.api.objects.Message;
|
||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
||||
@ -22,6 +24,10 @@ public abstract class TelegramLongPollingSessionBot extends TelegramLongPollingB
|
||||
}
|
||||
|
||||
public TelegramLongPollingSessionBot(ChatIdConverter chatIdConverter){
|
||||
this(chatIdConverter, ApiContext.getInstance(DefaultBotOptions.class));
|
||||
}
|
||||
|
||||
public TelegramLongPollingSessionBot(ChatIdConverter chatIdConverter, DefaultBotOptions defaultBotOptions){
|
||||
this.setSessionManager(new DefaultSessionManager());
|
||||
this.setChatIdConverter(chatIdConverter);
|
||||
AbstractSessionDAO sessionDAO = (AbstractSessionDAO) sessionManager.getSessionDAO();
|
||||
|
@ -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>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
2. Using Gradle:
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambotsextensions:4.9"
|
||||
compile "org.telegram:telegrambotsextensions:4.9.1"
|
||||
```
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambotsextensions</artifactId>
|
||||
@ -75,7 +75,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots-meta</artifactId>
|
||||
|
@ -39,11 +39,13 @@ public class SendInvoice extends BotApiMethod<Message> {
|
||||
private static final String NEED_PHONE_NUMBER_FIELD = "need_phone_number";
|
||||
private static final String NEED_EMAIL_FIELD = "need_email";
|
||||
private static final String NEED_SHIPPING_ADDRESS_FIELD = "need_shipping_address";
|
||||
private static final String SEND_PHONE_NUMBER_TO_PROVIDER_FIELD = "send_phone_number_to_provider";
|
||||
private static final String SEND_EMAIL_TO_PROVIDER_FIELD = "send_email_to_provider";
|
||||
private static final String IS_FLEXIBLE_FIELD = "is_flexible";
|
||||
private static final String DISABLE_NOTIFICATION_FIELD = "disable_notification";
|
||||
private static final String REPLY_TO_MESSAGE_ID_FIELD = "reply_to_message_id";
|
||||
private static final String REPLY_MARKUP_FIELD = "reply_markup";
|
||||
private static final String PRIVIDER_DATA_FIELD = "provider_data";
|
||||
private static final String PROVIDER_DATA_FIELD = "provider_data";
|
||||
|
||||
@JsonProperty(CHATID_FIELD)
|
||||
private Integer chatId; ///< Unique identifier for the target private chat
|
||||
@ -87,6 +89,11 @@ public class SendInvoice extends BotApiMethod<Message> {
|
||||
private Boolean disableNotification; ///< Optional. Sends the message silently. Users will receive a notification with no sound.
|
||||
@JsonProperty(REPLY_TO_MESSAGE_ID_FIELD)
|
||||
private Integer replyToMessageId; ///< Optional. If the message is a reply, ID of the original message
|
||||
|
||||
@JsonProperty(SEND_PHONE_NUMBER_TO_PROVIDER_FIELD)
|
||||
private Boolean sendPhoneNumberToProvider; ///< Optional. Pass True, if user's phone number should be sent to provider
|
||||
@JsonProperty(SEND_EMAIL_TO_PROVIDER_FIELD)
|
||||
private Boolean sendEmailToProvider; ///< Optional. Pass True, if user's email address should be sent to provider
|
||||
/**
|
||||
* Optional. A JSON-serialized object for an inline keyboard.
|
||||
*
|
||||
@ -99,11 +106,10 @@ public class SendInvoice extends BotApiMethod<Message> {
|
||||
*
|
||||
* @note A detailed description of required fields should be provided by the payment provider.
|
||||
*/
|
||||
@JsonProperty(PRIVIDER_DATA_FIELD)
|
||||
@JsonProperty(PROVIDER_DATA_FIELD)
|
||||
private String providerData;
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Build an empty SendInvoice object
|
||||
*/
|
||||
public SendInvoice() {
|
||||
@ -277,6 +283,20 @@ public class SendInvoice extends BotApiMethod<Message> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getSendPhoneNumberToProvider() { return sendPhoneNumberToProvider; }
|
||||
|
||||
public SendInvoice setSendPhoneNumberToProvider(Boolean sendPhoneNumberToProvider) {
|
||||
this.sendPhoneNumberToProvider = sendPhoneNumberToProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getSendEmailToProvider() { return sendEmailToProvider; }
|
||||
|
||||
public SendInvoice setSendEmailToProvider(Boolean sendEmailToProvider) {
|
||||
this.sendEmailToProvider = sendEmailToProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getFlexible() {
|
||||
return isFlexible;
|
||||
}
|
||||
@ -396,6 +416,8 @@ public class SendInvoice extends BotApiMethod<Message> {
|
||||
", needPhoneNumber=" + needPhoneNumber +
|
||||
", needEmail=" + needEmail +
|
||||
", needShippingAddress=" + needShippingAddress +
|
||||
", sendPhoneNumberToProvider=" + sendPhoneNumberToProvider +
|
||||
", sendEmailToProvider=" + sendEmailToProvider +
|
||||
", isFlexible=" + isFlexible +
|
||||
", disableNotification=" + disableNotification +
|
||||
", replyToMessageId=" + replyToMessageId +
|
||||
|
@ -18,14 +18,14 @@ Usage
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-spring-boot-starter</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Gradle**
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambots-spring-boot-starter:4.1.2"
|
||||
compile "org.telegram:telegrambots-spring-boot-starter:4.9.1"
|
||||
```
|
||||
|
||||
Motivation
|
||||
@ -45,7 +45,7 @@ public class YourApplicationMainClass {
|
||||
//Add this line to initialize bots context
|
||||
ApiContextInitializer.init();
|
||||
|
||||
SpringApplication.run(MusicUploaderApplication.class, args);
|
||||
SpringApplication.run(YourApplicationMainClass.class, args);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots-spring-boot-starter</artifactId>
|
||||
@ -79,7 +79,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots</artifactId>
|
||||
@ -95,7 +95,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-meta</artifactId>
|
||||
<version>4.9</version>
|
||||
<version>4.9.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
|
Loading…
Reference in New Issue
Block a user