#3 session API draft

This commit is contained in:
2021-09-23 14:56:07 +03:00
parent 05af2f05a4
commit c62de38f17
13 changed files with 258 additions and 138 deletions

View File

@@ -14,4 +14,5 @@ public interface BotRequest {
Long getChatId(); Long getChatId();
BotSession getSession();
} }

View File

@@ -0,0 +1,9 @@
package ru.penkrat.stbf.api;
public interface BotSession {
Object getAttribute(String name);
void setAttribute(String name, Object value);
}

View File

@@ -0,0 +1,8 @@
package ru.penkrat.stbf.api;
@FunctionalInterface
public interface SessionProvider {
BotSession get(Long chatId);
}

View File

@@ -0,0 +1,18 @@
package ru.penkrat.stbf.common.session;
import ru.penkrat.stbf.api.BotSession;
import ru.penkrat.stbf.api.SessionProvider;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class InMemBotSessionProvider implements SessionProvider {
private static final Map<Long, BotSession> MAP = new ConcurrentHashMap<>();
@Override
public BotSession get(Long chatId) {
return MAP.computeIfAbsent(chatId, k -> new MapBackedBotSession(new ConcurrentHashMap<>()));
}
}

View File

@@ -0,0 +1,22 @@
package ru.penkrat.stbf.common.session;
import lombok.RequiredArgsConstructor;
import ru.penkrat.stbf.api.BotSession;
import java.util.Map;
@RequiredArgsConstructor
class MapBackedBotSession implements BotSession {
private final Map<String, Object> map;
@Override
public Object getAttribute(String name) {
return map.get(name);
}
@Override
public void setAttribute(String name, Object value) {
map.put(name, value);
}
}

View File

@@ -34,6 +34,11 @@
<groupId>ru.penkrat.stbf</groupId> <groupId>ru.penkrat.stbf</groupId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<artifactId>stbf-common</artifactId>
<groupId>ru.penkrat.stbf</groupId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>info.picocli</groupId> <groupId>info.picocli</groupId>
<artifactId>picocli</artifactId> <artifactId>picocli</artifactId>

View File

