add multiple reply declaration support

This commit is contained in:
Valentin Afanasiev 2021-01-25 19:57:48 +03:00
parent 6342d1ff4e
commit aac8afe209
4 changed files with 140 additions and 49 deletions

View File

@ -350,13 +350,22 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
.map(returnReply(ext))) .map(returnReply(ext)))
.flatMap(Reply::stream); .flatMap(Reply::stream);
Stream<Reply> extensionCollectionReplies = extensions.stream()
.flatMap(extension -> stream(extension.getClass().getMethods())
.filter(checkReturnType(ReplyCollection.class))
.map(returnReplyCollection(extension))
.map(ReplyCollection::getReplies))
.flatMap(Collection::stream);
// Replies can be standalone or attached to abilities, fetch those too // Replies can be standalone or attached to abilities, fetch those too
Stream<Reply> abilityReplies = abilities.values().stream() Stream<Reply> abilityReplies = abilities.values().stream()
.flatMap(ability -> ability.replies().stream()) .flatMap(ability -> ability.replies().stream())
.flatMap(Reply::stream); .flatMap(Reply::stream);
// Now create the replies registry (list) // Now create the replies registry (list)
replies = Stream.concat(abilityReplies, extensionReplies).collect( replies = Stream.of(abilityReplies, extensionReplies, extensionCollectionReplies)
.flatMap(replyStream -> replyStream)
.collect(
ImmutableList::<Reply>builder, ImmutableList::<Reply>builder,
Builder::add, Builder::add,
(b1, b2) -> b1.addAll(b2.build())) (b1, b2) -> b1.addAll(b2.build()))
@ -439,6 +448,23 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
}; };
} }
/**
* Invokes the method and retrieves its return {@link ReplyCollection}.
*
* @param obj a bot or extension that this method is invoked with
* @return a {@link Function} which returns the {@link ReplyCollection} returned by the given method
*/
private static Function<? super Method, ReplyCollection> returnReplyCollection(Object obj) {
return method -> {
try {
return (ReplyCollection) method.invoke(obj);
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("Could not add Reply Collection", e);
throw new RuntimeException(e);
}
};
}
private void postConsumption(Pair<MessageContext, Ability> pair) { private void postConsumption(Pair<MessageContext, Ability> pair) {
ofNullable(pair.b().postAction()) ofNullable(pair.b().postAction())
.ifPresent(consumer -> consumer.accept(pair.a())); .ifPresent(consumer -> consumer.accept(pair.a()));

View File

@ -0,0 +1,17 @@
package org.telegram.abilitybots.api.objects;
import java.util.Collection;
public class ReplyCollection {
public final Collection<Reply> replies;
public ReplyCollection(Collection<Reply> replies) {
this.replies = replies;
}
public Collection<Reply> getReplies() {
return replies;
}
}

View File

@ -40,7 +40,7 @@ import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.mockito.internal.verification.VerificationModeFactory.times;
import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder; import static org.telegram.abilitybots.api.bot.DefaultBot.*;
import static org.telegram.abilitybots.api.bot.TestUtils.CREATOR; import static org.telegram.abilitybots.api.bot.TestUtils.CREATOR;
import static org.telegram.abilitybots.api.bot.TestUtils.*; import static org.telegram.abilitybots.api.bot.TestUtils.*;
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
@ -661,6 +661,30 @@ public class AbilityBotTest {
verify(silent, times(1)).send(expected, 1); verify(silent, times(1)).send(expected, 1);
} }
@Test
void canProcessRepliesRegisteredInCollection() {
Update firstUpdate = mock(Update.class);
Message firstMessage = mock(Message.class);
when(firstMessage.getText()).thenReturn(FIRST_REPLY_KEY_MESSAGE);
when(firstMessage.getChatId()).thenReturn(1L);
Update secondUpdate = mock(Update.class);
Message secondMessage = mock(Message.class);
when(secondMessage.getText()).thenReturn(SECOND_REPLY_KEY_MESSAGE);
when(secondMessage.getChatId()).thenReturn(1L);
mockUser(firstUpdate, firstMessage, USER);
mockUser(secondUpdate, secondMessage, USER);
bot.onUpdateReceived(firstUpdate);
bot.onUpdateReceived(secondUpdate);
verify(silent, times(2)).send(anyString(), anyLong());
verify(silent, times(1)).send("first reply answer", 1);
verify(silent, times(1)).send("second reply answer", 1);
}
private void handlesAllUpdates(Consumer<Update> utilMethod) { private void handlesAllUpdates(Consumer<Update> utilMethod) {
Arrays.stream(Update.class.getMethods()) Arrays.stream(Update.class.getMethods())
// filter to all these methods of hasXXX (hasPoll, hasMessage, etc...) // filter to all these methods of hasXXX (hasPoll, hasMessage, etc...)

View File

@ -5,8 +5,12 @@ import org.telegram.abilitybots.api.objects.Ability;
import org.telegram.abilitybots.api.objects.Ability.AbilityBuilder; import org.telegram.abilitybots.api.objects.Ability.AbilityBuilder;
import org.telegram.abilitybots.api.objects.Flag; import org.telegram.abilitybots.api.objects.Flag;
import org.telegram.abilitybots.api.objects.Reply; import org.telegram.abilitybots.api.objects.Reply;
import org.telegram.abilitybots.api.objects.ReplyCollection;
import org.telegram.abilitybots.api.toggle.AbilityToggle; import org.telegram.abilitybots.api.toggle.AbilityToggle;
import java.util.ArrayList;
import java.util.List;
import static org.telegram.abilitybots.api.objects.Ability.builder; 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.CALLBACK_QUERY;
import static org.telegram.abilitybots.api.objects.Flag.MESSAGE; import static org.telegram.abilitybots.api.objects.Flag.MESSAGE;
@ -15,6 +19,8 @@ import static org.telegram.abilitybots.api.objects.Privacy.ADMIN;
import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC; import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC;
public class DefaultBot extends AbilityBot { public class DefaultBot extends AbilityBot {
public static final String FIRST_REPLY_KEY_MESSAGE = "first reply key string";
public static final String SECOND_REPLY_KEY_MESSAGE = "second reply key string";
public DefaultBot(String token, String username, DBContext db) { public DefaultBot(String token, String username, DBContext db) {
super(token, username, db); super(token, username, db);
@ -79,6 +85,24 @@ public class DefaultBot extends AbilityBot {
); );
} }
public ReplyCollection createReplyCollection() {
List<Reply> replyList = new ArrayList<>();
replyList.add(
Reply.of(
upd -> silent.send("first reply answer", upd.getMessage().getChatId()),
update -> update.getMessage().getText().equalsIgnoreCase(FIRST_REPLY_KEY_MESSAGE)
)
);
replyList.add(
Reply.of(
upd -> silent.send("second reply answer", upd.getMessage().getChatId()),
update -> update.getMessage().getText().equalsIgnoreCase(SECOND_REPLY_KEY_MESSAGE)
)
);
return new ReplyCollection(replyList);
}
public Ability testAbility() { public Ability testAbility() {
return getDefaultBuilder().build(); return getDefaultBuilder().build();
} }