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.
*
@@ -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.
*
@@ -277,7 +316,8 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
// Replies can be standalone or attached to abilities, fetch those too
Stream 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 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 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 trio) {
Ability ability = trio.b();
Update update = trio.a();
diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Reply.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Reply.java
index e7479489..38677306 100644
--- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Reply.java
+++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Reply.java
@@ -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> conditions, Consumer action, String name) {
+ this(conditions, action);
+ if (Objects.nonNull(name)) {
+ enableStats(name);
+ }
+ }
+
public static Reply of(Consumer action, List> conditions) {
return new Reply(conditions, action);
}
diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/ReplyFlow.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/ReplyFlow.java
index 799a1a9b..5b0d8328 100644
--- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/ReplyFlow.java
+++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/ReplyFlow.java
@@ -20,8 +20,8 @@ public class ReplyFlow extends Reply {
private final Set nextReplies;
- private ReplyFlow(List> conditions, Consumer action, Set nextReplies) {
- super(conditions, action);
+ private ReplyFlow(List> conditions, Consumer action, Set nextReplies, String name) {
+ super(conditions, action, name);
this.nextReplies = nextReplies;
}
@@ -50,6 +50,7 @@ public class ReplyFlow extends Reply {
private List> conds;
private Consumer action;
private Set 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 pred) {
conds.add(pred);
return this;
@@ -79,7 +85,7 @@ public class ReplyFlow extends Reply {
db.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> 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 statefulAction = action.andThen(upd -> {
- Long chatId = AbilityUtils.getChatId(upd);
- db.getMap(STATES).put(chatId, id);
- });
- return new ReplyFlow(conds, statefulAction, nextReplies);
+ Consumer statefulAction;
+ if (nextReplies.size() > 0) {
+ statefulAction = action.andThen(upd -> {
+ Long chatId = AbilityUtils.getChatId(upd);
+ db.getMap(STATES).put(chatId, id);
+ });
+ } else {
+ statefulAction = action.andThen(upd -> {
+ Long chatId = AbilityUtils.getChatId(upd);
+ db.getMap(STATES).remove(chatId);
+ });
+ }
+
+ return new ReplyFlow(conds, statefulAction, nextReplies, name);
}
@NotNull
diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java
index 6382f866..6b8ca9ce 100644
--- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java
+++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java
@@ -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("_", "\\_");
}
}
\ No newline at end of file
diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java
index 476b3b1e..f6823690 100644
--- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java
+++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java
@@ -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 utilMethod) {
Arrays.stream(Update.class.getMethods())
// filter to all these methods of hasXXX (hasPoll, hasMessage, etc...)
diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/ContinuousTextTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/ContinuousTextTest.java
new file mode 100644
index 00000000..6e204625
--- /dev/null
+++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/ContinuousTextTest.java
@@ -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();
+ }
+ }
+}
\ No newline at end of file
diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/DefaultBot.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/DefaultBot.java
index 462453da..7838d07f 100644
--- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/DefaultBot.java
+++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/DefaultBot.java
@@ -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();
}
diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/ReplyFlowTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/ReplyFlowTest.java
index bb5cd9e3..b117ab7a 100644
--- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/ReplyFlowTest.java
+++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/ReplyFlowTest.java
@@ -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.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.getMap(STATES).containsKey(chatId), "User is still in a state");
+ }
+
+ @Test
+ void replyFlowsPertainNames() {
+ Set 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 hasMessageWith(String msg) {
return upd -> Flag.MESSAGE.test(upd) && upd.getMessage().getText().equalsIgnoreCase(msg);
diff --git a/telegrambots-chat-session-bot/README.md b/telegrambots-chat-session-bot/README.md
index 4b80eb7d..1802bdd4 100644
--- a/telegrambots-chat-session-bot/README.md
+++ b/telegrambots-chat-session-bot/README.md
@@ -15,7 +15,7 @@ Usage
org.telegram
telegrambots-chat-session-bot
- 4.9
+ 4.9.1
```
diff --git a/telegrambots-chat-session-bot/pom.xml b/telegrambots-chat-session-bot/pom.xml
index 715e0224..a1291c1f 100644
--- a/telegrambots-chat-session-bot/pom.xml
+++ b/telegrambots-chat-session-bot/pom.xml
@@ -7,7 +7,7 @@
org.telegram
Bots
- 4.9
+ 4.9.1
telegrambots-chat-session-bot
@@ -84,7 +84,7 @@
org.telegram
telegrambots
- 4.9
+ 4.9.1
diff --git a/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/TelegramLongPollingSessionBot.java b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/TelegramLongPollingSessionBot.java
index 8182578e..1cceff89 100644
--- a/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/TelegramLongPollingSessionBot.java
+++ b/telegrambots-chat-session-bot/src/main/java/org/telegram/telegrambots/session/TelegramLongPollingSessionBot.java
@@ -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();
diff --git a/telegrambots-extensions/README.md b/telegrambots-extensions/README.md
index 247bb691..998f63c4 100644
--- a/telegrambots-extensions/README.md
+++ b/telegrambots-extensions/README.md
@@ -16,12 +16,12 @@ Just import add the library to your project with one of these options:
org.telegram
telegrambotsextensions
- 4.9
+ 4.9.1
```
2. Using Gradle:
```gradle
- compile "org.telegram:telegrambotsextensions:4.9"
+ compile "org.telegram:telegrambotsextensions:4.9.1"
```
\ No newline at end of file
diff --git a/telegrambots-extensions/pom.xml b/telegrambots-extensions/pom.xml
index 7fde69c6..e0fdc053 100644
--- a/telegrambots-extensions/pom.xml
+++ b/telegrambots-extensions/pom.xml
@@ -7,7 +7,7 @@
org.telegram
Bots
- 4.9
+ 4.9.1
telegrambotsextensions
@@ -75,7 +75,7 @@
org.telegram
telegrambots
- 4.9
+ 4.9.1
diff --git a/telegrambots-meta/pom.xml b/telegrambots-meta/pom.xml
index 6a060936..c31ab809 100644
--- a/telegrambots-meta/pom.xml
+++ b/telegrambots-meta/pom.xml
@@ -7,7 +7,7 @@
org.telegram
Bots
- 4.9
+ 4.9.1
telegrambots-meta
diff --git a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendInvoice.java b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendInvoice.java
index 22dd87b1..5fa8debf 100644
--- a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendInvoice.java
+++ b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendInvoice.java
@@ -39,11 +39,13 @@ public class SendInvoice extends BotApiMethod {
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 {
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 {
*
* @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 {
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 {
", needPhoneNumber=" + needPhoneNumber +
", needEmail=" + needEmail +
", needShippingAddress=" + needShippingAddress +
+ ", sendPhoneNumberToProvider=" + sendPhoneNumberToProvider +
+ ", sendEmailToProvider=" + sendEmailToProvider +
", isFlexible=" + isFlexible +
", disableNotification=" + disableNotification +
", replyToMessageId=" + replyToMessageId +
diff --git a/telegrambots-spring-boot-starter/README.md b/telegrambots-spring-boot-starter/README.md
index 86cafe15..dc6b0e03 100644
--- a/telegrambots-spring-boot-starter/README.md
+++ b/telegrambots-spring-boot-starter/README.md
@@ -18,14 +18,14 @@ Usage
org.telegram
telegrambots-spring-boot-starter
- 4.1.2
+ 4.9.1
```
**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);
}
}
```
diff --git a/telegrambots-spring-boot-starter/pom.xml b/telegrambots-spring-boot-starter/pom.xml
index b9d59a0a..7155c80e 100644
--- a/telegrambots-spring-boot-starter/pom.xml
+++ b/telegrambots-spring-boot-starter/pom.xml
@@ -7,7 +7,7 @@
org.telegram
Bots
- 4.9
+ 4.9.1
telegrambots-spring-boot-starter
@@ -79,7 +79,7 @@
org.telegram
telegrambots
- 4.9
+ 4.9.1
org.springframework.boot
diff --git a/telegrambots/pom.xml b/telegrambots/pom.xml
index 03123e30..66e70503 100644
--- a/telegrambots/pom.xml
+++ b/telegrambots/pom.xml
@@ -7,7 +7,7 @@
org.telegram
Bots
- 4.9
+ 4.9.1
telegrambots
@@ -95,7 +95,7 @@
org.telegram
telegrambots-meta
- 4.9
+ 4.9.1
com.fasterxml.jackson.core