Merge pull request #466 from addo37/dev

Expose abilities and replies, add report command and reformat /commands, closes #436
This commit is contained in:
Ruben Bermudez 2018-05-26 12:30:14 +02:00 committed by GitHub
commit ce1b0402ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 176 additions and 83 deletions

View File

@ -102,8 +102,9 @@ If you're in doubt that you're missing some code, the full code example can be i
Go ahead and "/hello" to your bot. It should respond back with "Hello World!". Go ahead and "/hello" to your bot. It should respond back with "Hello World!".
Since you've implemented an AbilityBot, you get **factory abilities** as well. Try: Since you've implemented an AbilityBot, you get **factory abilities** as well. Try:
* /commands - Prints all commands supported by the bot * /report - Prints all user-defined commands supported by the bot
* This will essentially print "hello - says hello world!". Yes! This is the information we supplied to the ability. The bot prints the commands in the format accepted by BotFather. So, whenever you change, add or remove commands, you can simply /commands and forward that message to BotFather. * This will essentially print "hello - says hello world!". Yes! This is the information we supplied to the ability. The bot prints the commands in the format accepted by BotFather. So, whenever you change, add or remove commands, you can simply /report and forward that message to BotFather.
* /commands - Prints all commands exposed by the bot (factory and user-defined, with and without info)
* /claim - Claims this bot * /claim - Claims this bot
* /backup - returns a backup of the bot database * /backup - returns a backup of the bot database
* /recover - recovers the database * /recover - recovers the database

View File

