package org.telegram.abilitybots.api.objects; import org.jetbrains.annotations.NotNull; import org.telegram.abilitybots.api.bot.BaseAbilityBot; import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.util.AbilityUtils; import org.telegram.telegrambots.meta.api.objects.Update; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.Predicate; import java.util.stream.Stream; import static com.google.common.collect.Lists.newArrayList; public class ReplyFlow extends Reply { private final Set nextReplies; private ReplyFlow(List> conditions, BiConsumer action, Set nextReplies, String name) { super(conditions, action, name); this.nextReplies = nextReplies; } public static ReplyFlowBuilder builder(DBContext db) { return new ReplyFlowBuilder(db); } public static ReplyFlowBuilder builder(DBContext db, int id) { return new ReplyFlowBuilder(db, id); } public Set nextReplies() { return nextReplies; } @Override public Stream stream() { return Stream.concat(Stream.of(this), nextReplies.stream().flatMap(Reply::stream)); } public static class ReplyFlowBuilder { public static final String STATES = "user_state_replies"; private static AtomicInteger replyCounter = new AtomicInteger(); private final DBContext db; private final int id; private List> conds; private BiConsumer action; private Set nextReplies; private String name; private ReplyFlowBuilder(DBContext db, int id) { conds = new ArrayList<>(); nextReplies = new HashSet<>(); this.db = db; this.id = id; } private ReplyFlowBuilder(DBContext db) { this(db, replyCounter.getAndIncrement()); } public ReplyFlowBuilder action(BiConsumer action) { this.action = action; return this; } public ReplyFlowBuilder enableStats(String name) { this.name = name; return this; } public ReplyFlowBuilder onlyIf(Predicate pred) { conds.add(pred); return this; } public ReplyFlowBuilder next(Reply nextReply) { List> statefulConditions = toStateful(nextReply.conditions()); BiConsumer statefulAction = nextReply.action().andThen((unused, upd) -> { Long chatId = AbilityUtils.getChatId(upd); db.getMap(STATES).remove(chatId); }); Reply statefulReply = new Reply(statefulConditions, statefulAction, nextReply.name()); nextReplies.add(statefulReply); return this; } public ReplyFlowBuilder next(ReplyFlow nextReplyFlow) { List> statefulConditions = toStateful(nextReplyFlow.conditions()); ReplyFlow statefulReplyFlow = new ReplyFlow(statefulConditions, nextReplyFlow.action(), nextReplyFlow.nextReplies(), nextReplyFlow.name()); nextReplies.add(statefulReplyFlow); return this; } public ReplyFlow build() { if (action == null) action = (bot, upd) -> {}; BiConsumer statefulAction; if (nextReplies.size() > 0) { statefulAction = action.andThen((bot, upd) -> { Long chatId = AbilityUtils.getChatId(upd); db.getMap(STATES).put(chatId, id); }); } else { statefulAction = action.andThen((bot, upd) -> { Long chatId = AbilityUtils.getChatId(upd); db.getMap(STATES).remove(chatId); }); } return new ReplyFlow(conds, statefulAction, nextReplies, name); } @NotNull private List> toStateful(List> conditions) { List> statefulConditions = newArrayList(conditions); statefulConditions.add(0, upd -> { Long chatId = AbilityUtils.getChatId(upd); int stateId = db.getMap(STATES).getOrDefault(chatId, -1); return id == stateId; }); return statefulConditions; } } }