From 49cc3fb896cd0b19a92500204617af4a36945774 Mon Sep 17 00:00:00 2001 From: davioooh Date: Wed, 18 Apr 2018 17:14:32 +0200 Subject: [PATCH 01/22] Add basic internationalization support --- .../abilitybots/api/bot/AbilityBot.java | 50 ++++++++++++------- .../abilitybots/api/objects/EndUser.java | 21 ++++++-- .../abilitybots/api/util/AbilityUtils.java | 26 ++++++++++ .../resources/default_messages.properties | 22 ++++++++ .../abilitybots/api/bot/AbilityBotTest.java | 1 + 5 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 telegrambots-abilities/src/main/resources/default_messages.properties diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index a9c4e0e3..48296835 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -103,6 +103,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { protected static final String COMMANDS = "commands"; // Messages + // TODO replace hardcoded messages... protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; protected static final String RECOVER_SUCCESS = "I have successfully recovered."; @@ -306,7 +307,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { }) .sorted() .reduce((a, b) -> format("%s%n%s", a, b)) - .orElse("No public commands found."); + .orElse(getLocalizedMessage("ability.commands.notFound", ctx.user().locale())); silent.send(commands, ctx.chatId()); }) @@ -371,11 +372,13 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (db.recover(backupData)) { silent.send(RECOVER_SUCCESS, chatId); } else { - silent.send("Oops, something went wrong during recovery.", chatId); + silent.send(getLocalizedMessage("ability.recover.fail", + AbilityUtils.getUser(update).getLanguageCode()), chatId); } } catch (Exception e) { BotLogger.error("Could not recover DB from backup", TAG, e); - silent.send("I have failed to recover.", chatId); + silent.send(getLocalizedMessage("ability.recover.error", + AbilityUtils.getUser(update).getLanguageCode()), chatId); } }, MESSAGE, DOCUMENT, REPLY, isReplyTo(RECOVERY_MESSAGE)) .build(); @@ -411,10 +414,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (blacklist.contains(userId)) - silent.sendMd(format("%s is already *banned*.", escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.ban.alreadyBanned", ctx.user().locale(), escape(bannedUser)), ctx.chatId()); else { blacklist.add(userId); - silent.sendMd(format("%s is now *banned*.", escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.ban.banned", ctx.user().locale(), escape(bannedUser)), ctx.chatId()); } }) .post(commitTo(db)) @@ -439,9 +442,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (!blacklist.remove(userId)) - silent.sendMd(format("@%s is *not* on the *blacklist*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.unban.notBanned", ctx.user().locale(), escape(username)), ctx.chatId()); else { - silent.sendMd(format("@%s, your ban has been *lifted*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.unban.lifted", ctx.user().locale(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -463,10 +466,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.contains(userId)) - silent.sendMd(format("@%s is already an *admin*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.promote.alreadyPromoted", ctx.user().locale(), escape(username)), ctx.chatId()); else { admins.add(userId); - silent.sendMd(format("@%s has been *promoted*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.promote.promoted", ctx.user().locale(), escape(username)), ctx.chatId()); } }).post(commitTo(db)) .build(); @@ -487,9 +490,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.remove(userId)) { - silent.sendMd(format("@%s has been *demoted*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.demote.demoted", ctx.user().locale(), escape(username)), ctx.chatId()); } else { - silent.sendMd(format("@%s is *not* an *admin*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.demote.alreadyDemoted", ctx.user().locale(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -514,10 +517,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { long chatId = ctx.chatId(); if (admins.contains(id)) - silent.send("You're already my master.", chatId); + silent.send(getLocalizedMessage("ability.claim.alreadyClaimed", ctx.user().locale()), chatId); else { admins.add(id); - silent.send("You're now my master.", chatId); + silent.send(getLocalizedMessage("ability.claim.claimed", ctx.user().locale()), chatId); } } else { // This is not a joke @@ -615,7 +618,12 @@ public abstract class AbilityBot extends TelegramLongPollingBot { boolean isOk = abilityTokens == 0 || (tokens.length > 0 && tokens.length == abilityTokens); if (!isOk) - silent.send(format("Sorry, this feature requires %d additional %s.", abilityTokens, abilityTokens == 1 ? "input" : "inputs"), getChatId(trio.a())); + silent.send( + getLocalizedMessage( + "checkInput.fail", + AbilityUtils.getUser(trio.a()).getLanguageCode(), + abilityTokens, abilityTokens == 1 ? "input" : "inputs"), + getChatId(trio.a())); return isOk; } @@ -627,7 +635,12 @@ public abstract class AbilityBot extends TelegramLongPollingBot { boolean isOk = abilityLocality == ALL || locality == abilityLocality; if (!isOk) - silent.send(format("Sorry, %s-only feature.", abilityLocality.toString().toLowerCase()), getChatId(trio.a())); + silent.send( + getLocalizedMessage( + "checkLocality.fail", + AbilityUtils.getUser(trio.a()).getLanguageCode(), + abilityLocality.toString().toLowerCase()), + getChatId(trio.a())); return isOk; } @@ -642,8 +655,11 @@ public abstract class AbilityBot extends TelegramLongPollingBot { boolean isOk = privacy.compareTo(trio.b().privacy()) >= 0; if (!isOk) - silent.send("Sorry, you don't have the required access level to do that.", getChatId(trio.a())); - + silent.send( + getLocalizedMessage( + "checkPrivacy.fail", + AbilityUtils.getUser(trio.a()).getLanguageCode()), + getChatId(trio.a())); return isOk; } diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java index 7cc08145..0c123434 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java @@ -1,11 +1,14 @@ package org.telegram.abilitybots.api.objects; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.MoreObjects; +import com.google.common.base.Strings; import org.telegram.telegrambots.api.objects.User; import java.io.Serializable; +import java.util.Locale; import java.util.Objects; import java.util.StringJoiner; @@ -27,12 +30,15 @@ public final class EndUser implements Serializable { private final String lastName; @JsonProperty("username") private final String username; + @JsonIgnore + private Locale locale; - private EndUser(Integer id, String firstName, String lastName, String username) { + private EndUser(Integer id, String firstName, String lastName, String username, Locale locale) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.username = username; + this.locale = locale != null? locale : Locale.ENGLISH; } @JsonCreator @@ -40,7 +46,7 @@ public final class EndUser implements Serializable { @JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName, @JsonProperty("username") String username) { - return new EndUser(id, firstName, lastName, username); + return new EndUser(id, firstName, lastName, username, null); } /** @@ -50,7 +56,8 @@ public final class EndUser implements Serializable { * @return an augmented end-user */ public static EndUser fromUser(User user) { - return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName()); + Locale locale = Strings.isNullOrEmpty(user.getLanguageCode()) ? null : Locale.forLanguageTag(user.getLanguageCode()); + return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName(), locale); } public int id() { @@ -69,6 +76,8 @@ public final class EndUser implements Serializable { return username; } + public Locale locale() { return locale; } + /** * The full name is identified as the concatenation of the first and last name, separated by a space. * This method can return an empty name if both first and last name are empty. @@ -118,12 +127,13 @@ public final class EndUser implements Serializable { return Objects.equals(id, endUser.id) && Objects.equals(firstName, endUser.firstName) && Objects.equals(lastName, endUser.lastName) && - Objects.equals(username, endUser.username); + Objects.equals(username, endUser.username) && + Objects.equals(locale, endUser.locale); } @Override public int hashCode() { - return Objects.hash(id, firstName, lastName, username); + return Objects.hash(id, firstName, lastName, username, locale); } @Override @@ -133,6 +143,7 @@ public final class EndUser implements Serializable { .add("firstName", firstName) .add("lastName", lastName) .add("username", username) + .add("locale", locale.toString()) .toString(); } } diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java index 8852170f..c6d3e554 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java @@ -1,10 +1,15 @@ package org.telegram.abilitybots.api.util; +import com.google.common.base.Strings; import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.objects.MessageContext; import org.telegram.telegrambots.api.objects.Update; import org.telegram.telegrambots.api.objects.User; +import java.text.MessageFormat; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; import java.util.function.Consumer; import java.util.function.Predicate; @@ -150,4 +155,25 @@ public final class AbilityUtils { public static Predicate isReplyTo(String msg) { return update -> update.getMessage().getReplyToMessage().getText().equals(msg); } + + public static String getLocalizedMessage(String messageCode, Locale locale, Object...arguments) { + ResourceBundle bundle; + if(locale == null){ + bundle = ResourceBundle.getBundle("default_messages"); + }else { + try { + bundle = ResourceBundle.getBundle("messages", locale); + } catch (MissingResourceException e) { + bundle = ResourceBundle.getBundle("default_messages"); + } + } + String message = bundle.getString(messageCode); + return MessageFormat.format(message, arguments); + } + + public static String getLocalizedMessage(String messageCode, String languageCode, Object...arguments){ + Locale locale = Strings.isNullOrEmpty(languageCode) ? null : Locale.forLanguageTag(languageCode); + return getLocalizedMessage(messageCode, locale, arguments); + } + } diff --git a/telegrambots-abilities/src/main/resources/default_messages.properties b/telegrambots-abilities/src/main/resources/default_messages.properties new file mode 100644 index 00000000..18dc77df --- /dev/null +++ b/telegrambots-abilities/src/main/resources/default_messages.properties @@ -0,0 +1,22 @@ +ability.commands.notFound=No public commands found. +ability.recover.fail=Oops, something went wrong during recovery. +ability.recover.error=I have failed to recover. + +ability.ban.alreadyBanned={0} is already *banned*. +ability.ban.banned={0} is now *banned*. + +ability.unban.notBanned=@{0} is *not* on the *blacklist*. +ability.unban.lifted=@{0}, your ban has been *lifted*. + +ability.promote.alreadyPromoted=@{0} is already an *admin*. +ability.promote.promoted=@{0} has been *promoted*. + +ability.demote.alreadyDemoted=@{0} is *not* an *admin*. +ability.demote.demoted=@{0} has been *demoted*. + +ability.claim.alreadyClaimed=You''re already my master. +ability.claim.claimed=You''re now my master. + +checkInput.fail=Sorry, this feature requires {0,number,integer} additional {1}. +checkLocality.fail=Sorry, {0}-only feature. +checkPrivacy.fail=Sorry, you don''t have the required access level to do that. diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index ff335720..ebcd4c54 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -556,6 +556,7 @@ public class AbilityBotTest { when(message.hasText()).thenReturn(true); MessageContext context = mock(MessageContext.class); when(context.chatId()).thenReturn(GROUP_ID); + when(context.user()).thenReturn(MUSER); bot.reportCommands().action().accept(context); From 9f1aa6664fa57f0f74194032d877ad6406e5c57e Mon Sep 17 00:00:00 2001 From: davioooh Date: Mon, 30 Apr 2018 14:33:10 +0200 Subject: [PATCH 02/22] Update default messages --- .../src/main/resources/default_messages.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telegrambots-abilities/src/main/resources/default_messages.properties b/telegrambots-abilities/src/main/resources/default_messages.properties index 18dc77df..03ae86fc 100644 --- a/telegrambots-abilities/src/main/resources/default_messages.properties +++ b/telegrambots-abilities/src/main/resources/default_messages.properties @@ -1,4 +1,7 @@ ability.commands.notFound=No public commands found. + +ability.recover.message=I am ready to receive the backup file. Please reply to this message with the backup file attached. +ability.recover.success=I have successfully recovered. ability.recover.fail=Oops, something went wrong during recovery. ability.recover.error=I have failed to recover. From 16fa704a17fa35484161cd9598801cbe49770d20 Mon Sep 17 00:00:00 2001 From: davioooh Date: Mon, 30 Apr 2018 15:39:32 +0200 Subject: [PATCH 03/22] Refactor EndUser to serialize locale --- .../org/telegram/abilitybots/api/objects/EndUser.java | 8 ++++---- .../org/telegram/abilitybots/api/bot/AbilityBotTest.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java index 0c123434..0ea7919d 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java @@ -1,7 +1,6 @@ package org.telegram.abilitybots.api.objects; import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.MoreObjects; import com.google.common.base.Strings; @@ -30,7 +29,7 @@ public final class EndUser implements Serializable { private final String lastName; @JsonProperty("username") private final String username; - @JsonIgnore + @JsonProperty("locale") private Locale locale; private EndUser(Integer id, String firstName, String lastName, String username, Locale locale) { @@ -45,8 +44,9 @@ public final class EndUser implements Serializable { public static EndUser endUser(@JsonProperty("id") Integer id, @JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName, - @JsonProperty("username") String username) { - return new EndUser(id, firstName, lastName, username, null); + @JsonProperty("username") String username, + @JsonProperty("locale") Locale locale) { + return new EndUser(id, firstName, lastName, username, locale); } /** diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index ebcd4c54..689f1486 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -53,8 +53,8 @@ public class AbilityBotTest { private static final long GROUP_ID = 10L; private static final String TEST = "test"; private static final String[] TEXT = {TEST}; - public static final EndUser MUSER = endUser(1, "first", "last", "username"); - public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername"); + public static final EndUser MUSER = endUser(1, "first", "last", "username", null); + public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername", null); private DefaultBot bot; private DBContext db; @@ -293,7 +293,7 @@ public class AbilityBotTest { String newFirstName = MUSER.firstName() + "-test"; String newLastName = MUSER.lastName() + "-test"; int sameId = MUSER.id(); - EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername); + EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername, null); mockAlternateUser(update, message, user, changedUser); From f64d556610e5aff10bd8fd9d8b38879861f59b9c Mon Sep 17 00:00:00 2001 From: davioooh Date: Mon, 30 Apr 2018 19:50:44 +0200 Subject: [PATCH 04/22] Refactor localized message helper method --- .../org/telegram/abilitybots/api/util/AbilityUtils.java | 9 ++++++--- .../{default_messages.properties => messages.properties} | 0 2 files changed, 6 insertions(+), 3 deletions(-) rename telegrambots-abilities/src/main/resources/{default_messages.properties => messages.properties} (100%) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java index c6d3e554..b64e70bb 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java @@ -159,12 +159,15 @@ public final class AbilityUtils { public static String getLocalizedMessage(String messageCode, Locale locale, Object...arguments) { ResourceBundle bundle; if(locale == null){ - bundle = ResourceBundle.getBundle("default_messages"); + bundle = ResourceBundle.getBundle("messages", Locale.ROOT); }else { try { - bundle = ResourceBundle.getBundle("messages", locale); + bundle = ResourceBundle.getBundle( + "messages", + locale, + ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_PROPERTIES)); } catch (MissingResourceException e) { - bundle = ResourceBundle.getBundle("default_messages"); + bundle = ResourceBundle.getBundle("messages", Locale.ROOT); } } String message = bundle.getString(messageCode); diff --git a/telegrambots-abilities/src/main/resources/default_messages.properties b/telegrambots-abilities/src/main/resources/messages.properties similarity index 100% rename from telegrambots-abilities/src/main/resources/default_messages.properties rename to telegrambots-abilities/src/main/resources/messages.properties From 494f21040f5f09c46e05f02ea9ddad159a399f39 Mon Sep 17 00:00:00 2001 From: davioooh Date: Wed, 2 May 2018 11:06:39 +0200 Subject: [PATCH 05/22] Complete externalization of messages --- .../telegram/abilitybots/api/bot/AbilityBot.java | 15 ++++++--------- .../src/main/resources/messages.properties | 2 ++ .../abilitybots/api/bot/AbilityBotTest.java | 6 ++++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index 48296835..7ccbce6a 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -102,11 +102,6 @@ public abstract class AbilityBot extends TelegramLongPollingBot { protected static final String RECOVER = "recover"; protected static final String COMMANDS = "commands"; - // Messages - // TODO replace hardcoded messages... - protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; - protected static final String RECOVER_SUCCESS = "I have successfully recovered."; - // DB and sender protected final DBContext db; protected MessageSender sender; @@ -270,7 +265,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try { return getUser(username).id(); } catch (IllegalStateException ex) { - silent.send(format("Sorry, I could not find the user [%s].", username), chatId); + silent.send(getLocalizedMessage("userNotFound","", username), chatId); // TODO how to retrieve language? throw propagate(ex); } } @@ -362,7 +357,8 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .locality(USER) .privacy(CREATOR) .input(0) - .action(ctx -> silent.forceReply(RECOVERY_MESSAGE, ctx.chatId())) + .action(ctx -> silent.forceReply( + getLocalizedMessage("ability.recover.message", ctx.user().locale()), ctx.chatId())) .reply(update -> { Long chatId = update.getMessage().getChatId(); String fileId = update.getMessage().getDocument().getFileId(); @@ -370,7 +366,8 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try (FileReader reader = new FileReader(downloadFileWithId(fileId))) { String backupData = IOUtils.toString(reader); if (db.recover(backupData)) { - silent.send(RECOVER_SUCCESS, chatId); + silent.send(getLocalizedMessage("ability.recover.success", + AbilityUtils.getUser(update).getLanguageCode()), chatId); // TODO how to retrieve language? } else { silent.send(getLocalizedMessage("ability.recover.fail", AbilityUtils.getUser(update).getLanguageCode()), chatId); @@ -380,7 +377,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { silent.send(getLocalizedMessage("ability.recover.error", AbilityUtils.getUser(update).getLanguageCode()), chatId); } - }, MESSAGE, DOCUMENT, REPLY, isReplyTo(RECOVERY_MESSAGE)) + }, MESSAGE, DOCUMENT, REPLY, isReplyTo(getLocalizedMessage("ability.recover.success", ""))) // TODO how to retrieve language? .build(); } diff --git a/telegrambots-abilities/src/main/resources/messages.properties b/telegrambots-abilities/src/main/resources/messages.properties index 03ae86fc..efd03c44 100644 --- a/telegrambots-abilities/src/main/resources/messages.properties +++ b/telegrambots-abilities/src/main/resources/messages.properties @@ -23,3 +23,5 @@ ability.claim.claimed=You''re now my master. checkInput.fail=Sorry, this feature requires {0,number,integer} additional {1}. checkLocality.fail=Sorry, {0}-only feature. checkPrivacy.fail=Sorry, you don''t have the required access level to do that. + +userNotFound=Sorry, I could not find the user [{0}]. \ No newline at end of file diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 689f1486..51f26353 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -36,8 +36,6 @@ import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; import static org.mockito.internal.verification.VerificationModeFactory.times; -import static org.telegram.abilitybots.api.bot.AbilityBot.RECOVERY_MESSAGE; -import static org.telegram.abilitybots.api.bot.AbilityBot.RECOVER_SUCCESS; import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.EndUser.endUser; @@ -49,6 +47,10 @@ import static org.telegram.abilitybots.api.objects.MessageContext.newContext; import static org.telegram.abilitybots.api.objects.Privacy.*; public class AbilityBotTest { + // Messages + protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; + protected static final String RECOVER_SUCCESS = "I have successfully recovered."; + private static final String[] EMPTY_ARRAY = {}; private static final long GROUP_ID = 10L; private static final String TEST = "test"; From c97476f05dcf12eab35de0d58e0e051070941182 Mon Sep 17 00:00:00 2001 From: davioooh Date: Fri, 4 May 2018 18:15:02 +0200 Subject: [PATCH 06/22] Add basic unit tests --- .../api/bot/AbilityBotI18nTest.java | 76 +++++++++++++++++++ .../api/bot/NoPublicCommandsBot.java | 16 ++++ .../test/resources/messages_it_IT.properties | 1 + 3 files changed, 93 insertions(+) create mode 100644 telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java create mode 100644 telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java create mode 100644 telegrambots-abilities/src/test/resources/messages_it_IT.properties diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java new file mode 100644 index 00000000..b8799004 --- /dev/null +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -0,0 +1,76 @@ +package org.telegram.abilitybots.api.bot; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.telegram.abilitybots.api.db.DBContext; +import org.telegram.abilitybots.api.objects.EndUser; +import org.telegram.abilitybots.api.objects.MessageContext; +import org.telegram.abilitybots.api.sender.MessageSender; +import org.telegram.abilitybots.api.sender.SilentSender; + +import java.io.IOException; +import java.util.Locale; + +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.mockito.Mockito.*; +import static org.mockito.internal.verification.VerificationModeFactory.times; +import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; +import static org.telegram.abilitybots.api.objects.EndUser.endUser; + +public class AbilityBotI18nTest { + public static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username", null); + public static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username", Locale.ITALY); + + private DBContext db; + private DefaultBot bot; + + private NoPublicCommandsBot noCommandsBot; + + private MessageSender sender; + private SilentSender silent; + + @Before + public void setUp() { + db = offlineInstance("db"); + bot = new DefaultBot(EMPTY, EMPTY, db); + + silent = mock(SilentSender.class); + + bot.sender = sender; + bot.silent = silent; + } + + @Test + public void missingPublicCommandsLocalizedCorrectly() { + NoPublicCommandsBot noCommandsBot = new NoPublicCommandsBot(EMPTY, EMPTY, db); + noCommandsBot.silent = silent; + + MessageContext context = mock(MessageContext.class); + when(context.chatId()).thenReturn(Long.valueOf(NO_LANGUAGE_USER.id())); + when(context.user()).thenReturn(NO_LANGUAGE_USER); + + noCommandsBot.reportCommands().action().accept(context); + + verify(silent, times(1)) + .send("No public commands found.", NO_LANGUAGE_USER.id()); + + // + + MessageContext context1 = mock(MessageContext.class); + when(context1.chatId()).thenReturn(Long.valueOf(ITALIAN_USER.id())); + when(context1.user()).thenReturn(ITALIAN_USER); + + noCommandsBot.reportCommands().action().accept(context1); + + verify(silent, times(1)) + .send("Non sono presenti comandi pubblici.", ITALIAN_USER.id()); + } + + + @After + public void tearDown() throws IOException { + db.clear(); + db.close(); + } +} diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java new file mode 100644 index 00000000..fa7b70e5 --- /dev/null +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java @@ -0,0 +1,16 @@ +package org.telegram.abilitybots.api.bot; + +import org.telegram.abilitybots.api.db.DBContext; + +public class NoPublicCommandsBot extends AbilityBot { + + + protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { + super(botToken, botUsername, db); + } + + @Override + public int creatorId() { + return 0; + } +} \ No newline at end of file diff --git a/telegrambots-abilities/src/test/resources/messages_it_IT.properties b/telegrambots-abilities/src/test/resources/messages_it_IT.properties new file mode 100644 index 00000000..c5656cc1 --- /dev/null +++ b/telegrambots-abilities/src/test/resources/messages_it_IT.properties @@ -0,0 +1 @@ +ability.commands.notFound=Non sono presenti comandi pubblici. \ No newline at end of file From 02fbb67b598d5b2e2c8c9ebabebaa5eb5827c6f0 Mon Sep 17 00:00:00 2001 From: davioooh Date: Fri, 4 May 2018 18:16:04 +0200 Subject: [PATCH 07/22] Remove locale retrieval to avoid exception --- .../main/java/org/telegram/abilitybots/api/bot/AbilityBot.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index 7ccbce6a..d4b4cdc9 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -367,7 +367,8 @@ public abstract class AbilityBot extends TelegramLongPollingBot { String backupData = IOUtils.toString(reader); if (db.recover(backupData)) { silent.send(getLocalizedMessage("ability.recover.success", - AbilityUtils.getUser(update).getLanguageCode()), chatId); // TODO how to retrieve language? + ""), chatId); + // TODO how to retrieve language? Getting java.lang.IllegalStateException: Could not retrieve originating user from update } else { silent.send(getLocalizedMessage("ability.recover.fail", AbilityUtils.getUser(update).getLanguageCode()), chatId); From 288a4ab17a09f5820c6e8ed67bcb83b46c28018f Mon Sep 17 00:00:00 2001 From: davioooh Date: Tue, 8 May 2018 11:10:37 +0200 Subject: [PATCH 08/22] Fix issues - export message codes - standardize message codes - format/spacing --- .../abilitybots/api/bot/AbilityBot.java | 41 ++++++++++--------- .../abilitybots/api/objects/EndUser.java | 4 +- .../api/util/AbilityMessageCodes.java | 31 ++++++++++++++ .../abilitybots/api/util/AbilityUtils.java | 15 ++++--- .../src/main/resources/messages.properties | 22 +++++----- .../api/bot/AbilityBotI18nTest.java | 6 +-- .../abilitybots/api/bot/AbilityBotTest.java | 4 +- .../api/bot/NoPublicCommandsBot.java | 1 - 8 files changed, 78 insertions(+), 46 deletions(-) create mode 100644 telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityMessageCodes.java diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index d4b4cdc9..070a0fb1 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -49,6 +49,7 @@ import static org.telegram.abilitybots.api.objects.Flag.*; import static org.telegram.abilitybots.api.objects.Locality.*; import static org.telegram.abilitybots.api.objects.MessageContext.newContext; import static org.telegram.abilitybots.api.objects.Privacy.*; +import static org.telegram.abilitybots.api.util.AbilityMessageCodes.*; import static org.telegram.abilitybots.api.util.AbilityUtils.*; /** @@ -265,7 +266,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try { return getUser(username).id(); } catch (IllegalStateException ex) { - silent.send(getLocalizedMessage("userNotFound","", username), chatId); // TODO how to retrieve language? + silent.send(getLocalizedMessage(USER_NOT_FOUND,"", username), chatId); // TODO how to retrieve language? throw propagate(ex); } } @@ -302,7 +303,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { }) .sorted() .reduce((a, b) -> format("%s%n%s", a, b)) - .orElse(getLocalizedMessage("ability.commands.notFound", ctx.user().locale())); + .orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, ctx.user().locale())); silent.send(commands, ctx.chatId()); }) @@ -358,7 +359,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .privacy(CREATOR) .input(0) .action(ctx -> silent.forceReply( - getLocalizedMessage("ability.recover.message", ctx.user().locale()), ctx.chatId())) + getLocalizedMessage(ABILITY_RECOVER_MESSAGE, ctx.user().locale()), ctx.chatId())) .reply(update -> { Long chatId = update.getMessage().getChatId(); String fileId = update.getMessage().getDocument().getFileId(); @@ -366,19 +367,19 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try (FileReader reader = new FileReader(downloadFileWithId(fileId))) { String backupData = IOUtils.toString(reader); if (db.recover(backupData)) { - silent.send(getLocalizedMessage("ability.recover.success", + silent.send(getLocalizedMessage(ABILITY_RECOVER_SUCCESS, ""), chatId); // TODO how to retrieve language? Getting java.lang.IllegalStateException: Could not retrieve originating user from update } else { - silent.send(getLocalizedMessage("ability.recover.fail", + silent.send(getLocalizedMessage(ABILITY_RECOVER_FAIL, AbilityUtils.getUser(update).getLanguageCode()), chatId); } } catch (Exception e) { BotLogger.error("Could not recover DB from backup", TAG, e); - silent.send(getLocalizedMessage("ability.recover.error", + silent.send(getLocalizedMessage(ABILITY_RECOVER_ERROR, AbilityUtils.getUser(update).getLanguageCode()), chatId); } - }, MESSAGE, DOCUMENT, REPLY, isReplyTo(getLocalizedMessage("ability.recover.success", ""))) // TODO how to retrieve language? + }, MESSAGE, DOCUMENT, REPLY, isReplyTo(getLocalizedMessage(ABILITY_RECOVER_SUCCESS, ""))) // TODO how to retrieve language? .build(); } @@ -412,10 +413,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (blacklist.contains(userId)) - silent.sendMd(getLocalizedMessage("ability.ban.alreadyBanned", ctx.user().locale(), escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_BAN_FAIL, ctx.user().locale(), escape(bannedUser)), ctx.chatId()); else { blacklist.add(userId); - silent.sendMd(getLocalizedMessage("ability.ban.banned", ctx.user().locale(), escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_BAN_SUCCESS, ctx.user().locale(), escape(bannedUser)), ctx.chatId()); } }) .post(commitTo(db)) @@ -440,9 +441,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (!blacklist.remove(userId)) - silent.sendMd(getLocalizedMessage("ability.unban.notBanned", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); else { - silent.sendMd(getLocalizedMessage("ability.unban.lifted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -464,10 +465,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.contains(userId)) - silent.sendMd(getLocalizedMessage("ability.promote.alreadyPromoted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); else { admins.add(userId); - silent.sendMd(getLocalizedMessage("ability.promote.promoted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); } }).post(commitTo(db)) .build(); @@ -488,9 +489,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.remove(userId)) { - silent.sendMd(getLocalizedMessage("ability.demote.demoted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); } else { - silent.sendMd(getLocalizedMessage("ability.demote.alreadyDemoted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -515,10 +516,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { long chatId = ctx.chatId(); if (admins.contains(id)) - silent.send(getLocalizedMessage("ability.claim.alreadyClaimed", ctx.user().locale()), chatId); + silent.send(getLocalizedMessage(ABILITY_CLAIM_FAIL, ctx.user().locale()), chatId); else { admins.add(id); - silent.send(getLocalizedMessage("ability.claim.claimed", ctx.user().locale()), chatId); + silent.send(getLocalizedMessage(ABILITY_CLAIM_SUCCESS, ctx.user().locale()), chatId); } } else { // This is not a joke @@ -618,7 +619,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (!isOk) silent.send( getLocalizedMessage( - "checkInput.fail", + CHECK_INPUT_FAIL, AbilityUtils.getUser(trio.a()).getLanguageCode(), abilityTokens, abilityTokens == 1 ? "input" : "inputs"), getChatId(trio.a())); @@ -635,7 +636,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (!isOk) silent.send( getLocalizedMessage( - "checkLocality.fail", + CHECK_LOCALITY_FAIL, AbilityUtils.getUser(trio.a()).getLanguageCode(), abilityLocality.toString().toLowerCase()), getChatId(trio.a())); @@ -655,7 +656,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (!isOk) silent.send( getLocalizedMessage( - "checkPrivacy.fail", + CHECK_PRIVACY_FAIL, AbilityUtils.getUser(trio.a()).getLanguageCode()), getChatId(trio.a())); return isOk; diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java index 0ea7919d..0f65e39b 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java @@ -37,7 +37,7 @@ public final class EndUser implements Serializable { this.firstName = firstName; this.lastName = lastName; this.username = username; - this.locale = locale != null? locale : Locale.ENGLISH; + this.locale = locale; } @JsonCreator @@ -143,7 +143,7 @@ public final class EndUser implements Serializable { .add("firstName", firstName) .add("lastName", lastName) .add("username", username) - .add("locale", locale.toString()) + .add("locale", locale) .toString(); } } diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityMessageCodes.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityMessageCodes.java new file mode 100644 index 00000000..4f21f937 --- /dev/null +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityMessageCodes.java @@ -0,0 +1,31 @@ +package org.telegram.abilitybots.api.util; + +public final class AbilityMessageCodes { + public static String USER_NOT_FOUND = "userNotFound"; + public static String CHECK_INPUT_FAIL = "checkInput.fail"; + public static String CHECK_LOCALITY_FAIL = "checkLocality.fail"; + public static String CHECK_PRIVACY_FAIL = "checkPrivacy.fail"; + + public static String ABILITY_COMMANDS_NOT_FOUND = "ability.commands.notFound"; + + public static String ABILITY_RECOVER_SUCCESS = "ability.recover.success"; + public static String ABILITY_RECOVER_FAIL = "ability.recover.fail"; + public static String ABILITY_RECOVER_MESSAGE = "ability.recover.message"; + public static String ABILITY_RECOVER_ERROR = "ability.recover.error"; + + public static String ABILITY_BAN_SUCCESS = "ability.ban.success"; + public static String ABILITY_BAN_FAIL = "ability.ban.fail"; + + public static String ABILITY_UNBAN_SUCCESS = "ability.unban.success"; + public static String ABILITY_UNBAN_FAIL = "ability.unban.fail"; + + public static String ABILITY_PROMOTE_SUCCESS = "ability.promote.success"; + public static String ABILITY_PROMOTE_FAIL = "ability.promote.fail"; + + public static String ABILITY_DEMOTE_SUCCESS = "ability.demote.success"; + public static String ABILITY_DEMOTE_FAIL = "ability.demote.fail"; + + public static String ABILITY_CLAIM_SUCCESS = "ability.claim.success"; + public static String ABILITY_CLAIM_FAIL = "ability.claim.fail"; + +} diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java index b64e70bb..973d6ea6 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java @@ -13,6 +13,9 @@ import java.util.ResourceBundle; import java.util.function.Consumer; import java.util.function.Predicate; +import static java.util.ResourceBundle.Control.FORMAT_PROPERTIES; +import static java.util.ResourceBundle.Control.getNoFallbackControl; +import static java.util.ResourceBundle.getBundle; import static org.telegram.abilitybots.api.objects.Flag.*; /** @@ -158,16 +161,16 @@ public final class AbilityUtils { public static String getLocalizedMessage(String messageCode, Locale locale, Object...arguments) { ResourceBundle bundle; - if(locale == null){ - bundle = ResourceBundle.getBundle("messages", Locale.ROOT); - }else { + if (locale == null) { + bundle = getBundle("messages", Locale.ROOT); + } else { try { - bundle = ResourceBundle.getBundle( + bundle = getBundle( "messages", locale, - ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_PROPERTIES)); + getNoFallbackControl(FORMAT_PROPERTIES)); } catch (MissingResourceException e) { - bundle = ResourceBundle.getBundle("messages", Locale.ROOT); + bundle = getBundle("messages", Locale.ROOT); } } String message = bundle.getString(messageCode); diff --git a/telegrambots-abilities/src/main/resources/messages.properties b/telegrambots-abilities/src/main/resources/messages.properties index efd03c44..a8495e84 100644 --- a/telegrambots-abilities/src/main/resources/messages.properties +++ b/telegrambots-abilities/src/main/resources/messages.properties @@ -1,24 +1,24 @@ ability.commands.notFound=No public commands found. -ability.recover.message=I am ready to receive the backup file. Please reply to this message with the backup file attached. ability.recover.success=I have successfully recovered. ability.recover.fail=Oops, something went wrong during recovery. +ability.recover.message=I am ready to receive the backup file. Please reply to this message with the backup file attached. ability.recover.error=I have failed to recover. -ability.ban.alreadyBanned={0} is already *banned*. -ability.ban.banned={0} is now *banned*. +ability.ban.success={0} is now *banned*. +ability.ban.fail={0} is already *banned*. -ability.unban.notBanned=@{0} is *not* on the *blacklist*. -ability.unban.lifted=@{0}, your ban has been *lifted*. +ability.unban.success=@{0}, your ban has been *lifted*. +ability.unban.fail=@{0} is *not* on the *blacklist*. -ability.promote.alreadyPromoted=@{0} is already an *admin*. -ability.promote.promoted=@{0} has been *promoted*. +ability.promote.success=@{0} has been *promoted*. +ability.promote.fail=@{0} is already an *admin*. -ability.demote.alreadyDemoted=@{0} is *not* an *admin*. -ability.demote.demoted=@{0} has been *demoted*. +ability.demote.success=@{0} has been *demoted*. +ability.demote.fail=@{0} is *not* an *admin*. -ability.claim.alreadyClaimed=You''re already my master. -ability.claim.claimed=You''re now my master. +ability.claim.success=You''re now my master. +ability.claim.fail=You''re already my master. checkInput.fail=Sorry, this feature requires {0,number,integer} additional {1}. checkLocality.fail=Sorry, {0}-only feature. diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java index b8799004..d64cfe14 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -19,8 +19,8 @@ import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.EndUser.endUser; public class AbilityBotI18nTest { - public static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username", null); - public static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username", Locale.ITALY); + private static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username", null); + private static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username", Locale.ITALY); private DBContext db; private DefaultBot bot; @@ -55,8 +55,6 @@ public class AbilityBotI18nTest { verify(silent, times(1)) .send("No public commands found.", NO_LANGUAGE_USER.id()); - // - MessageContext context1 = mock(MessageContext.class); when(context1.chatId()).thenReturn(Long.valueOf(ITALIAN_USER.id())); when(context1.user()).thenReturn(ITALIAN_USER); diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 51f26353..dd896295 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -48,8 +48,8 @@ import static org.telegram.abilitybots.api.objects.Privacy.*; public class AbilityBotTest { // Messages - protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; - protected static final String RECOVER_SUCCESS = "I have successfully recovered."; + private static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; + private static final String RECOVER_SUCCESS = "I have successfully recovered."; private static final String[] EMPTY_ARRAY = {}; private static final long GROUP_ID = 10L; diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java index fa7b70e5..b4e49973 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java @@ -4,7 +4,6 @@ import org.telegram.abilitybots.api.db.DBContext; public class NoPublicCommandsBot extends AbilityBot { - protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { super(botToken, botUsername, db); } From 31f5c64058bcf0fc4baa48e62c1f9e41b9e28fc5 Mon Sep 17 00:00:00 2001 From: davioooh Date: Sun, 13 May 2018 11:16:51 +0200 Subject: [PATCH 09/22] Refactor localized messages retrievement --- .../abilitybots/api/bot/AbilityBot.java | 24 +++++++++---------- .../abilitybots/api/objects/EndUser.java | 23 +++++------------- .../api/bot/AbilityBotI18nTest.java | 5 ++-- .../abilitybots/api/bot/AbilityBotTest.java | 6 ++--- 4 files changed, 23 insertions(+), 35 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index 070a0fb1..0d905f20 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -303,7 +303,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { }) .sorted() .reduce((a, b) -> format("%s%n%s", a, b)) - .orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, ctx.user().locale())); + .orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, AbilityUtils.getUser(ctx.update()).getLanguageCode())); silent.send(commands, ctx.chatId()); }) @@ -359,7 +359,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .privacy(CREATOR) .input(0) .action(ctx -> silent.forceReply( - getLocalizedMessage(ABILITY_RECOVER_MESSAGE, ctx.user().locale()), ctx.chatId())) + getLocalizedMessage(ABILITY_RECOVER_MESSAGE, AbilityUtils.getUser(ctx.update()).getLanguageCode()), ctx.chatId())) .reply(update -> { Long chatId = update.getMessage().getChatId(); String fileId = update.getMessage().getDocument().getFileId(); @@ -413,10 +413,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (blacklist.contains(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_BAN_FAIL, ctx.user().locale(), escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_BAN_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(bannedUser)), ctx.chatId()); else { blacklist.add(userId); - silent.sendMd(getLocalizedMessage(ABILITY_BAN_SUCCESS, ctx.user().locale(), escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_BAN_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(bannedUser)), ctx.chatId()); } }) .post(commitTo(db)) @@ -441,9 +441,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (!blacklist.remove(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); else { - silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -465,10 +465,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.contains(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); else { admins.add(userId); - silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); } }).post(commitTo(db)) .build(); @@ -489,9 +489,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.remove(userId)) { - silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); } else { - silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -516,10 +516,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { long chatId = ctx.chatId(); if (admins.contains(id)) - silent.send(getLocalizedMessage(ABILITY_CLAIM_FAIL, ctx.user().locale()), chatId); + silent.send(getLocalizedMessage(ABILITY_CLAIM_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode()), chatId); else { admins.add(id); - silent.send(getLocalizedMessage(ABILITY_CLAIM_SUCCESS, ctx.user().locale()), chatId); + silent.send(getLocalizedMessage(ABILITY_CLAIM_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode()), chatId); } } else { // This is not a joke diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java index 0f65e39b..7cc08145 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java @@ -3,11 +3,9 @@ package org.telegram.abilitybots.api.objects; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.MoreObjects; -import com.google.common.base.Strings; import org.telegram.telegrambots.api.objects.User; import java.io.Serializable; -import java.util.Locale; import java.util.Objects; import java.util.StringJoiner; @@ -29,24 +27,20 @@ public final class EndUser implements Serializable { private final String lastName; @JsonProperty("username") private final String username; - @JsonProperty("locale") - private Locale locale; - private EndUser(Integer id, String firstName, String lastName, String username, Locale locale) { + private EndUser(Integer id, String firstName, String lastName, String username) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.username = username; - this.locale = locale; } @JsonCreator public static EndUser endUser(@JsonProperty("id") Integer id, @JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName, - @JsonProperty("username") String username, - @JsonProperty("locale") Locale locale) { - return new EndUser(id, firstName, lastName, username, locale); + @JsonProperty("username") String username) { + return new EndUser(id, firstName, lastName, username); } /** @@ -56,8 +50,7 @@ public final class EndUser implements Serializable { * @return an augmented end-user */ public static EndUser fromUser(User user) { - Locale locale = Strings.isNullOrEmpty(user.getLanguageCode()) ? null : Locale.forLanguageTag(user.getLanguageCode()); - return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName(), locale); + return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName()); } public int id() { @@ -76,8 +69,6 @@ public final class EndUser implements Serializable { return username; } - public Locale locale() { return locale; } - /** * The full name is identified as the concatenation of the first and last name, separated by a space. * This method can return an empty name if both first and last name are empty. @@ -127,13 +118,12 @@ public final class EndUser implements Serializable { return Objects.equals(id, endUser.id) && Objects.equals(firstName, endUser.firstName) && Objects.equals(lastName, endUser.lastName) && - Objects.equals(username, endUser.username) && - Objects.equals(locale, endUser.locale); + Objects.equals(username, endUser.username); } @Override public int hashCode() { - return Objects.hash(id, firstName, lastName, username, locale); + return Objects.hash(id, firstName, lastName, username); } @Override @@ -143,7 +133,6 @@ public final class EndUser implements Serializable { .add("firstName", firstName) .add("lastName", lastName) .add("username", username) - .add("locale", locale) .toString(); } } diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java index d64cfe14..68b178e1 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -10,7 +10,6 @@ import org.telegram.abilitybots.api.sender.MessageSender; import org.telegram.abilitybots.api.sender.SilentSender; import java.io.IOException; -import java.util.Locale; import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.mockito.Mockito.*; @@ -19,8 +18,8 @@ import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.EndUser.endUser; public class AbilityBotI18nTest { - private static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username", null); - private static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username", Locale.ITALY); + private static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username"); + private static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username"); private DBContext db; private DefaultBot bot; diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index dd896295..3d958717 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -55,8 +55,8 @@ public class AbilityBotTest { private static final long GROUP_ID = 10L; private static final String TEST = "test"; private static final String[] TEXT = {TEST}; - public static final EndUser MUSER = endUser(1, "first", "last", "username", null); - public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername", null); + public static final EndUser MUSER = endUser(1, "first", "last", "username"); + public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername"); private DefaultBot bot; private DBContext db; @@ -295,7 +295,7 @@ public class AbilityBotTest { String newFirstName = MUSER.firstName() + "-test"; String newLastName = MUSER.lastName() + "-test"; int sameId = MUSER.id(); - EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername, null); + EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername); mockAlternateUser(update, message, user, changedUser); From c713f9da48a82f2ef766619786bf53154d0c0319 Mon Sep 17 00:00:00 2001 From: Abbas Abou Daya Date: Fri, 18 May 2018 04:40:27 -0400 Subject: [PATCH 10/22] Fix tests --- .../api/bot/AbilityBotI18nTest.java | 91 ++++++++++--------- .../abilitybots/api/bot/AbilityBotTest.java | 63 +++++++++---- .../api/bot/NoPublicCommandsBot.java | 15 --- 3 files changed, 96 insertions(+), 73 deletions(-) delete mode 100644 telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java index 68b178e1..75aa6df0 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -4,70 +4,79 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.telegram.abilitybots.api.db.DBContext; -import org.telegram.abilitybots.api.objects.EndUser; import org.telegram.abilitybots.api.objects.MessageContext; import org.telegram.abilitybots.api.sender.MessageSender; import org.telegram.abilitybots.api.sender.SilentSender; +import org.telegram.telegrambots.api.objects.User; import java.io.IOException; +import static java.lang.Long.valueOf; import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.mockito.Mockito.*; import static org.mockito.internal.verification.VerificationModeFactory.times; +import static org.telegram.abilitybots.api.bot.AbilityBotTest.mockContext; +import static org.telegram.abilitybots.api.bot.AbilityBotTest.newUser; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; -import static org.telegram.abilitybots.api.objects.EndUser.endUser; public class AbilityBotI18nTest { - private static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username"); - private static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username"); + private static final User NO_LANGUAGE_USER = newUser(1, "first", "last", "username", null); + private static final User ITALIAN_USER = newUser(2, "first", "last", "username", "it-IT"); - private DBContext db; - private DefaultBot bot; + private DBContext db; + private NoPublicCommandsBot bot; - private NoPublicCommandsBot noCommandsBot; + private MessageSender sender; + private SilentSender silent; - private MessageSender sender; - private SilentSender silent; + @Before + public void setUp() { + db = offlineInstance("db"); + bot = new NoPublicCommandsBot(EMPTY, EMPTY, db); - @Before - public void setUp() { - db = offlineInstance("db"); - bot = new DefaultBot(EMPTY, EMPTY, db); + sender = mock(MessageSender.class); + silent = mock(SilentSender.class); - silent = mock(SilentSender.class); + bot.sender = sender; + bot.silent = silent; + } - bot.sender = sender; - bot.silent = silent; - } + @Test + public void missingPublicCommandsLocalizedCorrectly1() { + MessageContext context = mockContext(NO_LANGUAGE_USER); - @Test - public void missingPublicCommandsLocalizedCorrectly() { - NoPublicCommandsBot noCommandsBot = new NoPublicCommandsBot(EMPTY, EMPTY, db); - noCommandsBot.silent = silent; + bot.reportCommands().action().accept(context); - MessageContext context = mock(MessageContext.class); - when(context.chatId()).thenReturn(Long.valueOf(NO_LANGUAGE_USER.id())); - when(context.user()).thenReturn(NO_LANGUAGE_USER); + verify(silent, times(1)) + .send("No public commands found.", NO_LANGUAGE_USER.getId()); + } - noCommandsBot.reportCommands().action().accept(context); + @Test + public void missingPublicCommandsLocalizedCorrectly2() { + MessageContext context1 = mockContext(ITALIAN_USER); - verify(silent, times(1)) - .send("No public commands found.", NO_LANGUAGE_USER.id()); + bot.reportCommands().action().accept(context1); - MessageContext context1 = mock(MessageContext.class); - when(context1.chatId()).thenReturn(Long.valueOf(ITALIAN_USER.id())); - when(context1.user()).thenReturn(ITALIAN_USER); - - noCommandsBot.reportCommands().action().accept(context1); - - verify(silent, times(1)) - .send("Non sono presenti comandi pubblici.", ITALIAN_USER.id()); - } + verify(silent, times(1)) + .send("Non sono presenti comandi pubblici.", ITALIAN_USER.getId()); + } - @After - public void tearDown() throws IOException { - db.clear(); - db.close(); - } + @After + public void tearDown() throws IOException { + db.clear(); + db.close(); + } + + public static class NoPublicCommandsBot extends AbilityBot { + + protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { + super(botToken, botUsername, db); + } + + @Override + public int creatorId() { + return 0; + } + } } diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 3d958717..2e03ad6a 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -39,6 +39,7 @@ import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.EndUser.endUser; +import static org.telegram.abilitybots.api.objects.EndUser.fromUser; import static org.telegram.abilitybots.api.objects.Flag.DOCUMENT; import static org.telegram.abilitybots.api.objects.Flag.MESSAGE; import static org.telegram.abilitybots.api.objects.Locality.ALL; @@ -56,7 +57,9 @@ public class AbilityBotTest { private static final String TEST = "test"; private static final String[] TEXT = {TEST}; public static final EndUser MUSER = endUser(1, "first", "last", "username"); + public static final User TG_USER = newUser(1, "first", "last", "username", null); public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername"); + public static final User TG_CREATOR = newUser(1337, "creatorFirst", "creatorLast", "creatorUsername", null); private DefaultBot bot; private DBContext db; @@ -199,8 +202,7 @@ public class AbilityBotTest { @NotNull private MessageContext defaultContext() { - MessageContext context = mock(MessageContext.class); - when(context.user()).thenReturn(CREATOR); + MessageContext context = mockContext(TG_CREATOR, GROUP_ID); when(context.firstArg()).thenReturn(MUSER.username()); return context; } @@ -208,8 +210,7 @@ public class AbilityBotTest { @Test public void cannotBanCreator() { addUsers(MUSER, CREATOR); - MessageContext context = mock(MessageContext.class); - when(context.user()).thenReturn(MUSER); + MessageContext context = mockContext(TG_USER, GROUP_ID); when(context.firstArg()).thenReturn(CREATOR.username()); bot.banUser().action().accept(context); @@ -228,8 +229,7 @@ public class AbilityBotTest { @Test public void creatorCanClaimBot() { - MessageContext context = mock(MessageContext.class); - when(context.user()).thenReturn(CREATOR); + MessageContext context = mockContext(TG_CREATOR, GROUP_ID); bot.claimCreator().action().accept(context); @@ -241,8 +241,7 @@ public class AbilityBotTest { @Test public void userGetsBannedIfClaimsBot() { addUsers(MUSER); - MessageContext context = mock(MessageContext.class); - when(context.user()).thenReturn(MUSER); + MessageContext context = mockContext(TG_USER, GROUP_ID); bot.claimCreator().action().accept(context); @@ -550,21 +549,38 @@ public class AbilityBotTest { @Test public void canReportCommands() { - Update update = mock(Update.class); - Message message = mock(Message.class); - - when(update.hasMessage()).thenReturn(true); - when(update.getMessage()).thenReturn(message); - when(message.hasText()).thenReturn(true); - MessageContext context = mock(MessageContext.class); - when(context.chatId()).thenReturn(GROUP_ID); - when(context.user()).thenReturn(MUSER); + MessageContext context = mockContext(TG_USER, GROUP_ID); bot.reportCommands().action().accept(context); verify(silent, times(1)).send("default - dis iz default command", GROUP_ID); } + @NotNull + public static MessageContext mockContext(User user) { + return mockContext(user, user.getId()); + } + + @NotNull + public static MessageContext mockContext(User user, long groupId) { + Update update = mock(Update.class); + Message message = mock(Message.class); + EndUser endUser = fromUser(user); + + when(update.hasMessage()).thenReturn(true); + when(update.getMessage()).thenReturn(message); + + when(message.getFrom()).thenReturn(user); + when(message.hasText()).thenReturn(true); + + MessageContext context = mock(MessageContext.class); + when(context.update()).thenReturn(update); + when(context.chatId()).thenReturn(groupId); + when(context.user()).thenReturn(endUser); + + return context; + } + @After public void tearDown() throws IOException { db.clear(); @@ -655,4 +671,17 @@ public class AbilityBotTest { writer.close(); return backupFile; } + + public static User newUser(Integer id, String firstname, String lastname, String username, String languageCode) { + User user = mock(User.class); + + when(user.getBot()).thenReturn(false); + when(user.getFirstName()).thenReturn(firstname); + when(user.getId()).thenReturn(id); + when(user.getLastName()).thenReturn(lastname); + when(user.getUserName()).thenReturn(username); + when(user.getLanguageCode()).thenReturn(languageCode); + + return user; + } } diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java deleted file mode 100644 index b4e49973..00000000 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.telegram.abilitybots.api.bot; - -import org.telegram.abilitybots.api.db.DBContext; - -public class NoPublicCommandsBot extends AbilityBot { - - protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { - super(botToken, botUsername, db); - } - - @Override - public int creatorId() { - return 0; - } -} \ No newline at end of file From d77887fd2c4b6456225aa420131220c7750082d1 Mon Sep 17 00:00:00 2001 From: davioooh Date: Wed, 18 Apr 2018 17:14:32 +0200 Subject: [PATCH 11/22] Add basic internationalization support --- .../abilitybots/api/bot/AbilityBot.java | 50 ++++++++++++------- .../abilitybots/api/objects/EndUser.java | 21 ++++++-- .../abilitybots/api/util/AbilityUtils.java | 26 ++++++++++ .../resources/default_messages.properties | 22 ++++++++ .../abilitybots/api/bot/AbilityBotTest.java | 1 + 5 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 telegrambots-abilities/src/main/resources/default_messages.properties diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index c2024f46..fd4d4aae 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -103,6 +103,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { protected static final String COMMANDS = "commands"; // Messages + // TODO replace hardcoded messages... protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; protected static final String RECOVER_SUCCESS = "I have successfully recovered."; @@ -306,7 +307,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { }) .sorted() .reduce((a, b) -> format("%s%n%s", a, b)) - .orElse("No public commands found."); + .orElse(getLocalizedMessage("ability.commands.notFound", ctx.user().locale())); silent.send(commands, ctx.chatId()); }) @@ -371,11 +372,13 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (db.recover(backupData)) { silent.send(RECOVER_SUCCESS, chatId); } else { - silent.send("Oops, something went wrong during recovery.", chatId); + silent.send(getLocalizedMessage("ability.recover.fail", + AbilityUtils.getUser(update).getLanguageCode()), chatId); } } catch (Exception e) { BotLogger.error("Could not recover DB from backup", TAG, e); - silent.send("I have failed to recover.", chatId); + silent.send(getLocalizedMessage("ability.recover.error", + AbilityUtils.getUser(update).getLanguageCode()), chatId); } }, MESSAGE, DOCUMENT, REPLY, isReplyTo(RECOVERY_MESSAGE)) .build(); @@ -411,10 +414,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (blacklist.contains(userId)) - silent.sendMd(format("%s is already *banned*.", escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.ban.alreadyBanned", ctx.user().locale(), escape(bannedUser)), ctx.chatId()); else { blacklist.add(userId); - silent.sendMd(format("%s is now *banned*.", escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.ban.banned", ctx.user().locale(), escape(bannedUser)), ctx.chatId()); } }) .post(commitTo(db)) @@ -439,9 +442,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (!blacklist.remove(userId)) - silent.sendMd(format("@%s is *not* on the *blacklist*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.unban.notBanned", ctx.user().locale(), escape(username)), ctx.chatId()); else { - silent.sendMd(format("@%s, your ban has been *lifted*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.unban.lifted", ctx.user().locale(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -463,10 +466,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.contains(userId)) - silent.sendMd(format("@%s is already an *admin*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.promote.alreadyPromoted", ctx.user().locale(), escape(username)), ctx.chatId()); else { admins.add(userId); - silent.sendMd(format("@%s has been *promoted*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.promote.promoted", ctx.user().locale(), escape(username)), ctx.chatId()); } }).post(commitTo(db)) .build(); @@ -487,9 +490,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.remove(userId)) { - silent.sendMd(format("@%s has been *demoted*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.demote.demoted", ctx.user().locale(), escape(username)), ctx.chatId()); } else { - silent.sendMd(format("@%s is *not* an *admin*.", escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage("ability.demote.alreadyDemoted", ctx.user().locale(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -514,10 +517,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { long chatId = ctx.chatId(); if (admins.contains(id)) - silent.send("You're already my master.", chatId); + silent.send(getLocalizedMessage("ability.claim.alreadyClaimed", ctx.user().locale()), chatId); else { admins.add(id); - silent.send("You're now my master.", chatId); + silent.send(getLocalizedMessage("ability.claim.claimed", ctx.user().locale()), chatId); } } else { // This is not a joke @@ -615,7 +618,12 @@ public abstract class AbilityBot extends TelegramLongPollingBot { boolean isOk = abilityTokens == 0 || (tokens.length > 0 && tokens.length == abilityTokens); if (!isOk) - silent.send(format("Sorry, this feature requires %d additional %s.", abilityTokens, abilityTokens == 1 ? "input" : "inputs"), getChatId(trio.a())); + silent.send( + getLocalizedMessage( + "checkInput.fail", + AbilityUtils.getUser(trio.a()).getLanguageCode(), + abilityTokens, abilityTokens == 1 ? "input" : "inputs"), + getChatId(trio.a())); return isOk; } @@ -627,7 +635,12 @@ public abstract class AbilityBot extends TelegramLongPollingBot { boolean isOk = abilityLocality == ALL || locality == abilityLocality; if (!isOk) - silent.send(format("Sorry, %s-only feature.", abilityLocality.toString().toLowerCase()), getChatId(trio.a())); + silent.send( + getLocalizedMessage( + "checkLocality.fail", + AbilityUtils.getUser(trio.a()).getLanguageCode(), + abilityLocality.toString().toLowerCase()), + getChatId(trio.a())); return isOk; } @@ -642,8 +655,11 @@ public abstract class AbilityBot extends TelegramLongPollingBot { boolean isOk = privacy.compareTo(trio.b().privacy()) >= 0; if (!isOk) - silent.send("Sorry, you don't have the required access level to do that.", getChatId(trio.a())); - + silent.send( + getLocalizedMessage( + "checkPrivacy.fail", + AbilityUtils.getUser(trio.a()).getLanguageCode()), + getChatId(trio.a())); return isOk; } diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java index 7cc08145..0c123434 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java @@ -1,11 +1,14 @@ package org.telegram.abilitybots.api.objects; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.MoreObjects; +import com.google.common.base.Strings; import org.telegram.telegrambots.api.objects.User; import java.io.Serializable; +import java.util.Locale; import java.util.Objects; import java.util.StringJoiner; @@ -27,12 +30,15 @@ public final class EndUser implements Serializable { private final String lastName; @JsonProperty("username") private final String username; + @JsonIgnore + private Locale locale; - private EndUser(Integer id, String firstName, String lastName, String username) { + private EndUser(Integer id, String firstName, String lastName, String username, Locale locale) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.username = username; + this.locale = locale != null? locale : Locale.ENGLISH; } @JsonCreator @@ -40,7 +46,7 @@ public final class EndUser implements Serializable { @JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName, @JsonProperty("username") String username) { - return new EndUser(id, firstName, lastName, username); + return new EndUser(id, firstName, lastName, username, null); } /** @@ -50,7 +56,8 @@ public final class EndUser implements Serializable { * @return an augmented end-user */ public static EndUser fromUser(User user) { - return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName()); + Locale locale = Strings.isNullOrEmpty(user.getLanguageCode()) ? null : Locale.forLanguageTag(user.getLanguageCode()); + return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName(), locale); } public int id() { @@ -69,6 +76,8 @@ public final class EndUser implements Serializable { return username; } + public Locale locale() { return locale; } + /** * The full name is identified as the concatenation of the first and last name, separated by a space. * This method can return an empty name if both first and last name are empty. @@ -118,12 +127,13 @@ public final class EndUser implements Serializable { return Objects.equals(id, endUser.id) && Objects.equals(firstName, endUser.firstName) && Objects.equals(lastName, endUser.lastName) && - Objects.equals(username, endUser.username); + Objects.equals(username, endUser.username) && + Objects.equals(locale, endUser.locale); } @Override public int hashCode() { - return Objects.hash(id, firstName, lastName, username); + return Objects.hash(id, firstName, lastName, username, locale); } @Override @@ -133,6 +143,7 @@ public final class EndUser implements Serializable { .add("firstName", firstName) .add("lastName", lastName) .add("username", username) + .add("locale", locale.toString()) .toString(); } } diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java index 6e313df4..21043fb3 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java @@ -1,10 +1,15 @@ package org.telegram.abilitybots.api.util; +import com.google.common.base.Strings; import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.objects.MessageContext; import org.telegram.telegrambots.api.objects.Update; import org.telegram.telegrambots.api.objects.User; +import java.text.MessageFormat; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; import java.util.function.Consumer; import java.util.function.Predicate; @@ -172,4 +177,25 @@ public final class AbilityUtils { public static Predicate isReplyTo(String msg) { return update -> update.getMessage().getReplyToMessage().getText().equals(msg); } + + public static String getLocalizedMessage(String messageCode, Locale locale, Object...arguments) { + ResourceBundle bundle; + if(locale == null){ + bundle = ResourceBundle.getBundle("default_messages"); + }else { + try { + bundle = ResourceBundle.getBundle("messages", locale); + } catch (MissingResourceException e) { + bundle = ResourceBundle.getBundle("default_messages"); + } + } + String message = bundle.getString(messageCode); + return MessageFormat.format(message, arguments); + } + + public static String getLocalizedMessage(String messageCode, String languageCode, Object...arguments){ + Locale locale = Strings.isNullOrEmpty(languageCode) ? null : Locale.forLanguageTag(languageCode); + return getLocalizedMessage(messageCode, locale, arguments); + } + } diff --git a/telegrambots-abilities/src/main/resources/default_messages.properties b/telegrambots-abilities/src/main/resources/default_messages.properties new file mode 100644 index 00000000..18dc77df --- /dev/null +++ b/telegrambots-abilities/src/main/resources/default_messages.properties @@ -0,0 +1,22 @@ +ability.commands.notFound=No public commands found. +ability.recover.fail=Oops, something went wrong during recovery. +ability.recover.error=I have failed to recover. + +ability.ban.alreadyBanned={0} is already *banned*. +ability.ban.banned={0} is now *banned*. + +ability.unban.notBanned=@{0} is *not* on the *blacklist*. +ability.unban.lifted=@{0}, your ban has been *lifted*. + +ability.promote.alreadyPromoted=@{0} is already an *admin*. +ability.promote.promoted=@{0} has been *promoted*. + +ability.demote.alreadyDemoted=@{0} is *not* an *admin*. +ability.demote.demoted=@{0} has been *demoted*. + +ability.claim.alreadyClaimed=You''re already my master. +ability.claim.claimed=You''re now my master. + +checkInput.fail=Sorry, this feature requires {0,number,integer} additional {1}. +checkLocality.fail=Sorry, {0}-only feature. +checkPrivacy.fail=Sorry, you don''t have the required access level to do that. diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 29b26e01..8727e86f 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -556,6 +556,7 @@ public class AbilityBotTest { when(message.hasText()).thenReturn(true); MessageContext context = mock(MessageContext.class); when(context.chatId()).thenReturn(GROUP_ID); + when(context.user()).thenReturn(MUSER); bot.reportCommands().action().accept(context); From 45ea5af1271e06eaaebba6d6b271c59a52bf0a53 Mon Sep 17 00:00:00 2001 From: davioooh Date: Mon, 30 Apr 2018 14:33:10 +0200 Subject: [PATCH 12/22] Update default messages --- .../src/main/resources/default_messages.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telegrambots-abilities/src/main/resources/default_messages.properties b/telegrambots-abilities/src/main/resources/default_messages.properties index 18dc77df..03ae86fc 100644 --- a/telegrambots-abilities/src/main/resources/default_messages.properties +++ b/telegrambots-abilities/src/main/resources/default_messages.properties @@ -1,4 +1,7 @@ ability.commands.notFound=No public commands found. + +ability.recover.message=I am ready to receive the backup file. Please reply to this message with the backup file attached. +ability.recover.success=I have successfully recovered. ability.recover.fail=Oops, something went wrong during recovery. ability.recover.error=I have failed to recover. From 97a4c0031b4f837205b0fba09544c3ea8f01bf93 Mon Sep 17 00:00:00 2001 From: davioooh Date: Mon, 30 Apr 2018 15:39:32 +0200 Subject: [PATCH 13/22] Refactor EndUser to serialize locale --- .../org/telegram/abilitybots/api/objects/EndUser.java | 8 ++++---- .../org/telegram/abilitybots/api/bot/AbilityBotTest.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java index 0c123434..0ea7919d 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java @@ -1,7 +1,6 @@ package org.telegram.abilitybots.api.objects; import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.MoreObjects; import com.google.common.base.Strings; @@ -30,7 +29,7 @@ public final class EndUser implements Serializable { private final String lastName; @JsonProperty("username") private final String username; - @JsonIgnore + @JsonProperty("locale") private Locale locale; private EndUser(Integer id, String firstName, String lastName, String username, Locale locale) { @@ -45,8 +44,9 @@ public final class EndUser implements Serializable { public static EndUser endUser(@JsonProperty("id") Integer id, @JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName, - @JsonProperty("username") String username) { - return new EndUser(id, firstName, lastName, username, null); + @JsonProperty("username") String username, + @JsonProperty("locale") Locale locale) { + return new EndUser(id, firstName, lastName, username, locale); } /** diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 8727e86f..b66f28ef 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -53,8 +53,8 @@ public class AbilityBotTest { private static final long GROUP_ID = 10L; private static final String TEST = "test"; private static final String[] TEXT = {TEST}; - public static final EndUser MUSER = endUser(1, "first", "last", "username"); - public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername"); + public static final EndUser MUSER = endUser(1, "first", "last", "username", null); + public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername", null); private DefaultBot bot; private DBContext db; @@ -293,7 +293,7 @@ public class AbilityBotTest { String newFirstName = MUSER.firstName() + "-test"; String newLastName = MUSER.lastName() + "-test"; int sameId = MUSER.id(); - EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername); + EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername, null); mockAlternateUser(update, message, user, changedUser); From 7ff5be3a72bdb56bbe503933c875fc0db644505e Mon Sep 17 00:00:00 2001 From: davioooh Date: Mon, 30 Apr 2018 19:50:44 +0200 Subject: [PATCH 14/22] Refactor localized message helper method --- .../org/telegram/abilitybots/api/util/AbilityUtils.java | 9 ++++++--- .../{default_messages.properties => messages.properties} | 0 2 files changed, 6 insertions(+), 3 deletions(-) rename telegrambots-abilities/src/main/resources/{default_messages.properties => messages.properties} (100%) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java index 21043fb3..a213e43b 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java @@ -181,12 +181,15 @@ public final class AbilityUtils { public static String getLocalizedMessage(String messageCode, Locale locale, Object...arguments) { ResourceBundle bundle; if(locale == null){ - bundle = ResourceBundle.getBundle("default_messages"); + bundle = ResourceBundle.getBundle("messages", Locale.ROOT); }else { try { - bundle = ResourceBundle.getBundle("messages", locale); + bundle = ResourceBundle.getBundle( + "messages", + locale, + ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_PROPERTIES)); } catch (MissingResourceException e) { - bundle = ResourceBundle.getBundle("default_messages"); + bundle = ResourceBundle.getBundle("messages", Locale.ROOT); } } String message = bundle.getString(messageCode); diff --git a/telegrambots-abilities/src/main/resources/default_messages.properties b/telegrambots-abilities/src/main/resources/messages.properties similarity index 100% rename from telegrambots-abilities/src/main/resources/default_messages.properties rename to telegrambots-abilities/src/main/resources/messages.properties From c8f1c69fb2841c71a8afae8fff654db0ccf44e54 Mon Sep 17 00:00:00 2001 From: davioooh Date: Wed, 2 May 2018 11:06:39 +0200 Subject: [PATCH 15/22] Complete externalization of messages --- .../telegram/abilitybots/api/bot/AbilityBot.java | 15 ++++++--------- .../src/main/resources/messages.properties | 2 ++ .../abilitybots/api/bot/AbilityBotTest.java | 6 ++++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index fd4d4aae..44e99b0a 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -102,11 +102,6 @@ public abstract class AbilityBot extends TelegramLongPollingBot { protected static final String RECOVER = "recover"; protected static final String COMMANDS = "commands"; - // Messages - // TODO replace hardcoded messages... - protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; - protected static final String RECOVER_SUCCESS = "I have successfully recovered."; - // DB and sender protected final DBContext db; protected MessageSender sender; @@ -270,7 +265,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try { return getUser(username).id(); } catch (IllegalStateException ex) { - silent.send(format("Sorry, I could not find the user [%s].", username), chatId); + silent.send(getLocalizedMessage("userNotFound","", username), chatId); // TODO how to retrieve language? throw propagate(ex); } } @@ -362,7 +357,8 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .locality(USER) .privacy(CREATOR) .input(0) - .action(ctx -> silent.forceReply(RECOVERY_MESSAGE, ctx.chatId())) + .action(ctx -> silent.forceReply( + getLocalizedMessage("ability.recover.message", ctx.user().locale()), ctx.chatId())) .reply(update -> { Long chatId = update.getMessage().getChatId(); String fileId = update.getMessage().getDocument().getFileId(); @@ -370,7 +366,8 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try (FileReader reader = new FileReader(downloadFileWithId(fileId))) { String backupData = IOUtils.toString(reader); if (db.recover(backupData)) { - silent.send(RECOVER_SUCCESS, chatId); + silent.send(getLocalizedMessage("ability.recover.success", + AbilityUtils.getUser(update).getLanguageCode()), chatId); // TODO how to retrieve language? } else { silent.send(getLocalizedMessage("ability.recover.fail", AbilityUtils.getUser(update).getLanguageCode()), chatId); @@ -380,7 +377,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { silent.send(getLocalizedMessage("ability.recover.error", AbilityUtils.getUser(update).getLanguageCode()), chatId); } - }, MESSAGE, DOCUMENT, REPLY, isReplyTo(RECOVERY_MESSAGE)) + }, MESSAGE, DOCUMENT, REPLY, isReplyTo(getLocalizedMessage("ability.recover.success", ""))) // TODO how to retrieve language? .build(); } diff --git a/telegrambots-abilities/src/main/resources/messages.properties b/telegrambots-abilities/src/main/resources/messages.properties index 03ae86fc..efd03c44 100644 --- a/telegrambots-abilities/src/main/resources/messages.properties +++ b/telegrambots-abilities/src/main/resources/messages.properties @@ -23,3 +23,5 @@ ability.claim.claimed=You''re now my master. checkInput.fail=Sorry, this feature requires {0,number,integer} additional {1}. checkLocality.fail=Sorry, {0}-only feature. checkPrivacy.fail=Sorry, you don''t have the required access level to do that. + +userNotFound=Sorry, I could not find the user [{0}]. \ No newline at end of file diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index b66f28ef..5dda6847 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -36,8 +36,6 @@ import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; import static org.mockito.internal.verification.VerificationModeFactory.times; -import static org.telegram.abilitybots.api.bot.AbilityBot.RECOVERY_MESSAGE; -import static org.telegram.abilitybots.api.bot.AbilityBot.RECOVER_SUCCESS; import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.EndUser.endUser; @@ -49,6 +47,10 @@ import static org.telegram.abilitybots.api.objects.MessageContext.newContext; import static org.telegram.abilitybots.api.objects.Privacy.*; public class AbilityBotTest { + // Messages + protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; + protected static final String RECOVER_SUCCESS = "I have successfully recovered."; + private static final String[] EMPTY_ARRAY = {}; private static final long GROUP_ID = 10L; private static final String TEST = "test"; From aecfe7693a42ffc9d0b9ffde2583e725e09ed1c6 Mon Sep 17 00:00:00 2001 From: davioooh Date: Fri, 4 May 2018 18:15:02 +0200 Subject: [PATCH 16/22] Add basic unit tests --- .../api/bot/AbilityBotI18nTest.java | 76 +++++++++++++++++++ .../api/bot/NoPublicCommandsBot.java | 16 ++++ .../test/resources/messages_it_IT.properties | 1 + 3 files changed, 93 insertions(+) create mode 100644 telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java create mode 100644 telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java create mode 100644 telegrambots-abilities/src/test/resources/messages_it_IT.properties diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java new file mode 100644 index 00000000..b8799004 --- /dev/null +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -0,0 +1,76 @@ +package org.telegram.abilitybots.api.bot; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.telegram.abilitybots.api.db.DBContext; +import org.telegram.abilitybots.api.objects.EndUser; +import org.telegram.abilitybots.api.objects.MessageContext; +import org.telegram.abilitybots.api.sender.MessageSender; +import org.telegram.abilitybots.api.sender.SilentSender; + +import java.io.IOException; +import java.util.Locale; + +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.mockito.Mockito.*; +import static org.mockito.internal.verification.VerificationModeFactory.times; +import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; +import static org.telegram.abilitybots.api.objects.EndUser.endUser; + +public class AbilityBotI18nTest { + public static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username", null); + public static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username", Locale.ITALY); + + private DBContext db; + private DefaultBot bot; + + private NoPublicCommandsBot noCommandsBot; + + private MessageSender sender; + private SilentSender silent; + + @Before + public void setUp() { + db = offlineInstance("db"); + bot = new DefaultBot(EMPTY, EMPTY, db); + + silent = mock(SilentSender.class); + + bot.sender = sender; + bot.silent = silent; + } + + @Test + public void missingPublicCommandsLocalizedCorrectly() { + NoPublicCommandsBot noCommandsBot = new NoPublicCommandsBot(EMPTY, EMPTY, db); + noCommandsBot.silent = silent; + + MessageContext context = mock(MessageContext.class); + when(context.chatId()).thenReturn(Long.valueOf(NO_LANGUAGE_USER.id())); + when(context.user()).thenReturn(NO_LANGUAGE_USER); + + noCommandsBot.reportCommands().action().accept(context); + + verify(silent, times(1)) + .send("No public commands found.", NO_LANGUAGE_USER.id()); + + // + + MessageContext context1 = mock(MessageContext.class); + when(context1.chatId()).thenReturn(Long.valueOf(ITALIAN_USER.id())); + when(context1.user()).thenReturn(ITALIAN_USER); + + noCommandsBot.reportCommands().action().accept(context1); + + verify(silent, times(1)) + .send("Non sono presenti comandi pubblici.", ITALIAN_USER.id()); + } + + + @After + public void tearDown() throws IOException { + db.clear(); + db.close(); + } +} diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java new file mode 100644 index 00000000..fa7b70e5 --- /dev/null +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java @@ -0,0 +1,16 @@ +package org.telegram.abilitybots.api.bot; + +import org.telegram.abilitybots.api.db.DBContext; + +public class NoPublicCommandsBot extends AbilityBot { + + + protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { + super(botToken, botUsername, db); + } + + @Override + public int creatorId() { + return 0; + } +} \ No newline at end of file diff --git a/telegrambots-abilities/src/test/resources/messages_it_IT.properties b/telegrambots-abilities/src/test/resources/messages_it_IT.properties new file mode 100644 index 00000000..c5656cc1 --- /dev/null +++ b/telegrambots-abilities/src/test/resources/messages_it_IT.properties @@ -0,0 +1 @@ +ability.commands.notFound=Non sono presenti comandi pubblici. \ No newline at end of file From bd7092921a3d506e10569d30f4f9ed082bbc92af Mon Sep 17 00:00:00 2001 From: davioooh Date: Fri, 4 May 2018 18:16:04 +0200 Subject: [PATCH 17/22] Remove locale retrieval to avoid exception --- .../main/java/org/telegram/abilitybots/api/bot/AbilityBot.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index 44e99b0a..298b91b4 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -367,7 +367,8 @@ public abstract class AbilityBot extends TelegramLongPollingBot { String backupData = IOUtils.toString(reader); if (db.recover(backupData)) { silent.send(getLocalizedMessage("ability.recover.success", - AbilityUtils.getUser(update).getLanguageCode()), chatId); // TODO how to retrieve language? + ""), chatId); + // TODO how to retrieve language? Getting java.lang.IllegalStateException: Could not retrieve originating user from update } else { silent.send(getLocalizedMessage("ability.recover.fail", AbilityUtils.getUser(update).getLanguageCode()), chatId); From ab86947cc33cd842359d6500187ce84206b2a566 Mon Sep 17 00:00:00 2001 From: davioooh Date: Tue, 8 May 2018 11:10:37 +0200 Subject: [PATCH 18/22] Fix issues - export message codes - standardize message codes - format/spacing --- .../abilitybots/api/bot/AbilityBot.java | 41 ++++++++++--------- .../abilitybots/api/objects/EndUser.java | 4 +- .../api/util/AbilityMessageCodes.java | 31 ++++++++++++++ .../abilitybots/api/util/AbilityUtils.java | 15 ++++--- .../src/main/resources/messages.properties | 22 +++++----- .../api/bot/AbilityBotI18nTest.java | 6 +-- .../abilitybots/api/bot/AbilityBotTest.java | 4 +- .../api/bot/NoPublicCommandsBot.java | 1 - 8 files changed, 78 insertions(+), 46 deletions(-) create mode 100644 telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityMessageCodes.java diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index 298b91b4..b67b9760 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -49,6 +49,7 @@ import static org.telegram.abilitybots.api.objects.Flag.*; import static org.telegram.abilitybots.api.objects.Locality.*; import static org.telegram.abilitybots.api.objects.MessageContext.newContext; import static org.telegram.abilitybots.api.objects.Privacy.*; +import static org.telegram.abilitybots.api.util.AbilityMessageCodes.*; import static org.telegram.abilitybots.api.util.AbilityUtils.*; /** @@ -265,7 +266,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try { return getUser(username).id(); } catch (IllegalStateException ex) { - silent.send(getLocalizedMessage("userNotFound","", username), chatId); // TODO how to retrieve language? + silent.send(getLocalizedMessage(USER_NOT_FOUND,"", username), chatId); // TODO how to retrieve language? throw propagate(ex); } } @@ -302,7 +303,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { }) .sorted() .reduce((a, b) -> format("%s%n%s", a, b)) - .orElse(getLocalizedMessage("ability.commands.notFound", ctx.user().locale())); + .orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, ctx.user().locale())); silent.send(commands, ctx.chatId()); }) @@ -358,7 +359,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .privacy(CREATOR) .input(0) .action(ctx -> silent.forceReply( - getLocalizedMessage("ability.recover.message", ctx.user().locale()), ctx.chatId())) + getLocalizedMessage(ABILITY_RECOVER_MESSAGE, ctx.user().locale()), ctx.chatId())) .reply(update -> { Long chatId = update.getMessage().getChatId(); String fileId = update.getMessage().getDocument().getFileId(); @@ -366,19 +367,19 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try (FileReader reader = new FileReader(downloadFileWithId(fileId))) { String backupData = IOUtils.toString(reader); if (db.recover(backupData)) { - silent.send(getLocalizedMessage("ability.recover.success", + silent.send(getLocalizedMessage(ABILITY_RECOVER_SUCCESS, ""), chatId); // TODO how to retrieve language? Getting java.lang.IllegalStateException: Could not retrieve originating user from update } else { - silent.send(getLocalizedMessage("ability.recover.fail", + silent.send(getLocalizedMessage(ABILITY_RECOVER_FAIL, AbilityUtils.getUser(update).getLanguageCode()), chatId); } } catch (Exception e) { BotLogger.error("Could not recover DB from backup", TAG, e); - silent.send(getLocalizedMessage("ability.recover.error", + silent.send(getLocalizedMessage(ABILITY_RECOVER_ERROR, AbilityUtils.getUser(update).getLanguageCode()), chatId); } - }, MESSAGE, DOCUMENT, REPLY, isReplyTo(getLocalizedMessage("ability.recover.success", ""))) // TODO how to retrieve language? + }, MESSAGE, DOCUMENT, REPLY, isReplyTo(getLocalizedMessage(ABILITY_RECOVER_SUCCESS, ""))) // TODO how to retrieve language? .build(); } @@ -412,10 +413,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (blacklist.contains(userId)) - silent.sendMd(getLocalizedMessage("ability.ban.alreadyBanned", ctx.user().locale(), escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_BAN_FAIL, ctx.user().locale(), escape(bannedUser)), ctx.chatId()); else { blacklist.add(userId); - silent.sendMd(getLocalizedMessage("ability.ban.banned", ctx.user().locale(), escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_BAN_SUCCESS, ctx.user().locale(), escape(bannedUser)), ctx.chatId()); } }) .post(commitTo(db)) @@ -440,9 +441,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (!blacklist.remove(userId)) - silent.sendMd(getLocalizedMessage("ability.unban.notBanned", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); else { - silent.sendMd(getLocalizedMessage("ability.unban.lifted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -464,10 +465,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.contains(userId)) - silent.sendMd(getLocalizedMessage("ability.promote.alreadyPromoted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); else { admins.add(userId); - silent.sendMd(getLocalizedMessage("ability.promote.promoted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); } }).post(commitTo(db)) .build(); @@ -488,9 +489,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.remove(userId)) { - silent.sendMd(getLocalizedMessage("ability.demote.demoted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); } else { - silent.sendMd(getLocalizedMessage("ability.demote.alreadyDemoted", ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -515,10 +516,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { long chatId = ctx.chatId(); if (admins.contains(id)) - silent.send(getLocalizedMessage("ability.claim.alreadyClaimed", ctx.user().locale()), chatId); + silent.send(getLocalizedMessage(ABILITY_CLAIM_FAIL, ctx.user().locale()), chatId); else { admins.add(id); - silent.send(getLocalizedMessage("ability.claim.claimed", ctx.user().locale()), chatId); + silent.send(getLocalizedMessage(ABILITY_CLAIM_SUCCESS, ctx.user().locale()), chatId); } } else { // This is not a joke @@ -618,7 +619,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (!isOk) silent.send( getLocalizedMessage( - "checkInput.fail", + CHECK_INPUT_FAIL, AbilityUtils.getUser(trio.a()).getLanguageCode(), abilityTokens, abilityTokens == 1 ? "input" : "inputs"), getChatId(trio.a())); @@ -635,7 +636,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (!isOk) silent.send( getLocalizedMessage( - "checkLocality.fail", + CHECK_LOCALITY_FAIL, AbilityUtils.getUser(trio.a()).getLanguageCode(), abilityLocality.toString().toLowerCase()), getChatId(trio.a())); @@ -655,7 +656,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (!isOk) silent.send( getLocalizedMessage( - "checkPrivacy.fail", + CHECK_PRIVACY_FAIL, AbilityUtils.getUser(trio.a()).getLanguageCode()), getChatId(trio.a())); return isOk; diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java index 0ea7919d..0f65e39b 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java @@ -37,7 +37,7 @@ public final class EndUser implements Serializable { this.firstName = firstName; this.lastName = lastName; this.username = username; - this.locale = locale != null? locale : Locale.ENGLISH; + this.locale = locale; } @JsonCreator @@ -143,7 +143,7 @@ public final class EndUser implements Serializable { .add("firstName", firstName) .add("lastName", lastName) .add("username", username) - .add("locale", locale.toString()) + .add("locale", locale) .toString(); } } diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityMessageCodes.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityMessageCodes.java new file mode 100644 index 00000000..4f21f937 --- /dev/null +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityMessageCodes.java @@ -0,0 +1,31 @@ +package org.telegram.abilitybots.api.util; + +public final class AbilityMessageCodes { + public static String USER_NOT_FOUND = "userNotFound"; + public static String CHECK_INPUT_FAIL = "checkInput.fail"; + public static String CHECK_LOCALITY_FAIL = "checkLocality.fail"; + public static String CHECK_PRIVACY_FAIL = "checkPrivacy.fail"; + + public static String ABILITY_COMMANDS_NOT_FOUND = "ability.commands.notFound"; + + public static String ABILITY_RECOVER_SUCCESS = "ability.recover.success"; + public static String ABILITY_RECOVER_FAIL = "ability.recover.fail"; + public static String ABILITY_RECOVER_MESSAGE = "ability.recover.message"; + public static String ABILITY_RECOVER_ERROR = "ability.recover.error"; + + public static String ABILITY_BAN_SUCCESS = "ability.ban.success"; + public static String ABILITY_BAN_FAIL = "ability.ban.fail"; + + public static String ABILITY_UNBAN_SUCCESS = "ability.unban.success"; + public static String ABILITY_UNBAN_FAIL = "ability.unban.fail"; + + public static String ABILITY_PROMOTE_SUCCESS = "ability.promote.success"; + public static String ABILITY_PROMOTE_FAIL = "ability.promote.fail"; + + public static String ABILITY_DEMOTE_SUCCESS = "ability.demote.success"; + public static String ABILITY_DEMOTE_FAIL = "ability.demote.fail"; + + public static String ABILITY_CLAIM_SUCCESS = "ability.claim.success"; + public static String ABILITY_CLAIM_FAIL = "ability.claim.fail"; + +} diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java index a213e43b..81209885 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java @@ -13,6 +13,9 @@ import java.util.ResourceBundle; import java.util.function.Consumer; import java.util.function.Predicate; +import static java.util.ResourceBundle.Control.FORMAT_PROPERTIES; +import static java.util.ResourceBundle.Control.getNoFallbackControl; +import static java.util.ResourceBundle.getBundle; import static org.telegram.abilitybots.api.objects.Flag.*; /** @@ -180,16 +183,16 @@ public final class AbilityUtils { public static String getLocalizedMessage(String messageCode, Locale locale, Object...arguments) { ResourceBundle bundle; - if(locale == null){ - bundle = ResourceBundle.getBundle("messages", Locale.ROOT); - }else { + if (locale == null) { + bundle = getBundle("messages", Locale.ROOT); + } else { try { - bundle = ResourceBundle.getBundle( + bundle = getBundle( "messages", locale, - ResourceBundle.Control.getNoFallbackControl(ResourceBundle.Control.FORMAT_PROPERTIES)); + getNoFallbackControl(FORMAT_PROPERTIES)); } catch (MissingResourceException e) { - bundle = ResourceBundle.getBundle("messages", Locale.ROOT); + bundle = getBundle("messages", Locale.ROOT); } } String message = bundle.getString(messageCode); diff --git a/telegrambots-abilities/src/main/resources/messages.properties b/telegrambots-abilities/src/main/resources/messages.properties index efd03c44..a8495e84 100644 --- a/telegrambots-abilities/src/main/resources/messages.properties +++ b/telegrambots-abilities/src/main/resources/messages.properties @@ -1,24 +1,24 @@ ability.commands.notFound=No public commands found. -ability.recover.message=I am ready to receive the backup file. Please reply to this message with the backup file attached. ability.recover.success=I have successfully recovered. ability.recover.fail=Oops, something went wrong during recovery. +ability.recover.message=I am ready to receive the backup file. Please reply to this message with the backup file attached. ability.recover.error=I have failed to recover. -ability.ban.alreadyBanned={0} is already *banned*. -ability.ban.banned={0} is now *banned*. +ability.ban.success={0} is now *banned*. +ability.ban.fail={0} is already *banned*. -ability.unban.notBanned=@{0} is *not* on the *blacklist*. -ability.unban.lifted=@{0}, your ban has been *lifted*. +ability.unban.success=@{0}, your ban has been *lifted*. +ability.unban.fail=@{0} is *not* on the *blacklist*. -ability.promote.alreadyPromoted=@{0} is already an *admin*. -ability.promote.promoted=@{0} has been *promoted*. +ability.promote.success=@{0} has been *promoted*. +ability.promote.fail=@{0} is already an *admin*. -ability.demote.alreadyDemoted=@{0} is *not* an *admin*. -ability.demote.demoted=@{0} has been *demoted*. +ability.demote.success=@{0} has been *demoted*. +ability.demote.fail=@{0} is *not* an *admin*. -ability.claim.alreadyClaimed=You''re already my master. -ability.claim.claimed=You''re now my master. +ability.claim.success=You''re now my master. +ability.claim.fail=You''re already my master. checkInput.fail=Sorry, this feature requires {0,number,integer} additional {1}. checkLocality.fail=Sorry, {0}-only feature. diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java index b8799004..d64cfe14 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -19,8 +19,8 @@ import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.EndUser.endUser; public class AbilityBotI18nTest { - public static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username", null); - public static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username", Locale.ITALY); + private static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username", null); + private static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username", Locale.ITALY); private DBContext db; private DefaultBot bot; @@ -55,8 +55,6 @@ public class AbilityBotI18nTest { verify(silent, times(1)) .send("No public commands found.", NO_LANGUAGE_USER.id()); - // - MessageContext context1 = mock(MessageContext.class); when(context1.chatId()).thenReturn(Long.valueOf(ITALIAN_USER.id())); when(context1.user()).thenReturn(ITALIAN_USER); diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 5dda6847..9fc8f99d 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -48,8 +48,8 @@ import static org.telegram.abilitybots.api.objects.Privacy.*; public class AbilityBotTest { // Messages - protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; - protected static final String RECOVER_SUCCESS = "I have successfully recovered."; + private static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached."; + private static final String RECOVER_SUCCESS = "I have successfully recovered."; private static final String[] EMPTY_ARRAY = {}; private static final long GROUP_ID = 10L; diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java index fa7b70e5..b4e49973 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java @@ -4,7 +4,6 @@ import org.telegram.abilitybots.api.db.DBContext; public class NoPublicCommandsBot extends AbilityBot { - protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { super(botToken, botUsername, db); } From 9347d064c1e32907759aaba53367a7a7a1ec000d Mon Sep 17 00:00:00 2001 From: davioooh Date: Sun, 13 May 2018 11:16:51 +0200 Subject: [PATCH 19/22] Refactor localized messages retrievement --- .../abilitybots/api/bot/AbilityBot.java | 24 +++++++++---------- .../abilitybots/api/objects/EndUser.java | 23 +++++------------- .../api/bot/AbilityBotI18nTest.java | 5 ++-- .../abilitybots/api/bot/AbilityBotTest.java | 6 ++--- 4 files changed, 23 insertions(+), 35 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index b67b9760..4c25a9d8 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -303,7 +303,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { }) .sorted() .reduce((a, b) -> format("%s%n%s", a, b)) - .orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, ctx.user().locale())); + .orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, AbilityUtils.getUser(ctx.update()).getLanguageCode())); silent.send(commands, ctx.chatId()); }) @@ -359,7 +359,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .privacy(CREATOR) .input(0) .action(ctx -> silent.forceReply( - getLocalizedMessage(ABILITY_RECOVER_MESSAGE, ctx.user().locale()), ctx.chatId())) + getLocalizedMessage(ABILITY_RECOVER_MESSAGE, AbilityUtils.getUser(ctx.update()).getLanguageCode()), ctx.chatId())) .reply(update -> { Long chatId = update.getMessage().getChatId(); String fileId = update.getMessage().getDocument().getFileId(); @@ -413,10 +413,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (blacklist.contains(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_BAN_FAIL, ctx.user().locale(), escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_BAN_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(bannedUser)), ctx.chatId()); else { blacklist.add(userId); - silent.sendMd(getLocalizedMessage(ABILITY_BAN_SUCCESS, ctx.user().locale(), escape(bannedUser)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_BAN_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(bannedUser)), ctx.chatId()); } }) .post(commitTo(db)) @@ -441,9 +441,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (!blacklist.remove(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); else { - silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -465,10 +465,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.contains(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); else { admins.add(userId); - silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); } }).post(commitTo(db)) .build(); @@ -489,9 +489,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.remove(userId)) { - silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_SUCCESS, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); } else { - silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_FAIL, ctx.user().locale(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -516,10 +516,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { long chatId = ctx.chatId(); if (admins.contains(id)) - silent.send(getLocalizedMessage(ABILITY_CLAIM_FAIL, ctx.user().locale()), chatId); + silent.send(getLocalizedMessage(ABILITY_CLAIM_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode()), chatId); else { admins.add(id); - silent.send(getLocalizedMessage(ABILITY_CLAIM_SUCCESS, ctx.user().locale()), chatId); + silent.send(getLocalizedMessage(ABILITY_CLAIM_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode()), chatId); } } else { // This is not a joke diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java index 0f65e39b..7cc08145 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java @@ -3,11 +3,9 @@ package org.telegram.abilitybots.api.objects; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.MoreObjects; -import com.google.common.base.Strings; import org.telegram.telegrambots.api.objects.User; import java.io.Serializable; -import java.util.Locale; import java.util.Objects; import java.util.StringJoiner; @@ -29,24 +27,20 @@ public final class EndUser implements Serializable { private final String lastName; @JsonProperty("username") private final String username; - @JsonProperty("locale") - private Locale locale; - private EndUser(Integer id, String firstName, String lastName, String username, Locale locale) { + private EndUser(Integer id, String firstName, String lastName, String username) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.username = username; - this.locale = locale; } @JsonCreator public static EndUser endUser(@JsonProperty("id") Integer id, @JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName, - @JsonProperty("username") String username, - @JsonProperty("locale") Locale locale) { - return new EndUser(id, firstName, lastName, username, locale); + @JsonProperty("username") String username) { + return new EndUser(id, firstName, lastName, username); } /** @@ -56,8 +50,7 @@ public final class EndUser implements Serializable { * @return an augmented end-user */ public static EndUser fromUser(User user) { - Locale locale = Strings.isNullOrEmpty(user.getLanguageCode()) ? null : Locale.forLanguageTag(user.getLanguageCode()); - return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName(), locale); + return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName()); } public int id() { @@ -76,8 +69,6 @@ public final class EndUser implements Serializable { return username; } - public Locale locale() { return locale; } - /** * The full name is identified as the concatenation of the first and last name, separated by a space. * This method can return an empty name if both first and last name are empty. @@ -127,13 +118,12 @@ public final class EndUser implements Serializable { return Objects.equals(id, endUser.id) && Objects.equals(firstName, endUser.firstName) && Objects.equals(lastName, endUser.lastName) && - Objects.equals(username, endUser.username) && - Objects.equals(locale, endUser.locale); + Objects.equals(username, endUser.username); } @Override public int hashCode() { - return Objects.hash(id, firstName, lastName, username, locale); + return Objects.hash(id, firstName, lastName, username); } @Override @@ -143,7 +133,6 @@ public final class EndUser implements Serializable { .add("firstName", firstName) .add("lastName", lastName) .add("username", username) - .add("locale", locale) .toString(); } } diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java index d64cfe14..68b178e1 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -10,7 +10,6 @@ import org.telegram.abilitybots.api.sender.MessageSender; import org.telegram.abilitybots.api.sender.SilentSender; import java.io.IOException; -import java.util.Locale; import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.mockito.Mockito.*; @@ -19,8 +18,8 @@ import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.EndUser.endUser; public class AbilityBotI18nTest { - private static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username", null); - private static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username", Locale.ITALY); + private static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username"); + private static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username"); private DBContext db; private DefaultBot bot; diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 9fc8f99d..3d1f7ae3 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -55,8 +55,8 @@ public class AbilityBotTest { private static final long GROUP_ID = 10L; private static final String TEST = "test"; private static final String[] TEXT = {TEST}; - public static final EndUser MUSER = endUser(1, "first", "last", "username", null); - public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername", null); + public static final EndUser MUSER = endUser(1, "first", "last", "username"); + public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername"); private DefaultBot bot; private DBContext db; @@ -295,7 +295,7 @@ public class AbilityBotTest { String newFirstName = MUSER.firstName() + "-test"; String newLastName = MUSER.lastName() + "-test"; int sameId = MUSER.id(); - EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername, null); + EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername); mockAlternateUser(update, message, user, changedUser); From 8729271d34c9521e14e42b3f8931e52941261c81 Mon Sep 17 00:00:00 2001 From: Abbas Abou Daya Date: Fri, 18 May 2018 04:40:27 -0400 Subject: [PATCH 20/22] Fix tests --- .../api/bot/AbilityBotI18nTest.java | 91 ++++++++++--------- .../abilitybots/api/bot/AbilityBotTest.java | 63 +++++++++---- .../api/bot/NoPublicCommandsBot.java | 15 --- 3 files changed, 96 insertions(+), 73 deletions(-) delete mode 100644 telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java index 68b178e1..75aa6df0 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -4,70 +4,79 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.telegram.abilitybots.api.db.DBContext; -import org.telegram.abilitybots.api.objects.EndUser; import org.telegram.abilitybots.api.objects.MessageContext; import org.telegram.abilitybots.api.sender.MessageSender; import org.telegram.abilitybots.api.sender.SilentSender; +import org.telegram.telegrambots.api.objects.User; import java.io.IOException; +import static java.lang.Long.valueOf; import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.mockito.Mockito.*; import static org.mockito.internal.verification.VerificationModeFactory.times; +import static org.telegram.abilitybots.api.bot.AbilityBotTest.mockContext; +import static org.telegram.abilitybots.api.bot.AbilityBotTest.newUser; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; -import static org.telegram.abilitybots.api.objects.EndUser.endUser; public class AbilityBotI18nTest { - private static final EndUser NO_LANGUAGE_USER = endUser(1, "first", "last", "username"); - private static final EndUser ITALIAN_USER = endUser(2, "first", "last", "username"); + private static final User NO_LANGUAGE_USER = newUser(1, "first", "last", "username", null); + private static final User ITALIAN_USER = newUser(2, "first", "last", "username", "it-IT"); - private DBContext db; - private DefaultBot bot; + private DBContext db; + private NoPublicCommandsBot bot; - private NoPublicCommandsBot noCommandsBot; + private MessageSender sender; + private SilentSender silent; - private MessageSender sender; - private SilentSender silent; + @Before + public void setUp() { + db = offlineInstance("db"); + bot = new NoPublicCommandsBot(EMPTY, EMPTY, db); - @Before - public void setUp() { - db = offlineInstance("db"); - bot = new DefaultBot(EMPTY, EMPTY, db); + sender = mock(MessageSender.class); + silent = mock(SilentSender.class); - silent = mock(SilentSender.class); + bot.sender = sender; + bot.silent = silent; + } - bot.sender = sender; - bot.silent = silent; - } + @Test + public void missingPublicCommandsLocalizedCorrectly1() { + MessageContext context = mockContext(NO_LANGUAGE_USER); - @Test - public void missingPublicCommandsLocalizedCorrectly() { - NoPublicCommandsBot noCommandsBot = new NoPublicCommandsBot(EMPTY, EMPTY, db); - noCommandsBot.silent = silent; + bot.reportCommands().action().accept(context); - MessageContext context = mock(MessageContext.class); - when(context.chatId()).thenReturn(Long.valueOf(NO_LANGUAGE_USER.id())); - when(context.user()).thenReturn(NO_LANGUAGE_USER); + verify(silent, times(1)) + .send("No public commands found.", NO_LANGUAGE_USER.getId()); + } - noCommandsBot.reportCommands().action().accept(context); + @Test + public void missingPublicCommandsLocalizedCorrectly2() { + MessageContext context1 = mockContext(ITALIAN_USER); - verify(silent, times(1)) - .send("No public commands found.", NO_LANGUAGE_USER.id()); + bot.reportCommands().action().accept(context1); - MessageContext context1 = mock(MessageContext.class); - when(context1.chatId()).thenReturn(Long.valueOf(ITALIAN_USER.id())); - when(context1.user()).thenReturn(ITALIAN_USER); - - noCommandsBot.reportCommands().action().accept(context1); - - verify(silent, times(1)) - .send("Non sono presenti comandi pubblici.", ITALIAN_USER.id()); - } + verify(silent, times(1)) + .send("Non sono presenti comandi pubblici.", ITALIAN_USER.getId()); + } - @After - public void tearDown() throws IOException { - db.clear(); - db.close(); - } + @After + public void tearDown() throws IOException { + db.clear(); + db.close(); + } + + public static class NoPublicCommandsBot extends AbilityBot { + + protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { + super(botToken, botUsername, db); + } + + @Override + public int creatorId() { + return 0; + } + } } diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 3d1f7ae3..54e48308 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -39,6 +39,7 @@ import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.EndUser.endUser; +import static org.telegram.abilitybots.api.objects.EndUser.fromUser; import static org.telegram.abilitybots.api.objects.Flag.DOCUMENT; import static org.telegram.abilitybots.api.objects.Flag.MESSAGE; import static org.telegram.abilitybots.api.objects.Locality.ALL; @@ -56,7 +57,9 @@ public class AbilityBotTest { private static final String TEST = "test"; private static final String[] TEXT = {TEST}; public static final EndUser MUSER = endUser(1, "first", "last", "username"); + public static final User TG_USER = newUser(1, "first", "last", "username", null); public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername"); + public static final User TG_CREATOR = newUser(1337, "creatorFirst", "creatorLast", "creatorUsername", null); private DefaultBot bot; private DBContext db; @@ -199,8 +202,7 @@ public class AbilityBotTest { @NotNull private MessageContext defaultContext() { - MessageContext context = mock(MessageContext.class); - when(context.user()).thenReturn(CREATOR); + MessageContext context = mockContext(TG_CREATOR, GROUP_ID); when(context.firstArg()).thenReturn(MUSER.username()); return context; } @@ -208,8 +210,7 @@ public class AbilityBotTest { @Test public void cannotBanCreator() { addUsers(MUSER, CREATOR); - MessageContext context = mock(MessageContext.class); - when(context.user()).thenReturn(MUSER); + MessageContext context = mockContext(TG_USER, GROUP_ID); when(context.firstArg()).thenReturn(CREATOR.username()); bot.banUser().action().accept(context); @@ -228,8 +229,7 @@ public class AbilityBotTest { @Test public void creatorCanClaimBot() { - MessageContext context = mock(MessageContext.class); - when(context.user()).thenReturn(CREATOR); + MessageContext context = mockContext(TG_CREATOR, GROUP_ID); bot.claimCreator().action().accept(context); @@ -241,8 +241,7 @@ public class AbilityBotTest { @Test public void userGetsBannedIfClaimsBot() { addUsers(MUSER); - MessageContext context = mock(MessageContext.class); - when(context.user()).thenReturn(MUSER); + MessageContext context = mockContext(TG_USER, GROUP_ID); bot.claimCreator().action().accept(context); @@ -550,21 +549,38 @@ public class AbilityBotTest { @Test public void canReportCommands() { - Update update = mock(Update.class); - Message message = mock(Message.class); - - when(update.hasMessage()).thenReturn(true); - when(update.getMessage()).thenReturn(message); - when(message.hasText()).thenReturn(true); - MessageContext context = mock(MessageContext.class); - when(context.chatId()).thenReturn(GROUP_ID); - when(context.user()).thenReturn(MUSER); + MessageContext context = mockContext(TG_USER, GROUP_ID); bot.reportCommands().action().accept(context); verify(silent, times(1)).send("default - dis iz default command", GROUP_ID); } + @NotNull + public static MessageContext mockContext(User user) { + return mockContext(user, user.getId()); + } + + @NotNull + public static MessageContext mockContext(User user, long groupId) { + Update update = mock(Update.class); + Message message = mock(Message.class); + EndUser endUser = fromUser(user); + + when(update.hasMessage()).thenReturn(true); + when(update.getMessage()).thenReturn(message); + + when(message.getFrom()).thenReturn(user); + when(message.hasText()).thenReturn(true); + + MessageContext context = mock(MessageContext.class); + when(context.update()).thenReturn(update); + when(context.chatId()).thenReturn(groupId); + when(context.user()).thenReturn(endUser); + + return context; + } + @After public void tearDown() throws IOException { db.clear(); @@ -655,4 +671,17 @@ public class AbilityBotTest { writer.close(); return backupFile; } + + public static User newUser(Integer id, String firstname, String lastname, String username, String languageCode) { + User user = mock(User.class); + + when(user.getBot()).thenReturn(false); + when(user.getFirstName()).thenReturn(firstname); + when(user.getId()).thenReturn(id); + when(user.getLastName()).thenReturn(lastname); + when(user.getUserName()).thenReturn(username); + when(user.getLanguageCode()).thenReturn(languageCode); + + return user; + } } diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java deleted file mode 100644 index b4e49973..00000000 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/NoPublicCommandsBot.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.telegram.abilitybots.api.bot; - -import org.telegram.abilitybots.api.db.DBContext; - -public class NoPublicCommandsBot extends AbilityBot { - - protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { - super(botToken, botUsername, db); - } - - @Override - public int creatorId() { - return 0; - } -} \ No newline at end of file From a819d7f1786b3e8e3a4a8b9e8f9c864162f31a2d Mon Sep 17 00:00:00 2001 From: Abbas Abou Daya Date: Mon, 21 May 2018 07:01:45 -0400 Subject: [PATCH 21/22] Cleanup and refactoring --- .../abilitybots/api/bot/AbilityBot.java | 126 ++++++++------- .../abilitybots/api/objects/EndUser.java | 138 ---------------- .../api/objects/MessageContext.java | 9 +- .../abilitybots/api/objects/Reply.java | 2 +- .../abilitybots/api/util/AbilityUtils.java | 42 ++++- .../api/bot/AbilityBotI18nTest.java | 10 +- .../abilitybots/api/bot/AbilityBotTest.java | 151 +++++++----------- .../abilitybots/api/db/MapDBContextTest.java | 39 +++-- 8 files changed, 197 insertions(+), 320 deletions(-) delete mode 100644 telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index 4c25a9d8..4b0c03fd 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -14,6 +14,7 @@ import org.telegram.telegrambots.api.methods.groupadministration.GetChatAdminist import org.telegram.telegrambots.api.methods.send.SendDocument; import org.telegram.telegrambots.api.objects.Message; import org.telegram.telegrambots.api.objects.Update; +import org.telegram.telegrambots.api.objects.User; import org.telegram.telegrambots.bots.DefaultBotOptions; import org.telegram.telegrambots.bots.TelegramLongPollingBot; import org.telegram.telegrambots.exceptions.TelegramApiException; @@ -44,7 +45,6 @@ import static java.util.stream.Collectors.toMap; import static jersey.repackaged.com.google.common.base.Throwables.propagate; import static org.telegram.abilitybots.api.db.MapDBContext.onlineInstance; import static org.telegram.abilitybots.api.objects.Ability.builder; -import static org.telegram.abilitybots.api.objects.EndUser.fromUser; import static org.telegram.abilitybots.api.objects.Flag.*; import static org.telegram.abilitybots.api.objects.Locality.*; import static org.telegram.abilitybots.api.objects.MessageContext.newContext; @@ -145,9 +145,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { } /** - * @return the map of ID -> EndUser + * @return the map of ID -> User */ - protected Map users() { + protected Map users() { return db.getMap(USERS); } @@ -232,7 +232,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { * @param username the username of the required user * @return the user */ - protected EndUser getUser(String username) { + protected User getUser(String username) { Integer id = userIds().get(username.toLowerCase()); if (id == null) { throw new IllegalStateException(format("Could not find ID corresponding to username [%s]", username)); @@ -247,13 +247,13 @@ public abstract class AbilityBot extends TelegramLongPollingBot { * @param id the id of the required user * @return the user */ - protected EndUser getUser(int id) { - EndUser endUser = users().get(id); - if (endUser == null) { + protected User getUser(int id) { + User user = users().get(id); + if (user == null) { throw new IllegalStateException(format("Could not find user corresponding to id [%d]", id)); } - return endUser; + return user; } /** @@ -264,9 +264,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { */ protected int getUserIdSendError(String username, long chatId) { try { - return getUser(username).id(); + return getUser(username).getId(); } catch (IllegalStateException ex) { - silent.send(getLocalizedMessage(USER_NOT_FOUND,"", username), chatId); // TODO how to retrieve language? + silent.send(getLocalizedMessage(USER_NOT_FOUND, "", username), chatId); // TODO how to retrieve language? throw propagate(ex); } } @@ -303,7 +303,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { }) .sorted() .reduce((a, b) -> format("%s%n%s", a, b)) - .orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, AbilityUtils.getUser(ctx.update()).getLanguageCode())); + .orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, ctx.user().getLanguageCode())); silent.send(commands, ctx.chatId()); }) @@ -359,7 +359,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .privacy(CREATOR) .input(0) .action(ctx -> silent.forceReply( - getLocalizedMessage(ABILITY_RECOVER_MESSAGE, AbilityUtils.getUser(ctx.update()).getLanguageCode()), ctx.chatId())) + getLocalizedMessage(ABILITY_RECOVER_MESSAGE, ctx.user().getLanguageCode()), ctx.chatId())) .reply(update -> { Long chatId = update.getMessage().getChatId(); String fileId = update.getMessage().getDocument().getFileId(); @@ -367,17 +367,13 @@ public abstract class AbilityBot extends TelegramLongPollingBot { try (FileReader reader = new FileReader(downloadFileWithId(fileId))) { String backupData = IOUtils.toString(reader); if (db.recover(backupData)) { - silent.send(getLocalizedMessage(ABILITY_RECOVER_SUCCESS, - ""), chatId); - // TODO how to retrieve language? Getting java.lang.IllegalStateException: Could not retrieve originating user from update + send(ABILITY_RECOVER_SUCCESS, update, chatId); } else { - silent.send(getLocalizedMessage(ABILITY_RECOVER_FAIL, - AbilityUtils.getUser(update).getLanguageCode()), chatId); + send(ABILITY_RECOVER_FAIL, update, chatId); } } catch (Exception e) { BotLogger.error("Could not recover DB from backup", TAG, e); - silent.send(getLocalizedMessage(ABILITY_RECOVER_ERROR, - AbilityUtils.getUser(update).getLanguageCode()), chatId); + send(ABILITY_RECOVER_ERROR, update, chatId); } }, MESSAGE, DOCUMENT, REPLY, isReplyTo(getLocalizedMessage(ABILITY_RECOVER_SUCCESS, ""))) // TODO how to retrieve language? .build(); @@ -405,18 +401,18 @@ public abstract class AbilityBot extends TelegramLongPollingBot { // Protection from abuse if (userId == creatorId()) { - userId = ctx.user().id(); - bannedUser = isNullOrEmpty(ctx.user().username()) ? addTag(ctx.user().username()) : ctx.user().shortName(); + userId = ctx.user().getId(); + bannedUser = isNullOrEmpty(ctx.user().getUserName()) ? addTag(ctx.user().getUserName()) : shortName(ctx.user()); } else { bannedUser = addTag(username); } Set blacklist = blacklist(); if (blacklist.contains(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_BAN_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(bannedUser)), ctx.chatId()); + sendMd(ABILITY_BAN_FAIL, ctx, escape(bannedUser)); else { blacklist.add(userId); - silent.sendMd(getLocalizedMessage(ABILITY_BAN_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(bannedUser)), ctx.chatId()); + sendMd(ABILITY_BAN_SUCCESS, ctx, escape(bannedUser)); } }) .post(commitTo(db)) @@ -441,9 +437,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set blacklist = blacklist(); if (!blacklist.remove(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, ctx.user().getLanguageCode(), escape(username)), ctx.chatId()); else { - silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); + silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, ctx.user().getLanguageCode(), escape(username)), ctx.chatId()); } }) .post(commitTo(db)) @@ -465,10 +461,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.contains(userId)) - silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); + sendMd(ABILITY_PROMOTE_FAIL, ctx, escape(username)); else { admins.add(userId); - silent.sendMd(getLocalizedMessage(ABILITY_PROMOTE_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); + sendMd(ABILITY_PROMOTE_SUCCESS, ctx, escape(username)); } }).post(commitTo(db)) .build(); @@ -489,9 +485,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Set admins = admins(); if (admins.remove(userId)) { - silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); + sendMd(ABILITY_DEMOTE_SUCCESS, ctx, escape(username)); } else { - silent.sendMd(getLocalizedMessage(ABILITY_DEMOTE_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode(), escape(username)), ctx.chatId()); + sendMd(ABILITY_DEMOTE_FAIL, ctx, escape(username)); } }) .post(commitTo(db)) @@ -510,26 +506,37 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .privacy(PUBLIC) .input(0) .action(ctx -> { - if (ctx.user().id() == creatorId()) { + if (ctx.user().getId() == creatorId()) { Set admins = admins(); int id = creatorId(); - long chatId = ctx.chatId(); if (admins.contains(id)) - silent.send(getLocalizedMessage(ABILITY_CLAIM_FAIL, AbilityUtils.getUser(ctx.update()).getLanguageCode()), chatId); + send(ABILITY_CLAIM_FAIL, ctx); else { admins.add(id); - silent.send(getLocalizedMessage(ABILITY_CLAIM_SUCCESS, AbilityUtils.getUser(ctx.update()).getLanguageCode()), chatId); + send(ABILITY_CLAIM_SUCCESS, ctx); } } else { // This is not a joke - abilities.get(BAN).action().accept(newContext(ctx.update(), ctx.user(), ctx.chatId(), ctx.user().username())); + abilities.get(BAN).action().accept(newContext(ctx.update(), ctx.user(), ctx.chatId(), ctx.user().getUserName())); } }) .post(commitTo(db)) .build(); } + private Optional send(String message, MessageContext ctx, String... args) { + return silent.send(getLocalizedMessage(message, ctx.user().getLanguageCode(), args), ctx.chatId()); + } + + private Optional sendMd(String message, MessageContext ctx, String... args) { + return silent.sendMd(getLocalizedMessage(message, ctx.user().getLanguageCode(), args), ctx.chatId()); + } + + private Optional send(String message, Update upd, Long chatId) { + return silent.send(getLocalizedMessage(message, AbilityUtils.getUser(upd).getLanguageCode()), chatId); + } + /** * Registers the declared abilities using method reflection. Also, replies are accumulated using the built abilities and standalone methods that return a Reply. *

@@ -599,7 +606,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { Pair getContext(Trio trio) { Update update = trio.a(); - EndUser user = fromUser(AbilityUtils.getUser(update)); + User user = AbilityUtils.getUser(update); return Pair.of(newContext(update, user, getChatId(update), trio.c()), trio.b()); } @@ -618,11 +625,11 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (!isOk) silent.send( - getLocalizedMessage( - CHECK_INPUT_FAIL, - AbilityUtils.getUser(trio.a()).getLanguageCode(), - abilityTokens, abilityTokens == 1 ? "input" : "inputs"), - getChatId(trio.a())); + getLocalizedMessage( + CHECK_INPUT_FAIL, + AbilityUtils.getUser(trio.a()).getLanguageCode(), + abilityTokens, abilityTokens == 1 ? "input" : "inputs"), + getChatId(trio.a())); return isOk; } @@ -635,30 +642,30 @@ public abstract class AbilityBot extends TelegramLongPollingBot { if (!isOk) silent.send( - getLocalizedMessage( - CHECK_LOCALITY_FAIL, - AbilityUtils.getUser(trio.a()).getLanguageCode(), - abilityLocality.toString().toLowerCase()), - getChatId(trio.a())); + getLocalizedMessage( + CHECK_LOCALITY_FAIL, + AbilityUtils.getUser(trio.a()).getLanguageCode(), + abilityLocality.toString().toLowerCase()), + getChatId(trio.a())); return isOk; } boolean checkPrivacy(Trio trio) { Update update = trio.a(); - EndUser user = fromUser(AbilityUtils.getUser(update)); + User user = AbilityUtils.getUser(update); Privacy privacy; - int id = user.id(); + int id = user.getId(); - privacy = isCreator(id) ? CREATOR : isAdmin(id) ? ADMIN : (isGroupUpdate(update) || isSuperGroupUpdate(update)) && isGroupAdmin(update, id)? GROUP_ADMIN : PUBLIC; + privacy = isCreator(id) ? CREATOR : isAdmin(id) ? ADMIN : (isGroupUpdate(update) || isSuperGroupUpdate(update)) && isGroupAdmin(update, id) ? GROUP_ADMIN : PUBLIC; boolean isOk = privacy.compareTo(trio.b().privacy()) >= 0; if (!isOk) silent.send( - getLocalizedMessage( - CHECK_PRIVACY_FAIL, - AbilityUtils.getUser(trio.a()).getLanguageCode()), - getChatId(trio.a())); + getLocalizedMessage( + CHECK_PRIVACY_FAIL, + AbilityUtils.getUser(trio.a()).getLanguageCode()), + getChatId(trio.a())); return isOk; } @@ -709,9 +716,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot { } Update addUser(Update update) { - EndUser endUser = fromUser(AbilityUtils.getUser(update)); + User endUser = AbilityUtils.getUser(update); - users().compute(endUser.id(), (id, user) -> { + users().compute(endUser.getId(), (id, user) -> { if (user == null) { updateUserId(user, endUser); return endUser; @@ -729,15 +736,15 @@ public abstract class AbilityBot extends TelegramLongPollingBot { return update; } - private void updateUserId(EndUser oldUser, EndUser newUser) { - if (oldUser != null && oldUser.username() != null) { + private void updateUserId(User oldUser, User newUser) { + if (oldUser != null && oldUser.getUserName() != null) { // Remove old username -> ID - userIds().remove(oldUser.username()); + userIds().remove(oldUser.getUserName()); } - if (newUser.username() != null) { + if (newUser.getUserName() != null) { // Add new mapping with the new username - userIds().put(newUser.username().toLowerCase(), newUser.id()); + userIds().put(newUser.getUserName().toLowerCase(), newUser.getId()); } } @@ -765,6 +772,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { return sender.downloadFile(sender.execute(new GetFile().setFileId(fileId))); } + private String escape(String username) { return username.replace("_", "\\_"); } diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java deleted file mode 100644 index 7cc08145..00000000 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/EndUser.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.telegram.abilitybots.api.objects; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.base.MoreObjects; -import org.telegram.telegrambots.api.objects.User; - -import java.io.Serializable; -import java.util.Objects; -import java.util.StringJoiner; - -import static org.apache.commons.lang3.StringUtils.isEmpty; - -/** - * This class serves the purpose of separating the basic Telegram {@link User} and the augmented {@link EndUser}. - *

- * It adds proper hashCode, equals, toString as well as useful utility methods such as {@link EndUser#shortName} and {@link EndUser#fullName}. - * - * @author Abbas Abou Daya - */ -public final class EndUser implements Serializable { - @JsonProperty("id") - private final Integer id; - @JsonProperty("firstName") - private final String firstName; - @JsonProperty("lastName") - private final String lastName; - @JsonProperty("username") - private final String username; - - private EndUser(Integer id, String firstName, String lastName, String username) { - this.id = id; - this.firstName = firstName; - this.lastName = lastName; - this.username = username; - } - - @JsonCreator - public static EndUser endUser(@JsonProperty("id") Integer id, - @JsonProperty("firstName") String firstName, - @JsonProperty("lastName") String lastName, - @JsonProperty("username") String username) { - return new EndUser(id, firstName, lastName, username); - } - - /** - * Constructs an {@link EndUser} from a {@link User}. - * - * @param user the Telegram user - * @return an augmented end-user - */ - public static EndUser fromUser(User user) { - return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName()); - } - - public int id() { - return id; - } - - public String firstName() { - return firstName; - } - - public String lastName() { - return lastName; - } - - public String username() { - return username; - } - - /** - * The full name is identified as the concatenation of the first and last name, separated by a space. - * This method can return an empty name if both first and last name are empty. - * - * @return the full name of the user - */ - public String fullName() { - StringJoiner name = new StringJoiner(" "); - - if (!isEmpty(firstName)) - name.add(firstName); - if (!isEmpty(lastName)) - name.add(lastName); - - return name.toString(); - } - - /** - * The short name is one of the following: - *

    - *
  1. First name
  2. - *
  3. Last name
  4. - *
  5. Username
  6. - *
- * The method will try to return the first valid name in the specified order. - * - * @return the short name of the user - */ - public String shortName() { - if (!isEmpty(firstName)) - return firstName; - - if (!isEmpty(lastName)) - return lastName; - - return username; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - - EndUser endUser = (EndUser) o; - return Objects.equals(id, endUser.id) && - Objects.equals(firstName, endUser.firstName) && - Objects.equals(lastName, endUser.lastName) && - Objects.equals(username, endUser.username); - } - - @Override - public int hashCode() { - return Objects.hash(id, firstName, lastName, username); - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(this) - .add("id", id) - .add("firstName", firstName) - .add("lastName", lastName) - .add("username", username) - .toString(); - } -} diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/MessageContext.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/MessageContext.java index c3335af9..ca689cd1 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/MessageContext.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/MessageContext.java @@ -3,6 +3,7 @@ package org.telegram.abilitybots.api.objects; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import org.telegram.telegrambots.api.objects.Update; +import org.telegram.telegrambots.api.objects.User; import java.util.Arrays; @@ -14,26 +15,26 @@ import java.util.Arrays; * @author Abbas Abou Daya */ public class MessageContext { - private final EndUser user; + private final User user; private final Long chatId; private final String[] arguments; private final Update update; - private MessageContext(Update update, EndUser user, Long chatId, String[] arguments) { + private MessageContext(Update update, User user, Long chatId, String[] arguments) { this.user = user; this.chatId = chatId; this.update = update; this.arguments = arguments; } - public static MessageContext newContext(Update update, EndUser user, Long chatId, String... arguments) { + public static MessageContext newContext(Update update, User user, Long chatId, String... arguments) { return new MessageContext(update, user, chatId, arguments); } /** * @return the originating Telegram user of this update */ - public EndUser user() { + public User user() { return user; } diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Reply.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Reply.java index 113d26b8..d88a99e3 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Reply.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Reply.java @@ -14,7 +14,7 @@ import static java.util.Arrays.asList; /** * A reply consists of update conditionals and an action to be applied on the update. *

- * If an update satisfies the {@link Reply#conditions}set by the reply, then it's safe to {@link Reply#actOn(Update)}. + * If an update satisfies the {@link Reply#conditions} set by the reply, then it's safe to {@link Reply#actOn(Update)}. * * @author Abbas Abou Daya */ diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java index 81209885..a1aea560 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java @@ -10,12 +10,14 @@ import java.text.MessageFormat; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.StringJoiner; import java.util.function.Consumer; import java.util.function.Predicate; import static java.util.ResourceBundle.Control.FORMAT_PROPERTIES; import static java.util.ResourceBundle.Control.getNoFallbackControl; import static java.util.ResourceBundle.getBundle; +import static org.apache.commons.lang3.StringUtils.isEmpty; import static org.telegram.abilitybots.api.objects.Flag.*; /** @@ -204,4 +206,42 @@ public final class AbilityUtils { return getLocalizedMessage(messageCode, locale, arguments); } -} + /** + * The short name is one of the following: + *

    + *
  1. First name
  2. + *
  3. Last name
  4. + *
  5. Username
  6. + *
+ * The method will try to return the first valid name in the specified order. + * + * @return the short name of the user + */ + public static String shortName(User user) { + if (!isEmpty(user.getFirstName())) + return user.getFirstName(); + + if (!isEmpty(user.getLastName())) + return user.getLastName(); + + return user.getUserName(); + } + + /** + * The full name is identified as the concatenation of the first and last name, separated by a space. + * This method can return an empty name if both first and last name are empty. + * + * @return the full name of the user + * @param user + */ + public static String fullName(User user) { + StringJoiner name = new StringJoiner(" "); + + if (!isEmpty(user.getFirstName())) + name.add(user.getFirstName()); + if (!isEmpty(user.getLastName())) + name.add(user.getLastName()); + + return name.toString(); + } +} \ No newline at end of file diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java index 75aa6df0..fdb8f92c 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -11,17 +11,15 @@ import org.telegram.telegrambots.api.objects.User; import java.io.IOException; -import static java.lang.Long.valueOf; import static org.apache.commons.lang3.StringUtils.EMPTY; import static org.mockito.Mockito.*; import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.telegram.abilitybots.api.bot.AbilityBotTest.mockContext; -import static org.telegram.abilitybots.api.bot.AbilityBotTest.newUser; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; public class AbilityBotI18nTest { - private static final User NO_LANGUAGE_USER = newUser(1, "first", "last", "username", null); - private static final User ITALIAN_USER = newUser(2, "first", "last", "username", "it-IT"); + private static final User NO_LANGUAGE_USER = new User(1, "first", false, "last", "username", null); + private static final User ITALIAN_USER = new User(2, "first", false, "last", "username", "it-IT"); private DBContext db; private NoPublicCommandsBot bot; @@ -53,9 +51,9 @@ public class AbilityBotI18nTest { @Test public void missingPublicCommandsLocalizedCorrectly2() { - MessageContext context1 = mockContext(ITALIAN_USER); + MessageContext context = mockContext(ITALIAN_USER); - bot.reportCommands().action().accept(context1); + bot.reportCommands().action().accept(context); verify(silent, times(1)) .send("Non sono presenti comandi pubblici.", ITALIAN_USER.getId()); diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java index 54e48308..c2fa81b7 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotTest.java @@ -38,8 +38,6 @@ import static org.mockito.Mockito.*; import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; -import static org.telegram.abilitybots.api.objects.EndUser.endUser; -import static org.telegram.abilitybots.api.objects.EndUser.fromUser; import static org.telegram.abilitybots.api.objects.Flag.DOCUMENT; import static org.telegram.abilitybots.api.objects.Flag.MESSAGE; import static org.telegram.abilitybots.api.objects.Locality.ALL; @@ -56,10 +54,8 @@ public class AbilityBotTest { private static final long GROUP_ID = 10L; private static final String TEST = "test"; private static final String[] TEXT = {TEST}; - public static final EndUser MUSER = endUser(1, "first", "last", "username"); - public static final User TG_USER = newUser(1, "first", "last", "username", null); - public static final EndUser CREATOR = endUser(1337, "creatorFirst", "creatorLast", "creatorUsername"); - public static final User TG_CREATOR = newUser(1337, "creatorFirst", "creatorLast", "creatorUsername", null); + public static final User USER = new User(1, "first", false, "last", "username", null); + public static final User CREATOR = new User(1337, "creatorFirst", false, "creatorLast", "creatorUsername", null); private DefaultBot bot; private DBContext db; @@ -80,39 +76,39 @@ public class AbilityBotTest { @Test public void sendsPrivacyViolation() { - Update update = mockFullUpdate(MUSER, "/admin"); + Update update = mockFullUpdate(USER, "/admin"); bot.onUpdateReceived(update); - verify(silent, times(1)).send("Sorry, you don't have the required access level to do that.", MUSER.id()); + verify(silent, times(1)).send("Sorry, you don't have the required access level to do that.", USER.getId()); } @Test public void sendsLocalityViolation() { - Update update = mockFullUpdate(MUSER, "/group"); + Update update = mockFullUpdate(USER, "/group"); bot.onUpdateReceived(update); - verify(silent, times(1)).send(format("Sorry, %s-only feature.", "group"), MUSER.id()); + verify(silent, times(1)).send(format("Sorry, %s-only feature.", "group"), USER.getId()); } @Test public void sendsInputArgsViolation() { - Update update = mockFullUpdate(MUSER, "/count 1 2 3"); + Update update = mockFullUpdate(USER, "/count 1 2 3"); bot.onUpdateReceived(update); - verify(silent, times(1)).send(format("Sorry, this feature requires %d additional inputs.", 4), MUSER.id()); + verify(silent, times(1)).send(format("Sorry, this feature requires %d additional inputs.", 4), USER.getId()); } @Test public void canProcessRepliesIfSatisfyRequirements() { - Update update = mockFullUpdate(MUSER, "must reply"); + Update update = mockFullUpdate(USER, "must reply"); // False means the update was not pushed down the stream since it has been consumed by the reply assertFalse(bot.filterReply(update)); - verify(silent, times(1)).send("reply", MUSER.id()); + verify(silent, times(1)).send("reply", USER.getId()); } @Test @@ -149,8 +145,8 @@ public class AbilityBotTest { @Test public void canDemote() { - addUsers(MUSER); - bot.admins().add(MUSER.id()); + addUsers(USER); + bot.admins().add(USER.getId()); MessageContext context = defaultContext(); @@ -163,33 +159,33 @@ public class AbilityBotTest { @Test public void canPromote() { - addUsers(MUSER); + addUsers(USER); MessageContext context = defaultContext(); bot.promoteAdmin().action().accept(context); Set actual = bot.admins(); - Set expected = newHashSet(MUSER.id()); + Set expected = newHashSet(USER.getId()); assertEquals("Could not sudo user", expected, actual); } @Test public void canBanUser() { - addUsers(MUSER); + addUsers(USER); MessageContext context = defaultContext(); bot.banUser().action().accept(context); Set actual = bot.blacklist(); - Set expected = newHashSet(MUSER.id()); + Set expected = newHashSet(USER.getId()); assertEquals("The ban was not emplaced", expected, actual); } @Test public void canUnbanUser() { - addUsers(MUSER); - bot.blacklist().add(MUSER.id()); + addUsers(USER); + bot.blacklist().add(USER.getId()); MessageContext context = defaultContext(); @@ -202,51 +198,49 @@ public class AbilityBotTest { @NotNull private MessageContext defaultContext() { - MessageContext context = mockContext(TG_CREATOR, GROUP_ID); - when(context.firstArg()).thenReturn(MUSER.username()); + MessageContext context = mockContext(CREATOR, GROUP_ID, USER.getUserName()); return context; } @Test public void cannotBanCreator() { - addUsers(MUSER, CREATOR); - MessageContext context = mockContext(TG_USER, GROUP_ID); - when(context.firstArg()).thenReturn(CREATOR.username()); + addUsers(USER, CREATOR); + MessageContext context = mockContext(USER, GROUP_ID, CREATOR.getUserName()); bot.banUser().action().accept(context); Set actual = bot.blacklist(); - Set expected = newHashSet(MUSER.id()); + Set expected = newHashSet(USER.getId()); assertEquals("Impostor was not added to the blacklist", expected, actual); } - private void addUsers(EndUser... users) { + private void addUsers(User... users) { Arrays.stream(users).forEach(user -> { - bot.users().put(user.id(), user); - bot.userIds().put(user.username().toLowerCase(), user.id()); + bot.users().put(user.getId(), user); + bot.userIds().put(user.getUserName().toLowerCase(), user.getId()); }); } @Test public void creatorCanClaimBot() { - MessageContext context = mockContext(TG_CREATOR, GROUP_ID); + MessageContext context = mockContext(CREATOR, GROUP_ID); bot.claimCreator().action().accept(context); Set actual = bot.admins(); - Set expected = newHashSet(CREATOR.id()); + Set expected = newHashSet(CREATOR.getId()); assertEquals("Creator was not properly added to the super admins set", expected, actual); } @Test public void userGetsBannedIfClaimsBot() { - addUsers(MUSER); - MessageContext context = mockContext(TG_USER, GROUP_ID); + addUsers(USER); + MessageContext context = mockContext(USER, GROUP_ID); bot.claimCreator().action().accept(context); Set actual = bot.blacklist(); - Set expected = newHashSet(MUSER.id()); + Set expected = newHashSet(USER.getId()); assertEquals("Could not find user on the blacklist", expected, actual); actual = bot.admins(); @@ -256,7 +250,7 @@ public class AbilityBotTest { @Test public void bannedCreatorPassesBlacklistCheck() { - bot.blacklist().add(CREATOR.id()); + bot.blacklist().add(CREATOR.getId()); Update update = mock(Update.class); Message message = mock(Message.class); User user = mock(User.class); @@ -273,35 +267,35 @@ public class AbilityBotTest { Message message = mock(Message.class); User user = mock(User.class); - mockAlternateUser(update, message, user, MUSER); + mockAlternateUser(update, message, USER); bot.addUser(update); - Map expectedUserIds = ImmutableMap.of(MUSER.username(), MUSER.id()); - Map expectedUsers = ImmutableMap.of(MUSER.id(), MUSER); + Map expectedUserIds = ImmutableMap.of(USER.getUserName(), USER.getId()); + Map expectedUsers = ImmutableMap.of(USER.getId(), USER); assertEquals("User was not added", expectedUserIds, bot.userIds()); assertEquals("User was not added", expectedUsers, bot.users()); } @Test public void canEditUser() { - addUsers(MUSER); + addUsers(USER); Update update = mock(Update.class); Message message = mock(Message.class); User user = mock(User.class); - String newUsername = MUSER.username() + "-test"; - String newFirstName = MUSER.firstName() + "-test"; - String newLastName = MUSER.lastName() + "-test"; - int sameId = MUSER.id(); - EndUser changedUser = endUser(sameId, newFirstName, newLastName, newUsername); + String newUsername = USER.getUserName() + "-test"; + String newFirstName = USER.getFirstName() + "-test"; + String newLastName = USER.getLastName() + "-test"; + int sameId = USER.getId(); + User changedUser = new User(sameId, newFirstName, false, newLastName, newUsername, null); - mockAlternateUser(update, message, user, changedUser); + mockAlternateUser(update, message, changedUser); bot.addUser(update); - Map expectedUserIds = ImmutableMap.of(changedUser.username(), changedUser.id()); - Map expectedUsers = ImmutableMap.of(changedUser.id(), changedUser); + Map expectedUserIds = ImmutableMap.of(changedUser.getUserName(), changedUser.getId()); + Map expectedUsers = ImmutableMap.of(changedUser.getId(), changedUser); assertEquals("User was not properly edited", bot.userIds(), expectedUserIds); assertEquals("User was not properly edited", expectedUsers, expectedUsers); } @@ -318,7 +312,7 @@ public class AbilityBotTest { @Test public void canCheckInput() { - Update update = mockFullUpdate(MUSER, "/something"); + Update update = mockFullUpdate(USER, "/something"); Ability abilityWithOneInput = getDefaultBuilder() .build(); Ability abilityWithZeroInput = getDefaultBuilder() @@ -409,7 +403,7 @@ public class AbilityBotTest { Trio creatorTrio = Trio.of(update, creatorAbility, TEXT); - bot.admins().add(MUSER.id()); + bot.admins().add(USER.getId()); mockUser(update, message, user); assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(creatorTrio)); @@ -440,15 +434,14 @@ public class AbilityBotTest { public void canRetrieveContext() { Update update = mock(Update.class); Message message = mock(Message.class); - User user = mock(User.class); Ability ability = getDefaultBuilder().build(); Trio trio = Trio.of(update, ability, TEXT); when(message.getChatId()).thenReturn(GROUP_ID); - mockUser(update, message, user); + mockUser(update, message, USER); Pair actualPair = bot.getContext(trio); - Pair expectedPair = Pair.of(newContext(update, MUSER, GROUP_ID, TEXT), ability); + Pair expectedPair = Pair.of(newContext(update, USER, GROUP_ID, TEXT), ability); assertEquals("Unexpected result when fetching for context", expectedPair, actualPair); } @@ -549,7 +542,7 @@ public class AbilityBotTest { @Test public void canReportCommands() { - MessageContext context = mockContext(TG_USER, GROUP_ID); + MessageContext context = mockContext(USER, GROUP_ID); bot.reportCommands().action().accept(context); @@ -562,10 +555,9 @@ public class AbilityBotTest { } @NotNull - public static MessageContext mockContext(User user, long groupId) { + public static MessageContext mockContext(User user, long groupId, String... args) { Update update = mock(Update.class); Message message = mock(Message.class); - EndUser endUser = fromUser(user); when(update.hasMessage()).thenReturn(true); when(update.getMessage()).thenReturn(message); @@ -573,12 +565,7 @@ public class AbilityBotTest { when(message.getFrom()).thenReturn(user); when(message.hasText()).thenReturn(true); - MessageContext context = mock(MessageContext.class); - when(context.update()).thenReturn(update); - when(context.chatId()).thenReturn(groupId); - when(context.user()).thenReturn(endUser); - - return context; + return newContext(update, user, groupId, args); } @After @@ -587,26 +574,14 @@ public class AbilityBotTest { db.close(); } - private User mockUser(EndUser fromUser) { - User user = mock(User.class); - when(user.getId()).thenReturn(fromUser.id()); - when(user.getUserName()).thenReturn(fromUser.username()); - when(user.getFirstName()).thenReturn(fromUser.firstName()); - when(user.getLastName()).thenReturn(fromUser.lastName()); - - return user; - } - @NotNull - private Update mockFullUpdate(EndUser fromUser, String args) { - bot.users().put(MUSER.id(), MUSER); - bot.users().put(CREATOR.id(), CREATOR); - bot.userIds().put(CREATOR.username(), CREATOR.id()); - bot.userIds().put(MUSER.username(), MUSER.id()); + private Update mockFullUpdate(User user, String args) { + bot.users().put(USER.getId(), USER); + bot.users().put(CREATOR.getId(), CREATOR); + bot.userIds().put(CREATOR.getUserName(), CREATOR.getId()); + bot.userIds().put(USER.getUserName(), USER.getId()); - bot.admins().add(CREATOR.id()); - - User user = mockUser(fromUser); + bot.admins().add(CREATOR.getId()); Update update = mock(Update.class); when(update.hasMessage()).thenReturn(true); @@ -615,7 +590,7 @@ public class AbilityBotTest { when(message.getText()).thenReturn(args); when(message.hasText()).thenReturn(true); when(message.isUserMessage()).thenReturn(true); - when(message.getChatId()).thenReturn((long) fromUser.id()); + when(message.getChatId()).thenReturn((long) user.getId()); when(update.getMessage()).thenReturn(message); return update; } @@ -624,17 +599,9 @@ public class AbilityBotTest { when(update.hasMessage()).thenReturn(true); when(update.getMessage()).thenReturn(message); when(message.getFrom()).thenReturn(user); - when(user.getFirstName()).thenReturn(MUSER.firstName()); - when(user.getLastName()).thenReturn(MUSER.lastName()); - when(user.getId()).thenReturn(MUSER.id()); - when(user.getUserName()).thenReturn(MUSER.username()); } - private void mockAlternateUser(Update update, Message message, User user, EndUser changedUser) { - when(user.getId()).thenReturn(changedUser.id()); - when(user.getFirstName()).thenReturn(changedUser.firstName()); - when(user.getLastName()).thenReturn(changedUser.lastName()); - when(user.getUserName()).thenReturn(changedUser.username()); + private void mockAlternateUser(Update update, Message message, User user) { when(message.getFrom()).thenReturn(user); when(update.hasMessage()).thenReturn(true); when(update.getMessage()).thenReturn(message); @@ -646,10 +613,12 @@ public class AbilityBotTest { Message botMessage = mock(Message.class); Document document = mock(Document.class); + when(message.getFrom()).thenReturn(CREATOR); when(update.getMessage()).thenReturn(message); when(message.getDocument()).thenReturn(document); when(botMessage.getText()).thenReturn(RECOVERY_MESSAGE); when(message.isReply()).thenReturn(true); + when(update.hasMessage()).thenReturn(true); when(message.hasDocument()).thenReturn(true); when(message.getReplyToMessage()).thenReturn(botMessage); when(message.getChatId()).thenReturn(GROUP_ID); diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/db/MapDBContextTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/db/MapDBContextTest.java index 7e53584b..502f70a1 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/db/MapDBContextTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/db/MapDBContextTest.java @@ -3,7 +3,7 @@ package org.telegram.abilitybots.api.db; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.telegram.abilitybots.api.objects.EndUser; +import org.telegram.telegrambots.api.objects.User; import java.io.IOException; import java.util.Map; @@ -12,12 +12,11 @@ import java.util.Set; import static com.google.common.collect.Maps.newHashMap; import static com.google.common.collect.Sets.newHashSet; import static java.lang.String.format; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import static org.telegram.abilitybots.api.bot.AbilityBot.USERS; import static org.telegram.abilitybots.api.bot.AbilityBot.USER_ID; import static org.telegram.abilitybots.api.bot.AbilityBotTest.CREATOR; -import static org.telegram.abilitybots.api.bot.AbilityBotTest.MUSER; +import static org.telegram.abilitybots.api.bot.AbilityBotTest.USER; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; public class MapDBContextTest { @@ -32,22 +31,22 @@ public class MapDBContextTest { @Test public void canRecoverDB() { - Map users = db.getMap(USERS); + Map users = db.getMap(USERS); Map userIds = db.getMap(USER_ID); - users.put(CREATOR.id(), CREATOR); - users.put(MUSER.id(), MUSER); - userIds.put(CREATOR.username(), CREATOR.id()); - userIds.put(MUSER.username(), MUSER.id()); + users.put(CREATOR.getId(), CREATOR); + users.put(USER.getId(), USER); + userIds.put(CREATOR.getUserName(), CREATOR.getId()); + userIds.put(USER.getUserName(), USER.getId()); db.getSet("AYRE").add(123123); - Map originalUsers = newHashMap(users); + Map originalUsers = newHashMap(users); String beforeBackupInfo = db.info(USERS); Object jsonBackup = db.backup(); db.clear(); boolean recovered = db.recover(jsonBackup); - Map recoveredUsers = db.getMap(USERS); + Map recoveredUsers = db.getMap(USERS); String afterRecoveryInfo = db.info(USERS); assertTrue("Could not recover database successfully", recovered); @@ -56,24 +55,24 @@ public class MapDBContextTest { } @Test - public void canFallbackDBIfRecoveryFails() throws IOException { - Set users = db.getSet(USERS); + public void canFallbackDBIfRecoveryFails() { + Set users = db.getSet(USERS); users.add(CREATOR); - users.add(MUSER); + users.add(USER); - Set originalSet = newHashSet(users); + Set originalSet = newHashSet(users); Object jsonBackup = db.backup(); String corruptBackup = "!@#$" + String.valueOf(jsonBackup); boolean recovered = db.recover(corruptBackup); - Set recoveredSet = db.getSet(USERS); + Set recoveredSet = db.getSet(USERS); - assertEquals("Recovery was successful from a CORRUPT backup", false, recovered); + assertFalse("Recovery was successful from a CORRUPT backup", recovered); assertEquals("Set before and after corrupt recovery are not equal", originalSet, recoveredSet); } @Test - public void canGetSummary() throws IOException { + public void canGetSummary() { String anotherTest = TEST + 1; db.getSet(TEST).add(TEST); db.getSet(anotherTest).add(anotherTest); @@ -86,7 +85,7 @@ public class MapDBContextTest { } @Test - public void canGetInfo() throws IOException { + public void canGetInfo() { db.getSet(TEST).add(TEST); String actualInfo = db.info(TEST); @@ -97,7 +96,7 @@ public class MapDBContextTest { } @Test(expected = IllegalStateException.class) - public void cantGetInfoFromNonexistentDBStructureName() throws IOException { + public void cantGetInfoFromNonexistentDBStructureName() { db.info(TEST); } From 7d216a1faed78ae2447bc7f6dc257bfa59c54437 Mon Sep 17 00:00:00 2001 From: Abbas Abou Daya Date: Tue, 22 May 2018 03:12:47 -0400 Subject: [PATCH 22/22] Fix todos, all ability bot messages are now properly localized --- .../abilitybots/api/bot/AbilityBot.java | 31 +++++++++++-------- .../api/bot/AbilityBotI18nTest.java | 19 ++++++------ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java index 4b0c03fd..d4d2c2ea 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/AbilityBot.java @@ -260,13 +260,14 @@ public abstract class AbilityBot extends TelegramLongPollingBot { * Gets the user with the specified username. If user was not found, the bot will send a message on Telegram. * * @param username the username of the required user + * @param ctx the message context with the originating user * @return the id of the user */ - protected int getUserIdSendError(String username, long chatId) { + protected int getUserIdSendError(String username, MessageContext ctx) { try { return getUser(username).getId(); } catch (IllegalStateException ex) { - silent.send(getLocalizedMessage(USER_NOT_FOUND, "", username), chatId); // TODO how to retrieve language? + silent.send(getLocalizedMessage(USER_NOT_FOUND, ctx.user().getLanguageCode(), username), ctx.chatId()); throw propagate(ex); } } @@ -361,21 +362,24 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .action(ctx -> silent.forceReply( getLocalizedMessage(ABILITY_RECOVER_MESSAGE, ctx.user().getLanguageCode()), ctx.chatId())) .reply(update -> { - Long chatId = update.getMessage().getChatId(); - String fileId = update.getMessage().getDocument().getFileId(); + String replyToMsg = update.getMessage().getReplyToMessage().getText(); + String recoverMessage = getLocalizedMessage(ABILITY_RECOVER_MESSAGE, AbilityUtils.getUser(update).getLanguageCode()); + if (!replyToMsg.equals(recoverMessage)) + return; + String fileId = update.getMessage().getDocument().getFileId(); try (FileReader reader = new FileReader(downloadFileWithId(fileId))) { String backupData = IOUtils.toString(reader); if (db.recover(backupData)) { - send(ABILITY_RECOVER_SUCCESS, update, chatId); + send(ABILITY_RECOVER_SUCCESS, update); } else { - send(ABILITY_RECOVER_FAIL, update, chatId); + send(ABILITY_RECOVER_FAIL, update); } } catch (Exception e) { BotLogger.error("Could not recover DB from backup", TAG, e); - send(ABILITY_RECOVER_ERROR, update, chatId); + send(ABILITY_RECOVER_ERROR, update); } - }, MESSAGE, DOCUMENT, REPLY, isReplyTo(getLocalizedMessage(ABILITY_RECOVER_SUCCESS, ""))) // TODO how to retrieve language? + }, MESSAGE, DOCUMENT, REPLY) .build(); } @@ -396,7 +400,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .input(1) .action(ctx -> { String username = stripTag(ctx.firstArg()); - int userId = getUserIdSendError(username, ctx.chatId()); + int userId = getUserIdSendError(username, ctx); String bannedUser; // Protection from abuse @@ -432,7 +436,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .input(1) .action(ctx -> { String username = stripTag(ctx.firstArg()); - Integer userId = getUserIdSendError(username, ctx.chatId()); + Integer userId = getUserIdSendError(username, ctx); Set blacklist = blacklist(); @@ -457,7 +461,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .input(1) .action(ctx -> { String username = stripTag(ctx.firstArg()); - Integer userId = getUserIdSendError(username, ctx.chatId()); + Integer userId = getUserIdSendError(username, ctx); Set admins = admins(); if (admins.contains(userId)) @@ -481,7 +485,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot { .input(1) .action(ctx -> { String username = stripTag(ctx.firstArg()); - Integer userId = getUserIdSendError(username, ctx.chatId()); + Integer userId = getUserIdSendError(username, ctx); Set admins = admins(); if (admins.remove(userId)) { @@ -533,7 +537,8 @@ public abstract class AbilityBot extends TelegramLongPollingBot { return silent.sendMd(getLocalizedMessage(message, ctx.user().getLanguageCode(), args), ctx.chatId()); } - private Optional send(String message, Update upd, Long chatId) { + private Optional send(String message, Update upd) { + Long chatId = upd.getMessage().getChatId(); return silent.send(getLocalizedMessage(message, AbilityUtils.getUser(upd).getLanguageCode()), chatId); } diff --git a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java index fdb8f92c..808b4eda 100644 --- a/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java +++ b/telegrambots-abilities/src/test/java/org/telegram/abilitybots/api/bot/AbilityBotI18nTest.java @@ -12,7 +12,8 @@ import org.telegram.telegrambots.api.objects.User; import java.io.IOException; import static org.apache.commons.lang3.StringUtils.EMPTY; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.internal.verification.VerificationModeFactory.times; import static org.telegram.abilitybots.api.bot.AbilityBotTest.mockContext; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; @@ -37,6 +38,7 @@ public class AbilityBotI18nTest { bot.sender = sender; bot.silent = silent; + } @Test @@ -59,7 +61,6 @@ public class AbilityBotI18nTest { .send("Non sono presenti comandi pubblici.", ITALIAN_USER.getId()); } - @After public void tearDown() throws IOException { db.clear(); @@ -68,13 +69,13 @@ public class AbilityBotI18nTest { public static class NoPublicCommandsBot extends AbilityBot { - protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { - super(botToken, botUsername, db); - } + protected NoPublicCommandsBot(String botToken, String botUsername, DBContext db) { + super(botToken, botUsername, db); + } - @Override - public int creatorId() { - return 0; - } + @Override + public int creatorId() { + return 1; + } } }