@ -1,6 +1,12 @@
package org.telegram.abilitybots.api.bot; package org.telegram.abilitybots.api.bot;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull;
import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.db.DBContext;
import org.telegram.abilitybots.api.objects.*; import org.telegram.abilitybots.api.objects.*;
import org.telegram.abilitybots.api.sender.DefaultSender; import org.telegram.abilitybots.api.sender.DefaultSender;
@ -27,22 +33,24 @@ import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import java.util.Map.Entry;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.MultimapBuilder.hashKeys;
import static java.lang.String.format; import static java.lang.String.format;
import static java.time.ZonedDateTime.now; import static java.time.ZonedDateTime.now;
import static java.util.Arrays.stream; import static java.util.Arrays.stream;
import static java.util.Comparator.comparing;
import static java.util.Objects.nonNull; import static java.util.Objects.nonNull;
import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity;
import static java.util.regex.Pattern.CASE_INSENSITIVE; import static java.util.regex.Pattern.CASE_INSENSITIVE;
import static java.util.regex.Pattern.compile; import static java.util.regex.Pattern.compile;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toMap;
import static jersey.repackaged.com.google.common.base.Throwables.propagate; import static jersey.repackaged.com.google.common.base.Throwables.propagate;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import static org.telegram.abilitybots.api.db.MapDBContext.onlineInstance; 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.Ability.builder;
import static org.telegram.abilitybots.api.objects.Flag.*; import static org.telegram.abilitybots.api.objects.Flag.*;
@ -64,10 +72,11 @@ import static org.telegram.abilitybots.api.util.AbilityUtils.*;
* <li>Sets the user as the {@link Privacy#CREATOR} of the bot</li> * <li>Sets the user as the {@link Privacy#CREATOR} of the bot</li>
* <li>Only the user with the ID returned by {@link AbilityBot#creatorId()} can genuinely claim the bot</li> * <li>Only the user with the ID returned by {@link AbilityBot#creatorId()} can genuinely claim the bot</li>
* </ul> * </ul>
* <li>/commands - reports all user-defined commands (abilities)</li> * <li>/report - reports all user-defined commands (abilities)</li>
* <ul> * <ul>
* <li>The same format acceptable by BotFather</li> * <li>The same format acceptable by BotFather</li>
* </ul> * </ul>
* <li>/commands - returns a list of all possible bot commands based on the privacy of the requesting user</li>
* <li>/backup - returns a backup of the bot database</li> * <li>/backup - returns a backup of the bot database</li>
* <li>/recover - recovers the database</li> * <li>/recover - recovers the database</li>
* <li>/promote <code>@username</code> - promotes user to bot admin</li> * <li>/promote <code>@username</code> - promotes user to bot admin</li>
@ -102,6 +111,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
protected static final String BACKUP = "backup"; protected static final String BACKUP = "backup";
protected static final String RECOVER = "recover"; protected static final String RECOVER = "recover";
protected static final String COMMANDS = "commands"; protected static final String COMMANDS = "commands";
protected static final String REPORT = "report";
// DB and sender // DB and sender
protected final DBContext db; protected final DBContext db;
@ -172,6 +182,20 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
return db.getSet(ADMINS); return db.getSet(ADMINS);
} }
/**
* @return the immutable map of String -> Ability
*/
public Map<String, Ability> abilities() {
return abilities;
}
/**
* @return the immutable list carrying the embedded replies
*/
public List<Reply> replies() {
return replies;
}
/** /**
* This method contains the stream of actions that are applied on any update. * This method contains the stream of actions that are applied on any update.
* <p> * <p>
@ -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. * 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 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 * @return the id of the user
*/ */
protected int getUserIdSendError(String username, MessageContext ctx) { protected int getUserIdSendError(String username, MessageContext ctx) {
@ -290,9 +314,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
*/ */
public Ability reportCommands() { public Ability reportCommands() {
return builder() return builder()
.name(COMMANDS) .name(REPORT)
.locality(ALL) .locality(ALL)
.privacy(PUBLIC) .privacy(CREATOR)
.input(0) .input(0)
.action(ctx -> { .action(ctx -> {
String commands = abilities.entrySet().stream() String commands = abilities.entrySet().stream()
@ -311,6 +335,63 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
.build(); .build();
} }
/**
* Default format:
* <p>
* PUBLIC
* <p>
* [command1] - [description1]
* <p>
* [command2] - [description2]
* <p>
* GROUP_ADMIN
* <p>
* [command1] - [description1]
* <p>
* ...
*
* @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<Privacy, String> 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. * This backup ability returns the object defined by {@link DBContext#backup()} as a message document.
* <p> * <p>
@ -507,22 +588,17 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
return builder() return builder()
.name(CLAIM) .name(CLAIM)
.locality(ALL) .locality(ALL)
.privacy(PUBLIC) .privacy(CREATOR)
.input(0) .input(0)
.action(ctx -> { .action(ctx -> {
if (ctx.user().getId() == creatorId()) { Set<Integer> admins = admins();
Set<Integer> admins = admins(); int id = creatorId();
int id = creatorId();
if (admins.contains(id)) if (admins.contains(id))
send(ABILITY_CLAIM_FAIL, ctx); send(ABILITY_CLAIM_FAIL, ctx);
else { else {
admins.add(id); admins.add(id);
send(ABILITY_CLAIM_SUCCESS, ctx); 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()));
} }
}) })
.post(commitTo(db)) .post(commitTo(db))
@ -552,7 +628,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
abilities = stream(this.getClass().getMethods()) abilities = stream(this.getClass().getMethods())
.filter(method -> method.getReturnType().equals(Ability.class)) .filter(method -> method.getReturnType().equals(Ability.class))
.map(this::returnAbility) .map(this::returnAbility)
.collect(toMap(ability -> ability.name().toLowerCase(), identity())); .collect(ImmutableMap::<String, Ability>builder,
(b, a) -> b.put(a.name(), a),
(b1, b2) -> b1.putAll(b2.build()))
.build();
Stream<Reply> methodReplies = stream(this.getClass().getMethods()) Stream<Reply> methodReplies = stream(this.getClass().getMethods())
.filter(method -> method.getReturnType().equals(Reply.class)) .filter(method -> method.getReturnType().equals(Reply.class))
@ -561,7 +640,11 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
Stream<Reply> abilityReplies = abilities.values().stream() Stream<Reply> abilityReplies = abilities.values().stream()
.flatMap(ability -> ability.replies().stream()); .flatMap(ability -> ability.replies().stream());
replies = Stream.concat(methodReplies, abilityReplies).collect(toList()); replies = Stream.concat(methodReplies, abilityReplies).collect(
ImmutableList::<Reply>builder,
Builder::add,
(b1, b2) -> b1.addAll(b2.build()))
.build();
} catch (IllegalStateException e) { } 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); 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); throw propagate(e);
@ -661,7 +744,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
Privacy privacy; Privacy privacy;
int id = user.getId(); 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; boolean isOk = privacy.compareTo(trio.b().privacy()) >= 0;
@ -674,6 +757,14 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
return isOk; 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) { private boolean isGroupAdmin(Update update, int id) {
GetChatAdministrators admins = new GetChatAdministrators().setChatId(getChatId(update)); GetChatAdministrators admins = new GetChatAdministrators().setChatId(getChatId(update));

View File

@ -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.success=I have successfully recovered.
ability.recover.fail=Oops, something went wrong during recovery. ability.recover.fail=Oops, something went wrong during recovery.

View File

@ -42,23 +42,23 @@ public class AbilityBotI18nTest {
} }
@Test @Test
public void missingPublicCommandsLocalizedCorrectly1() { public void missingPublicCommandsLocalizedInEnglishByDefault() {
MessageContext context = mockContext(NO_LANGUAGE_USER); MessageContext context = mockContext(NO_LANGUAGE_USER);
bot.reportCommands().action().accept(context); bot.reportCommands().action().accept(context);
verify(silent, times(1)) verify(silent, times(1))
.send("No public commands found.", NO_LANGUAGE_USER.getId()); .send("No available commands found.", NO_LANGUAGE_USER.getId());
} }
@Test @Test
public void missingPublicCommandsLocalizedCorrectly2() { public void missingPublicCommandsLocalizedInItalian() {
MessageContext context = mockContext(ITALIAN_USER); MessageContext context = mockContext(ITALIAN_USER);
bot.reportCommands().action().accept(context); bot.reportCommands().action().accept(context);
verify(silent, times(1)) verify(silent, times(1))
.send("Non sono presenti comandi pubblici.", ITALIAN_USER.getId()); .send("Non sono presenti comandi disponibile.", ITALIAN_USER.getId());
} }
@After @After

View File

@ -198,8 +198,7 @@ public class AbilityBotTest {
@NotNull @NotNull
private MessageContext defaultContext() { private MessageContext defaultContext() {
MessageContext context = mockContext(CREATOR, GROUP_ID, USER.getUserName()); return mockContext(CREATOR, GROUP_ID, USER.getUserName());
return context;
} }
@Test @Test
@ -232,22 +231,6 @@ public class AbilityBotTest {
assertEquals("Creator was not properly added to the super admins set", expected, actual); 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<Integer> actual = bot.blacklist();
Set<Integer> 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 @Test
public void bannedCreatorPassesBlacklistCheck() { public void bannedCreatorPassesBlacklistCheck() {
bot.blacklist().add(CREATOR.getId()); bot.blacklist().add(CREATOR.getId());
@ -265,7 +248,6 @@ public class AbilityBotTest {
public void canAddUser() { public void canAddUser() {
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
User user = mock(User.class);
mockAlternateUser(update, message, USER); mockAlternateUser(update, message, USER);
@ -282,7 +264,6 @@ public class AbilityBotTest {
addUsers(USER); addUsers(USER);
Update update = mock(Update.class); Update update = mock(Update.class);
Message message = mock(Message.class); Message message = mock(Message.class);
User user = mock(User.class);
String newUsername = USER.getUserName() + "-test"; String newUsername = USER.getUserName() + "-test";
String newFirstName = USER.getFirstName() + "-test"; String newFirstName = USER.getFirstName() + "-test";
@ -306,8 +287,8 @@ public class AbilityBotTest {
Ability validAbility = getDefaultBuilder().build(); Ability validAbility = getDefaultBuilder().build();
Trio<Update, Ability, String[]> validPair = Trio.of(null, validAbility, null); Trio<Update, Ability, String[]> validPair = Trio.of(null, validAbility, null);
assertEquals("Bot can't validate ability properly", false, bot.validateAbility(invalidPair)); assertFalse("Bot can't validate ability properly", bot.validateAbility(invalidPair));
assertEquals("Bot can't validate ability properly", true, bot.validateAbility(validPair)); assertTrue("Bot can't validate ability properly", bot.validateAbility(validPair));
} }
@Test @Test
@ -322,15 +303,15 @@ public class AbilityBotTest {
Trio<Update, Ability, String[]> trioOneArg = Trio.of(update, abilityWithOneInput, TEXT); Trio<Update, Ability, String[]> trioOneArg = Trio.of(update, abilityWithOneInput, TEXT);
Trio<Update, Ability, String[]> trioZeroArg = Trio.of(update, abilityWithZeroInput, TEXT); Trio<Update, Ability, String[]> 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)); 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); 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 @Test
@ -350,10 +331,10 @@ public class AbilityBotTest {
mockUser(update, message, user); mockUser(update, message, user);
assertEquals("Unexpected result when checking for privacy", true, bot.checkPrivacy(publicTrio)); assertTrue("Unexpected result when checking for privacy", bot.checkPrivacy(publicTrio));
assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(groupAdminTrio)); assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(groupAdminTrio));
assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(adminTrio)); assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(adminTrio));
assertEquals("Unexpected result when checking for privacy", false, bot.checkPrivacy(creatorTrio)); assertFalse("Unexpected result when checking for privacy", bot.checkPrivacy(creatorTrio));
} }
@Test @Test
@ -374,7 +355,7 @@ public class AbilityBotTest {
when(silent.execute(any(GetChatAdministrators.class))).thenReturn(Optional.of(newArrayList(member))); 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 @Test
@ -391,7 +372,7 @@ public class AbilityBotTest {
when(silent.execute(any(GetChatAdministrators.class))).thenReturn(empty()); 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 @Test
@ -406,7 +387,7 @@ public class AbilityBotTest {
bot.admins().add(USER.getId()); bot.admins().add(USER.getId());
mockUser(update, message, user); 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 @Test
@ -425,9 +406,9 @@ public class AbilityBotTest {
mockUser(update, message, user); mockUser(update, message, user);
when(message.isUserMessage()).thenReturn(true); when(message.isUserMessage()).thenReturn(true);
assertEquals("Unexpected result when checking for locality", true, bot.checkLocality(publicTrio)); assertTrue("Unexpected result when checking for locality", bot.checkLocality(publicTrio));
assertEquals("Unexpected result when checking for locality", true, bot.checkLocality(userTrio)); assertTrue("Unexpected result when checking for locality", bot.checkLocality(userTrio));
assertEquals("Unexpected result when checking for locality", false, bot.checkLocality(groupTrio)); assertFalse("Unexpected result when checking for locality", bot.checkLocality(groupTrio));
} }
@Test @Test
@ -449,7 +430,7 @@ public class AbilityBotTest {
@Test @Test
public void defaultGlobalFlagIsTrue() { public void defaultGlobalFlagIsTrue() {
Update update = mock(Update.class); 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) @Test(expected = ArithmeticException.class)
@ -536,8 +517,8 @@ public class AbilityBotTest {
Trio<Update, Ability, String[]> docTrio = Trio.of(update, documentAbility, TEXT); Trio<Update, Ability, String[]> docTrio = Trio.of(update, documentAbility, TEXT);
Trio<Update, Ability, String[]> textTrio = Trio.of(update, textAbility, TEXT); Trio<Update, Ability, String[]> textTrio = Trio.of(update, textAbility, TEXT);
assertEquals("Unexpected result when checking for message flags", false, bot.checkMessageFlags(docTrio)); assertFalse("Unexpected result when checking for message flags", bot.checkMessageFlags(docTrio));
assertEquals("Unexpected result when checking for message flags", true, bot.checkMessageFlags(textTrio)); assertTrue("Unexpected result when checking for message flags", bot.checkMessageFlags(textTrio));
} }
@Test @Test
@ -568,6 +549,39 @@ public class AbilityBotTest {
return newContext(update, user, groupId, args); 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 @After
public void tearDown() throws IOException { public void tearDown() throws IOException {
db.clear(); db.clear();
@ -640,17 +654,4 @@ public class AbilityBotTest {
writer.close(); writer.close();
return backupFile; 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;
}
} }

View File

@ -1 +1 @@
ability.commands.notFound=Non sono presenti comandi pubblici. ability.commands.notFound=Non sono presenti comandi disponibile.