@@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory;
import picocli.CommandLine; import picocli.CommandLine;
import ru.penkrat.stbf.api.BotCommandChain; import ru.penkrat.stbf.api.BotCommandChain;
import ru.penkrat.stbf.api.CommandChain; import ru.penkrat.stbf.api.CommandChain;
import ru.penkrat.stbf.common.session.InMemBotSessionProvider;
import ru.penkrat.stbf.impl.pengrad.PengradTelegramBot; import ru.penkrat.stbf.impl.pengrad.PengradTelegramBot;
import ru.penkrat.stbf.templates.xml.XmlFlowResolver; import ru.penkrat.stbf.templates.xml.XmlFlowResolver;
@@ -38,7 +39,7 @@ public class App implements Runnable {
} }
private Runnable start(String token, CommandChain chain) { private Runnable start(String token, CommandChain chain) {
return () -> botAtomicReference.set(new PengradTelegramBot(token, chain)); return () -> botAtomicReference.set(new PengradTelegramBot(token, chain, new InMemBotSessionProvider()));
} }
private void onShutdown() { private void onShutdown() {

View File

@@ -1,17 +1,17 @@
package ru.penkrat.stbf.impl.pengrad; package ru.penkrat.stbf.impl.pengrad;
import static lombok.AccessLevel.PROTECTED;
import java.util.Optional;
import com.pengrad.telegrambot.model.CallbackQuery; import com.pengrad.telegrambot.model.CallbackQuery;
import com.pengrad.telegrambot.model.Contact; import com.pengrad.telegrambot.model.Contact;
import com.pengrad.telegrambot.model.Message; import com.pengrad.telegrambot.model.Message;
import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.Update;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import ru.penkrat.stbf.api.BotRequest; import ru.penkrat.stbf.api.BotRequest;
import ru.penkrat.stbf.api.BotSession;
import java.util.Optional;
import static lombok.AccessLevel.PROTECTED;
@RequiredArgsConstructor @RequiredArgsConstructor
public class BotRequestImpl implements BotRequest { public class BotRequestImpl implements BotRequest {
@@ -19,6 +19,9 @@ public class BotRequestImpl implements BotRequest {
@Getter(PROTECTED) @Getter(PROTECTED)
private final Update update; private final Update update;
@Getter
private final BotSession session;
@Override @Override
public Optional<String> getMessageText() { public Optional<String> getMessageText() {
if (update.message() != null) { if (update.message() != null) {

View File

@@ -2,21 +2,35 @@ package ru.penkrat.stbf.impl.pengrad;
import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.UpdatesListener; import com.pengrad.telegrambot.UpdatesListener;
import com.pengrad.telegrambot.model.CallbackQuery;
import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.Update;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import ru.penkrat.stbf.api.CommandChain; import ru.penkrat.stbf.api.CommandChain;
import ru.penkrat.stbf.api.SessionProvider;
import java.util.Optional;
@Slf4j @Slf4j
public class PengradTelegramBot extends TelegramBot implements AutoCloseable { public class PengradTelegramBot extends TelegramBot implements AutoCloseable {
public PengradTelegramBot(String botToken, CommandChain commandChain) { public PengradTelegramBot(String botToken, CommandChain commandChain) {
this(botToken, commandChain, (id) -> {
throw new IllegalArgumentException("'SessionProvider' is not defined");
});
}
public PengradTelegramBot(String botToken, CommandChain commandChain, SessionProvider sessionProvider) {
super(botToken); super(botToken);
this.setUpdatesListener(updates -> { this.setUpdatesListener(updates -> {
for (Update update : updates) { for (Update update : updates) {
try { try {
final Long chatId = Optional.of(update)
.map(Update::callbackQuery)
.map(CallbackQuery::message)
.orElseGet(() -> update.message()).chat().id();
commandChain.processCommand( commandChain.processCommand(
new BotRequestImpl(update), new BotRequestImpl(update, sessionProvider.get(chatId)),
new BotResponseImpl(update, this)); new BotResponseImpl(update, this));
} catch (Exception e) { } catch (Exception e) {
log.error("Bot Error:", e); log.error("Bot Error:", e);

View File

@@ -1,17 +1,17 @@
package ru.penkrat.stbf.impl.rubenlagus; package ru.penkrat.stbf.impl.rubenlagus;
import static lombok.AccessLevel.PROTECTED; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Optional;
import org.telegram.telegrambots.meta.api.objects.CallbackQuery; import org.telegram.telegrambots.meta.api.objects.CallbackQuery;
import org.telegram.telegrambots.meta.api.objects.Contact; import org.telegram.telegrambots.meta.api.objects.Contact;
import org.telegram.telegrambots.meta.api.objects.Message; import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.Update;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import ru.penkrat.stbf.api.BotRequest; import ru.penkrat.stbf.api.BotRequest;
import ru.penkrat.stbf.api.BotSession;
import java.util.Optional;
import static lombok.AccessLevel.PROTECTED;
@RequiredArgsConstructor @RequiredArgsConstructor
class BotRequestImpl implements BotRequest { class BotRequestImpl implements BotRequest {
@@ -19,6 +19,9 @@ class BotRequestImpl implements BotRequest {
@Getter(PROTECTED) @Getter(PROTECTED)
private final Update update; private final Update update;
@Getter
private final BotSession session;
@Override @Override
public Optional<String> getMessageText() { public Optional<String> getMessageText() {
if (update.hasMessage()) { if (update.hasMessage()) {
@@ -52,7 +55,7 @@ class BotRequestImpl implements BotRequest {
@Override @Override
public Long getChatId() { public Long getChatId() {
return update.getMessage().getChatId(); return Utils.getChatId(update);
} }
} }

View File

@@ -1,13 +1,13 @@
package ru.penkrat.stbf.impl.rubenlagus; package ru.penkrat.stbf.impl.rubenlagus;
import lombok.extern.slf4j.Slf4j;
import org.telegram.telegrambots.bots.TelegramLongPollingBot; import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.TelegramBotsApi; import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.api.objects.Update; import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException; import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession; import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
import lombok.extern.slf4j.Slf4j;
import ru.penkrat.stbf.api.BotCommandChain; import ru.penkrat.stbf.api.BotCommandChain;
import ru.penkrat.stbf.api.SessionProvider;
@Slf4j @Slf4j
public class RubenlagusTelegramBot extends TelegramLongPollingBot { public class RubenlagusTelegramBot extends TelegramLongPollingBot {
@@ -15,11 +15,19 @@ public class RubenlagusTelegramBot extends TelegramLongPollingBot {
private final String botUsername; private final String botUsername;
private final String botToken; private final String botToken;
private final BotCommandChain commandChain; private final BotCommandChain commandChain;
private final SessionProvider sessionProvider;
public RubenlagusTelegramBot(String botUsername, String botToken, BotCommandChain botCommandChain) { public RubenlagusTelegramBot(String botUsername, String botToken, BotCommandChain botCommandChain) {
this(botUsername, botToken, botCommandChain, (id) -> {
throw new IllegalArgumentException("'SessionProvider' is not defined");
});
}
public RubenlagusTelegramBot(String botUsername, String botToken, BotCommandChain botCommandChain, SessionProvider sessionProvider) {
this.botUsername = botUsername; this.botUsername = botUsername;
this.botToken = botToken; this.botToken = botToken;
this.commandChain = botCommandChain; this.commandChain = botCommandChain;
this.sessionProvider = sessionProvider;
TelegramBotsApi telegramBotsApi; TelegramBotsApi telegramBotsApi;
try { try {
@@ -34,7 +42,7 @@ public class RubenlagusTelegramBot extends TelegramLongPollingBot {
public void onUpdateReceived(Update update) { public void onUpdateReceived(Update update) {
try { try {
commandChain.processCommand( commandChain.processCommand(
new BotRequestImpl(update), new BotRequestImpl(update, sessionProvider.get(Utils.getChatId(update))),
new BotResponseImpl(update, this)); new BotResponseImpl(update, this));
} catch (Exception e) { } catch (Exception e) {
log.error("Bot Error:", e); log.error("Bot Error:", e);

View File

@@ -0,0 +1,21 @@
package ru.penkrat.stbf.impl.rubenlagus;
import lombok.experimental.UtilityClass;
import org.telegram.telegrambots.meta.api.objects.Update;
@UtilityClass
class Utils {
Long getChatId(Update update) {
if (update.getMessage() != null) {
return update.getMessage().getChatId();
}
if (update.getCallbackQuery() != null) {
update.getCallbackQuery().getMessage().getChatId();
}
throw new IllegalStateException("Can't extract chatId from 'Update'");
}
}

View File

@@ -6,6 +6,7 @@ import java.util.Random;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import ru.penkrat.stbf.api.BotRequest; import ru.penkrat.stbf.api.BotRequest;
import ru.penkrat.stbf.api.BotSession;
@Builder @Builder
class BotRequestImpl implements BotRequest { class BotRequestImpl implements BotRequest {
@@ -14,6 +15,7 @@ class BotRequestImpl implements BotRequest {
private String phoneNumber; private String phoneNumber;
private String callbackData; private String callbackData;
private String callbackMessageText; private String callbackMessageText;
private BotSession session;
@Getter @Getter
@Builder.Default @Builder.Default
@@ -39,4 +41,9 @@ class BotRequestImpl implements BotRequest {
return Optional.ofNullable(callbackMessageText); return Optional.ofNullable(callbackMessageText);
} }
@Override
public BotSession getSession() {
return session;
}
} }