replies() {
+ return replies;
+ }
+
/**
* This method contains the stream of actions that are applied on any update.
*
@@ -260,7 +284,7 @@ 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
+ * @param ctx the message context with the originating user
* @return the id of the user
*/
protected int getUserIdSendError(String username, MessageContext ctx) {
@@ -290,9 +314,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
*/
public Ability reportCommands() {
return builder()
- .name(COMMANDS)
+ .name(REPORT)
.locality(ALL)
- .privacy(PUBLIC)
+ .privacy(CREATOR)
.input(0)
.action(ctx -> {
String commands = abilities.entrySet().stream()
@@ -311,6 +335,63 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
.build();
}
+ /**
+ * Default format:
+ *
+ * PUBLIC
+ *
+ * [command1] - [description1]
+ *
+ * [command2] - [description2]
+ *
+ * GROUP_ADMIN
+ *
+ * [command1] - [description1]
+ *
+ * ...
+ *
+ * @return the ability to print commands based on the privacy of the requesting user
+ */
+ public Ability commands() {
+ return builder()
+ .name(COMMANDS)
+ .locality(USER)
+ .privacy(PUBLIC)
+ .input(0)
+ .action(ctx -> {
+ Privacy privacy = getPrivacy(ctx.update(), ctx.user().getId());
+
+ ListMultimap abilitiesPerPrivacy = abilities.entrySet().stream()
+ .map(entry -> {
+ String name = entry.getValue().name();
+ String info = entry.getValue().info();
+
+ if (!isEmpty(info))
+ return Pair.of(entry.getValue().privacy(), format("/%s - %s", name, info));
+ return Pair.of(entry.getValue().privacy(), format("/%s", name));
+ })
+ .sorted(comparing(Pair::b))
+ .collect(() -> hashKeys().arrayListValues().build(),
+ (map, pair) -> map.put(pair.a(), pair.b()),
+ Multimap::putAll);
+
+ String commands = abilitiesPerPrivacy.asMap().entrySet().stream()
+ .filter(entry -> privacy.compareTo(entry.getKey()) >= 0)
+ .sorted(comparing(Entry::getKey))
+ .map(entry ->
+ entry.getValue().stream()
+ .reduce(entry.getKey().toString(), (a, b) -> format("%s\n%s", a, b))
+ )
+ .collect(joining("\n"));
+
+ if (commands.isEmpty())
+ commands = getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, ctx.user().getLanguageCode());
+
+ silent.send(commands, ctx.chatId());
+ })
+ .build();
+ }
+
/**
* This backup ability returns the object defined by {@link DBContext#backup()} as a message document.
*
@@ -507,22 +588,17 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
return builder()
.name(CLAIM)
.locality(ALL)
- .privacy(PUBLIC)
+ .privacy(CREATOR)
.input(0)
.action(ctx -> {
- if (ctx.user().getId() == creatorId()) {
- Set admins = admins();
- int id = creatorId();
+ Set admins = admins();
+ int id = creatorId();
- if (admins.contains(id))
- send(ABILITY_CLAIM_FAIL, ctx);
- else {
- admins.add(id);
- 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().getUserName()));
+ if (admins.contains(id))
+ send(ABILITY_CLAIM_FAIL, ctx);
+ else {
+ admins.add(id);
+ send(ABILITY_CLAIM_SUCCESS, ctx);
}
})
.post(commitTo(db))
@@ -552,7 +628,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
abilities = stream(this.getClass().getMethods())
.filter(method -> method.getReturnType().equals(Ability.class))
.map(this::returnAbility)
- .collect(toMap(ability -> ability.name().toLowerCase(), identity()));
+ .collect(ImmutableMap::builder,
+ (b, a) -> b.put(a.name(), a),
+ (b1, b2) -> b1.putAll(b2.build()))
+ .build();
Stream methodReplies = stream(this.getClass().getMethods())
.filter(method -> method.getReturnType().equals(Reply.class))
@@ -561,7 +640,11 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
Stream abilityReplies = abilities.values().stream()
.flatMap(ability -> ability.replies().stream());
- replies = Stream.concat(methodReplies, abilityReplies).collect(toList());
+ replies = Stream.concat(methodReplies, abilityReplies).collect(
+ ImmutableList::builder,
+ Builder::add,
+ (b1, b2) -> b1.addAll(b2.build()))
+ .build();
} catch (IllegalStateException e) {
BotLogger.error(TAG, "Duplicate names found while registering abilities. Make sure that the abilities declared don't clash with the reserved ones.", e);
throw propagate(e);
@@ -661,7 +744,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
Privacy privacy;
int id = user.getId();
- privacy = isCreator(id) ? CREATOR : isAdmin(id) ? ADMIN : (isGroupUpdate(update) || isSuperGroupUpdate(update)) && isGroupAdmin(update, id) ? GROUP_ADMIN : PUBLIC;
+ privacy = getPrivacy(update, id);
boolean isOk = privacy.compareTo(trio.b().privacy()) >= 0;
@@ -674,6 +757,14 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
return isOk;
}
+ @NotNull
+ private Privacy getPrivacy(Update update, int id) {
+ return isCreator(id) ?
+ CREATOR : isAdmin(id) ?
+ ADMIN : (isGroupUpdate(update) || isSuperGroupUpdate(update)) && isGroupAdmin(update, id) ?
+ GROUP_ADMIN : PUBLIC;
+ }
+
private boolean isGroupAdmin(Update update, int id) {
GetChatAdministrators admins = new GetChatAdministrators().setChatId(getChatId(update));
diff --git a/telegrambots-abilities/src/main/resources/messages.properties b/telegrambots-abilities/src/main/resources/messages.properties
index a8495e84..57e2485b 100644
--- a/telegrambots-abilities/src/main/resources/messages.properties
+++ b/telegrambots-abilities/src/main/resources/messages.properties
@@ -1,4 +1,4 @@
-ability.commands.notFound=No public commands found.
+ability.commands.notFound=No available commands found.
ability.recover.success=I have successfully recovered.
ability.recover.fail=Oops, something went wrong during recovery.
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 808b4eda..fd1b75f9 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
@@ -42,23 +42,23 @@ public class AbilityBotI18nTest {
}
@Test
- public void missingPublicCommandsLocalizedCorrectly1() {
+ public void missingPublicCommandsLocalizedInEnglishByDefault() {
MessageContext context = mockContext(NO_LANGUAGE_USER);
bot.reportCommands().action().accept(context);
verify(silent, times(1))
- .send("No public commands found.", NO_LANGUAGE_USER.getId());
+ .send("No available commands found.", NO_LANGUAGE_USER.getId());
}
@Test
- public void missingPublicCommandsLocalizedCorrectly2() {
+ public void missingPublicCommandsLocalizedInItalian() {
MessageContext context = mockContext(ITALIAN_USER);
bot.reportCommands().action().accept(context);
verify(silent, times(1))
- .send("Non sono presenti comandi pubblici.", ITALIAN_USER.getId());
+ .send("Non sono presenti comandi disponibile.", ITALIAN_USER.getId());
}
@After
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 c2fa81b7..d7cdb9d7 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
@@ -198,8 +198,7 @@ public class AbilityBotTest {
@NotNull
private MessageContext defaultContext() {
- MessageContext context = mockContext(CREATOR, GROUP_ID, USER.getUserName());
- return context;
+ return mockContext(CREATOR, GROUP_ID, USER.getUserName());
}
@Test
@@ -232,22 +231,6 @@ public class AbilityBotTest {
assertEquals("Creator was not properly added to the super admins set", expected, actual);
}
- @Test
- public void userGetsBannedIfClaimsBot() {
- addUsers(USER);
- MessageContext context = mockContext(USER, GROUP_ID);
-
- bot.claimCreator().action().accept(context);
-
- Set actual = bot.blacklist();
- Set expected = newHashSet(USER.getId());
- assertEquals("Could not find user on the blacklist", expected, actual);
-
- actual = bot.admins();
- expected = emptySet();
- assertEquals("Admins set is not empty", expected, actual);
- }
-
@Test
public void bannedCreatorPassesBlacklistCheck() {
bot.blacklist().add(CREATOR.getId());
@@ -265,7 +248,6 @@ public class AbilityBotTest {
public void canAddUser() {
Update update = mock(Update.class);
Message message = mock(Message.class);
- User user = mock(User.class);
mockAlternateUser(update, message, USER);
@@ -282,7 +264,6 @@ public class AbilityBotTest {
addUsers(USER);
Update update = mock(Update.class);
Message message = mock(Message.class);
- User user = mock(User.class);
String newUsername = USER.getUserName() + "-test";
String newFirstName = USER.getFirstName() + "-test";
@@ -306,8 +287,8 @@ public class AbilityBotTest {
Ability validAbility = getDefaultBuilder().build();
Trio validPair = Trio.of(null, validAbility, null);
- assertEquals("Bot can't validate ability properly", false, bot.validateAbility(invalidPair));
- assertEquals("Bot can't validate ability properly", true, bot.validateAbility(validPair));
+ assertFalse("Bot can't validate ability properly", bot.validateAbility(invalidPair));
+ assertTrue("Bot can't validate ability properly", bot.validateAbility(validPair));
}
@Test
@@ -322,15 +303,15 @@ public class AbilityBotTest {
Trio trioOneArg = Trio.of(update, abilityWithOneInput, TEXT);
Trio trioZeroArg = Trio.of(update, abilityWithZeroInput, TEXT);
- assertEquals("Unexpected result when applying token filter", true, bot.checkInput(trioOneArg));
+ assertTrue("Unexpected result when applying token filter", bot.checkInput(trioOneArg));
trioOneArg = Trio.of(update, abilityWithOneInput, addAll(TEXT, TEXT));
- assertEquals("Unexpected result when applying token filter", false, bot.checkInput(trioOneArg));
+ assertFalse("Unexpected result when applying token filter", bot.checkInput(trioOneArg));
- assertEquals("Unexpected result when applying token filter", true, bot.checkInput(trioZeroArg));
+ assertTrue("Unexpected result when applying token filter", bot.checkInput(trioZeroArg));
trioZeroArg = Trio.of(update, abilityWithZeroInput, EMPTY_ARRAY);
- assertEquals("Unexpected result when applying token filter", true, bot.checkInput(trioZeroArg));
+ assertTrue("Unexpected result when applying token filter", bot.checkInput(trioZeroArg));
}
@Test
@@ -350,10 +331,10 @@ public class AbilityBotTest {
mockUser(update, message, user);
- assertEquals("Unexpected result when checking for privacy", true, bot.checkPrivacy(publicTrio));
- assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(groupAdminTrio));
- assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(adminTrio));
- assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(creatorTrio));
+ assertTrue("Unexpected result when checking for privacy", bot.checkPrivacy(publicTrio));
+ assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(groupAdminTrio));
+ assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(adminTrio));
+ assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(creatorTrio));
}
@Test
@@ -374,7 +355,7 @@ public class AbilityBotTest {
when(silent.execute(any(GetChatAdministrators.class))).thenReturn(Optional.of(newArrayList(member)));
- assertEquals("Unexpected result when checking for privacy", true, bot.checkPrivacy(groupAdminTrio));
+ assertTrue("Unexpected result when checking for privacy", bot.checkPrivacy(groupAdminTrio));
}
@Test
@@ -391,7 +372,7 @@ public class AbilityBotTest {
when(silent.execute(any(GetChatAdministrators.class))).thenReturn(empty());
- assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(groupAdminTrio));
+ assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(groupAdminTrio));
}
@Test
@@ -406,7 +387,7 @@ public class AbilityBotTest {
bot.admins().add(USER.getId());
mockUser(update, message, user);
- assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(creatorTrio));
+ assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(creatorTrio));
}
@Test
@@ -425,9 +406,9 @@ public class AbilityBotTest {
mockUser(update, message, user);
when(message.isUserMessage()).thenReturn(true);
- assertEquals("Unexpected result when checking for locality", true, bot.checkLocality(publicTrio));
- assertEquals("Unexpected result when checking for locality", true, bot.checkLocality(userTrio));
- assertEquals("Unexpected result when checking for locality", false, bot.checkLocality(groupTrio));
+ assertTrue("Unexpected result when checking for locality", bot.checkLocality(publicTrio));
+ assertTrue("Unexpected result when checking for locality", bot.checkLocality(userTrio));
+ assertFalse("Unexpected result when checking for locality", bot.checkLocality(groupTrio));
}
@Test
@@ -449,7 +430,7 @@ public class AbilityBotTest {
@Test
public void defaultGlobalFlagIsTrue() {
Update update = mock(Update.class);
- assertEquals("Unexpected result when checking for the default global flags", true, bot.checkGlobalFlags(update));
+ assertTrue("Unexpected result when checking for the default global flags", bot.checkGlobalFlags(update));
}
@Test(expected = ArithmeticException.class)
@@ -536,8 +517,8 @@ public class AbilityBotTest {
Trio docTrio = Trio.of(update, documentAbility, TEXT);
Trio textTrio = Trio.of(update, textAbility, TEXT);
- assertEquals("Unexpected result when checking for message flags", false, bot.checkMessageFlags(docTrio));
- assertEquals("Unexpected result when checking for message flags", true, bot.checkMessageFlags(textTrio));
+ assertFalse("Unexpected result when checking for message flags", bot.checkMessageFlags(docTrio));
+ assertTrue("Unexpected result when checking for message flags", bot.checkMessageFlags(textTrio));
}
@Test
@@ -568,6 +549,39 @@ public class AbilityBotTest {
return newContext(update, user, groupId, args);
}
+ @Test
+ public void canPrintCommandsBasedOnPrivacy() {
+ 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 creatorCtx = newContext(update, CREATOR, GROUP_ID);
+
+ bot.commands().action().accept(creatorCtx);
+
+ String expected = "PUBLIC\n/commands\n/count\n/default - dis iz default command\n/group\n/test\nADMIN\n/admin\n/ban\n/demote\n/promote\n/unban\nCREATOR\n/backup\n/claim\n/recover\n/report";
+ verify(silent, times(1)).send(expected, GROUP_ID);
+ }
+
+ @Test
+ public void printsOnlyPublicCommandsForNormalUser() {
+ 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 userCtx = newContext(update, USER, GROUP_ID);
+
+ bot.commands().action().accept(userCtx);
+
+ String expected = "PUBLIC\n/commands\n/count\n/default - dis iz default command\n/group\n/test";
+ verify(silent, times(1)).send(expected, GROUP_ID);
+ }
+
@After
public void tearDown() throws IOException {
db.clear();
@@ -640,17 +654,4 @@ 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/resources/messages_it_IT.properties b/telegrambots-abilities/src/test/resources/messages_it_IT.properties
index c5656cc1..52f1377d 100644
--- a/telegrambots-abilities/src/test/resources/messages_it_IT.properties
+++ b/telegrambots-abilities/src/test/resources/messages_it_IT.properties
@@ -1 +1 @@
-ability.commands.notFound=Non sono presenti comandi pubblici.
\ No newline at end of file
+ability.commands.notFound=Non sono presenti comandi disponibile.
\ No newline at end of file