Merge pull request #671 from addo37/add-ability-toggle
Add Abillity toggles and export default abilities to their own class
This commit is contained in:
commit
fc12de81c0
@ -8,6 +8,7 @@
|
|||||||
* [[Simple Example]]
|
* [[Simple Example]]
|
||||||
* [[Hello Ability]]
|
* [[Hello Ability]]
|
||||||
* [[Using Replies]]
|
* [[Using Replies]]
|
||||||
|
* [[Ability Toggle]]
|
||||||
* [[State Machines]]
|
* [[State Machines]]
|
||||||
* [[Database Handling]]
|
* [[Database Handling]]
|
||||||
* [[Ability Extensions]]
|
* [[Ability Extensions]]
|
||||||
|
42
TelegramBots.wiki/abilities/Ability-Toggle.md
Normal file
42
TelegramBots.wiki/abilities/Ability-Toggle.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Ability Toggle
|
||||||
|
Well, what if you don't like all the default abilities that AbilityBot supplies? Fear not, you are able to disable all of them, even rename them if you will!
|
||||||
|
|
||||||
|
You may pass a custom toggle to your abilitybot constructor to customize how these abilities get registered.
|
||||||
|
|
||||||
|
## The Barebone Toggle
|
||||||
|
The barebone toggle is used to **turn off** all the default abilities that come with the bot (ban, unban, demote, promte, etc...). To use the barebone toggle, call your super constructor with:
|
||||||
|
```java
|
||||||
|
import org.telegram.abilitybots.api.toggle.BareboneToggle;
|
||||||
|
|
||||||
|
public class YourAwesomeBot extends AbilityBot {
|
||||||
|
public YourAwesomeBot(String token, String username) {
|
||||||
|
BareboneToggle toggle = new BareboneToggle();
|
||||||
|
super(token, username, toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override ceatorId()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Obviously, you can export this as a parameter that you can pass to your bot's constructor.
|
||||||
|
|
||||||
|
## The Custom Toggle
|
||||||
|
The custom toggle allows you to customize or turn off the names of the abilities that the abilitybot exposes.
|
||||||
|
```java
|
||||||
|
import org.telegram.abilitybots.api.toggle.CustomToggle;
|
||||||
|
|
||||||
|
public class YourAwesomeBot extends AbilityBot {
|
||||||
|
public YourAwesomeBot(String token, String username) {
|
||||||
|
CustomToggle toggle = new CustomToggle()
|
||||||
|
.turnOff("ban")
|
||||||
|
.toggle("promote", "upgrade");
|
||||||
|
|
||||||
|
super(token, username, toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override ceatorId()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
With these changes, the ability "ban" is no longer available and the "promote" ability has been renamed to "upgrade".
|
||||||
|
## The Default Toggle
|
||||||
|
The default toggle is automatically used if the user does not specify a toggle. The default toggle allows all the abilities to be effective and unchanged.
|
@ -1,6 +1,8 @@
|
|||||||
package org.telegram.abilitybots.api.bot;
|
package org.telegram.abilitybots.api.bot;
|
||||||
|
|
||||||
import org.telegram.abilitybots.api.db.DBContext;
|
import org.telegram.abilitybots.api.db.DBContext;
|
||||||
|
import org.telegram.abilitybots.api.toggle.AbilityToggle;
|
||||||
|
import org.telegram.abilitybots.api.toggle.DefaultToggle;
|
||||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||||
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
||||||
@ -16,18 +18,34 @@ import static org.telegram.abilitybots.api.db.MapDBContext.onlineInstance;
|
|||||||
* @author Abbas Abou Daya
|
* @author Abbas Abou Daya
|
||||||
*/
|
*/
|
||||||
public abstract class AbilityBot extends BaseAbilityBot implements LongPollingBot {
|
public abstract class AbilityBot extends BaseAbilityBot implements LongPollingBot {
|
||||||
protected AbilityBot(String botToken, String botUsername, DBContext db, DefaultBotOptions botOptions) {
|
protected AbilityBot(String botToken, String botUsername, DBContext db, AbilityToggle toggle, DefaultBotOptions botOptions) {
|
||||||
super(botToken, botUsername, db, botOptions);
|
super(botToken, botUsername, db, toggle, botOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbilityBot(String botToken, String botUsername, DBContext db) {
|
protected AbilityBot(String botToken, String botUsername, AbilityToggle toggle, DefaultBotOptions options) {
|
||||||
this(botToken, botUsername, db, new DefaultBotOptions());
|
this(botToken, botUsername, onlineInstance(botUsername), toggle, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbilityBot(String botToken, String botUsername, DBContext db, AbilityToggle toggle) {
|
||||||
|
this(botToken, botUsername, db, toggle, new DefaultBotOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbilityBot(String botToken, String botUsername, DBContext db, DefaultBotOptions options) {
|
||||||
|
this(botToken, botUsername, db, new DefaultToggle(), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbilityBot(String botToken, String botUsername, DefaultBotOptions botOptions) {
|
protected AbilityBot(String botToken, String botUsername, DefaultBotOptions botOptions) {
|
||||||
this(botToken, botUsername, onlineInstance(botUsername), botOptions);
|
this(botToken, botUsername, onlineInstance(botUsername), botOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected AbilityBot(String botToken, String botUsername, AbilityToggle toggle) {
|
||||||
|
this(botToken, botUsername, onlineInstance(botUsername), toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbilityBot(String botToken, String botUsername, DBContext db) {
|
||||||
|
this(botToken, botUsername, db, new DefaultToggle());
|
||||||
|
}
|
||||||
|
|
||||||
protected AbilityBot(String botToken, String botUsername) {
|
protected AbilityBot(String botToken, String botUsername) {
|
||||||
this(botToken, botUsername, onlineInstance(botUsername));
|
this(botToken, botUsername, onlineInstance(botUsername));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package org.telegram.abilitybots.api.bot;
|
package org.telegram.abilitybots.api.bot;
|
||||||
|
|
||||||
import org.telegram.abilitybots.api.db.DBContext;
|
import org.telegram.abilitybots.api.db.DBContext;
|
||||||
|
import org.telegram.abilitybots.api.toggle.AbilityToggle;
|
||||||
|
import org.telegram.abilitybots.api.toggle.DefaultToggle;
|
||||||
import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
|
import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
|
||||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||||
@ -21,19 +23,35 @@ public abstract class AbilityWebhookBot extends BaseAbilityBot implements Webhoo
|
|||||||
|
|
||||||
private final String botPath;
|
private final String botPath;
|
||||||
|
|
||||||
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, DBContext db, DefaultBotOptions botOptions) {
|
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, DBContext db, AbilityToggle toggle, DefaultBotOptions botOptions) {
|
||||||
super(botToken, botUsername, db, botOptions);
|
super(botToken, botUsername, db, toggle, botOptions);
|
||||||
this.botPath = botPath;
|
this.botPath = botPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, DBContext db) {
|
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, AbilityToggle toggle, DefaultBotOptions options) {
|
||||||
this(botToken, botUsername, botPath, db, new DefaultBotOptions());
|
this(botToken, botUsername, botPath, onlineInstance(botUsername), toggle, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, DBContext db, AbilityToggle toggle) {
|
||||||
|
this(botToken, botUsername, botPath, db, toggle, new DefaultBotOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, DBContext db, DefaultBotOptions options) {
|
||||||
|
this(botToken, botUsername, botPath, db, new DefaultToggle(), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, DefaultBotOptions botOptions) {
|
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, DefaultBotOptions botOptions) {
|
||||||
this(botToken, botUsername, botPath, onlineInstance(botUsername), botOptions);
|
this(botToken, botUsername, botPath, onlineInstance(botUsername), botOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, AbilityToggle toggle) {
|
||||||
|
this(botToken, botUsername, botPath, onlineInstance(botUsername), toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbilityWebhookBot(String botToken, String botUsername, String botPath, DBContext db) {
|
||||||
|
this(botToken, botUsername, botPath, db, new DefaultToggle());
|
||||||
|
}
|
||||||
|
|
||||||
protected AbilityWebhookBot(String botToken, String botUsername, String botPath) {
|
protected AbilityWebhookBot(String botToken, String botUsername, String botPath) {
|
||||||
this(botToken, botUsername, botPath, onlineInstance(botUsername));
|
this(botToken, botUsername, botPath, onlineInstance(botUsername));
|
||||||
}
|
}
|
||||||
|
@ -3,21 +3,15 @@ package org.telegram.abilitybots.api.bot;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableList.Builder;
|
import com.google.common.collect.ImmutableList.Builder;
|
||||||
import com.google.common.collect.ImmutableMap;
|
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.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.Ability;
|
import org.telegram.abilitybots.api.objects.*;
|
||||||
import org.telegram.abilitybots.api.objects.Locality;
|
|
||||||
import org.telegram.abilitybots.api.objects.MessageContext;
|
|
||||||
import org.telegram.abilitybots.api.objects.Privacy;
|
|
||||||
import org.telegram.abilitybots.api.objects.Reply;
|
|
||||||
import org.telegram.abilitybots.api.sender.DefaultSender;
|
import org.telegram.abilitybots.api.sender.DefaultSender;
|
||||||
import org.telegram.abilitybots.api.sender.MessageSender;
|
import org.telegram.abilitybots.api.sender.MessageSender;
|
||||||
import org.telegram.abilitybots.api.sender.SilentSender;
|
import org.telegram.abilitybots.api.sender.SilentSender;
|
||||||
|
import org.telegram.abilitybots.api.toggle.AbilityToggle;
|
||||||
import org.telegram.abilitybots.api.util.AbilityExtension;
|
import org.telegram.abilitybots.api.util.AbilityExtension;
|
||||||
import org.telegram.abilitybots.api.util.AbilityUtils;
|
import org.telegram.abilitybots.api.util.AbilityUtils;
|
||||||
import org.telegram.abilitybots.api.util.Pair;
|
import org.telegram.abilitybots.api.util.Pair;
|
||||||
@ -25,85 +19,31 @@ import org.telegram.abilitybots.api.util.Trio;
|
|||||||
import org.telegram.telegrambots.bots.DefaultAbsSender;
|
import org.telegram.telegrambots.bots.DefaultAbsSender;
|
||||||
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
import org.telegram.telegrambots.bots.DefaultBotOptions;
|
||||||
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
||||||
import org.telegram.telegrambots.meta.api.methods.GetFile;
|
|
||||||
import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators;
|
import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators;
|
||||||
import org.telegram.telegrambots.meta.api.methods.send.SendDocument;
|
|
||||||
import org.telegram.telegrambots.meta.api.objects.Message;
|
import org.telegram.telegrambots.meta.api.objects.Message;
|
||||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||||
import org.telegram.telegrambots.meta.api.objects.User;
|
import org.telegram.telegrambots.meta.api.objects.User;
|
||||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileReader;
|
|
||||||
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.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
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.Optional.ofNullable;
|
import static java.util.Optional.ofNullable;
|
||||||
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.joining;
|
import static org.telegram.abilitybots.api.objects.Locality.*;
|
||||||
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
|
||||||
import static org.telegram.abilitybots.api.objects.Ability.builder;
|
|
||||||
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.Flag.REPLY;
|
|
||||||
import static org.telegram.abilitybots.api.objects.Locality.ALL;
|
|
||||||
import static org.telegram.abilitybots.api.objects.Locality.GROUP;
|
|
||||||
import static org.telegram.abilitybots.api.objects.Locality.USER;
|
|
||||||
import static org.telegram.abilitybots.api.objects.MessageContext.newContext;
|
import static org.telegram.abilitybots.api.objects.MessageContext.newContext;
|
||||||
import static org.telegram.abilitybots.api.objects.Privacy.ADMIN;
|
import static org.telegram.abilitybots.api.objects.Privacy.*;
|
||||||
import static org.telegram.abilitybots.api.objects.Privacy.CREATOR;
|
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.*;
|
||||||
import static org.telegram.abilitybots.api.objects.Privacy.GROUP_ADMIN;
|
import static org.telegram.abilitybots.api.util.AbilityUtils.*;
|
||||||
import static org.telegram.abilitybots.api.objects.Privacy.PUBLIC;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_BAN_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_BAN_SUCCESS;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_CLAIM_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_CLAIM_SUCCESS;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_COMMANDS_NOT_FOUND;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_DEMOTE_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_DEMOTE_SUCCESS;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_PROMOTE_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_PROMOTE_SUCCESS;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_RECOVER_ERROR;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_RECOVER_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_RECOVER_MESSAGE;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_RECOVER_SUCCESS;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_UNBAN_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_UNBAN_SUCCESS;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.CHECK_INPUT_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.CHECK_LOCALITY_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.CHECK_PRIVACY_FAIL;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.USER_NOT_FOUND;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.addTag;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.commitTo;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.getChatId;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.getLocalizedMessage;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.isGroupUpdate;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.isSuperGroupUpdate;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.isUserMessage;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.shortName;
|
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.stripTag;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <b>father</b> of all ability bots. Bots that need to utilize abilities need to extend this bot.
|
* The <b>father</b> of all ability bots. Bots that need to utilize abilities need to extend this bot.
|
||||||
@ -141,29 +81,21 @@ import static org.telegram.abilitybots.api.util.AbilityUtils.stripTag;
|
|||||||
public abstract class BaseAbilityBot extends DefaultAbsSender implements AbilityExtension {
|
public abstract class BaseAbilityBot extends DefaultAbsSender implements AbilityExtension {
|
||||||
private static final Logger log = LogManager.getLogger(BaseAbilityBot.class);
|
private static final Logger log = LogManager.getLogger(BaseAbilityBot.class);
|
||||||
|
|
||||||
|
protected static final String DEFAULT = "default";
|
||||||
// DB objects
|
// DB objects
|
||||||
public static final String ADMINS = "ADMINS";
|
public static final String ADMINS = "ADMINS";
|
||||||
public static final String USERS = "USERS";
|
public static final String USERS = "USERS";
|
||||||
public static final String USER_ID = "USER_ID";
|
public static final String USER_ID = "USER_ID";
|
||||||
public static final String BLACKLIST = "BLACKLIST";
|
public static final String BLACKLIST = "BLACKLIST";
|
||||||
|
|
||||||
// Factory commands
|
|
||||||
protected static final String DEFAULT = "default";
|
|
||||||
protected static final String CLAIM = "claim";
|
|
||||||
protected static final String BAN = "ban";
|
|
||||||
protected static final String PROMOTE = "promote";
|
|
||||||
protected static final String DEMOTE = "demote";
|
|
||||||
protected static final String UNBAN = "unban";
|
|
||||||
protected static final String BACKUP = "backup";
|
|
||||||
protected static final String RECOVER = "recover";
|
|
||||||
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;
|
||||||
protected MessageSender sender;
|
protected MessageSender sender;
|
||||||
protected SilentSender silent;
|
protected SilentSender silent;
|
||||||
|
|
||||||
|
// Ability toggle
|
||||||
|
private final AbilityToggle toggle;
|
||||||
|
|
||||||
// Bot token and username
|
// Bot token and username
|
||||||
private final String botToken;
|
private final String botToken;
|
||||||
private final String botUsername;
|
private final String botUsername;
|
||||||
@ -176,12 +108,13 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
|
|
||||||
public abstract int creatorId();
|
public abstract int creatorId();
|
||||||
|
|
||||||
protected BaseAbilityBot(String botToken, String botUsername, DBContext db, DefaultBotOptions botOptions) {
|
protected BaseAbilityBot(String botToken, String botUsername, DBContext db, AbilityToggle toggle, DefaultBotOptions botOptions) {
|
||||||
super(botOptions);
|
super(botOptions);
|
||||||
|
|
||||||
this.botToken = botToken;
|
this.botToken = botToken;
|
||||||
this.botUsername = botUsername;
|
this.botUsername = botUsername;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
this.toggle = toggle;
|
||||||
this.sender = new DefaultSender(this);
|
this.sender = new DefaultSender(this);
|
||||||
silent = new SilentSender(sender);
|
silent = new SilentSender(sender);
|
||||||
|
|
||||||
@ -281,374 +214,6 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the user with the specified username.
|
|
||||||
*
|
|
||||||
* @param username the username of the required user
|
|
||||||
* @return the user
|
|
||||||
*/
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
return getUser(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the user with the specified ID.
|
|
||||||
*
|
|
||||||
* @param id the id of the required user
|
|
||||||
* @return the user
|
|
||||||
*/
|
|
||||||
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 user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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, MessageContext ctx) {
|
|
||||||
try {
|
|
||||||
return getUser(username).getId();
|
|
||||||
} catch (IllegalStateException ex) {
|
|
||||||
silent.send(getLocalizedMessage(USER_NOT_FOUND, ctx.user().getLanguageCode(), username), ctx.chatId());
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Format of the report:
|
|
||||||
* <p>
|
|
||||||
* [command1] - [description1]
|
|
||||||
* <p>
|
|
||||||
* [command2] - [description2]
|
|
||||||
* <p>
|
|
||||||
* ...
|
|
||||||
* <p>
|
|
||||||
* Once you invoke it, the bot will send the available commands to the chat. This is a public ability so anyone can invoke it.
|
|
||||||
* <p>
|
|
||||||
* Usage: <code>/commands</code>
|
|
||||||
*
|
|
||||||
* @return the ability to report commands defined by the child bot.
|
|
||||||
*/
|
|
||||||
public Ability reportCommands() {
|
|
||||||
return builder()
|
|
||||||
.name(REPORT)
|
|
||||||
.locality(ALL)
|
|
||||||
.privacy(CREATOR)
|
|
||||||
.input(0)
|
|
||||||
.action(ctx -> {
|
|
||||||
String commands = abilities.values().stream()
|
|
||||||
.filter(ability -> nonNull(ability.info()))
|
|
||||||
.map(ability -> {
|
|
||||||
String name = ability.name();
|
|
||||||
String info = ability.info();
|
|
||||||
return format("%s - %s", name, info);
|
|
||||||
})
|
|
||||||
.sorted()
|
|
||||||
.reduce((a, b) -> format("%s%n%s", a, b))
|
|
||||||
.orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, ctx.user().getLanguageCode()));
|
|
||||||
|
|
||||||
silent.send(commands, ctx.chatId());
|
|
||||||
})
|
|
||||||
.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.values().stream()
|
|
||||||
.map(ability -> {
|
|
||||||
String name = ability.name();
|
|
||||||
String info = ability.info();
|
|
||||||
|
|
||||||
if (!isEmpty(info))
|
|
||||||
return Pair.of(ability.privacy(), format("/%s - %s", name, info));
|
|
||||||
return Pair.of(ability.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.
|
|
||||||
* <p>
|
|
||||||
* This is a high-profile ability and is restricted to the CREATOR only.
|
|
||||||
* <p>
|
|
||||||
* Usage: <code>/backup</code>
|
|
||||||
*
|
|
||||||
* @return the ability to back-up the database of the bot
|
|
||||||
*/
|
|
||||||
public Ability backupDB() {
|
|
||||||
return builder()
|
|
||||||
.name(BACKUP)
|
|
||||||
.locality(USER)
|
|
||||||
.privacy(CREATOR)
|
|
||||||
.input(0)
|
|
||||||
.action(ctx -> {
|
|
||||||
File backup = new File("backup.json");
|
|
||||||
|
|
||||||
try (PrintStream printStream = new PrintStream(backup)) {
|
|
||||||
printStream.print(db.backup());
|
|
||||||
sender.sendDocument(new SendDocument()
|
|
||||||
.setDocument(backup)
|
|
||||||
.setChatId(ctx.chatId())
|
|
||||||
);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
log.error("Error while fetching backup", e);
|
|
||||||
} catch (TelegramApiException e) {
|
|
||||||
log.error("Error while sending document/backup file", e);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recovers the bot database using {@link DBContext#recover(Object)}.
|
|
||||||
* <p>
|
|
||||||
* The bot recovery process hugely depends on the implementation of the recovery method of {@link DBContext}.
|
|
||||||
* <p>
|
|
||||||
* Usage: <code>/recover</code>
|
|
||||||
*
|
|
||||||
* @return the ability to recover the database of the bot
|
|
||||||
*/
|
|
||||||
public Ability recoverDB() {
|
|
||||||
return builder()
|
|
||||||
.name(RECOVER)
|
|
||||||
.locality(USER)
|
|
||||||
.privacy(CREATOR)
|
|
||||||
.input(0)
|
|
||||||
.action(ctx -> silent.forceReply(
|
|
||||||
getLocalizedMessage(ABILITY_RECOVER_MESSAGE, ctx.user().getLanguageCode()), ctx.chatId()))
|
|
||||||
.reply(update -> {
|
|
||||||
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);
|
|
||||||
} else {
|
|
||||||
send(ABILITY_RECOVER_FAIL, update);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Could not recover DB from backup", e);
|
|
||||||
send(ABILITY_RECOVER_ERROR, update);
|
|
||||||
}
|
|
||||||
}, MESSAGE, DOCUMENT, REPLY)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Banned users are accumulated in the blacklist. Use {@link DBContext#getSet(String)} with name specified by {@link BaseAbilityBot#BLACKLIST}.
|
|
||||||
* <p>
|
|
||||||
* Usage: <code>/ban @username</code>
|
|
||||||
* <p>
|
|
||||||
* <u>Note that admins who try to ban the creator, get banned.</u>
|
|
||||||
*
|
|
||||||
* @return the ability to ban the user from any kind of <b>bot interaction</b>
|
|
||||||
*/
|
|
||||||
public Ability banUser() {
|
|
||||||
return builder()
|
|
||||||
.name(BAN)
|
|
||||||
.locality(ALL)
|
|
||||||
.privacy(ADMIN)
|
|
||||||
.input(1)
|
|
||||||
.action(ctx -> {
|
|
||||||
String username = stripTag(ctx.firstArg());
|
|
||||||
int userId = getUserIdSendError(username, ctx);
|
|
||||||
String bannedUser;
|
|
||||||
|
|
||||||
// Protection from abuse
|
|
||||||
if (userId == creatorId()) {
|
|
||||||
userId = ctx.user().getId();
|
|
||||||
bannedUser = isNullOrEmpty(ctx.user().getUserName()) ? addTag(ctx.user().getUserName()) : shortName(ctx.user());
|
|
||||||
} else {
|
|
||||||
bannedUser = addTag(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<Integer> blacklist = blacklist();
|
|
||||||
if (blacklist.contains(userId))
|
|
||||||
sendMd(ABILITY_BAN_FAIL, ctx, escape(bannedUser));
|
|
||||||
else {
|
|
||||||
blacklist.add(userId);
|
|
||||||
sendMd(ABILITY_BAN_SUCCESS, ctx, escape(bannedUser));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.post(commitTo(db))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Usage: <code>/unban @username</code>
|
|
||||||
*
|
|
||||||
* @return the ability to unban a user
|
|
||||||
*/
|
|
||||||
public Ability unbanUser() {
|
|
||||||
return builder()
|
|
||||||
.name(UNBAN)
|
|
||||||
.locality(ALL)
|
|
||||||
.privacy(ADMIN)
|
|
||||||
.input(1)
|
|
||||||
.action(ctx -> {
|
|
||||||
String username = stripTag(ctx.firstArg());
|
|
||||||
Integer userId = getUserIdSendError(username, ctx);
|
|
||||||
|
|
||||||
Set<Integer> blacklist = blacklist();
|
|
||||||
|
|
||||||
if (!blacklist.remove(userId))
|
|
||||||
silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, ctx.user().getLanguageCode(), escape(username)), ctx.chatId());
|
|
||||||
else {
|
|
||||||
silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, ctx.user().getLanguageCode(), escape(username)), ctx.chatId());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.post(commitTo(db))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ability to promote a user to a bot admin
|
|
||||||
*/
|
|
||||||
public Ability promoteAdmin() {
|
|
||||||
return builder()
|
|
||||||
.name(PROMOTE)
|
|
||||||
.locality(ALL)
|
|
||||||
.privacy(ADMIN)
|
|
||||||
.input(1)
|
|
||||||
.action(ctx -> {
|
|
||||||
String username = stripTag(ctx.firstArg());
|
|
||||||
Integer userId = getUserIdSendError(username, ctx);
|
|
||||||
|
|
||||||
Set<Integer> admins = admins();
|
|
||||||
if (admins.contains(userId))
|
|
||||||
sendMd(ABILITY_PROMOTE_FAIL, ctx, escape(username));
|
|
||||||
else {
|
|
||||||
admins.add(userId);
|
|
||||||
sendMd(ABILITY_PROMOTE_SUCCESS, ctx, escape(username));
|
|
||||||
}
|
|
||||||
}).post(commitTo(db))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ability to demote an admin to a user
|
|
||||||
*/
|
|
||||||
public Ability demoteAdmin() {
|
|
||||||
return builder()
|
|
||||||
.name(DEMOTE)
|
|
||||||
.locality(ALL)
|
|
||||||
.privacy(ADMIN)
|
|
||||||
.input(1)
|
|
||||||
.action(ctx -> {
|
|
||||||
String username = stripTag(ctx.firstArg());
|
|
||||||
Integer userId = getUserIdSendError(username, ctx);
|
|
||||||
|
|
||||||
Set<Integer> admins = admins();
|
|
||||||
if (admins.remove(userId)) {
|
|
||||||
sendMd(ABILITY_DEMOTE_SUCCESS, ctx, escape(username));
|
|
||||||
} else {
|
|
||||||
sendMd(ABILITY_DEMOTE_FAIL, ctx, escape(username));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.post(commitTo(db))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regular users and admins who try to claim the bot will get <b>banned</b>.
|
|
||||||
*
|
|
||||||
* @return the ability to claim yourself as the master and creator of the bot
|
|
||||||
*/
|
|
||||||
public Ability claimCreator() {
|
|
||||||
return builder()
|
|
||||||
.name(CLAIM)
|
|
||||||
.locality(ALL)
|
|
||||||
.privacy(CREATOR)
|
|
||||||
.input(0)
|
|
||||||
.action(ctx -> {
|
|
||||||
Set<Integer> admins = admins();
|
|
||||||
int id = creatorId();
|
|
||||||
|
|
||||||
if (admins.contains(id))
|
|
||||||
send(ABILITY_CLAIM_FAIL, ctx);
|
|
||||||
else {
|
|
||||||
admins.add(id);
|
|
||||||
send(ABILITY_CLAIM_SUCCESS, ctx);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.post(commitTo(db))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Message> send(String message, MessageContext ctx, String... args) {
|
|
||||||
return silent.send(getLocalizedMessage(message, ctx.user().getLanguageCode(), args), ctx.chatId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Message> sendMd(String message, MessageContext ctx, String... args) {
|
|
||||||
return silent.sendMd(getLocalizedMessage(message, ctx.user().getLanguageCode(), args), ctx.chatId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Message> send(String message, Update upd) {
|
|
||||||
Long chatId = upd.getMessage().getChatId();
|
|
||||||
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.
|
* Registers the declared abilities using method reflection. Also, replies are accumulated using the built abilities and standalone methods that return a Reply.
|
||||||
* <p>
|
* <p>
|
||||||
@ -665,11 +230,19 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
// Add the bot itself as it is an AbilityExtension
|
// Add the bot itself as it is an AbilityExtension
|
||||||
extensions.add(this);
|
extensions.add(this);
|
||||||
|
|
||||||
|
DefaultAbilities defaultAbs = new DefaultAbilities(this);
|
||||||
|
Stream<Ability> defaultAbsStream = stream(DefaultAbilities.class.getMethods())
|
||||||
|
.filter(checkReturnType(Ability.class))
|
||||||
|
.map(returnAbility(defaultAbs))
|
||||||
|
.filter(ab -> !toggle.isOff(ab))
|
||||||
|
.map(toggle::processAbility);
|
||||||
|
|
||||||
// Extract all abilities from every single extension instance
|
// Extract all abilities from every single extension instance
|
||||||
abilities = extensions.stream()
|
abilities = Stream.concat(defaultAbsStream,
|
||||||
|
extensions.stream()
|
||||||
.flatMap(ext -> stream(ext.getClass().getMethods())
|
.flatMap(ext -> stream(ext.getClass().getMethods())
|
||||||
.filter(checkReturnType(Ability.class))
|
.filter(checkReturnType(Ability.class))
|
||||||
.map(returnAbility(ext)))
|
.map(returnAbility(ext))))
|
||||||
// Abilities are immutable, build it respectively
|
// Abilities are immutable, build it respectively
|
||||||
.collect(ImmutableMap::<String, Ability>builder,
|
.collect(ImmutableMap::<String, Ability>builder,
|
||||||
(b, a) -> b.put(a.name(), a),
|
(b, a) -> b.put(a.name(), a),
|
||||||
@ -703,7 +276,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
* @param clazz the type to be tested
|
* @param clazz the type to be tested
|
||||||
* @return a predicate testing the return type of the method corresponding to the class parameter
|
* @return a predicate testing the return type of the method corresponding to the class parameter
|
||||||
*/
|
*/
|
||||||
private Predicate<Method> checkReturnType(Class<?> clazz) {
|
private static Predicate<Method> checkReturnType(Class<?> clazz) {
|
||||||
return method -> clazz.isAssignableFrom(method.getReturnType());
|
return method -> clazz.isAssignableFrom(method.getReturnType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +303,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
* @param obj a bot or extension that this method is invoked with
|
* @param obj a bot or extension that this method is invoked with
|
||||||
* @return a {@link Function} which returns the {@link Ability} returned by the given method
|
* @return a {@link Function} which returns the {@link Ability} returned by the given method
|
||||||
*/
|
*/
|
||||||
private Function<? super Method, Ability> returnAbility(Object obj) {
|
private static Function<? super Method, Ability> returnAbility(Object obj) {
|
||||||
return method -> {
|
return method -> {
|
||||||
try {
|
try {
|
||||||
return (Ability) method.invoke(obj);
|
return (Ability) method.invoke(obj);
|
||||||
@ -747,7 +320,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
* @param obj a bot or extension that this method is invoked with
|
* @param obj a bot or extension that this method is invoked with
|
||||||
* @return a {@link Function} which returns the {@link Reply} returned by the given method
|
* @return a {@link Function} which returns the {@link Reply} returned by the given method
|
||||||
*/
|
*/
|
||||||
private Function<? super Method, Reply> returnReply(Object obj) {
|
private static Function<? super Method, Reply> returnReply(Object obj) {
|
||||||
return method -> {
|
return method -> {
|
||||||
try {
|
try {
|
||||||
return (Reply) method.invoke(obj);
|
return (Reply) method.invoke(obj);
|
||||||
@ -834,7 +407,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Privacy getPrivacy(Update update, int id) {
|
Privacy getPrivacy(Update update, int id) {
|
||||||
return isCreator(id) ?
|
return isCreator(id) ?
|
||||||
CREATOR : isAdmin(id) ?
|
CREATOR : isAdmin(id) ?
|
||||||
ADMIN : (isGroupUpdate(update) || isSuperGroupUpdate(update)) && isGroupAdmin(update, id) ?
|
ADMIN : (isGroupUpdate(update) || isSuperGroupUpdate(update)) && isGroupAdmin(update, id) ?
|
||||||
@ -939,13 +512,4 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
return ability.flags().stream()
|
return ability.flags().stream()
|
||||||
.reduce(true, flagAnd, Boolean::logicalAnd);
|
.reduce(true, flagAnd, Boolean::logicalAnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private File downloadFileWithId(String fileId) throws TelegramApiException {
|
|
||||||
return sender.downloadFile(sender.execute(new GetFile().setFileId(fileId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String escape(String username) {
|
|
||||||
return username.replace("_", "\\_");
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,435 @@
|
|||||||
|
package org.telegram.abilitybots.api.bot;
|
||||||
|
|
||||||
|
import com.google.common.collect.ListMultimap;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.telegram.abilitybots.api.db.DBContext;
|
||||||
|
import org.telegram.abilitybots.api.objects.Ability;
|
||||||
|
import org.telegram.abilitybots.api.objects.MessageContext;
|
||||||
|
import org.telegram.abilitybots.api.objects.Privacy;
|
||||||
|
import org.telegram.abilitybots.api.util.AbilityExtension;
|
||||||
|
import org.telegram.abilitybots.api.util.AbilityUtils;
|
||||||
|
import org.telegram.abilitybots.api.util.Pair;
|
||||||
|
import org.telegram.telegrambots.meta.api.methods.GetFile;
|
||||||
|
import org.telegram.telegrambots.meta.api.methods.send.SendDocument;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.Message;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.User;
|
||||||
|
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
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.util.Comparator.comparing;
|
||||||
|
import static java.util.Objects.nonNull;
|
||||||
|
import static java.util.stream.Collectors.joining;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isEmpty;
|
||||||
|
import static org.telegram.abilitybots.api.objects.Ability.builder;
|
||||||
|
import static org.telegram.abilitybots.api.objects.Flag.*;
|
||||||
|
import static org.telegram.abilitybots.api.objects.Locality.ALL;
|
||||||
|
import static org.telegram.abilitybots.api.objects.Locality.USER;
|
||||||
|
import static org.telegram.abilitybots.api.objects.Privacy.*;
|
||||||
|
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.*;
|
||||||
|
import static org.telegram.abilitybots.api.util.AbilityUtils.*;
|
||||||
|
|
||||||
|
public final class DefaultAbilities implements AbilityExtension {
|
||||||
|
// Default commands
|
||||||
|
public static final String CLAIM = "claim";
|
||||||
|
public static final String BAN = "ban";
|
||||||
|
public static final String PROMOTE = "promote";
|
||||||
|
public static final String DEMOTE = "demote";
|
||||||
|
public static final String UNBAN = "unban";
|
||||||
|
public static final String BACKUP = "backup";
|
||||||
|
public static final String RECOVER = "recover";
|
||||||
|
public static final String COMMANDS = "commands";
|
||||||
|
public static final String REPORT = "report";
|
||||||
|
private static final Logger log = LogManager.getLogger(DefaultAbilities.class);
|
||||||
|
private final BaseAbilityBot bot;
|
||||||
|
|
||||||
|
public DefaultAbilities(BaseAbilityBot bot) {
|
||||||
|
this.bot = bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Format of the report:
|
||||||
|
* <p>
|
||||||
|
* [command1] - [description1]
|
||||||
|
* <p>
|
||||||
|
* [command2] - [description2]
|
||||||
|
* <p>
|
||||||
|
* ...
|
||||||
|
* <p>
|
||||||
|
* Once you invoke it, the bot will send the available commands to the chat. This is a public ability so anyone can invoke it.
|
||||||
|
* <p>
|
||||||
|
* Usage: <code>/commands</code>
|
||||||
|
*
|
||||||
|
* @return the ability to report commands defined by the child bot.
|
||||||
|
*/
|
||||||
|
public Ability reportCommands() {
|
||||||
|
return builder()
|
||||||
|
.name(REPORT)
|
||||||
|
.locality(ALL)
|
||||||
|
.privacy(CREATOR)
|
||||||
|
.input(0)
|
||||||
|
.action(ctx -> {
|
||||||
|
String commands = bot.abilities().values().stream()
|
||||||
|
.filter(ability -> nonNull(ability.info()))
|
||||||
|
.map(ability -> {
|
||||||
|
String name = ability.name();
|
||||||
|
String info = ability.info();
|
||||||
|
return format("%s - %s", name, info);
|
||||||
|
})
|
||||||
|
.sorted()
|
||||||
|
.reduce((a, b) -> format("%s%n%s", a, b))
|
||||||
|
.orElse(getLocalizedMessage(ABILITY_COMMANDS_NOT_FOUND, ctx.user().getLanguageCode()));
|
||||||
|
|
||||||
|
bot.silent.send(commands, ctx.chatId());
|
||||||
|
})
|
||||||
|
.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 = bot.getPrivacy(ctx.update(), ctx.user().getId());
|
||||||
|
|
||||||
|
ListMultimap<Privacy, String> abilitiesPerPrivacy = bot.abilities().values().stream()
|
||||||
|
.map(ability -> {
|
||||||
|
String name = ability.name();
|
||||||
|
String info = ability.info();
|
||||||
|
|
||||||
|
if (!isEmpty(info))
|
||||||
|
return Pair.of(ability.privacy(), format("/%s - %s", name, info));
|
||||||
|
return Pair.of(ability.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(Map.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());
|
||||||
|
|
||||||
|
bot.silent.send(commands, ctx.chatId());
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This backup ability returns the object defined by {@link DBContext#backup()} as a message document.
|
||||||
|
* <p>
|
||||||
|
* This is a high-profile ability and is restricted to the CREATOR only.
|
||||||
|
* <p>
|
||||||
|
* Usage: <code>/backup</code>
|
||||||
|
*
|
||||||
|
* @return the ability to back-up the database of the bot
|
||||||
|
*/
|
||||||
|
public Ability backupDB() {
|
||||||
|
return builder()
|
||||||
|
.name(BACKUP)
|
||||||
|
.locality(USER)
|
||||||
|
.privacy(CREATOR)
|
||||||
|
.input(0)
|
||||||
|
.action(ctx -> {
|
||||||
|
File backup = new File("backup.json");
|
||||||
|
|
||||||
|
try (PrintStream printStream = new PrintStream(backup)) {
|
||||||
|
printStream.print(bot.db.backup());
|
||||||
|
bot.sender.sendDocument(new SendDocument()
|
||||||
|
.setDocument(backup)
|
||||||
|
.setChatId(ctx.chatId())
|
||||||
|
);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
log.error("Error while fetching backup", e);
|
||||||
|
} catch (TelegramApiException e) {
|
||||||
|
log.error("Error while sending document/backup file", e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recovers the bot database using {@link DBContext#recover(Object)}.
|
||||||
|
* <p>
|
||||||
|
* The bot recovery process hugely depends on the implementation of the recovery method of {@link DBContext}.
|
||||||
|
* <p>
|
||||||
|
* Usage: <code>/recover</code>
|
||||||
|
*
|
||||||
|
* @return the ability to recover the database of the bot
|
||||||
|
*/
|
||||||
|
public Ability recoverDB() {
|
||||||
|
return builder()
|
||||||
|
.name(RECOVER)
|
||||||
|
.locality(USER)
|
||||||
|
.privacy(CREATOR)
|
||||||
|
.input(0)
|
||||||
|
.action(ctx -> bot.silent.forceReply(
|
||||||
|
getLocalizedMessage(ABILITY_RECOVER_MESSAGE, ctx.user().getLanguageCode()), ctx.chatId()))
|
||||||
|
.reply(update -> {
|
||||||
|
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 (bot.db.recover(backupData)) {
|
||||||
|
send(ABILITY_RECOVER_SUCCESS, update);
|
||||||
|
} else {
|
||||||
|
send(ABILITY_RECOVER_FAIL, update);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Could not recover DB from backup", e);
|
||||||
|
send(ABILITY_RECOVER_ERROR, update);
|
||||||
|
}
|
||||||
|
}, MESSAGE, DOCUMENT, REPLY)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Banned users are accumulated in the blacklist. Use {@link DBContext#getSet(String)} with name specified by {@link BaseAbilityBot#BLACKLIST}.
|
||||||
|
* <p>
|
||||||
|
* Usage: <code>/ban @username</code>
|
||||||
|
* <p>
|
||||||
|
* <u>Note that admins who try to ban the creator, get banned.</u>
|
||||||
|
*
|
||||||
|
* @return the ability to ban the user from any kind of <b>bot interaction</b>
|
||||||
|
*/
|
||||||
|
public Ability banUser() {
|
||||||
|
return builder()
|
||||||
|
.name(BAN)
|
||||||
|
.locality(ALL)
|
||||||
|
.privacy(ADMIN)
|
||||||
|
.input(1)
|
||||||
|
.action(ctx -> {
|
||||||
|
String username = stripTag(ctx.firstArg());
|
||||||
|
int userId = getUserIdSendError(username, ctx);
|
||||||
|
String bannedUser;
|
||||||
|
|
||||||
|
// Protection from abuse
|
||||||
|
if (userId == bot.creatorId()) {
|
||||||
|
userId = ctx.user().getId();
|
||||||
|
bannedUser = isNullOrEmpty(ctx.user().getUserName()) ? addTag(ctx.user().getUserName()) : shortName(ctx.user());
|
||||||
|
} else {
|
||||||
|
bannedUser = addTag(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Integer> blacklist = bot.blacklist();
|
||||||
|
if (blacklist.contains(userId))
|
||||||
|
sendMd(ABILITY_BAN_FAIL, ctx, escape(bannedUser));
|
||||||
|
else {
|
||||||
|
blacklist.add(userId);
|
||||||
|
sendMd(ABILITY_BAN_SUCCESS, ctx, escape(bannedUser));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.post(commitTo(bot.db))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage: <code>/unban @username</code>
|
||||||
|
*
|
||||||
|
* @return the ability to unban a user
|
||||||
|
*/
|
||||||
|
public Ability unbanUser() {
|
||||||
|
return builder()
|
||||||
|
.name(UNBAN)
|
||||||
|
.locality(ALL)
|
||||||
|
.privacy(ADMIN)
|
||||||
|
.input(1)
|
||||||
|
.action(ctx -> {
|
||||||
|
String username = stripTag(ctx.firstArg());
|
||||||
|
Integer userId = getUserIdSendError(username, ctx);
|
||||||
|
|
||||||
|
Set<Integer> blacklist = bot.blacklist();
|
||||||
|
|
||||||
|
if (!blacklist.remove(userId))
|
||||||
|
bot.silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_FAIL, ctx.user().getLanguageCode(), escape(username)), ctx.chatId());
|
||||||
|
else {
|
||||||
|
bot.silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, ctx.user().getLanguageCode(), escape(username)), ctx.chatId());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.post(commitTo(bot.db))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ability to promote a user to a bot admin
|
||||||
|
*/
|
||||||
|
public Ability promoteAdmin() {
|
||||||
|
return builder()
|
||||||
|
.name(PROMOTE)
|
||||||
|
.locality(ALL)
|
||||||
|
.privacy(ADMIN)
|
||||||
|
.input(1)
|
||||||
|
.action(ctx -> {
|
||||||
|
String username = stripTag(ctx.firstArg());
|
||||||
|
Integer userId = getUserIdSendError(username, ctx);
|
||||||
|
|
||||||
|
Set<Integer> admins = bot.admins();
|
||||||
|
if (admins.contains(userId))
|
||||||
|
sendMd(ABILITY_PROMOTE_FAIL, ctx, escape(username));
|
||||||
|
else {
|
||||||
|
admins.add(userId);
|
||||||
|
sendMd(ABILITY_PROMOTE_SUCCESS, ctx, escape(username));
|
||||||
|
}
|
||||||
|
}).post(commitTo(bot.db))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ability to demote an admin to a user
|
||||||
|
*/
|
||||||
|
public Ability demoteAdmin() {
|
||||||
|
return builder()
|
||||||
|
.name(DEMOTE)
|
||||||
|
.locality(ALL)
|
||||||
|
.privacy(ADMIN)
|
||||||
|
.input(1)
|
||||||
|
.action(ctx -> {
|
||||||
|
String username = stripTag(ctx.firstArg());
|
||||||
|
Integer userId = getUserIdSendError(username, ctx);
|
||||||
|
|
||||||
|
Set<Integer> admins = bot.admins();
|
||||||
|
if (admins.remove(userId)) {
|
||||||
|
sendMd(ABILITY_DEMOTE_SUCCESS, ctx, escape(username));
|
||||||
|
} else {
|
||||||
|
sendMd(ABILITY_DEMOTE_FAIL, ctx, escape(username));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.post(commitTo(bot.db))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular users and admins who try to claim the bot will get <b>banned</b>.
|
||||||
|
*
|
||||||
|
* @return the ability to claim yourself as the master and creator of the bot
|
||||||
|
*/
|
||||||
|
public Ability claimCreator() {
|
||||||
|
return builder()
|
||||||
|
.name(CLAIM)
|
||||||
|
.locality(ALL)
|
||||||
|
.privacy(CREATOR)
|
||||||
|
.input(0)
|
||||||
|
.action(ctx -> {
|
||||||
|
Set<Integer> admins = bot.admins();
|
||||||
|
int id = bot.creatorId();
|
||||||
|
|
||||||
|
if (admins.contains(id))
|
||||||
|
send(ABILITY_CLAIM_FAIL, ctx);
|
||||||
|
else {
|
||||||
|
admins.add(id);
|
||||||
|
send(ABILITY_CLAIM_SUCCESS, ctx);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.post(commitTo(bot.db))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user with the specified username.
|
||||||
|
*
|
||||||
|
* @param username the username of the required user
|
||||||
|
* @return the user
|
||||||
|
*/
|
||||||
|
private User getUser(String username) {
|
||||||
|
Integer id = bot.userIds().get(username.toLowerCase());
|
||||||
|
if (id == null) {
|
||||||
|
throw new IllegalStateException(format("Could not find ID corresponding to username [%s]", username));
|
||||||
|
}
|
||||||
|
|
||||||
|
return getUser(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user with the specified ID.
|
||||||
|
*
|
||||||
|
* @param id the id of the required user
|
||||||
|
* @return the user
|
||||||
|
*/
|
||||||
|
private User getUser(int id) {
|
||||||
|
User user = bot.users().get(id);
|
||||||
|
if (user == null) {
|
||||||
|
throw new IllegalStateException(format("Could not find user corresponding to id [%d]", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
private int getUserIdSendError(String username, MessageContext ctx) {
|
||||||
|
try {
|
||||||
|
return getUser(username).getId();
|
||||||
|
} catch (IllegalStateException ex) {
|
||||||
|
bot.silent.send(getLocalizedMessage(USER_NOT_FOUND, ctx.user().getLanguageCode(), username), ctx.chatId());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Optional<Message> send(String message, MessageContext ctx, String... args) {
|
||||||
|
return bot.silent.send(getLocalizedMessage(message, ctx.user().getLanguageCode(), args), ctx.chatId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Message> sendMd(String message, MessageContext ctx, String... args) {
|
||||||
|
return bot.silent.sendMd(getLocalizedMessage(message, ctx.user().getLanguageCode(), args), ctx.chatId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Message> send(String message, Update upd) {
|
||||||
|
Long chatId = upd.getMessage().getChatId();
|
||||||
|
return bot.silent.send(getLocalizedMessage(message, AbilityUtils.getUser(upd).getLanguageCode()), chatId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File downloadFileWithId(String fileId) throws TelegramApiException {
|
||||||
|
return bot.sender.downloadFile(bot.sender.execute(new GetFile().setFileId(fileId)));
|
||||||
|
}
|
||||||
|
}
|
@ -147,8 +147,8 @@ public final class Ability {
|
|||||||
private Privacy privacy;
|
private Privacy privacy;
|
||||||
private Locality locality;
|
private Locality locality;
|
||||||
private int argNum;
|
private int argNum;
|
||||||
private Consumer<MessageContext> consumer;
|
private Consumer<MessageContext> action;
|
||||||
private Consumer<MessageContext> postConsumer;
|
private Consumer<MessageContext> postAction;
|
||||||
private List<Reply> replies;
|
private List<Reply> replies;
|
||||||
private Predicate<Update>[] flags;
|
private Predicate<Update>[] flags;
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ public final class Ability {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AbilityBuilder action(Consumer<MessageContext> consumer) {
|
public AbilityBuilder action(Consumer<MessageContext> consumer) {
|
||||||
this.consumer = consumer;
|
this.action = consumer;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +191,8 @@ public final class Ability {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbilityBuilder post(Consumer<MessageContext> postConsumer) {
|
public AbilityBuilder post(Consumer<MessageContext> postAction) {
|
||||||
this.postConsumer = postConsumer;
|
this.postAction = postAction;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,8 +202,21 @@ public final class Ability {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AbilityBuilder basedOn(Ability ability) {
|
||||||
|
replies.clear();
|
||||||
|
replies.addAll(ability.replies());
|
||||||
|
|
||||||
|
return name(ability.name())
|
||||||
|
.info(ability.info())
|
||||||
|
.input(ability.tokens())
|
||||||
|
.locality(ability.locality())
|
||||||
|
.privacy(ability.privacy())
|
||||||
|
.action(ability.action())
|
||||||
|
.post(ability.postAction());
|
||||||
|
}
|
||||||
|
|
||||||
public Ability build() {
|
public Ability build() {
|
||||||
return new Ability(name, info, locality, privacy, argNum, consumer, postConsumer, replies, flags);
|
return new Ability(name, info, locality, privacy, argNum, action, postAction, replies, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.telegram.abilitybots.api.toggle;
|
||||||
|
|
||||||
|
import org.telegram.abilitybots.api.objects.Ability;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface can be used to toggle or customize unwanted default abilities by the user.
|
||||||
|
*/
|
||||||
|
public interface AbilityToggle {
|
||||||
|
/**
|
||||||
|
* @param ab the target ability
|
||||||
|
* @return true if the ability has been turned off
|
||||||
|
*/
|
||||||
|
boolean isOff(Ability ab);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abilities that are ON (and have failed the {@link AbilityToggle#isOff} condition) will be processed by this method.
|
||||||
|
* @param ab the target ability
|
||||||
|
* @return the processed ability
|
||||||
|
*/
|
||||||
|
Ability processAbility(Ability ab);
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.telegram.abilitybots.api.toggle;
|
||||||
|
|
||||||
|
import org.telegram.abilitybots.api.objects.Ability;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This toggle can be used as-is to turn off ALL the default abilities supplied by the library.
|
||||||
|
* This is for users who are interested in the barebone functionality of AbilityBot.
|
||||||
|
*/
|
||||||
|
public class BareboneToggle implements AbilityToggle {
|
||||||
|
@Override
|
||||||
|
public boolean isOff(Ability ability) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Ability processAbility(Ability ab) {
|
||||||
|
// Should never hit this
|
||||||
|
throw new RuntimeException("Should not process any ability in a vanilla toggle");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package org.telegram.abilitybots.api.toggle;
|
||||||
|
|
||||||
|
import org.telegram.abilitybots.api.objects.Ability;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This custom toggle can be used to customize default abilities supplied by the library. Users can call {@link CustomToggle#toggle} to
|
||||||
|
* rename the default abilites or {@link CustomToggle#turnOff} to simply turn off the said ability.
|
||||||
|
*/
|
||||||
|
public class CustomToggle implements AbilityToggle {
|
||||||
|
public static final String OFF = "turn_off_base_ability";
|
||||||
|
|
||||||
|
private final Map<String, String> baseMapping;
|
||||||
|
|
||||||
|
public CustomToggle() {
|
||||||
|
baseMapping = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOff(Ability ability) {
|
||||||
|
return OFF.equalsIgnoreCase(baseMapping.get(ability.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Ability processAbility(Ability ability) {
|
||||||
|
if (baseMapping.containsKey(ability.name())) {
|
||||||
|
return Ability.builder()
|
||||||
|
.basedOn(ability)
|
||||||
|
.name(baseMapping.get(ability.name()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ability;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param abilityName the ability you want to change
|
||||||
|
* @param targetName the final name for this ability
|
||||||
|
* @return the toggle instance
|
||||||
|
*/
|
||||||
|
public CustomToggle toggle(String abilityName, String targetName) {
|
||||||
|
baseMapping.put(abilityName, targetName);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ability the ability name you would like turned off
|
||||||
|
* @return the toggle instance
|
||||||
|
*/
|
||||||
|
public CustomToggle turnOff(String ability) {
|
||||||
|
baseMapping.put(ability, OFF);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.telegram.abilitybots.api.toggle;
|
||||||
|
|
||||||
|
import org.telegram.abilitybots.api.objects.Ability;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the user does not supply a toggle to their constructor, the default toggle will be instantiated.
|
||||||
|
* This default toggle allows all the default abilities to be registered.
|
||||||
|
*/
|
||||||
|
public class DefaultToggle implements AbilityToggle {
|
||||||
|
@Override
|
||||||
|
public boolean isOff(Ability ability) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Ability processAbility(Ability ab) {
|
||||||
|
return ab;
|
||||||
|
}
|
||||||
|
}
|
@ -244,4 +244,8 @@ public final class AbilityUtils {
|
|||||||
|
|
||||||
return name.toString();
|
return name.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String escape(String username) {
|
||||||
|
return username.replace("_", "\\_");
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,6 +24,7 @@ class AbilityBotI18nTest {
|
|||||||
|
|
||||||
private DBContext db;
|
private DBContext db;
|
||||||
private NoPublicCommandsBot bot;
|
private NoPublicCommandsBot bot;
|
||||||
|
private DefaultAbilities defaultAbs;
|
||||||
|
|
||||||
private MessageSender sender;
|
private MessageSender sender;
|
||||||
private SilentSender silent;
|
private SilentSender silent;
|
||||||
@ -32,6 +33,7 @@ class AbilityBotI18nTest {
|
|||||||
void setUp() {
|
void setUp() {
|
||||||
db = offlineInstance("db");
|
db = offlineInstance("db");
|
||||||
bot = new NoPublicCommandsBot(EMPTY, EMPTY, db);
|
bot = new NoPublicCommandsBot(EMPTY, EMPTY, db);
|
||||||
|
defaultAbs = new DefaultAbilities(bot);
|
||||||
|
|
||||||
sender = mock(MessageSender.class);
|
sender = mock(MessageSender.class);
|
||||||
silent = mock(SilentSender.class);
|
silent = mock(SilentSender.class);
|
||||||
@ -50,7 +52,7 @@ class AbilityBotI18nTest {
|
|||||||
void missingPublicCommandsLocalizedInEnglishByDefault() {
|
void missingPublicCommandsLocalizedInEnglishByDefault() {
|
||||||
MessageContext context = mockContext(NO_LANGUAGE_USER);
|
MessageContext context = mockContext(NO_LANGUAGE_USER);
|
||||||
|
|
||||||
bot.reportCommands().action().accept(context);
|
defaultAbs.reportCommands().action().accept(context);
|
||||||
|
|
||||||
verify(silent, times(1))
|
verify(silent, times(1))
|
||||||
.send("No available commands found.", NO_LANGUAGE_USER.getId());
|
.send("No available commands found.", NO_LANGUAGE_USER.getId());
|
||||||
@ -60,7 +62,7 @@ class AbilityBotI18nTest {
|
|||||||
void missingPublicCommandsLocalizedInItalian() {
|
void missingPublicCommandsLocalizedInItalian() {
|
||||||
MessageContext context = mockContext(ITALIAN_USER);
|
MessageContext context = mockContext(ITALIAN_USER);
|
||||||
|
|
||||||
bot.reportCommands().action().accept(context);
|
defaultAbs.reportCommands().action().accept(context);
|
||||||
|
|
||||||
verify(silent, times(1))
|
verify(silent, times(1))
|
||||||
.send("Non sono presenti comandi disponibile.", ITALIAN_USER.getId());
|
.send("Non sono presenti comandi disponibile.", ITALIAN_USER.getId());
|
||||||
|
@ -59,6 +59,7 @@ public class AbilityBotTest {
|
|||||||
private static final String[] TEXT = {TEST};
|
private static final String[] TEXT = {TEST};
|
||||||
|
|
||||||
private DefaultBot bot;
|
private DefaultBot bot;
|
||||||
|
private DefaultAbilities defaultAbs;
|
||||||
private DBContext db;
|
private DBContext db;
|
||||||
private MessageSender sender;
|
private MessageSender sender;
|
||||||
private SilentSender silent;
|
private SilentSender silent;
|
||||||
@ -67,6 +68,7 @@ public class AbilityBotTest {
|
|||||||
void setUp() {
|
void setUp() {
|
||||||
db = offlineInstance("db");
|
db = offlineInstance("db");
|
||||||
bot = new DefaultBot(EMPTY, EMPTY, db);
|
bot = new DefaultBot(EMPTY, EMPTY, db);
|
||||||
|
defaultAbs = new DefaultAbilities(bot);
|
||||||
|
|
||||||
sender = mock(MessageSender.class);
|
sender = mock(MessageSender.class);
|
||||||
silent = mock(SilentSender.class);
|
silent = mock(SilentSender.class);
|
||||||
@ -122,7 +124,7 @@ public class AbilityBotTest {
|
|||||||
void canBackupDB() throws TelegramApiException {
|
void canBackupDB() throws TelegramApiException {
|
||||||
MessageContext context = defaultContext();
|
MessageContext context = defaultContext();
|
||||||
|
|
||||||
bot.backupDB().action().accept(context);
|
defaultAbs.backupDB().action().accept(context);
|
||||||
deleteQuietly(new java.io.File("backup.json"));
|
deleteQuietly(new java.io.File("backup.json"));
|
||||||
|
|
||||||
verify(sender, times(1)).sendDocument(any());
|
verify(sender, times(1)).sendDocument(any());
|
||||||
@ -137,7 +139,7 @@ public class AbilityBotTest {
|
|||||||
// Support for null parameter matching since due to mocking API changes
|
// Support for null parameter matching since due to mocking API changes
|
||||||
when(sender.downloadFile(ArgumentMatchers.<File>isNull())).thenReturn(backupFile);
|
when(sender.downloadFile(ArgumentMatchers.<File>isNull())).thenReturn(backupFile);
|
||||||
|
|
||||||
bot.recoverDB().replies().get(0).actOn(update);
|
defaultAbs.recoverDB().replies().get(0).actOn(update);
|
||||||
|
|
||||||
verify(silent, times(1)).send(RECOVER_SUCCESS, GROUP_ID);
|
verify(silent, times(1)).send(RECOVER_SUCCESS, GROUP_ID);
|
||||||
assertEquals(db.getSet(TEST), newHashSet(TEST), "Bot recovered but the DB is still not in sync");
|
assertEquals(db.getSet(TEST), newHashSet(TEST), "Bot recovered but the DB is still not in sync");
|
||||||
@ -159,7 +161,7 @@ public class AbilityBotTest {
|
|||||||
|
|
||||||
MessageContext context = defaultContext();
|
MessageContext context = defaultContext();
|
||||||
|
|
||||||
bot.demoteAdmin().action().accept(context);
|
defaultAbs.demoteAdmin().action().accept(context);
|
||||||
|
|
||||||
Set<Integer> actual = bot.admins();
|
Set<Integer> actual = bot.admins();
|
||||||
Set<Integer> expected = emptySet();
|
Set<Integer> expected = emptySet();
|
||||||
@ -172,7 +174,7 @@ public class AbilityBotTest {
|
|||||||
|
|
||||||
MessageContext context = defaultContext();
|
MessageContext context = defaultContext();
|
||||||
|
|
||||||
bot.promoteAdmin().action().accept(context);
|
defaultAbs.promoteAdmin().action().accept(context);
|
||||||
|
|
||||||
Set<Integer> actual = bot.admins();
|
Set<Integer> actual = bot.admins();
|
||||||
Set<Integer> expected = newHashSet(USER.getId());
|
Set<Integer> expected = newHashSet(USER.getId());
|
||||||
@ -184,7 +186,7 @@ public class AbilityBotTest {
|
|||||||
addUsers(USER);
|
addUsers(USER);
|
||||||
MessageContext context = defaultContext();
|
MessageContext context = defaultContext();
|
||||||
|
|
||||||
bot.banUser().action().accept(context);
|
defaultAbs.banUser().action().accept(context);
|
||||||
|
|
||||||
Set<Integer> actual = bot.blacklist();
|
Set<Integer> actual = bot.blacklist();
|
||||||
Set<Integer> expected = newHashSet(USER.getId());
|
Set<Integer> expected = newHashSet(USER.getId());
|
||||||
@ -198,7 +200,7 @@ public class AbilityBotTest {
|
|||||||
|
|
||||||
MessageContext context = defaultContext();
|
MessageContext context = defaultContext();
|
||||||
|
|
||||||
bot.unbanUser().action().accept(context);
|
defaultAbs.unbanUser().action().accept(context);
|
||||||
|
|
||||||
Set<Integer> actual = bot.blacklist();
|
Set<Integer> actual = bot.blacklist();
|
||||||
Set<Integer> expected = newHashSet();
|
Set<Integer> expected = newHashSet();
|
||||||
@ -215,7 +217,7 @@ public class AbilityBotTest {
|
|||||||
addUsers(USER, CREATOR);
|
addUsers(USER, CREATOR);
|
||||||
MessageContext context = mockContext(USER, GROUP_ID, CREATOR.getUserName());
|
MessageContext context = mockContext(USER, GROUP_ID, CREATOR.getUserName());
|
||||||
|
|
||||||
bot.banUser().action().accept(context);
|
defaultAbs.banUser().action().accept(context);
|
||||||
|
|
||||||
Set<Integer> actual = bot.blacklist();
|
Set<Integer> actual = bot.blacklist();
|
||||||
Set<Integer> expected = newHashSet(USER.getId());
|
Set<Integer> expected = newHashSet(USER.getId());
|
||||||
@ -233,7 +235,7 @@ public class AbilityBotTest {
|
|||||||
void creatorCanClaimBot() {
|
void creatorCanClaimBot() {
|
||||||
MessageContext context = mockContext(CREATOR, GROUP_ID);
|
MessageContext context = mockContext(CREATOR, GROUP_ID);
|
||||||
|
|
||||||
bot.claimCreator().action().accept(context);
|
defaultAbs.claimCreator().action().accept(context);
|
||||||
|
|
||||||
Set<Integer> actual = bot.admins();
|
Set<Integer> actual = bot.admins();
|
||||||
Set<Integer> expected = newHashSet(CREATOR.getId());
|
Set<Integer> expected = newHashSet(CREATOR.getId());
|
||||||
@ -534,7 +536,7 @@ public class AbilityBotTest {
|
|||||||
void canReportCommands() {
|
void canReportCommands() {
|
||||||
MessageContext context = mockContext(USER, GROUP_ID);
|
MessageContext context = mockContext(USER, GROUP_ID);
|
||||||
|
|
||||||
bot.reportCommands().action().accept(context);
|
defaultAbs.reportCommands().action().accept(context);
|
||||||
|
|
||||||
verify(silent, times(1)).send("default - dis iz default command", GROUP_ID);
|
verify(silent, times(1)).send("default - dis iz default command", GROUP_ID);
|
||||||
}
|
}
|
||||||
@ -549,7 +551,7 @@ public class AbilityBotTest {
|
|||||||
when(message.hasText()).thenReturn(true);
|
when(message.hasText()).thenReturn(true);
|
||||||
MessageContext creatorCtx = newContext(update, CREATOR, GROUP_ID);
|
MessageContext creatorCtx = newContext(update, CREATOR, GROUP_ID);
|
||||||
|
|
||||||
bot.commands().action().accept(creatorCtx);
|
defaultAbs.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";
|
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);
|
verify(silent, times(1)).send(expected, GROUP_ID);
|
||||||
@ -566,7 +568,7 @@ public class AbilityBotTest {
|
|||||||
|
|
||||||
MessageContext userCtx = newContext(update, USER, GROUP_ID);
|
MessageContext userCtx = newContext(update, USER, GROUP_ID);
|
||||||
|
|
||||||
bot.commands().action().accept(userCtx);
|
defaultAbs.commands().action().accept(userCtx);
|
||||||
|
|
||||||
String expected = "PUBLIC\n/commands\n/count\n/default - dis iz default command\n/group\n/test";
|
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);
|
verify(silent, times(1)).send(expected, GROUP_ID);
|
||||||
|
@ -3,6 +3,7 @@ package org.telegram.abilitybots.api.bot;
|
|||||||
import org.telegram.abilitybots.api.db.DBContext;
|
import org.telegram.abilitybots.api.db.DBContext;
|
||||||
import org.telegram.abilitybots.api.objects.Ability;
|
import org.telegram.abilitybots.api.objects.Ability;
|
||||||
import org.telegram.abilitybots.api.objects.Ability.AbilityBuilder;
|
import org.telegram.abilitybots.api.objects.Ability.AbilityBuilder;
|
||||||
|
import org.telegram.abilitybots.api.toggle.AbilityToggle;
|
||||||
|
|
||||||
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.CALLBACK_QUERY;
|
import static org.telegram.abilitybots.api.objects.Flag.CALLBACK_QUERY;
|
||||||
@ -17,6 +18,10 @@ public class DefaultBot extends AbilityBot {
|
|||||||
super(token, username, db);
|
super(token, username, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DefaultBot(String token, String username, DBContext db, AbilityToggle toggle) {
|
||||||
|
super(token, username, db, toggle);
|
||||||
|
}
|
||||||
|
|
||||||
public static AbilityBuilder getDefaultBuilder() {
|
public static AbilityBuilder getDefaultBuilder() {
|
||||||
return builder()
|
return builder()
|
||||||
.name("test")
|
.name("test")
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package org.telegram.abilitybots.api.toggle;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.telegram.abilitybots.api.bot.DefaultAbilities;
|
||||||
|
import org.telegram.abilitybots.api.bot.DefaultBot;
|
||||||
|
import org.telegram.abilitybots.api.db.DBContext;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
|
||||||
|
|
||||||
|
public class BareboneToggleTest {
|
||||||
|
|
||||||
|
private DBContext db;
|
||||||
|
private AbilityToggle toggle;
|
||||||
|
private DefaultBot bareboneBot;
|
||||||
|
private DefaultAbilities defaultAbs;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
db = offlineInstance("db");
|
||||||
|
toggle = new BareboneToggle();
|
||||||
|
bareboneBot = new DefaultBot(EMPTY, EMPTY, db, toggle);
|
||||||
|
defaultAbs = new DefaultAbilities(bareboneBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() throws IOException {
|
||||||
|
db.clear();
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void turnsOffAllAbilities() {
|
||||||
|
assertFalse(bareboneBot.abilities().containsKey(DefaultAbilities.CLAIM));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void throwsOnProcessingAbility() {
|
||||||
|
Assertions.assertThrows(RuntimeException.class, () -> toggle.processAbility(defaultAbs.claimCreator()));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package org.telegram.abilitybots.api.toggle;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.telegram.abilitybots.api.bot.DefaultAbilities;
|
||||||
|
import org.telegram.abilitybots.api.bot.DefaultBot;
|
||||||
|
import org.telegram.abilitybots.api.db.DBContext;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
|
||||||
|
|
||||||
|
class CustomToggleTest {
|
||||||
|
private DBContext db;
|
||||||
|
private AbilityToggle toggle;
|
||||||
|
private DefaultBot customBot;
|
||||||
|
private DefaultAbilities defaultAbs;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
db = offlineInstance("db");
|
||||||
|
defaultAbs = new DefaultAbilities(customBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() throws IOException {
|
||||||
|
db.clear();
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void canTurnOffAbilities() {
|
||||||
|
toggle = new CustomToggle().turnOff(DefaultAbilities.CLAIM);
|
||||||
|
customBot = new DefaultBot(EMPTY, EMPTY, db, toggle);
|
||||||
|
assertFalse(customBot.abilities().containsKey(DefaultAbilities.CLAIM));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void canProcessAbilities() {
|
||||||
|
String targetName = DefaultAbilities.CLAIM + "1toggle";
|
||||||
|
toggle = new CustomToggle().toggle(DefaultAbilities.CLAIM, targetName);
|
||||||
|
customBot = new DefaultBot(EMPTY, EMPTY, db, toggle);
|
||||||
|
|
||||||
|
assertTrue(customBot.abilities().containsKey(targetName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package org.telegram.abilitybots.api.toggle;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.telegram.abilitybots.api.bot.DefaultAbilities;
|
||||||
|
import org.telegram.abilitybots.api.bot.DefaultBot;
|
||||||
|
import org.telegram.abilitybots.api.db.DBContext;
|
||||||
|
import org.telegram.abilitybots.api.objects.Ability;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Sets.newHashSet;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.EMPTY;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.telegram.abilitybots.api.bot.DefaultAbilities.*;
|
||||||
|
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
|
||||||
|
|
||||||
|
class DefaultToggleTest {
|
||||||
|
private DBContext db;
|
||||||
|
private AbilityToggle toggle;
|
||||||
|
private DefaultBot defaultBot;
|
||||||
|
private DefaultAbilities defaultAbs;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
db = offlineInstance("db");
|
||||||
|
defaultAbs = new DefaultAbilities(defaultBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() throws IOException {
|
||||||
|
db.clear();
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void claimsEveryAbilityIsOn() {
|
||||||
|
Ability random = DefaultBot.getDefaultBuilder()
|
||||||
|
.name("randomsomethingrandom").build();
|
||||||
|
toggle = new DefaultToggle();
|
||||||
|
defaultBot = new DefaultBot(EMPTY, EMPTY, db, toggle);
|
||||||
|
|
||||||
|
assertFalse(toggle.isOff(random));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void passedSameAbilityRefOnProcess() {
|
||||||
|
Ability random = DefaultBot.getDefaultBuilder()
|
||||||
|
.name("randomsomethingrandom").build();
|
||||||
|
toggle = new DefaultToggle();
|
||||||
|
defaultBot = new DefaultBot(EMPTY, EMPTY, db, toggle);
|
||||||
|
|
||||||
|
assertSame(random, toggle.processAbility(random), "Toggle returned a different ability");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void allAbilitiesAreRegistered() {
|
||||||
|
toggle = new DefaultToggle();
|
||||||
|
defaultBot = new DefaultBot(EMPTY, EMPTY, db, toggle);
|
||||||
|
Set<String> defaultNames = newHashSet(
|
||||||
|
CLAIM, BAN, UNBAN,
|
||||||
|
PROMOTE, DEMOTE, RECOVER,
|
||||||
|
BACKUP, REPORT, COMMANDS);
|
||||||
|
|
||||||
|
assertTrue(defaultBot.abilities().keySet().containsAll(defaultNames), "Toggle returned a different ability");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user