feat: complete show help button event
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
* Code refactor so that help command and event use the same logic * Fix invasive string rename (ty intellij) * Fix Processor not returning right locale key name * Add tests and add todos for the one remainingpull/3/head
parent
53cdd4aa22
commit
3e094ec72a
|
@ -2,6 +2,7 @@ package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -9,6 +10,16 @@ import javax.inject.Singleton;
|
||||||
|
|
||||||
public class CallbackQueryDI extends AbstractModule {
|
public class CallbackQueryDI extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
super.configure();
|
||||||
|
|
||||||
|
install(
|
||||||
|
new FactoryModuleBuilder()
|
||||||
|
.implement(Processor.class, NotFound.class)
|
||||||
|
.build(NotFoundFactory.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("eventProcessors")
|
@Named("eventProcessors")
|
||||||
|
|
|
@ -3,8 +3,8 @@ package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||||
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
||||||
import com.pengrad.telegrambot.model.Update;
|
import com.pengrad.telegrambot.model.Update;
|
||||||
import com.pengrad.telegrambot.request.BaseRequest;
|
import com.pengrad.telegrambot.request.BaseRequest;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -22,15 +22,18 @@ import javax.inject.Singleton;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class Dispatcher {
|
public class Dispatcher {
|
||||||
|
|
||||||
private final Set<Processor> tgEventProcessors;
|
private final Map<String, Processor> tgEventProcessors;
|
||||||
private final Executor threadPool;
|
private final Executor threadPool;
|
||||||
|
private final NotFoundFactory notFoundFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Dispatcher(
|
public Dispatcher(
|
||||||
@Named("eventProcessors") Set<Processor> tgEventProcessors,
|
@Named("eventProcessors") Map<String, Processor> tgEventProcessors,
|
||||||
@Named("eventThreadPool") Executor threadPool) {
|
@Named("eventThreadPool") Executor threadPool,
|
||||||
|
NotFoundFactory notFoundFactory) {
|
||||||
this.tgEventProcessors = tgEventProcessors;
|
this.tgEventProcessors = tgEventProcessors;
|
||||||
this.threadPool = threadPool;
|
this.threadPool = threadPool;
|
||||||
|
this.notFoundFactory = notFoundFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,14 +53,11 @@ public class Dispatcher {
|
||||||
.thenComposeAsync(
|
.thenComposeAsync(
|
||||||
ignored ->
|
ignored ->
|
||||||
Optional.of(callbackQueryContext.getFields().getEvent())
|
Optional.of(callbackQueryContext.getFields().getEvent())
|
||||||
.flatMap(
|
.map(
|
||||||
eventName ->
|
eventName ->
|
||||||
tgEventProcessors.stream()
|
tgEventProcessors
|
||||||
// FIXME this is fucking stupid, why iterate over, just use a map!
|
.getOrDefault(eventName, notFoundFactory.create(eventName))
|
||||||
// Make mapping at startup then we're gucci for the rest of the run
|
.process(callbackQueryContext, update))
|
||||||
.filter(processor -> processor.getEventName().equals(eventName))
|
|
||||||
.findAny())
|
|
||||||
.map(processor -> processor.process(callbackQueryContext, update))
|
|
||||||
.orElse(CompletableFuture.failedFuture(new EventProcessorNotFoundException())),
|
.orElse(CompletableFuture.failedFuture(new EventProcessorNotFoundException())),
|
||||||
threadPool);
|
threadPool);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||||
|
|
||||||
|
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.pengrad.telegrambot.model.Update;
|
||||||
|
import com.pengrad.telegrambot.request.BaseRequest;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
public class NotFound implements Processor {
|
||||||
|
|
||||||
|
private final Logger log;
|
||||||
|
private final String eventName;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NotFound(Logger logger, @Assisted String eventName) {
|
||||||
|
this.log = logger;
|
||||||
|
this.eventName = eventName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEventName() {
|
||||||
|
return "eventNotFound";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Optional<BaseRequest<?, ?>>> process(
|
||||||
|
CallbackQueryContext callbackQueryContext, Update update) {
|
||||||
|
log.warn(
|
||||||
|
"A stray event was detected for callback "
|
||||||
|
+ callbackQueryContext.getId()
|
||||||
|
+ " event name "
|
||||||
|
+ eventName);
|
||||||
|
return CompletableFuture.completedFuture(Optional.empty());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||||
|
|
||||||
|
public interface NotFoundFactory {
|
||||||
|
NotFound create(String eventName);
|
||||||
|
}
|
|
@ -3,10 +3,8 @@ package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||||
import com.github.polpetta.mezzotre.i18n.TemplateContentGenerator;
|
import com.github.polpetta.mezzotre.i18n.TemplateContentGenerator;
|
||||||
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
||||||
import com.github.polpetta.mezzotre.orm.model.query.QCallbackQueryContext;
|
import com.github.polpetta.mezzotre.orm.model.query.QCallbackQueryContext;
|
||||||
import com.github.polpetta.mezzotre.orm.model.query.QTgChat;
|
|
||||||
import com.github.polpetta.mezzotre.util.UUIDGenerator;
|
import com.github.polpetta.mezzotre.util.UUIDGenerator;
|
||||||
import com.github.polpetta.types.json.CallbackQueryMetadata;
|
import com.github.polpetta.types.json.CallbackQueryMetadata;
|
||||||
import com.pengrad.telegrambot.model.Message;
|
|
||||||
import com.pengrad.telegrambot.model.Update;
|
import com.pengrad.telegrambot.model.Update;
|
||||||
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
|
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
|
||||||
import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
|
import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
|
||||||
|
@ -61,16 +59,7 @@ public class SelectLanguageTutorial implements Processor {
|
||||||
CallbackQueryContext callbackQueryContext, Update update) {
|
CallbackQueryContext callbackQueryContext, Update update) {
|
||||||
return CompletableFuture.supplyAsync(
|
return CompletableFuture.supplyAsync(
|
||||||
() ->
|
() ->
|
||||||
Optional.of(callbackQueryContext.getFields().getTelegramChatId())
|
Util.extractChat(callbackQueryContext, update)
|
||||||
.map(Double::longValue)
|
|
||||||
// If we're desperate, search in the message for the chat id
|
|
||||||
.or(
|
|
||||||
() ->
|
|
||||||
Optional.ofNullable(update.callbackQuery().message())
|
|
||||||
.map(Message::messageId)
|
|
||||||
.map(Long::valueOf))
|
|
||||||
.filter(chatId -> chatId != 0L && chatId != Long.MIN_VALUE)
|
|
||||||
.flatMap(chatId -> new QTgChat().id.eq(chatId).findOneOrEmpty())
|
|
||||||
.map(
|
.map(
|
||||||
tgChat -> {
|
tgChat -> {
|
||||||
tgChat.setLocale(
|
tgChat.setLocale(
|
||||||
|
@ -119,8 +108,7 @@ public class SelectLanguageTutorial implements Processor {
|
||||||
+ " entries regarding callback group "
|
+ " entries regarding callback group "
|
||||||
+ callBackGroupToDelete);
|
+ callBackGroupToDelete);
|
||||||
|
|
||||||
final Optional<Integer> messageId =
|
final Optional<Integer> messageId = Util.extractMessageId(update);
|
||||||
Optional.ofNullable(update.callbackQuery().message()).map(Message::messageId);
|
|
||||||
BaseRequest<?, ?> baseRequest;
|
BaseRequest<?, ?> baseRequest;
|
||||||
Optional<InlineKeyboardMarkup> helpButton = Optional.empty();
|
Optional<InlineKeyboardMarkup> helpButton = Optional.empty();
|
||||||
if (!tgChat.getHasHelpBeenShown()) {
|
if (!tgChat.getHasHelpBeenShown()) {
|
||||||
|
|
|
@ -1,15 +1,45 @@
|
||||||
package com.github.polpetta.mezzotre.telegram.callbackquery;
|
package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||||
|
|
||||||
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
||||||
|
import com.github.polpetta.mezzotre.telegram.model.Help;
|
||||||
import com.pengrad.telegrambot.model.Update;
|
import com.pengrad.telegrambot.model.Update;
|
||||||
|
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
|
||||||
|
import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
|
||||||
|
import com.pengrad.telegrambot.model.request.ParseMode;
|
||||||
import com.pengrad.telegrambot.request.BaseRequest;
|
import com.pengrad.telegrambot.request.BaseRequest;
|
||||||
|
import com.pengrad.telegrambot.request.EditMessageText;
|
||||||
import com.pengrad.telegrambot.request.SendMessage;
|
import com.pengrad.telegrambot.request.SendMessage;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
class ShowHelp implements Processor {
|
class ShowHelp implements Processor {
|
||||||
|
|
||||||
public static String EVENT_NAME = "showHelp";
|
public static String EVENT_NAME = "showHelp";
|
||||||
|
private final Executor threadPool;
|
||||||
|
private final Help modelHelp;
|
||||||
|
private final Map<String, com.github.polpetta.mezzotre.telegram.command.Processor>
|
||||||
|
tgCommandProcessors;
|
||||||
|
private final Map<String, Processor> eventProcessor;
|
||||||
|
|
||||||
|
// FIXME tests
|
||||||
|
@Inject
|
||||||
|
public ShowHelp(
|
||||||
|
@Named("eventThreadPool") Executor threadPool,
|
||||||
|
com.github.polpetta.mezzotre.telegram.model.Help modelHelp,
|
||||||
|
@Named("commandProcessor")
|
||||||
|
Map<String, com.github.polpetta.mezzotre.telegram.command.Processor> tgCommandProcessors,
|
||||||
|
@Named("eventProcessors")
|
||||||
|
Map<String, com.github.polpetta.mezzotre.telegram.callbackquery.Processor>
|
||||||
|
eventProcessor) {
|
||||||
|
this.threadPool = threadPool;
|
||||||
|
this.modelHelp = modelHelp;
|
||||||
|
this.tgCommandProcessors = tgCommandProcessors;
|
||||||
|
this.eventProcessor = eventProcessor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getEventName() {
|
public String getEventName() {
|
||||||
|
@ -19,8 +49,30 @@ class ShowHelp implements Processor {
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Optional<BaseRequest<?, ?>>> process(
|
public CompletableFuture<Optional<BaseRequest<?, ?>>> process(
|
||||||
CallbackQueryContext callbackQueryContext, Update update) {
|
CallbackQueryContext callbackQueryContext, Update update) {
|
||||||
// TODO implement this method and put `hasHelpBeenShown` in tgChat to false
|
return CompletableFuture.supplyAsync(
|
||||||
return CompletableFuture.completedFuture(
|
() ->
|
||||||
Optional.of(new SendMessage(callbackQueryContext.getFields().getTelegramChatId(), "TODO")));
|
Util.extractChat(callbackQueryContext, update)
|
||||||
|
.map(
|
||||||
|
chat -> {
|
||||||
|
final String message = modelHelp.getMessage(chat, tgCommandProcessors);
|
||||||
|
final Optional<Integer> messageId = Util.extractMessageId(update);
|
||||||
|
final InlineKeyboardButton[] buttons =
|
||||||
|
modelHelp.generateInlineKeyBoardButton(chat, eventProcessor);
|
||||||
|
BaseRequest<?, ?> request;
|
||||||
|
if (messageId.isPresent()) {
|
||||||
|
final EditMessageText editMessageText =
|
||||||
|
new EditMessageText(chat.getId(), messageId.get(), message);
|
||||||
|
editMessageText.replyMarkup(new InlineKeyboardMarkup(buttons));
|
||||||
|
request = editMessageText;
|
||||||
|
} else {
|
||||||
|
final SendMessage sendMessage =
|
||||||
|
new SendMessage(chat.getId(), message).parseMode(ParseMode.Markdown);
|
||||||
|
sendMessage.replyMarkup(new InlineKeyboardMarkup(buttons));
|
||||||
|
request = sendMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}),
|
||||||
|
threadPool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||||
|
|
||||||
|
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
||||||
|
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
||||||
|
import com.github.polpetta.mezzotre.orm.model.query.QTgChat;
|
||||||
|
import com.pengrad.telegrambot.model.Message;
|
||||||
|
import com.pengrad.telegrambot.model.Update;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
|
||||||
|
public static Optional<TgChat> extractChat(
|
||||||
|
CallbackQueryContext callbackQueryContext, Update update) {
|
||||||
|
return Optional.of(callbackQueryContext.getFields().getTelegramChatId())
|
||||||
|
.map(Double::longValue)
|
||||||
|
// If we're desperate, search in the message for the chat id
|
||||||
|
.or(
|
||||||
|
() ->
|
||||||
|
Optional.ofNullable(update.callbackQuery().message())
|
||||||
|
.map(Message::messageId)
|
||||||
|
.map(Long::valueOf))
|
||||||
|
.filter(chatId -> chatId != 0L && chatId != Long.MIN_VALUE)
|
||||||
|
.flatMap(chatId -> new QTgChat().id.eq(chatId).findOneOrEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<Integer> extractMessageId(Update update) {
|
||||||
|
return Optional.ofNullable(update.callbackQuery().message()).map(Message::messageId);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,6 @@
|
||||||
package com.github.polpetta.mezzotre.telegram.command;
|
package com.github.polpetta.mezzotre.telegram.command;
|
||||||
|
|
||||||
import com.github.polpetta.mezzotre.i18n.TemplateContentGenerator;
|
|
||||||
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
|
||||||
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
||||||
import com.github.polpetta.mezzotre.telegram.callbackquery.Field;
|
|
||||||
import com.github.polpetta.mezzotre.util.Clock;
|
|
||||||
import com.github.polpetta.mezzotre.util.UUIDGenerator;
|
|
||||||
import com.github.polpetta.types.json.CallbackQueryMetadata;
|
|
||||||
import com.github.polpetta.types.json.ChatContext;
|
|
||||||
import com.pengrad.telegrambot.model.Update;
|
import com.pengrad.telegrambot.model.Update;
|
||||||
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
|
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
|
||||||
import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
|
import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
|
||||||
|
@ -19,38 +12,30 @@ import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
public class Help implements Processor {
|
public class Help implements Processor {
|
||||||
|
|
||||||
private static final String TRIGGERING_STAGING_NAME = "/help";
|
private static final String TRIGGERING_STAGING_NAME = "/help";
|
||||||
|
|
||||||
private final TemplateContentGenerator templateContentGenerator;
|
|
||||||
private final Executor threadPool;
|
private final Executor threadPool;
|
||||||
private final Clock clock;
|
|
||||||
private final Map<String, Processor> tgCommandProcessors;
|
private final Map<String, Processor> tgCommandProcessors;
|
||||||
private final Map<String, com.github.polpetta.mezzotre.telegram.callbackquery.Processor>
|
private final Map<String, com.github.polpetta.mezzotre.telegram.callbackquery.Processor>
|
||||||
eventProcessor;
|
eventProcessor;
|
||||||
private final UUIDGenerator uuidGenerator;
|
private final com.github.polpetta.mezzotre.telegram.model.Help modelHelp;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Help(
|
public Help(
|
||||||
TemplateContentGenerator templateContentGenerator,
|
|
||||||
@Named("eventThreadPool") Executor threadPool,
|
@Named("eventThreadPool") Executor threadPool,
|
||||||
Clock clock,
|
|
||||||
@Named("commandProcessor") Map<String, Processor> tgCommandProcessors,
|
@Named("commandProcessor") Map<String, Processor> tgCommandProcessors,
|
||||||
@Named("eventProcessors")
|
@Named("eventProcessors")
|
||||||
Map<String, com.github.polpetta.mezzotre.telegram.callbackquery.Processor> eventProcessor,
|
Map<String, com.github.polpetta.mezzotre.telegram.callbackquery.Processor> eventProcessor,
|
||||||
UUIDGenerator uuidGenerator) {
|
com.github.polpetta.mezzotre.telegram.model.Help modelHelp) {
|
||||||
this.templateContentGenerator = templateContentGenerator;
|
|
||||||
this.threadPool = threadPool;
|
this.threadPool = threadPool;
|
||||||
this.clock = clock;
|
|
||||||
this.tgCommandProcessors = tgCommandProcessors;
|
this.tgCommandProcessors = tgCommandProcessors;
|
||||||
this.eventProcessor = eventProcessor;
|
this.eventProcessor = eventProcessor;
|
||||||
this.uuidGenerator = uuidGenerator;
|
this.modelHelp = modelHelp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -62,66 +47,17 @@ public class Help implements Processor {
|
||||||
public CompletableFuture<Optional<BaseRequest<?, ?>>> process(TgChat chat, Update update) {
|
public CompletableFuture<Optional<BaseRequest<?, ?>>> process(TgChat chat, Update update) {
|
||||||
return CompletableFuture.supplyAsync(
|
return CompletableFuture.supplyAsync(
|
||||||
() -> {
|
() -> {
|
||||||
final String message =
|
final String message = modelHelp.getMessage(chat, tgCommandProcessors);
|
||||||
templateContentGenerator.mergeTemplate(
|
|
||||||
velocityContext -> {
|
|
||||||
velocityContext.put(
|
|
||||||
"commands",
|
|
||||||
tgCommandProcessors.values().stream()
|
|
||||||
.distinct()
|
|
||||||
.map(
|
|
||||||
p ->
|
|
||||||
Pair.of(
|
|
||||||
p.getTriggerKeywords().stream()
|
|
||||||
.sorted()
|
|
||||||
.collect(Collectors.toList()),
|
|
||||||
p.getLocaleDescriptionKeyword()))
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
},
|
|
||||||
chat.getLocale(),
|
|
||||||
"template/telegram/help.vm");
|
|
||||||
|
|
||||||
final ChatContext chatContext = chat.getChatContext();
|
|
||||||
chatContext.setStage(TRIGGERING_STAGING_NAME);
|
|
||||||
chatContext.setStep(0);
|
|
||||||
chatContext.setPreviousMessageUnixTimestampInSeconds(clock.now());
|
|
||||||
chat.setChatContext(chatContext);
|
|
||||||
chat.setHasHelpBeenShown(true);
|
|
||||||
chat.save();
|
|
||||||
|
|
||||||
final SendMessage sendMessage =
|
final SendMessage sendMessage =
|
||||||
new SendMessage(chat.getId(), message).parseMode(ParseMode.Markdown);
|
new SendMessage(chat.getId(), message).parseMode(ParseMode.Markdown);
|
||||||
|
|
||||||
final String callBackGroupId = uuidGenerator.generateAsString();
|
final InlineKeyboardButton[] buttons =
|
||||||
final InlineKeyboardButton[] collect =
|
modelHelp.generateInlineKeyBoardButton(chat, eventProcessor);
|
||||||
eventProcessor.values().stream()
|
|
||||||
.filter(
|
|
||||||
com.github.polpetta.mezzotre.telegram.callbackquery.Processor
|
|
||||||
::canBeDirectlyInvokedByTheUser)
|
|
||||||
.filter(e -> e.getPrettyPrintLocaleKeyName().isPresent())
|
|
||||||
.map(
|
|
||||||
eventProcessor -> {
|
|
||||||
final CallbackQueryContext callbackQueryContext =
|
|
||||||
new CallbackQueryContext(
|
|
||||||
uuidGenerator.generateAsString(),
|
|
||||||
callBackGroupId,
|
|
||||||
new CallbackQueryMetadata.CallbackQueryMetadataBuilder()
|
|
||||||
.withEvent(eventProcessor.getEventName())
|
|
||||||
.withTelegramChatId(chat.getId())
|
|
||||||
.withAdditionalProperty(
|
|
||||||
Field.ShowHelp.InvokedFromHelpMessage.getName(), true)
|
|
||||||
.build());
|
|
||||||
callbackQueryContext.save();
|
|
||||||
|
|
||||||
return new InlineKeyboardButton(
|
if (buttons.length > 0) {
|
||||||
templateContentGenerator.getString(
|
sendMessage.replyMarkup(new InlineKeyboardMarkup(buttons));
|
||||||
chat.getLocale(),
|
}
|
||||||
eventProcessor.getPrettyPrintLocaleKeyName().get()))
|
|
||||||
.callbackData(callbackQueryContext.getId());
|
|
||||||
})
|
|
||||||
.toArray(InlineKeyboardButton[]::new);
|
|
||||||
|
|
||||||
sendMessage.replyMarkup(new InlineKeyboardMarkup(collect));
|
|
||||||
|
|
||||||
return Optional.of(sendMessage);
|
return Optional.of(sendMessage);
|
||||||
},
|
},
|
||||||
|
|
|
@ -43,6 +43,6 @@ public interface Processor {
|
||||||
* description
|
* description
|
||||||
*/
|
*/
|
||||||
default String getLocaleDescriptionKeyword() {
|
default String getLocaleDescriptionKeyword() {
|
||||||
return this.getClass().getName().toLowerCase() + ".cmdDescription";
|
return this.getClass().getSimpleName().toLowerCase() + ".cmdDescription";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,97 @@
|
||||||
package com.github.polpetta.mezzotre.telegram.model;
|
package com.github.polpetta.mezzotre.telegram.model;
|
||||||
|
|
||||||
import com.github.polpetta.mezzotre.i18n.LocalizedMessageFactory;
|
import com.github.polpetta.mezzotre.i18n.TemplateContentGenerator;
|
||||||
|
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
||||||
|
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
||||||
|
import com.github.polpetta.mezzotre.telegram.callbackquery.Field;
|
||||||
|
import com.github.polpetta.mezzotre.telegram.command.Processor;
|
||||||
|
import com.github.polpetta.mezzotre.util.Clock;
|
||||||
|
import com.github.polpetta.mezzotre.util.UUIDGenerator;
|
||||||
|
import com.github.polpetta.types.json.CallbackQueryMetadata;
|
||||||
|
import com.github.polpetta.types.json.ChatContext;
|
||||||
|
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
// FIXME tests!
|
||||||
public class Help {
|
public class Help {
|
||||||
|
|
||||||
private final LocalizedMessageFactory localizedMessageFactory;
|
private static final String TRIGGERING_STAGING_NAME = "/help";
|
||||||
|
|
||||||
|
private final TemplateContentGenerator templateContentGenerator;
|
||||||
|
private final Clock clock;
|
||||||
|
private final UUIDGenerator uuidGenerator;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Help(LocalizedMessageFactory localizedMessageFactory) {
|
public Help(
|
||||||
this.localizedMessageFactory = localizedMessageFactory;
|
TemplateContentGenerator templateContentGenerator, Clock clock, UUIDGenerator uuidGenerator) {
|
||||||
|
|
||||||
|
this.templateContentGenerator = templateContentGenerator;
|
||||||
|
this.clock = clock;
|
||||||
|
this.uuidGenerator = uuidGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateErrorMessage() {
|
public String getMessage(TgChat chat, Map<String, Processor> tgCommandProcessors) {
|
||||||
return "";
|
final String message =
|
||||||
|
templateContentGenerator.mergeTemplate(
|
||||||
|
velocityContext -> {
|
||||||
|
velocityContext.put(
|
||||||
|
"commands",
|
||||||
|
tgCommandProcessors.values().stream()
|
||||||
|
.distinct()
|
||||||
|
.map(
|
||||||
|
p ->
|
||||||
|
Pair.of(
|
||||||
|
p.getTriggerKeywords().stream()
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.toList()),
|
||||||
|
p.getLocaleDescriptionKeyword()))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
},
|
||||||
|
chat.getLocale(),
|
||||||
|
"template/telegram/help.vm");
|
||||||
|
|
||||||
|
// FIXME this shouldn't stay here. We need to move it into another method
|
||||||
|
final ChatContext chatContext = chat.getChatContext();
|
||||||
|
chatContext.setStage(TRIGGERING_STAGING_NAME);
|
||||||
|
chatContext.setStep(0);
|
||||||
|
chatContext.setPreviousMessageUnixTimestampInSeconds(clock.now());
|
||||||
|
chat.setChatContext(chatContext);
|
||||||
|
chat.setHasHelpBeenShown(true);
|
||||||
|
chat.save();
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InlineKeyboardButton[] generateInlineKeyBoardButton(
|
||||||
|
TgChat chat,
|
||||||
|
Map<String, com.github.polpetta.mezzotre.telegram.callbackquery.Processor> eventProcessors) {
|
||||||
|
final String callBackGroupId = uuidGenerator.generateAsString();
|
||||||
|
return eventProcessors.values().stream()
|
||||||
|
.filter(
|
||||||
|
com.github.polpetta.mezzotre.telegram.callbackquery.Processor
|
||||||
|
::canBeDirectlyInvokedByTheUser)
|
||||||
|
.filter(e -> e.getPrettyPrintLocaleKeyName().isPresent())
|
||||||
|
.map(
|
||||||
|
eventProcessor -> {
|
||||||
|
final CallbackQueryContext callbackQueryContext =
|
||||||
|
new CallbackQueryContext(
|
||||||
|
uuidGenerator.generateAsString(),
|
||||||
|
callBackGroupId,
|
||||||
|
new CallbackQueryMetadata.CallbackQueryMetadataBuilder()
|
||||||
|
.withEvent(eventProcessor.getEventName())
|
||||||
|
.withTelegramChatId(chat.getId())
|
||||||
|
.withAdditionalProperty(
|
||||||
|
Field.ShowHelp.InvokedFromHelpMessage.getName(), true)
|
||||||
|
.build());
|
||||||
|
callbackQueryContext.save();
|
||||||
|
|
||||||
|
return new InlineKeyboardButton(
|
||||||
|
templateContentGenerator.getString(
|
||||||
|
chat.getLocale(), eventProcessor.getPrettyPrintLocaleKeyName().get()))
|
||||||
|
.callbackData(callbackQueryContext.getId());
|
||||||
|
})
|
||||||
|
.toArray(InlineKeyboardButton[]::new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
start.helloFirstName=Hello {0}! \ud83d\udc4b
|
start.helloFirstName=Hello {0}! \ud83d\udc4b
|
||||||
start.description=This is {0}, a simple bot focused on DnD content management! Please start by choosing a selectLanguageTutorial down below \ud83d\udc47
|
start.description=This is {0}, a simple bot focused on DnD content management! Please start by choosing a language down below \ud83d\udc47
|
||||||
start.cmdDescription=Trigger this very bot
|
start.cmdDescription=Trigger this very bot
|
||||||
start.inlineKeyboardButtonName=Let''s begin!
|
start.inlineKeyboardButtonName=Let''s begin!
|
||||||
selectLanguageTutorial.inlineKeyboardButtonName=Select language
|
selectLanguageTutorial.inlineKeyboardButtonName=Select language
|
||||||
selectLanguageTutorial.drinkAction=*Proceeds to drink a potion with a strange, multicolor liquid*
|
selectLanguageTutorial.drinkAction=*Proceeds to drink a potion with a strange, multicolor liquid*
|
||||||
selectLanguageTutorial.setLanguage=Thanks! Now that I drank this modified potion of {0} that I''ve found at the "Crystal Fermentary" magic potion shop yesterday I can speak with you in the selectLanguageTutorial that you prefer!
|
selectLanguageTutorial.setLanguage=Thanks! Now that I drank this modified potion of {0} that I''ve found at the "Crystal Fermentary" magic potion shop yesterday I can speak with you in the language that you prefer!
|
||||||
selectLanguageTutorial.instructions=You can always change your selectLanguageTutorial settings by typing /selectLanguageTutorial in the chat.
|
selectLanguageTutorial.instructions=You can always change your language settings by typing /changeLanguage in the chat.
|
||||||
changeLanguage.english=English
|
changeLanguage.english=English
|
||||||
changeLanguage.italian=Italian
|
changeLanguage.italian=Italian
|
||||||
changeLanguage.cmdDescription=Select the new language I will use to speak to you
|
changeLanguage.cmdDescription=Select the new language I will use to speak to you
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
start.helloFirstName=Hello {0}! \ud83d\udc4b
|
start.helloFirstName=Hello {0}! \ud83d\udc4b
|
||||||
start.description=This is {0}, a simple bot focused on DnD content management! Please start by choosing a selectLanguageTutorial down below \ud83d\udc47
|
start.description=This is {0}, a simple bot focused on DnD content management! Please start by choosing a language down below \ud83d\udc47
|
||||||
|
start.cmdDescription=Trigger this very bot
|
||||||
|
start.inlineKeyboardButtonName=Let''s begin!
|
||||||
|
selectLanguageTutorial.inlineKeyboardButtonName=Select language
|
||||||
selectLanguageTutorial.drinkAction=*Proceeds to drink a potion with a strange, multicolor liquid*
|
selectLanguageTutorial.drinkAction=*Proceeds to drink a potion with a strange, multicolor liquid*
|
||||||
selectLanguageTutorial.setLanguage=Thanks! Now that I drank this modified potion of {0} that I''ve found at the "Crystal Fermentary" magic potion shop yesterday I can speak with you in the selectLanguageTutorial that you prefer!
|
selectLanguageTutorial.setLanguage=Thanks! Now that I drank this modified potion of {0} that I''ve found at the "Crystal Fermentary" magic potion shop yesterday I can speak with you in the language that you prefer!
|
||||||
selectLanguageTutorial.instructions=You can always change your selectLanguageTutorial settings by typing /selectLanguageTutorial in the chat.
|
selectLanguageTutorial.instructions=You can always change your language settings by typing /changeLanguage in the chat.
|
||||||
selectLanguageTutorial.english=English
|
changeLanguage.english=English
|
||||||
selectLanguageTutorial.italian=Italian
|
changeLanguage.italian=Italian
|
||||||
|
changeLanguage.cmdDescription=Select the new language I will use to speak to you
|
||||||
|
changeLanguage.inlineKeyboardButtonName=Change language
|
||||||
spell.speakWithAnimals=Speak with animals
|
spell.speakWithAnimals=Speak with animals
|
||||||
selectLanguageTutorial.showMeTutorialInlineKeyboardButtonName=Show me what you can do!
|
selectLanguageTutorial.showMeTutorialInlineKeyboardButtonName=Show me what you can do!
|
||||||
help.notShownYet=It seems you haven''t checked out what I can do yet! To have a complete list of my abilities, type /help in chat at any time!
|
help.notShownYet=It seems you haven''t checked out what I can do yet! To have a complete list of my abilities, type /help in chat at any time!
|
||||||
help.buttonBelow=Alternatively, you can click the button down below.
|
help.buttonBelow=Alternatively, you can click the button down below.
|
||||||
|
help.description=Here is a list of what I can do
|
||||||
|
help.buttonsToo=You can do the same operations you''d do with the commands aforementioned by selecting the corresponding button below \ud83d\udc47
|
||||||
|
help.cmdDescription=Print the help message
|
||||||
|
|
|
@ -2,7 +2,7 @@ start.helloFirstName=Ciao {0}! \ud83d\udc4b
|
||||||
start.description=Questo è {0}, un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto \ud83d\udc47
|
start.description=Questo è {0}, un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto \ud83d\udc47
|
||||||
selectLanguageTutorial.drinkAction=*Procede a bere una pozione al cui suo interno si trova uno strano liquido multicolore*
|
selectLanguageTutorial.drinkAction=*Procede a bere una pozione al cui suo interno si trova uno strano liquido multicolore*
|
||||||
selectLanguageTutorial.setLanguage=Grazie! Ora che ho bevuto questa posizione modificata di {0} che ho trovato ieri al negozio di pozioni magiche la "Cristalleria Fermentatrice" posso parlare con te nel linguaggio che preferisci!
|
selectLanguageTutorial.setLanguage=Grazie! Ora che ho bevuto questa posizione modificata di {0} che ho trovato ieri al negozio di pozioni magiche la "Cristalleria Fermentatrice" posso parlare con te nel linguaggio che preferisci!
|
||||||
selectLanguageTutorial.instructions=Puoi sempre cambiare le preferenze della tua lingua scrivendo /selectLanguageTutorial nella chat.
|
selectLanguageTutorial.instructions=Puoi sempre cambiare le preferenze della tua lingua scrivendo /changeLanguage nella chat.
|
||||||
selectLanguageTutorial.english=Inglese
|
selectLanguageTutorial.english=Inglese
|
||||||
selectLanguageTutorial.italian=Italiano
|
selectLanguageTutorial.italian=Italiano
|
||||||
spell.speakWithAnimals=Parlare con animali
|
spell.speakWithAnimals=Parlare con animali
|
||||||
|
|
|
@ -2,7 +2,7 @@ start.helloFirstName=Ciao {0}! \ud83d\udc4b
|
||||||
start.description=Questo è {0}, un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto \ud83d\udc47
|
start.description=Questo è {0}, un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto \ud83d\udc47
|
||||||
selectLanguageTutorial.drinkAction=*Procede a bere una pozione al cui suo interno si trova uno strano liquido multicolore*
|
selectLanguageTutorial.drinkAction=*Procede a bere una pozione al cui suo interno si trova uno strano liquido multicolore*
|
||||||
selectLanguageTutorial.setLanguage=Grazie! Ora che ho bevuto questa posizione modificata di {0} che ho trovato ieri al negozio di pozioni magiche la "Cristalleria Fermentatrice" posso parlare con te nel linguaggio che preferisci!
|
selectLanguageTutorial.setLanguage=Grazie! Ora che ho bevuto questa posizione modificata di {0} che ho trovato ieri al negozio di pozioni magiche la "Cristalleria Fermentatrice" posso parlare con te nel linguaggio che preferisci!
|
||||||
selectLanguageTutorial.instructions=Puoi sempre cambiare le preferenze della tua lingua scrivendo /selectLanguageTutorial nella chat.
|
selectLanguageTutorial.instructions=Puoi sempre cambiare le preferenze della tua lingua scrivendo /changeLanguage nella chat.
|
||||||
selectLanguageTutorial.english=Inglese
|
selectLanguageTutorial.english=Inglese
|
||||||
selectLanguageTutorial.italian=Italiano
|
selectLanguageTutorial.italian=Italiano
|
||||||
spell.speakWithAnimals=Parlare con animali
|
spell.speakWithAnimals=Parlare con animali
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
${i18n.help.description}:
|
${i18n.help.description}:
|
||||||
|
|
||||||
#foreach(${command} in ${commands})
|
#foreach(${command} in ${commands})
|
||||||
|
## FIXME this is not displayed correctly in telegram!
|
||||||
*#foreach(${key} in ${command.left}) ${key}#end: ${i18n.get(${command.right})}
|
*#foreach(${key} in ${command.left}) ${key}#end: ${i18n.get(${command.right})}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ class SelectLanguageTutorialIntegrationTest {
|
||||||
+ " posso parlare con te nel linguaggio che preferisci!\n"
|
+ " posso parlare con te nel linguaggio che preferisci!\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "Puoi sempre cambiare le preferenze della tua lingua scrivendo"
|
+ "Puoi sempre cambiare le preferenze della tua lingua scrivendo"
|
||||||
+ " /selectLanguageTutorial nella chat.\n"
|
+ " /changeLanguage nella chat.\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "Sembra tu non abbia ancora visto cosa posso fare! Per avere una lista completa"
|
+ "Sembra tu non abbia ancora visto cosa posso fare! Per avere una lista completa"
|
||||||
+ " delle mie abilità, scrivi /help nella chat in qualsiasi momento!"
|
+ " delle mie abilità, scrivi /help nella chat in qualsiasi momento!"
|
||||||
|
@ -102,7 +102,7 @@ class SelectLanguageTutorialIntegrationTest {
|
||||||
+ " found at the \"Crystal Fermentary\" magic potion shop yesterday I can speak"
|
+ " found at the \"Crystal Fermentary\" magic potion shop yesterday I can speak"
|
||||||
+ " with you in the language that you prefer!\n"
|
+ " with you in the language that you prefer!\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "You can always change your language settings by typing /selectLanguageTutorial"
|
+ "You can always change your language settings by typing /changeLanguage"
|
||||||
+ " in the chat.\n"
|
+ " in the chat.\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "It seems you haven't checked out what I can do yet! To have a complete list of"
|
+ "It seems you haven't checked out what I can do yet! To have a complete list of"
|
||||||
|
@ -121,7 +121,7 @@ class SelectLanguageTutorialIntegrationTest {
|
||||||
+ " posso parlare con te nel linguaggio che preferisci!\n"
|
+ " posso parlare con te nel linguaggio che preferisci!\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "Puoi sempre cambiare le preferenze della tua lingua scrivendo"
|
+ "Puoi sempre cambiare le preferenze della tua lingua scrivendo"
|
||||||
+ " /selectLanguageTutorial nella chat.\n\n",
|
+ " /changeLanguage nella chat.\n\n",
|
||||||
"en-US",
|
"en-US",
|
||||||
"Mostrami cosa puoi fare!",
|
"Mostrami cosa puoi fare!",
|
||||||
true),
|
true),
|
||||||
|
@ -133,7 +133,7 @@ class SelectLanguageTutorialIntegrationTest {
|
||||||
+ " found at the \"Crystal Fermentary\" magic potion shop yesterday I can speak"
|
+ " found at the \"Crystal Fermentary\" magic potion shop yesterday I can speak"
|
||||||
+ " with you in the language that you prefer!\n"
|
+ " with you in the language that you prefer!\n"
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ "You can always change your language settings by typing /selectLanguageTutorial"
|
+ "You can always change your language settings by typing /changeLanguage"
|
||||||
+ " in the chat.\n\n",
|
+ " in the chat.\n\n",
|
||||||
"it-IT",
|
"it-IT",
|
||||||
"Show me what you can do!",
|
"Show me what you can do!",
|
||||||
|
|
|
@ -169,15 +169,14 @@ class HelpIntegrationTest {
|
||||||
events.put(dummyEvent1.getEventName(), dummyEvent1);
|
events.put(dummyEvent1.getEventName(), dummyEvent1);
|
||||||
events.put(dummyEvent2.getEventName(), dummyEvent2);
|
events.put(dummyEvent2.getEventName(), dummyEvent2);
|
||||||
|
|
||||||
help =
|
final com.github.polpetta.mezzotre.telegram.model.Help modelHelp =
|
||||||
new Help(
|
new com.github.polpetta.mezzotre.telegram.model.Help(
|
||||||
new TemplateContentGenerator(new LocalizedMessageFactory(velocityEngine)),
|
new TemplateContentGenerator(new LocalizedMessageFactory(velocityEngine)),
|
||||||
Executors.newSingleThreadExecutor(),
|
|
||||||
fakeClock,
|
fakeClock,
|
||||||
commands,
|
|
||||||
events,
|
|
||||||
new UUIDGenerator());
|
new UUIDGenerator());
|
||||||
|
|
||||||
|
help = new Help(Executors.newSingleThreadExecutor(), commands, events, modelHelp);
|
||||||
|
|
||||||
final Update update =
|
final Update update =
|
||||||
gson.fromJson(
|
gson.fromJson(
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.github.polpetta.mezzotre.telegram.command;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
||||||
|
import com.pengrad.telegrambot.model.Update;
|
||||||
|
import com.pengrad.telegrambot.request.BaseRequest;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.parallel.Execution;
|
||||||
|
import org.junit.jupiter.api.parallel.ExecutionMode;
|
||||||
|
|
||||||
|
@Execution(ExecutionMode.CONCURRENT)
|
||||||
|
class ProcessorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldGetSimpleNameClassIfNotDefined() {
|
||||||
|
|
||||||
|
class Test implements Processor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getTriggerKeywords() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<Optional<BaseRequest<?, ?>>> process(TgChat chat, Update update) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Test test = new Test();
|
||||||
|
|
||||||
|
assertEquals("test.cmdDescription", test.getLocaleDescriptionKeyword());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue