diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java index 8e3b8365..c9979ae9 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java @@ -180,6 +180,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability .filter(this::checkBlacklist) .map(this::addUser) .filter(this::filterReply) + .filter(this::hasUser) .map(this::getAbility) .filter(this::validateAbility) .filter(this::checkPrivacy) @@ -487,6 +488,12 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability return update; } + private boolean hasUser(Update update) { + // Valid updates without users should return an empty user + // Updates that are not recognized by the getUser method will throw an exception + return !AbilityUtils.getUser(update).equals(EMPTY_USER); + } + private void updateUserId(User oldUser, User newUser) { if (oldUser != null && oldUser.getUserName() != null) { // Remove old username -> ID 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 241bf141..f5817bb4 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 @@ -24,7 +24,7 @@ import static org.telegram.abilitybots.api.objects.Flag.*; * Helper and utility methods */ public final class AbilityUtils { - public static User EMPTY_USER = new User(); + public static User EMPTY_USER = new User(0, "", false, "", "", ""); private AbilityUtils() { 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 36717ac0..23bb280b 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 @@ -12,6 +12,7 @@ import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.objects.*; import org.telegram.abilitybots.api.sender.MessageSender; import org.telegram.abilitybots.api.sender.SilentSender; +import org.telegram.abilitybots.api.util.AbilityUtils; import org.telegram.abilitybots.api.util.Pair; import org.telegram.abilitybots.api.util.Trio; import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators; @@ -38,8 +39,8 @@ import static org.junit.jupiter.api.Assertions.*; 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.bot.TestUtils.*; import static org.telegram.abilitybots.api.bot.TestUtils.CREATOR; +import static org.telegram.abilitybots.api.bot.TestUtils.*; import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance; import static org.telegram.abilitybots.api.objects.Flag.DOCUMENT; import static org.telegram.abilitybots.api.objects.Flag.MESSAGE; @@ -120,6 +121,39 @@ public class AbilityBotTest { verify(silent, times(1)).send("reply", USER.getId()); } + @Test + void canProcessUpdatesWithoutUserInfo() { + Update update = mock(Update.class); + // At the moment, only poll updates carry no user information + when(update.hasPoll()).thenReturn(true); + + bot.onUpdateReceived(update); + } + + @Test + void getUserHasAllMethodsDefined() { + Arrays.stream(Update.class.getMethods()) + // filter to all these methods of hasXXX (hasPoll, hasMessage, etc...) + .filter(method -> method.getName().startsWith("has")) + // Gotta filter out hashCode + .filter(method -> method.getReturnType().getName().equals("boolean")) + .forEach(method -> { + Update update = mock(Update.class); + try { + // Mock the method and make sure it returns true so that it gets processed by the following method + when(method.invoke(update)).thenReturn(true); + // Call the getUser function, throws an IllegalStateException if there's an update that can't be processed + AbilityUtils.getUser(update); + } catch (IllegalStateException e) { + throw new RuntimeException( + format("Found an update variation that is not handled by the getUser util method [%s]", method.getName()), e); + } catch (NullPointerException | ReflectiveOperationException e) { + // This is fine, the mock isn't complete and we're only + // looking for IllegalStateExceptions thrown by the method + } + }); + } + @Test void canBackupDB() throws TelegramApiException { MessageContext context = defaultContext();