feat: add first changeLanguage event implementation
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
421909d5ae
commit
3705840989
8
pom.xml
8
pom.xml
|
@ -40,6 +40,7 @@
|
|||
<org.testcontainers.junit-jupiter.version>1.16.3</org.testcontainers.junit-jupiter.version>
|
||||
<jsonschema2pojo.version>1.1.1</jsonschema2pojo.version>
|
||||
<jackson-databind.version>2.13.3</jackson-databind.version>
|
||||
<junit-jupiter-params.version>5.9.1</junit-jupiter-params.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -68,6 +69,13 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${junit-jupiter-params.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.jooby</groupId>
|
||||
<artifactId>jooby-test</artifactId>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
"default": {},
|
||||
"required": [
|
||||
"event",
|
||||
"messageId",
|
||||
"telegramChatId"
|
||||
],
|
||||
"additionalProperties": true,
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.github.polpetta.mezzotre;
|
|||
import com.github.polpetta.mezzotre.orm.di.Db;
|
||||
import com.github.polpetta.mezzotre.route.Telegram;
|
||||
import com.github.polpetta.mezzotre.route.di.Route;
|
||||
import com.github.polpetta.mezzotre.telegram.callbackquery.di.CallbackQuery;
|
||||
import com.github.polpetta.mezzotre.telegram.command.di.Command;
|
||||
import com.github.polpetta.mezzotre.util.di.ThreadPool;
|
||||
import com.google.inject.*;
|
||||
|
@ -26,6 +27,7 @@ public class App extends Jooby {
|
|||
modules.add(new ThreadPool());
|
||||
modules.add(new Route());
|
||||
modules.add(new Command());
|
||||
modules.add(new CallbackQuery());
|
||||
return modules;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@ public class LocalizedMessageFactory {
|
|||
|
||||
public ToolManager create(Locale locale) {
|
||||
|
||||
// properties.setProperty("file.resource.loader.class", FileResourceLoader.class.getName());.
|
||||
|
||||
final ToolManager toolManager = new ToolManager();
|
||||
toolManager.setVelocityEngine(velocityEngine);
|
||||
final FactoryConfiguration factoryConfiguration = new FactoryConfiguration();
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.github.polpetta.mezzotre.orm.model;
|
|||
|
||||
import com.github.polpetta.types.json.CallbackQueryMetadata;
|
||||
import io.ebean.annotation.DbJson;
|
||||
import io.ebean.annotation.Length;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
@ -22,12 +23,19 @@ import javax.validation.constraints.NotNull;
|
|||
@Table(name = "callback_query_context")
|
||||
public class CallbackQueryContext extends Base {
|
||||
|
||||
@Id private final String id;
|
||||
@Id
|
||||
@Length(36)
|
||||
private final String id;
|
||||
|
||||
@NotNull
|
||||
@Length(36)
|
||||
private final String entryGroup;
|
||||
|
||||
@DbJson @NotNull private final CallbackQueryMetadata fields;
|
||||
|
||||
public CallbackQueryContext(String id, CallbackQueryMetadata fields) {
|
||||
public CallbackQueryContext(String id, String entryGroup, CallbackQueryMetadata fields) {
|
||||
this.id = id;
|
||||
this.entryGroup = entryGroup;
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
|
@ -35,6 +43,10 @@ public class CallbackQueryContext extends Base {
|
|||
return id;
|
||||
}
|
||||
|
||||
public String getEntryGroup() {
|
||||
return entryGroup;
|
||||
}
|
||||
|
||||
public CallbackQueryMetadata getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
|
|
@ -1,27 +1,157 @@
|
|||
package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||
|
||||
import com.github.polpetta.mezzotre.i18n.LocalizedMessageFactory;
|
||||
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.QTgChat;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
import com.pengrad.telegrambot.model.request.ParseMode;
|
||||
import com.pengrad.telegrambot.request.BaseRequest;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import io.vavr.control.Try;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Locale;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
import org.apache.velocity.tools.ToolManager;
|
||||
import org.apache.velocity.util.StringBuilderWriter;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@Singleton
|
||||
public class ChangeLanguage implements Processor {
|
||||
|
||||
public static final String EVENT_NAME = "changeLanguage";
|
||||
private final Executor threadPool;
|
||||
private final LocalizedMessageFactory localizedMessageFactory;
|
||||
private final Logger log;
|
||||
|
||||
public enum Field {
|
||||
NewLanguage("newLanguage");
|
||||
|
||||
private final String name;
|
||||
|
||||
Field(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Language {
|
||||
English("en-US"),
|
||||
Italian("it-IT");
|
||||
|
||||
private final String locale;
|
||||
|
||||
Language(String locale) {
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public String getLocale() {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
public ChangeLanguage() {}
|
||||
public ChangeLanguage(
|
||||
@Named("eventThreadPool") Executor threadPool,
|
||||
LocalizedMessageFactory localizedMessageFactory,
|
||||
Logger log) {
|
||||
this.threadPool = threadPool;
|
||||
this.localizedMessageFactory = localizedMessageFactory;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return "changeLanguage";
|
||||
return EVENT_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Optional<BaseRequest<?, ?>>> process(
|
||||
CallbackQueryContext callbackQueryContext, Update update) {
|
||||
return null;
|
||||
return CompletableFuture.supplyAsync(
|
||||
() ->
|
||||
Optional.of(callbackQueryContext.getFields().getTelegramChatId())
|
||||
.filter(
|
||||
chatId ->
|
||||
chatId.longValue() != 0L
|
||||
&& !chatId.isNaN()
|
||||
&& !chatId.isInfinite()
|
||||
&& chatId != Double.MIN_VALUE)
|
||||
.flatMap(chatId -> new QTgChat().id.eq(chatId.longValue()).findOneOrEmpty())
|
||||
.map(
|
||||
tgChat -> {
|
||||
tgChat.setLocale(
|
||||
(String)
|
||||
callbackQueryContext
|
||||
.getFields()
|
||||
.getAdditionalProperties()
|
||||
.getOrDefault(
|
||||
Field.NewLanguage.getName(),
|
||||
Language.English.getLocale()));
|
||||
tgChat.save();
|
||||
return tgChat;
|
||||
})
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new NoSuchElementException(
|
||||
"Unable to find telegram chat "
|
||||
+ Double.valueOf(
|
||||
callbackQueryContext.getFields().getTelegramChatId())
|
||||
.longValue()
|
||||
+ " in the database")),
|
||||
threadPool)
|
||||
.thenApplyAsync(
|
||||
// If we are here then we're sure there is at least a chat associated with this callback
|
||||
tgChat -> {
|
||||
final String message =
|
||||
Try.of(
|
||||
() -> {
|
||||
final Locale locale = Locale.forLanguageTag(tgChat.getLocale());
|
||||
final ToolManager toolManager = localizedMessageFactory.create(locale);
|
||||
final VelocityContext velocityContext =
|
||||
new VelocityContext(toolManager.createContext());
|
||||
|
||||
final StringBuilder content = new StringBuilder();
|
||||
final StringBuilderWriter stringBuilderWriter =
|
||||
new StringBuilderWriter(content);
|
||||
|
||||
toolManager
|
||||
.getVelocityEngine()
|
||||
.mergeTemplate(
|
||||
"/template/callbackQuery/changeLanguage.vm",
|
||||
StandardCharsets.UTF_8.name(),
|
||||
velocityContext,
|
||||
stringBuilderWriter);
|
||||
|
||||
stringBuilderWriter.close();
|
||||
return content.toString();
|
||||
})
|
||||
.get();
|
||||
|
||||
log.trace("ChangeLanguage event - message to send back: " + message);
|
||||
|
||||
final String callBackGroupToDelete = callbackQueryContext.getEntryGroup();
|
||||
final int delete =
|
||||
new QCallbackQueryContext().entryGroup.eq(callBackGroupToDelete).delete();
|
||||
log.trace(
|
||||
"Deleted "
|
||||
+ delete
|
||||
+ " entries regarding callback group "
|
||||
+ callBackGroupToDelete);
|
||||
|
||||
return Optional.of(
|
||||
new SendMessage(tgChat.getId(), message).parseMode(ParseMode.Markdown));
|
||||
},
|
||||
threadPool);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
package com.github.polpetta.mezzotre.telegram.command;
|
||||
|
||||
import com.github.polpetta.mezzotre.i18n.LocalizedMessageFactory;
|
||||
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
||||
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
||||
import com.github.polpetta.mezzotre.telegram.callbackquery.ChangeLanguage;
|
||||
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.google.inject.Singleton;
|
||||
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.SendMessage;
|
||||
|
@ -13,6 +20,7 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
|
@ -29,18 +37,24 @@ import org.slf4j.Logger;
|
|||
@Singleton
|
||||
public class Start implements Processor {
|
||||
|
||||
private final java.util.concurrent.Executor threadPool;
|
||||
private final Executor threadPool;
|
||||
private final Logger log;
|
||||
private final UUIDGenerator uuidGenerator;
|
||||
private final Clock clock;
|
||||
private final LocalizedMessageFactory localizedMessageFactory;
|
||||
|
||||
@Inject
|
||||
public Start(
|
||||
LocalizedMessageFactory localizedMessageFactory,
|
||||
@Named("eventThreadPool") java.util.concurrent.Executor threadPool,
|
||||
Logger log) {
|
||||
@Named("eventThreadPool") Executor threadPool,
|
||||
Logger log,
|
||||
UUIDGenerator uuidGenerator,
|
||||
Clock clock) {
|
||||
this.localizedMessageFactory = localizedMessageFactory;
|
||||
this.threadPool = threadPool;
|
||||
this.log = log;
|
||||
this.uuidGenerator = uuidGenerator;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,17 +76,17 @@ public class Start implements Processor {
|
|||
Try.of(
|
||||
() -> {
|
||||
final Locale locale = Locale.forLanguageTag(chat.getLocale());
|
||||
final ToolManager toolContext = localizedMessageFactory.create(locale);
|
||||
final ToolManager toolManager = localizedMessageFactory.create(locale);
|
||||
final VelocityContext context =
|
||||
new VelocityContext(toolContext.createContext());
|
||||
new VelocityContext(toolManager.createContext());
|
||||
context.put("firstName", update.message().chat().firstName());
|
||||
context.put("programName", "Mezzotre");
|
||||
context.put("programName", "_Mezzotre_");
|
||||
|
||||
final StringBuilder content = new StringBuilder();
|
||||
final StringBuilderWriter stringBuilderWriter =
|
||||
new StringBuilderWriter(content);
|
||||
|
||||
toolContext
|
||||
toolManager
|
||||
.getVelocityEngine()
|
||||
.mergeTemplate(
|
||||
"template/command/start.0.vm",
|
||||
|
@ -87,14 +101,51 @@ public class Start implements Processor {
|
|||
log.trace("Start command - message to send back: " + message);
|
||||
|
||||
final ChatContext chatContext = chat.getChatContext();
|
||||
chatContext.setLastMessageSentId(update.message().messageId());
|
||||
chatContext.setStage(getTriggerKeyword());
|
||||
chatContext.setStep(0);
|
||||
chatContext.setPreviousMessageUnixTimestampInSeconds(update.message().date());
|
||||
chatContext.setPreviousMessageUnixTimestampInSeconds(clock.now());
|
||||
chat.setChatContext(chatContext);
|
||||
chat.save();
|
||||
|
||||
return Optional.of(new SendMessage(chat.getId(), message).parseMode(ParseMode.Markdown));
|
||||
// To get the messageId we should send the message first, then save it in the database!
|
||||
final String groupId = uuidGenerator.generateAsString();
|
||||
final CallbackQueryContext switchToEnglish =
|
||||
new CallbackQueryContext(
|
||||
uuidGenerator.generateAsString(),
|
||||
groupId,
|
||||
new CallbackQueryMetadata.CallbackQueryMetadataBuilder()
|
||||
.withEvent(ChangeLanguage.EVENT_NAME)
|
||||
.withTelegramChatId(update.message().chat().id())
|
||||
.withAdditionalProperty(
|
||||
ChangeLanguage.Field.NewLanguage.getName(),
|
||||
ChangeLanguage.Language.English)
|
||||
.build());
|
||||
|
||||
final CallbackQueryContext switchToItalian =
|
||||
new CallbackQueryContext(
|
||||
uuidGenerator.generateAsString(),
|
||||
groupId,
|
||||
new CallbackQueryMetadata.CallbackQueryMetadataBuilder()
|
||||
.withEvent(ChangeLanguage.EVENT_NAME)
|
||||
.withTelegramChatId(update.message().chat().id())
|
||||
.withAdditionalProperty(
|
||||
ChangeLanguage.Field.NewLanguage.getName(),
|
||||
ChangeLanguage.Language.Italian)
|
||||
.build());
|
||||
|
||||
final SendMessage messageToSend =
|
||||
new SendMessage(chat.getId(), message)
|
||||
.parseMode(ParseMode.Markdown)
|
||||
.replyMarkup(
|
||||
new InlineKeyboardMarkup(
|
||||
new InlineKeyboardButton("English").callbackData(switchToEnglish.getId()),
|
||||
new InlineKeyboardButton("Italian")
|
||||
.callbackData(switchToItalian.getId())));
|
||||
|
||||
switchToEnglish.save();
|
||||
switchToItalian.save();
|
||||
|
||||
return Optional.of(messageToSend);
|
||||
},
|
||||
threadPool);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
start.hello=Hello
|
||||
start.thisIs=This is
|
||||
start.description=a simple bot focused on DnD content management! Please start by choosing a language down below.
|
||||
start.helloFirstName=Hello {0}! \ud83d\udc4b
|
||||
start.description=This is {0}, a simple bot focused on DnD content management! Please start by choosing a language down below \ud83d\udc47
|
||||
changeLanguage.drinkAction=*Proceeds to drink a potion with a strange, multicolor liquid*
|
||||
changeLanguage.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 you prefer!
|
||||
changeLanguage.instructions=You can always change your language settings by typing /changeLanguage in the chat.
|
||||
spell.speakWithAnimals=Speak with animals
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
start.hello=Hello
|
||||
start.thisIs=This is
|
||||
start.description=a simple bot focused on DnD content management! Please start by choosing a language down below.
|
||||
start.helloFirstName=Hello {0}! \ud83d\udc4b
|
||||
start.description=This is {0}, a simple bot focused on DnD content management! Please start by choosing a language down below \ud83d\udc47
|
||||
changeLanguage.drinkAction=*Proceeds to drink a potion with a strange, multicolor liquid*
|
||||
changeLanguage.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 you prefer!
|
||||
changeLanguage.instructions=You can always change your language settings by typing /changeLanguage in the chat.
|
||||
spell.speakWithAnimals=Speak with animals
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
start.hello=Ciao
|
||||
start.thisIs=Questo è
|
||||
start.description=un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto
|
||||
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
|
||||
changeLanguage.drinkAction=*Procede a bere una pozione al cui suo interno si trova uno strano liquido multicolore*
|
||||
changeLanguage.setLanguage=Grazie! Ora che ho bevuto quest posizione modificata di {0} che ho trovato ieri al negozio di pozioni magiche la "Cristalleria Fermentatrice" posso parlare con te nel linguaggio che preferisci!
|
||||
changeLanguage.instructions=Puoi sempre cambiare le preferenze della tua lingua scrivendo /changeLanguage nella chat.
|
||||
spell.speakWithAnimals=Parlare con animali
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
start.hello=Ciao
|
||||
start.thisIs=Questo è
|
||||
start.description=un semplice bot che ci concenta sulla gestione di contenuto per DnD! Per favore comincia selezionando la lingua qui sotto
|
||||
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
|
||||
changeLanguage.drinkAction=*Procede a bere una pozione al cui suo interno si trova uno strano liquido multicolore*
|
||||
changeLanguage.setLanguage=Grazie! Ora che ho bevuto quest posizione modificata di {0} che ho trovato ieri al negozio di pozioni magiche la "Cristalleria Fermentatrice" posso parlare con te nel linguaggio che preferisci!
|
||||
changeLanguage.instructions=Puoi sempre cambiare le preferenze della tua lingua scrivendo /changeLanguage nella chat.
|
||||
spell.speakWithAnimals=Parlare con animali
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
_${i18n.changeLanguage.drinkAction}_
|
||||
|
||||
${i18n.changeLanguage.setLanguage.insert(${i18n.spell.speakWithAnimals})}
|
||||
|
||||
${i18n.changeLanguage.instructions}
|
|
@ -1,4 +1,3 @@
|
|||
## https://velocity.apache.org/tools/2.0/apidocs/org/apache/velocity/tools/generic/ResourceTool.html
|
||||
**$i18n.start.hello $firstName! 👋**
|
||||
**${i18n.start.helloFirstName.insert(${firstName})}**
|
||||
|
||||
$i18n.start.thisIs _${programName}_, $i18n.start.description 👇
|
||||
${i18n.start.description.insert(${programName})}
|
|
@ -11,6 +11,9 @@ import java.io.InputStream;
|
|||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.runtime.RuntimeConstants;
|
||||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
public class Loader {
|
||||
|
@ -49,4 +52,13 @@ public class Loader {
|
|||
public static Database connectToDatabase(Pair<Properties, Properties> connectionProperties) {
|
||||
return connectToDatabase(connectionProperties.getLeft(), connectionProperties.getRight());
|
||||
}
|
||||
|
||||
public static VelocityEngine defaultVelocityEngine() {
|
||||
final VelocityEngine velocityEngine = new VelocityEngine();
|
||||
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADERS, "classpath");
|
||||
velocityEngine.setProperty(
|
||||
"resource.loader.classpath.class", ClasspathResourceLoader.class.getName());
|
||||
velocityEngine.init();
|
||||
return velocityEngine;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ class TelegramIntegrationTest {
|
|||
final CallbackQueryContext callbackQueryContext =
|
||||
new CallbackQueryContext(
|
||||
"41427473-0d81-40a8-af60-9517163615a4",
|
||||
"2ee7f5c6-93f0-4859-b902-af9476cf74ad",
|
||||
new CallbackQueryMetadata.CallbackQueryMetadataBuilder()
|
||||
.withTelegramChatId(666L)
|
||||
.withMessageId(42L)
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
package com.github.polpetta.mezzotre.telegram.callbackquery;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import com.github.polpetta.mezzotre.helper.Loader;
|
||||
import com.github.polpetta.mezzotre.helper.TestConfig;
|
||||
import com.github.polpetta.mezzotre.i18n.LocalizedMessageFactory;
|
||||
import com.github.polpetta.mezzotre.orm.model.CallbackQueryContext;
|
||||
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
||||
import com.github.polpetta.mezzotre.orm.model.query.QCallbackQueryContext;
|
||||
import com.github.polpetta.mezzotre.orm.model.query.QTgChat;
|
||||
import com.github.polpetta.types.json.CallbackQueryMetadata;
|
||||
import com.github.polpetta.types.json.ChatContext;
|
||||
import com.google.gson.Gson;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
import com.pengrad.telegrambot.request.BaseRequest;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import io.ebean.Database;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
@Tag("slow")
|
||||
@Tag("database")
|
||||
@Tag("velocity")
|
||||
@Testcontainers
|
||||
class ChangeLanguageIntegrationTest {
|
||||
|
||||
private static Gson gson;
|
||||
|
||||
@Container
|
||||
private final PostgreSQLContainer<?> postgresServer =
|
||||
new PostgreSQLContainer<>(TestConfig.POSTGRES_DOCKER_IMAGE);
|
||||
|
||||
private Database database;
|
||||
private ChangeLanguage changeLanguage;
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() {
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
database =
|
||||
Loader.connectToDatabase(Loader.loadDefaultEbeanConfigWithPostgresSettings(postgresServer));
|
||||
|
||||
changeLanguage =
|
||||
new ChangeLanguage(
|
||||
Executors.newSingleThreadExecutor(),
|
||||
new LocalizedMessageFactory(Loader.defaultVelocityEngine()),
|
||||
LoggerFactory.getLogger(ChangeLanguage.class));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> getTestLocales() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
ChangeLanguage.Language.Italian,
|
||||
"_*Procede a bere una pozione al cui suo interno si trova uno strano liquido"
|
||||
+ " multicolore*_\n"
|
||||
+ "\n"
|
||||
+ "Grazie! Ora che ho bevuto quest posizione modificata di Parlare con animali che"
|
||||
+ " ho trovato ieri al negozio di pozioni magiche la \"Cristalleria Fermentatrice\""
|
||||
+ " posso parlare con te nel linguaggio che preferisci!\n"
|
||||
+ "\n"
|
||||
+ "Puoi sempre cambiare le preferenze della tua lingua scrivendo /changeLanguage"
|
||||
+ " nella chat.",
|
||||
"en-US"),
|
||||
Arguments.of(
|
||||
ChangeLanguage.Language.English,
|
||||
"_*Proceeds to drink a potion with a strange, multicolor liquid*_\n"
|
||||
+ "\n"
|
||||
+ "Thanks! Now that I drank this modified potion of Speak with animals that I've"
|
||||
+ " found at the \"Crystal Fermentary\" magic potion shop yesterday I can speak"
|
||||
+ " with you in the language you prefer!\n"
|
||||
+ "\n"
|
||||
+ "You can always change your language settings by typing /changeLanguage in the"
|
||||
+ " chat.",
|
||||
"it-IT"));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@Timeout(value = 1, unit = TimeUnit.MINUTES)
|
||||
@MethodSource("getTestLocales")
|
||||
void shouldProcessChangeLanguageToDesiredOne(
|
||||
ChangeLanguage.Language language, String expectedResult, String startingLocale)
|
||||
throws Exception {
|
||||
|
||||
final Update update =
|
||||
gson.fromJson(
|
||||
"{\n"
|
||||
+ "\"update_id\":10000,\n"
|
||||
+ "\"callback_query\":{\n"
|
||||
+ " \"id\": \"4382bfdwdsb323b2d9\",\n"
|
||||
+ " \"from\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"type\": \"private\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"data\": \"Data from button callback\",\n"
|
||||
+ " \"inline_message_id\": \"1234csdbsk4839\"\n"
|
||||
+ "}\n"
|
||||
+ "}",
|
||||
Update.class);
|
||||
|
||||
final long tgChatId = 1111111L;
|
||||
final ChatContext chatContext = new ChatContext();
|
||||
final TgChat tgChat = new TgChat(tgChatId, chatContext, startingLocale);
|
||||
tgChat.save();
|
||||
|
||||
final CallbackQueryMetadata callbackQueryMetadata =
|
||||
new CallbackQueryMetadata.CallbackQueryMetadataBuilder()
|
||||
.withEvent("changeLanguage")
|
||||
.withTelegramChatId(tgChatId)
|
||||
.withAdditionalProperty(
|
||||
ChangeLanguage.Field.NewLanguage.getName(), language.getLocale())
|
||||
.build();
|
||||
final String entryGroupId = "2e67774a-e4e4-4369-a414-a7f8bfe74b80";
|
||||
final CallbackQueryContext changeLanguageCallbackQueryContext =
|
||||
new CallbackQueryContext(
|
||||
"c018108f-6612-4848-8fca-cf301460d4eb", entryGroupId, callbackQueryMetadata);
|
||||
changeLanguageCallbackQueryContext.save();
|
||||
|
||||
final CompletableFuture<Optional<BaseRequest<?, ?>>> processFuture =
|
||||
changeLanguage.process(changeLanguageCallbackQueryContext, update);
|
||||
final Optional<BaseRequest<?, ?>> gotResponseOpt = processFuture.get();
|
||||
final SendMessage gotMessage = (SendMessage) gotResponseOpt.get();
|
||||
assertEquals(expectedResult, gotMessage.getParameters().get("text"));
|
||||
|
||||
final TgChat retrievedTgChat = new QTgChat().id.eq(tgChatId).findOne();
|
||||
assertNotNull(retrievedTgChat);
|
||||
assertEquals(language.getLocale(), retrievedTgChat.getLocale());
|
||||
|
||||
assertEquals(0, new QCallbackQueryContext().entryGroup.eq(entryGroupId).findCount());
|
||||
}
|
||||
}
|
|
@ -1,12 +1,15 @@
|
|||
package com.github.polpetta.mezzotre.telegram.command;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.github.polpetta.mezzotre.helper.Loader;
|
||||
import com.github.polpetta.mezzotre.helper.TestConfig;
|
||||
import com.github.polpetta.mezzotre.i18n.LocalizedMessageFactory;
|
||||
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
||||
import com.github.polpetta.mezzotre.orm.model.query.QTgChat;
|
||||
import com.github.polpetta.mezzotre.util.Clock;
|
||||
import com.github.polpetta.mezzotre.util.UUIDGenerator;
|
||||
import com.github.polpetta.types.json.ChatContext;
|
||||
import com.google.gson.Gson;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
|
@ -15,6 +18,7 @@ import com.pengrad.telegrambot.request.SendMessage;
|
|||
import io.ebean.Database;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.runtime.RuntimeConstants;
|
||||
|
@ -45,6 +49,8 @@ class StartIntegrationTest {
|
|||
private LocalizedMessageFactory localizedMessageFactory;
|
||||
private Start start;
|
||||
private Database database;
|
||||
private Clock fakeClock;
|
||||
private UUIDGenerator fakeUUIDGenerator;
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() {
|
||||
|
@ -64,11 +70,25 @@ class StartIntegrationTest {
|
|||
|
||||
final Logger log = LoggerFactory.getLogger(Start.class);
|
||||
|
||||
start = new Start(localizedMessageFactory, Executors.newSingleThreadExecutor(), log);
|
||||
fakeClock = mock(Clock.class);
|
||||
fakeUUIDGenerator = mock(UUIDGenerator.class);
|
||||
|
||||
start =
|
||||
new Start(
|
||||
localizedMessageFactory,
|
||||
Executors.newSingleThreadExecutor(),
|
||||
log,
|
||||
fakeUUIDGenerator,
|
||||
fakeClock);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateContextInTheDatabase() throws Exception {
|
||||
when(fakeClock.now()).thenReturn(42L);
|
||||
when(fakeUUIDGenerator.generateAsString())
|
||||
.thenReturn("e86e6fa1-fdd4-4120-b85d-a5482db2e8b5")
|
||||
.thenReturn("16507fbd-9f28-48a8-9de1-3ea1c943af67")
|
||||
.thenReturn("0b0ac18e-f621-484e-aa8d-9b176be5b930");
|
||||
final TgChat tgChat = new TgChat(1111111L, new ChatContext());
|
||||
tgChat.setLocale("en-US");
|
||||
tgChat.save();
|
||||
|
@ -108,16 +128,104 @@ class StartIntegrationTest {
|
|||
assertEquals(
|
||||
"**Hello Test Firstname! \uD83D\uDC4B**\n\n"
|
||||
+ "This is _Mezzotre_, a simple bot focused on DnD content management! Please start by"
|
||||
+ " choosing a language down below. \uD83D\uDC47",
|
||||
+ " choosing a language down below \uD83D\uDC47",
|
||||
message);
|
||||
assertEquals(1111111L, (Long) gotMessage.getParameters().get("chat_id"));
|
||||
|
||||
final TgChat retrievedTgChat = new QTgChat().id.eq(1111111L).findOne();
|
||||
assertNotNull(retrievedTgChat);
|
||||
final ChatContext gotChatContext = retrievedTgChat.getChatContext();
|
||||
assertEquals(1441645532, gotChatContext.getPreviousMessageUnixTimestampInSeconds());
|
||||
assertEquals(1365, gotChatContext.getLastMessageSentId());
|
||||
assertEquals(42, gotChatContext.getPreviousMessageUnixTimestampInSeconds());
|
||||
assertEquals(0, gotChatContext.getLastMessageSentId());
|
||||
assertEquals("/start", gotChatContext.getStage());
|
||||
assertEquals(0, gotChatContext.getStep());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReceiveHelloIntroduction() throws Exception {
|
||||
when(fakeClock.now()).thenReturn(42L);
|
||||
when(fakeUUIDGenerator.generateAsString())
|
||||
.thenReturn("e86e6fa1-fdd4-4120-b85d-a5482db2e8b5")
|
||||
.thenReturn("16507fbd-9f28-48a8-9de1-3ea1c943af67")
|
||||
.thenReturn("0b0ac18e-f621-484e-aa8d-9b176be5b930");
|
||||
|
||||
final TgChat tgChat = new TgChat(1111111L, new ChatContext(), "en-US");
|
||||
|
||||
final Update update =
|
||||
gson.fromJson(
|
||||
"{\n"
|
||||
+ "\"update_id\":10000,\n"
|
||||
+ "\"message\":{\n"
|
||||
+ " \"date\":1441645532,\n"
|
||||
+ " \"chat\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"type\": \"private\",\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"message_id\":1365,\n"
|
||||
+ " \"from\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"text\":\"/start\"\n"
|
||||
+ "}\n"
|
||||
+ "}",
|
||||
Update.class);
|
||||
|
||||
final CompletableFuture<Optional<BaseRequest<?, ?>>> gotFuture = start.process(tgChat, update);
|
||||
assertDoesNotThrow(() -> gotFuture.get());
|
||||
final Optional<BaseRequest<?, ?>> gotMessageOptional = gotFuture.get();
|
||||
assertDoesNotThrow(gotMessageOptional::get);
|
||||
final BaseRequest<?, ?> gotMessage = gotMessageOptional.get();
|
||||
assertInstanceOf(SendMessage.class, gotMessage);
|
||||
final String message = (String) gotMessage.getParameters().get("text");
|
||||
assertEquals(
|
||||
"**Hello Test Firstname! \uD83D\uDC4B**\n\n"
|
||||
+ "This is _Mezzotre_, a simple bot focused on DnD content management! Please start by"
|
||||
+ " choosing a language down below \uD83D\uDC47",
|
||||
message);
|
||||
assertEquals(1111111L, (Long) gotMessage.getParameters().get("chat_id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowErrorIfLocaleNonExists() {
|
||||
when(fakeClock.now()).thenReturn(42L);
|
||||
when(fakeUUIDGenerator.generateAsString())
|
||||
.thenReturn("e86e6fa1-fdd4-4120-b85d-a5482db2e8b5")
|
||||
.thenReturn("16507fbd-9f28-48a8-9de1-3ea1c943af67")
|
||||
.thenReturn("0b0ac18e-f621-484e-aa8d-9b176be5b930");
|
||||
final TgChat tgChat = new TgChat(1111111L, null);
|
||||
|
||||
final Update update =
|
||||
gson.fromJson(
|
||||
"{\n"
|
||||
+ "\"update_id\":10000,\n"
|
||||
+ "\"message\":{\n"
|
||||
+ " \"date\":1441645532,\n"
|
||||
+ " \"chat\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"type\": \"private\",\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"message_id\":1365,\n"
|
||||
+ " \"from\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"text\":\"/start\"\n"
|
||||
+ "}\n"
|
||||
+ "}",
|
||||
Update.class);
|
||||
|
||||
final CompletableFuture<Optional<BaseRequest<?, ?>>> gotFuture = start.process(tgChat, update);
|
||||
assertThrows(ExecutionException.class, gotFuture::get);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
package com.github.polpetta.mezzotre.telegram.command;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.github.polpetta.mezzotre.i18n.LocalizedMessageFactory;
|
||||
import com.github.polpetta.mezzotre.orm.model.TgChat;
|
||||
import com.github.polpetta.types.json.ChatContext;
|
||||
import com.google.gson.Gson;
|
||||
import com.pengrad.telegrambot.model.Update;
|
||||
import com.pengrad.telegrambot.request.BaseRequest;
|
||||
import com.pengrad.telegrambot.request.SendMessage;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
import org.apache.velocity.runtime.RuntimeConstants;
|
||||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.parallel.Execution;
|
||||
import org.junit.jupiter.api.parallel.ExecutionMode;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@Tag("velocity")
|
||||
@Execution(ExecutionMode.CONCURRENT)
|
||||
class StartTest {
|
||||
|
||||
private VelocityEngine velocityEngine;
|
||||
private LocalizedMessageFactory localizedMessageFactory;
|
||||
private Start start;
|
||||
private static Gson gson;
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() {
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
velocityEngine = new VelocityEngine();
|
||||
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADERS, "classpath");
|
||||
velocityEngine.setProperty(
|
||||
"resource.loader.classpath.class", ClasspathResourceLoader.class.getName());
|
||||
velocityEngine.init();
|
||||
localizedMessageFactory = new LocalizedMessageFactory(velocityEngine);
|
||||
|
||||
final Logger fakeLog = mock(Logger.class);
|
||||
|
||||
start = new Start(localizedMessageFactory, Executors.newSingleThreadExecutor(), fakeLog);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReceiveHelloIntroduction() throws Exception {
|
||||
final TgChat fakeChat = mock(TgChat.class);
|
||||
when(fakeChat.getLocale()).thenReturn("en-US");
|
||||
when(fakeChat.getChatContext()).thenReturn(new ChatContext());
|
||||
when(fakeChat.getId()).thenReturn(1111111L);
|
||||
|
||||
final Update update =
|
||||
gson.fromJson(
|
||||
"{\n"
|
||||
+ "\"update_id\":10000,\n"
|
||||
+ "\"message\":{\n"
|
||||
+ " \"date\":1441645532,\n"
|
||||
+ " \"chat\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"type\": \"private\",\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"message_id\":1365,\n"
|
||||
+ " \"from\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"text\":\"/start\"\n"
|
||||
+ "}\n"
|
||||
+ "}",
|
||||
Update.class);
|
||||
|
||||
final CompletableFuture<Optional<BaseRequest<?, ?>>> gotFuture =
|
||||
start.process(fakeChat, update);
|
||||
assertDoesNotThrow(() -> gotFuture.get());
|
||||
final Optional<BaseRequest<?, ?>> gotMessageOptional = gotFuture.get();
|
||||
assertDoesNotThrow(gotMessageOptional::get);
|
||||
final BaseRequest<?, ?> gotMessage = gotMessageOptional.get();
|
||||
assertInstanceOf(SendMessage.class, gotMessage);
|
||||
final String message = (String) gotMessage.getParameters().get("text");
|
||||
assertEquals(
|
||||
"**Hello Test Firstname! \uD83D\uDC4B**\n\n"
|
||||
+ "This is _Mezzotre_, a simple bot focused on DnD content management! Please start by"
|
||||
+ " choosing a language down below. \uD83D\uDC47",
|
||||
message);
|
||||
assertEquals(1111111L, (Long) gotMessage.getParameters().get("chat_id"));
|
||||
verify(fakeChat, times(1)).save();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowErrorIfLocaleNonExists() {
|
||||
final TgChat fakeChat = mock(TgChat.class);
|
||||
// Do not set Locale on purpose
|
||||
when(fakeChat.getId()).thenReturn(1111111L);
|
||||
|
||||
final Update update =
|
||||
gson.fromJson(
|
||||
"{\n"
|
||||
+ "\"update_id\":10000,\n"
|
||||
+ "\"message\":{\n"
|
||||
+ " \"date\":1441645532,\n"
|
||||
+ " \"chat\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"type\": \"private\",\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"message_id\":1365,\n"
|
||||
+ " \"from\":{\n"
|
||||
+ " \"last_name\":\"Test Lastname\",\n"
|
||||
+ " \"id\":1111111,\n"
|
||||
+ " \"first_name\":\"Test Firstname\",\n"
|
||||
+ " \"username\":\"Testusername\"\n"
|
||||
+ " },\n"
|
||||
+ " \"text\":\"/start\"\n"
|
||||
+ "}\n"
|
||||
+ "}",
|
||||
Update.class);
|
||||
|
||||
final CompletableFuture<Optional<BaseRequest<?, ?>>> gotFuture =
|
||||
start.process(fakeChat, update);
|
||||
assertThrows(ExecutionException.class, gotFuture::get);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue