commit
1a2e7c9773
7
.gitignore
vendored
7
.gitignore
vendored
@ -35,12 +35,11 @@ hs_err_pid*
|
|||||||
.idea/
|
.idea/
|
||||||
copyright/
|
copyright/
|
||||||
*.iml
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
.classpath
|
.classpath
|
||||||
.project
|
.project
|
||||||
.settings/
|
.settings/
|
||||||
|
|
||||||
#File System specific files
|
#File System specific files
|
||||||
.DS_STORE
|
.DS_Store
|
||||||
|
|
||||||
# Default ignored files
|
|
||||||
/Bots.iws
|
|
||||||
|
@ -27,16 +27,16 @@ Just import add the library to your project with one of these options:
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots</artifactId>
|
<artifactId>telegrambots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
```gradle
|
```gradle
|
||||||
compile "org.telegram:telegrambots:4.8.1"
|
compile "org.telegram:telegrambots:4.9"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.8.1)
|
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.9)
|
||||||
3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.8.1)
|
3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.9)
|
||||||
|
|
||||||
In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`.
|
In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`.
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
### <a id="4.9"></a>4.9 ###
|
||||||
|
1. Update Api version [4.9](https://core.telegram.org/bots/api-changelog#june-4-2020)
|
||||||
|
2. Bug fixing: #731, #749, #752 and #753
|
||||||
|
|
||||||
### <a id="4.8.1"></a>4.8.1 ###
|
### <a id="4.8.1"></a>4.8.1 ###
|
||||||
1. Update Api version [4.8](https://core.telegram.org/bots/api-changelog#april-24-2020)
|
1. Update Api version [4.8](https://core.telegram.org/bots/api-changelog#april-24-2020)
|
||||||
2. Add stats for Abilities
|
2. Add stats for Abilities
|
||||||
|
@ -11,13 +11,13 @@ First you need ot get the library and add it to your project. There are few poss
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots</artifactId>
|
<artifactId>telegrambots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
* With **Gradle**:
|
* With **Gradle**:
|
||||||
|
|
||||||
```groovy
|
```groovy
|
||||||
compile group: 'org.telegram', name: 'telegrambots', version: '4.8.1'
|
compile group: 'org.telegram', name: 'telegrambots', version: '4.9'
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Don't like **Maven Central Repository**? It can also be taken from [Jitpack](https://jitpack.io/#rubenlagus/TelegramBots).
|
2. Don't like **Maven Central Repository**? It can also be taken from [Jitpack](https://jitpack.io/#rubenlagus/TelegramBots).
|
||||||
|
@ -31,4 +31,7 @@ As an example, if you want to restrict the updates to photos only, then you may
|
|||||||
public boolean checkGlobalFlags(Update update) {
|
public boolean checkGlobalFlags(Update update) {
|
||||||
return Flag.PHOTO;
|
return Flag.PHOTO;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Statistics
|
||||||
|
AbilityBot can accrue basic statistics about the usage of your abilities and replies. Simply `enableStats()` on an Ability builder or `enableStats(<name>)` on replies to activate this feature. Once activated, you may call `/stats` and the bot will print a basic list of statistics. At the moment, AbilityBot only tracks hits. In the future, this will be enhanced to track more stats.
|
@ -9,12 +9,12 @@ As with any Java project, you will need to set your dependencies.
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots-abilities</artifactId>
|
<artifactId>telegrambots-abilities</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
* **Gradle**
|
* **Gradle**
|
||||||
```groovy
|
```groovy
|
||||||
implementation group: 'org.telegram', name: 'telegrambots-abilities', version: '4.8.1'
|
implementation group: 'org.telegram', name: 'telegrambots-abilities', version: '4.9'
|
||||||
```
|
```
|
||||||
* [JitPack](https://jitpack.io/#rubenlagus/TelegramBots)
|
* [JitPack](https://jitpack.io/#rubenlagus/TelegramBots)
|
||||||
|
|
||||||
|
@ -70,30 +70,29 @@ Now, after your naughty bot retaliates, the user can say "go left or else" to fo
|
|||||||
|
|
||||||
## Complete Example
|
## Complete Example
|
||||||
```java
|
```java
|
||||||
public static class ReplyFlowBot extends AbilityBot {
|
public class ReplyFlowBot extends AbilityBot {
|
||||||
public class ReplyFlowBot extends AbilityBot {
|
|
||||||
public ReplyFlowBot(String botToken, String botUsername) {
|
public ReplyFlowBot(String botToken, String botUsername) {
|
||||||
super(botToken, botUsername);
|
super(botToken, botUsername);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int creatorId() {
|
public int creatorId() {
|
||||||
return <YOUR ID HERE>;
|
return <YOUR ID HERE>;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReplyFlow directionFlow() {
|
public ReplyFlow directionFlow() {
|
||||||
Reply saidLeft = Reply.of(upd -> silent.send("Sir, I have gone left.", getChatId(upd)),
|
Reply saidLeft = Reply.of(upd -> silent.send("Sir, I have gone left.", getChatId(upd)),
|
||||||
hasMessageWith("go left or else"));
|
hasMessageWith("go left or else"));
|
||||||
|
|
||||||
ReplyFlow leftflow = ReplyFlow.builder(db)
|
ReplyFlow leftflow = ReplyFlow.builder(db)
|
||||||
.action(upd -> silent.send("I don't know how to go left.", getChatId(upd)))
|
.action(upd -> silent.send("I don't know how to go left.", getChatId(upd)))
|
||||||
.onlyIf(hasMessageWith("left"))
|
.onlyIf(hasMessageWith("left"))
|
||||||
.next(saidLeft).build();
|
.next(saidLeft).build();
|
||||||
|
|
||||||
Reply saidRight = Reply.of(upd -> silent.send("Sir, I have gone right.", getChatId(upd)),
|
Reply saidRight = Reply.of(upd -> silent.send("Sir, I have gone right.", getChatId(upd)),
|
||||||
hasMessageWith("right"));
|
hasMessageWith("right"));
|
||||||
|
|
||||||
return ReplyFlow.builder(db)
|
return ReplyFlow.builder(db)
|
||||||
.action(upd -> silent.send("Command me to go left or right!", getChatId(upd)))
|
.action(upd -> silent.send("Command me to go left or right!", getChatId(upd)))
|
||||||
.onlyIf(hasMessageWith("wake up"))
|
.onlyIf(hasMessageWith("wake up"))
|
||||||
.next(leftflow)
|
.next(leftflow)
|
||||||
@ -103,9 +102,9 @@ public static class ReplyFlowBot extends AbilityBot {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Predicate<Update> hasMessageWith(String msg) {
|
private Predicate<Update> hasMessageWith(String msg) {
|
||||||
return upd -> upd.getMessage().getText().equalsIgnoreCase(msg);
|
return upd -> upd.getMessage().getText().equalsIgnoreCase(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
## Inline Declaration
|
## Inline Declaration
|
||||||
As you can see in the above example, we used a bottom-up approach. We declared the leaf replies before we got to the root reply flow.
|
As you can see in the above example, we used a bottom-up approach. We declared the leaf replies before we got to the root reply flow.
|
||||||
|
2
pom.xml
2
pom.xml
@ -7,7 +7,7 @@
|
|||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>Bots</artifactId>
|
<artifactId>Bots</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>telegrambots</module>
|
<module>telegrambots</module>
|
||||||
|
@ -18,19 +18,19 @@ Usage
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots-abilities</artifactId>
|
<artifactId>telegrambots-abilities</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Gradle**
|
**Gradle**
|
||||||
|
|
||||||
```gradle
|
```gradle
|
||||||
compile "org.telegram:telegrambots-abilities:4.8.1"
|
compile "org.telegram:telegrambots-abilities:4.9"
|
||||||
```
|
```
|
||||||
|
|
||||||
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.8.1)
|
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.9)
|
||||||
|
|
||||||
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.8.1)
|
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.9)
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
----------
|
----------
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>Bots</artifactId>
|
<artifactId>Bots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>telegrambots-abilities</artifactId>
|
<artifactId>telegrambots-abilities</artifactId>
|
||||||
@ -84,7 +84,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots</artifactId>
|
<artifactId>telegrambots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.telegram.abilitybots.api.bot;
|
package org.telegram.abilitybots.api.bot;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.*;
|
||||||
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 org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -33,15 +33,18 @@ 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.collect.Sets.difference;
|
||||||
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.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.toSet;
|
||||||
import static org.telegram.abilitybots.api.objects.Locality.*;
|
import static org.telegram.abilitybots.api.objects.Locality.*;
|
||||||
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.*;
|
import static org.telegram.abilitybots.api.objects.Privacy.*;
|
||||||
|
import static org.telegram.abilitybots.api.objects.Stats.createStats;
|
||||||
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.*;
|
import static org.telegram.abilitybots.api.util.AbilityMessageCodes.*;
|
||||||
import static org.telegram.abilitybots.api.util.AbilityUtils.*;
|
import static org.telegram.abilitybots.api.util.AbilityUtils.*;
|
||||||
|
|
||||||
@ -87,6 +90,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
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";
|
||||||
|
public static final String STATS = "ABILITYBOT_STATS";
|
||||||
|
|
||||||
// DB and sender
|
// DB and sender
|
||||||
protected final DBContext db;
|
protected final DBContext db;
|
||||||
@ -102,6 +106,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
|
|
||||||
// Ability registry
|
// Ability registry
|
||||||
private Map<String, Ability> abilities;
|
private Map<String, Ability> abilities;
|
||||||
|
private Map<String, Stats> stats;
|
||||||
|
|
||||||
// Reply registry
|
// Reply registry
|
||||||
private List<Reply> replies;
|
private List<Reply> replies;
|
||||||
@ -119,6 +124,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
silent = new SilentSender(sender);
|
silent = new SilentSender(sender);
|
||||||
|
|
||||||
registerAbilities();
|
registerAbilities();
|
||||||
|
initStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,6 +155,13 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
return db.getSet(ADMINS);
|
return db.getSet(ADMINS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a mapping of ability and reply names to their corresponding statistics
|
||||||
|
*/
|
||||||
|
protected Map<String, Stats> stats() {
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the immutable map of <String,Ability>
|
* @return the immutable map of <String,Ability>
|
||||||
*/
|
*/
|
||||||
@ -163,6 +176,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
return 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>
|
||||||
@ -180,6 +194,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
.filter(this::checkBlacklist)
|
.filter(this::checkBlacklist)
|
||||||
.map(this::addUser)
|
.map(this::addUser)
|
||||||
.filter(this::filterReply)
|
.filter(this::filterReply)
|
||||||
|
.filter(this::hasUser)
|
||||||
.map(this::getAbility)
|
.map(this::getAbility)
|
||||||
.filter(this::validateAbility)
|
.filter(this::validateAbility)
|
||||||
.filter(this::checkPrivacy)
|
.filter(this::checkPrivacy)
|
||||||
@ -188,6 +203,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
.filter(this::checkMessageFlags)
|
.filter(this::checkMessageFlags)
|
||||||
.map(this::getContext)
|
.map(this::getContext)
|
||||||
.map(this::consumeUpdate)
|
.map(this::consumeUpdate)
|
||||||
|
.map(this::updateStats)
|
||||||
.forEach(this::postConsumption);
|
.forEach(this::postConsumption);
|
||||||
|
|
||||||
// Commit to DB now after all the actions have been dealt
|
// Commit to DB now after all the actions have been dealt
|
||||||
@ -275,6 +291,19 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initStats() {
|
||||||
|
Set<String> enabledStats = Stream.concat(
|
||||||
|
replies.stream().filter(Reply::statsEnabled).map(Reply::name),
|
||||||
|
abilities.entrySet().stream()
|
||||||
|
.filter(entry -> entry.getValue().statsEnabled())
|
||||||
|
.map(Map.Entry::getKey)).collect(toSet());
|
||||||
|
stats = db.getMap(STATS);
|
||||||
|
Set<String> toBeRemoved = difference(stats.keySet(), enabledStats);
|
||||||
|
toBeRemoved.forEach(stats::remove);
|
||||||
|
enabledStats.forEach(abName -> stats.computeIfAbsent(abName,
|
||||||
|
name -> createStats(abName, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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
|
||||||
@ -344,6 +373,26 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
return pair;
|
return pair;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pair<MessageContext, Ability> updateStats(Pair<MessageContext, Ability> pair) {
|
||||||
|
Ability ab = pair.b();
|
||||||
|
if (ab.statsEnabled()) {
|
||||||
|
updateStats(pair.b().name());
|
||||||
|
}
|
||||||
|
return pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateReplyStats(Reply reply) {
|
||||||
|
if (reply.statsEnabled()) {
|
||||||
|
updateStats(reply.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateStats(String name) {
|
||||||
|
Stats statsObj = stats.get(name);
|
||||||
|
statsObj.hit();
|
||||||
|
stats.put(name, statsObj);
|
||||||
|
}
|
||||||
|
|
||||||
Pair<MessageContext, Ability> getContext(Trio<Update, Ability, String[]> trio) {
|
Pair<MessageContext, Ability> getContext(Trio<Update, Ability, String[]> trio) {
|
||||||
Update update = trio.a();
|
Update update = trio.a();
|
||||||
User user = AbilityUtils.getUser(update);
|
User user = AbilityUtils.getUser(update);
|
||||||
@ -487,6 +536,12 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasUser(Update update) {
|
||||||
|
// Valid updates without users should return an empty user
|
||||||
|
// Updates that are not recognized by the getUser method will throw an exception
|
||||||
|
return !AbilityUtils.getUser(update).equals(EMPTY_USER);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateUserId(User oldUser, User newUser) {
|
private void updateUserId(User oldUser, User newUser) {
|
||||||
if (oldUser != null && oldUser.getUserName() != null) {
|
if (oldUser != null && oldUser.getUserName() != null) {
|
||||||
// Remove old username -> ID
|
// Remove old username -> ID
|
||||||
@ -504,6 +559,7 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability
|
|||||||
.filter(reply -> reply.isOkFor(update))
|
.filter(reply -> reply.isOkFor(update))
|
||||||
.map(reply -> {
|
.map(reply -> {
|
||||||
reply.actOn(update);
|
reply.actOn(update);
|
||||||
|
updateReplyStats(reply);
|
||||||
return false;
|
return false;
|
||||||
})
|
})
|
||||||
.reduce(true, Boolean::logicalAnd);
|
.reduce(true, Boolean::logicalAnd);
|
||||||
|
@ -26,6 +26,7 @@ import java.io.PrintStream;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
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 com.google.common.collect.MultimapBuilder.hashKeys;
|
||||||
@ -76,6 +77,7 @@ public final class DefaultAbilities implements AbilityExtension {
|
|||||||
public static final String RECOVER = "recover";
|
public static final String RECOVER = "recover";
|
||||||
public static final String COMMANDS = "commands";
|
public static final String COMMANDS = "commands";
|
||||||
public static final String REPORT = "report";
|
public static final String REPORT = "report";
|
||||||
|
public static final String STATS = "stats";
|
||||||
private static final Logger log = LoggerFactory.getLogger(DefaultAbilities.class);
|
private static final Logger log = LoggerFactory.getLogger(DefaultAbilities.class);
|
||||||
private final BaseAbilityBot bot;
|
private final BaseAbilityBot bot;
|
||||||
|
|
||||||
@ -179,6 +181,26 @@ public final class DefaultAbilities implements AbilityExtension {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ability to report statistics for abilities and replies.
|
||||||
|
*/
|
||||||
|
public Ability reportStats() {
|
||||||
|
return builder()
|
||||||
|
.name(STATS)
|
||||||
|
.locality(ALL)
|
||||||
|
.privacy(ADMIN)
|
||||||
|
.input(0)
|
||||||
|
.action(ctx -> {
|
||||||
|
String stats = bot.stats().entrySet().stream()
|
||||||
|
.map(entry -> String.format("%s: %d", entry.getKey(), entry.getValue().hits()))
|
||||||
|
.reduce(new StringJoiner("\n"), StringJoiner::add, StringJoiner::merge)
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
bot.silent.send(stats, 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>
|
||||||
@ -212,6 +234,7 @@ public final class DefaultAbilities implements AbilityExtension {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recovers the bot database using {@link DBContext#recover(Object)}.
|
* Recovers the bot database using {@link DBContext#recover(Object)}.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -42,13 +42,14 @@ public final class Ability {
|
|||||||
private final Locality locality;
|
private final Locality locality;
|
||||||
private final Privacy privacy;
|
private final Privacy privacy;
|
||||||
private final int argNum;
|
private final int argNum;
|
||||||
|
private final boolean statsEnabled;
|
||||||
private final Consumer<MessageContext> action;
|
private final Consumer<MessageContext> action;
|
||||||
private final Consumer<MessageContext> postAction;
|
private final Consumer<MessageContext> postAction;
|
||||||
private final List<Reply> replies;
|
private final List<Reply> replies;
|
||||||
private final List<Predicate<Update>> flags;
|
private final List<Predicate<Update>> flags;
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
private Ability(String name, String info, Locality locality, Privacy privacy, int argNum, Consumer<MessageContext> action, Consumer<MessageContext> postAction, List<Reply> replies, Predicate<Update>... flags) {
|
private Ability(String name, String info, Locality locality, Privacy privacy, int argNum, boolean statsEnabled, Consumer<MessageContext> action, Consumer<MessageContext> postAction, List<Reply> replies, Predicate<Update>... flags) {
|
||||||
checkArgument(!isEmpty(name), "Method name cannot be empty");
|
checkArgument(!isEmpty(name), "Method name cannot be empty");
|
||||||
checkArgument(!containsWhitespace(name), "Method name cannot contain spaces");
|
checkArgument(!containsWhitespace(name), "Method name cannot contain spaces");
|
||||||
checkArgument(isAlphanumeric(name), "Method name can only be alpha-numeric", name);
|
checkArgument(isAlphanumeric(name), "Method name can only be alpha-numeric", name);
|
||||||
@ -70,6 +71,7 @@ public final class Ability {
|
|||||||
|
|
||||||
this.postAction = postAction;
|
this.postAction = postAction;
|
||||||
this.replies = replies;
|
this.replies = replies;
|
||||||
|
this.statsEnabled = statsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AbilityBuilder builder() {
|
public static AbilityBuilder builder() {
|
||||||
@ -96,6 +98,10 @@ public final class Ability {
|
|||||||
return argNum;
|
return argNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean statsEnabled() {
|
||||||
|
return statsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
public Consumer<MessageContext> action() {
|
public Consumer<MessageContext> action() {
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
@ -147,12 +153,14 @@ public final class Ability {
|
|||||||
private Privacy privacy;
|
private Privacy privacy;
|
||||||
private Locality locality;
|
private Locality locality;
|
||||||
private int argNum;
|
private int argNum;
|
||||||
|
private boolean statsEnabled;
|
||||||
private Consumer<MessageContext> action;
|
private Consumer<MessageContext> action;
|
||||||
private Consumer<MessageContext> postAction;
|
private Consumer<MessageContext> postAction;
|
||||||
private List<Reply> replies;
|
private List<Reply> replies;
|
||||||
private Predicate<Update>[] flags;
|
private Predicate<Update>[] flags;
|
||||||
|
|
||||||
private AbilityBuilder() {
|
private AbilityBuilder() {
|
||||||
|
statsEnabled = false;
|
||||||
replies = newArrayList();
|
replies = newArrayList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,6 +194,11 @@ public final class Ability {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AbilityBuilder enableStats() {
|
||||||
|
statsEnabled = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public AbilityBuilder privacy(Privacy privacy) {
|
public AbilityBuilder privacy(Privacy privacy) {
|
||||||
this.privacy = privacy;
|
this.privacy = privacy;
|
||||||
return this;
|
return this;
|
||||||
@ -202,6 +215,11 @@ public final class Ability {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final AbilityBuilder reply(Reply reply) {
|
||||||
|
replies.add(reply);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public AbilityBuilder basedOn(Ability ability) {
|
public AbilityBuilder basedOn(Ability ability) {
|
||||||
replies.clear();
|
replies.clear();
|
||||||
replies.addAll(ability.replies());
|
replies.addAll(ability.replies());
|
||||||
@ -216,7 +234,7 @@ public final class Ability {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Ability build() {
|
public Ability build() {
|
||||||
return new Ability(name, info, locality, privacy, argNum, action, postAction, replies, flags);
|
return new Ability(name, info, locality, privacy, argNum, statsEnabled, action, postAction, replies, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,12 +26,15 @@ import static java.util.Arrays.asList;
|
|||||||
public class Reply {
|
public class Reply {
|
||||||
public final List<Predicate<Update>> conditions;
|
public final List<Predicate<Update>> conditions;
|
||||||
public final Consumer<Update> action;
|
public final Consumer<Update> action;
|
||||||
|
private boolean statsEnabled;
|
||||||
|
private String name;
|
||||||
|
|
||||||
Reply(List<Predicate<Update>> conditions, Consumer<Update> action) {
|
Reply(List<Predicate<Update>> conditions, Consumer<Update> action) {
|
||||||
this.conditions = ImmutableList.<Predicate<Update>>builder()
|
this.conditions = ImmutableList.<Predicate<Update>>builder()
|
||||||
.addAll(conditions)
|
.addAll(conditions)
|
||||||
.build();
|
.build();
|
||||||
this.action = action;
|
this.action = action;
|
||||||
|
statsEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Reply of(Consumer<Update> action, List<Predicate<Update>> conditions) {
|
public static Reply of(Consumer<Update> action, List<Predicate<Update>> conditions) {
|
||||||
@ -65,6 +68,20 @@ public class Reply {
|
|||||||
return Stream.of(this);
|
return Stream.of(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Reply enableStats(String name) {
|
||||||
|
this.name = name;
|
||||||
|
statsEnabled = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean statsEnabled() {
|
||||||
|
return statsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o)
|
if (this == o)
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package org.telegram.abilitybots.api.objects;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
import org.json.JSONPropertyIgnore;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic POJO to track ability and reply hits. The current implementation is NOT thread safe.
|
||||||
|
*
|
||||||
|
* @author Abbas Abou Daya
|
||||||
|
*/
|
||||||
|
public final class Stats implements Serializable {
|
||||||
|
@JsonProperty
|
||||||
|
private final String name;
|
||||||
|
@JsonProperty
|
||||||
|
private long hits;
|
||||||
|
|
||||||
|
private Stats(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public static Stats createStats(@JsonProperty("name") String name, @JsonProperty("hits") long hits) {
|
||||||
|
return new Stats(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long hits() {
|
||||||
|
return hits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hit() {
|
||||||
|
hits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Stats that = (Stats) o;
|
||||||
|
return hits == that.hits &&
|
||||||
|
Objects.equals(name, that.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(name, hits);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return MoreObjects.toStringHelper(this)
|
||||||
|
.add("name", name)
|
||||||
|
.add("hits", hits)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ import static org.telegram.abilitybots.api.objects.Flag.*;
|
|||||||
* Helper and utility methods
|
* Helper and utility methods
|
||||||
*/
|
*/
|
||||||
public final class AbilityUtils {
|
public final class AbilityUtils {
|
||||||
public static User EMPTY_USER = new User();
|
public static User EMPTY_USER = new User(0, "", false, "", "", "");
|
||||||
|
|
||||||
private AbilityUtils() {
|
private AbilityUtils() {
|
||||||
|
|
||||||
@ -150,6 +150,14 @@ public final class AbilityUtils {
|
|||||||
return update.getEditedMessage().getChatId();
|
return update.getEditedMessage().getChatId();
|
||||||
} else if (CHOSEN_INLINE_QUERY.test(update)) {
|
} else if (CHOSEN_INLINE_QUERY.test(update)) {
|
||||||
return (long) update.getChosenInlineQuery().getFrom().getId();
|
return (long) update.getChosenInlineQuery().getFrom().getId();
|
||||||
|
} else if (SHIPPING_QUERY.test(update)) {
|
||||||
|
return (long) update.getShippingQuery().getFrom().getId();
|
||||||
|
} else if (PRECHECKOUT_QUERY.test(update)) {
|
||||||
|
return (long) update.getPreCheckoutQuery().getFrom().getId();
|
||||||
|
} else if (POLL_ANSWER.test(update)) {
|
||||||
|
return (long) update.getPollAnswer().getUser().getId();
|
||||||
|
} else if (POLL.test(update)) {
|
||||||
|
return (long) EMPTY_USER.getId();
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Could not retrieve originating chat ID from update");
|
throw new IllegalStateException("Could not retrieve originating chat ID from update");
|
||||||
}
|
}
|
||||||
@ -170,10 +178,8 @@ public final class AbilityUtils {
|
|||||||
return update.getEditedChannelPost().isUserMessage();
|
return update.getEditedChannelPost().isUserMessage();
|
||||||
} else if (EDITED_MESSAGE.test(update)) {
|
} else if (EDITED_MESSAGE.test(update)) {
|
||||||
return update.getEditedMessage().isUserMessage();
|
return update.getEditedMessage().isUserMessage();
|
||||||
} else if (CHOSEN_INLINE_QUERY.test(update) || INLINE_QUERY.test(update)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Could not retrieve update context origin (user/group)");
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,10 +8,12 @@ import org.junit.jupiter.api.Assertions;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.ArgumentMatchers;
|
import org.mockito.ArgumentMatchers;
|
||||||
|
import org.mockito.Mockito;
|
||||||
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.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.util.AbilityUtils;
|
||||||
import org.telegram.abilitybots.api.util.Pair;
|
import org.telegram.abilitybots.api.util.Pair;
|
||||||
import org.telegram.abilitybots.api.util.Trio;
|
import org.telegram.abilitybots.api.util.Trio;
|
||||||
import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators;
|
import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators;
|
||||||
@ -25,6 +27,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static com.google.common.collect.Lists.newArrayList;
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
import static com.google.common.collect.Sets.newHashSet;
|
import static com.google.common.collect.Sets.newHashSet;
|
||||||
@ -38,8 +41,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||||
import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder;
|
import static org.telegram.abilitybots.api.bot.DefaultBot.getDefaultBuilder;
|
||||||
import static org.telegram.abilitybots.api.bot.TestUtils.*;
|
|
||||||
import static org.telegram.abilitybots.api.bot.TestUtils.CREATOR;
|
import static org.telegram.abilitybots.api.bot.TestUtils.CREATOR;
|
||||||
|
import static org.telegram.abilitybots.api.bot.TestUtils.*;
|
||||||
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
|
import static org.telegram.abilitybots.api.db.MapDBContext.offlineInstance;
|
||||||
import static org.telegram.abilitybots.api.objects.Flag.DOCUMENT;
|
import static org.telegram.abilitybots.api.objects.Flag.DOCUMENT;
|
||||||
import static org.telegram.abilitybots.api.objects.Flag.MESSAGE;
|
import static org.telegram.abilitybots.api.objects.Flag.MESSAGE;
|
||||||
@ -120,6 +123,49 @@ public class AbilityBotTest {
|
|||||||
verify(silent, times(1)).send("reply", USER.getId());
|
verify(silent, times(1)).send("reply", USER.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void canProcessUpdatesWithoutUserInfo() {
|
||||||
|
Update update = mock(Update.class);
|
||||||
|
// At the moment, only poll updates carry no user information
|
||||||
|
when(update.hasPoll()).thenReturn(true);
|
||||||
|
|
||||||
|
bot.onUpdateReceived(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getUserHasAllMethodsDefined() {
|
||||||
|
Arrays.stream(Update.class.getMethods())
|
||||||
|
// filter to all these methods of hasXXX (hasPoll, hasMessage, etc...)
|
||||||
|
.filter(method -> method.getName().startsWith("has"))
|
||||||
|
// Gotta filter out hashCode
|
||||||
|
.filter(method -> method.getReturnType().getName().equals("boolean"))
|
||||||
|
.forEach(method -> {
|
||||||
|
Update update = mock(Update.class);
|
||||||
|
try {
|
||||||
|
// Mock the method and make sure it returns true so that it gets processed by the following method
|
||||||
|
when(method.invoke(update)).thenReturn(true);
|
||||||
|
// Call the getUser function, throws an IllegalStateException if there's an update that can't be processed
|
||||||
|
AbilityUtils.getUser(update);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
format("Found an update variation that is not handled by the getUser util method [%s]", method.getName()), e);
|
||||||
|
} catch (NullPointerException | ReflectiveOperationException e) {
|
||||||
|
// This is fine, the mock isn't complete and we're only
|
||||||
|
// looking for IllegalStateExceptions thrown by the method
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getChatIdCanHandleAllKindsOfUpdates() {
|
||||||
|
handlesAllUpdates(AbilityUtils::getUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getUserCanHandleAllKindsOfUpdates() {
|
||||||
|
handlesAllUpdates(AbilityUtils::getChatId);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void canBackupDB() throws TelegramApiException {
|
void canBackupDB() throws TelegramApiException {
|
||||||
MessageContext context = defaultContext();
|
MessageContext context = defaultContext();
|
||||||
@ -130,6 +176,30 @@ public class AbilityBotTest {
|
|||||||
verify(sender, times(1)).sendDocument(any());
|
verify(sender, times(1)).sendDocument(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void canReportStatistics() {
|
||||||
|
MessageContext context = defaultContext();
|
||||||
|
|
||||||
|
defaultAbs.reportStats().action().accept(context);
|
||||||
|
|
||||||
|
verify(silent, times(1)).send("count: 0\nmustreply: 0", GROUP_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void canReportUpdatedStatistics() {
|
||||||
|
Update upd1 = mockFullUpdate(bot, CREATOR, "/count 1 2 3 4");
|
||||||
|
bot.onUpdateReceived(upd1);
|
||||||
|
Update upd2 = mockFullUpdate(bot, CREATOR, "must reply");
|
||||||
|
bot.onUpdateReceived(upd2);
|
||||||
|
|
||||||
|
Mockito.reset(silent);
|
||||||
|
|
||||||
|
Update statUpd = mockFullUpdate(bot, CREATOR, "/stats");
|
||||||
|
bot.onUpdateReceived(statUpd);
|
||||||
|
|
||||||
|
verify(silent, times(1)).send("count: 1\nmustreply: 1", CREATOR.getId());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void canRecoverDB() throws TelegramApiException, IOException {
|
void canRecoverDB() throws TelegramApiException, IOException {
|
||||||
Update update = mockBackupUpdate();
|
Update update = mockBackupUpdate();
|
||||||
@ -553,7 +623,7 @@ public class AbilityBotTest {
|
|||||||
|
|
||||||
defaultAbs.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/stats\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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,6 +644,29 @@ public class AbilityBotTest {
|
|||||||
verify(silent, times(1)).send(expected, GROUP_ID);
|
verify(silent, times(1)).send(expected, GROUP_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handlesAllUpdates(Consumer<Update> utilMethod) {
|
||||||
|
Arrays.stream(Update.class.getMethods())
|
||||||
|
// filter to all these methods of hasXXX (hasPoll, hasMessage, etc...)
|
||||||
|
.filter(method -> method.getName().startsWith("has"))
|
||||||
|
// Gotta filter out hashCode
|
||||||
|
.filter(method -> method.getReturnType().getName().equals("boolean"))
|
||||||
|
.forEach(method -> {
|
||||||
|
Update update = mock(Update.class);
|
||||||
|
try {
|
||||||
|
// Mock the method and make sure it returns true so that it gets processed by the following method
|
||||||
|
when(method.invoke(update)).thenReturn(true);
|
||||||
|
// Call the function, throws an IllegalStateException if there's an update that can't be processed
|
||||||
|
utilMethod.accept(update);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
format("Found an update variation that is not handled by the getChatId util method [%s]", method.getName()), e);
|
||||||
|
} catch (NullPointerException | ReflectiveOperationException e) {
|
||||||
|
// This is fine, the mock isn't complete and we're only
|
||||||
|
// looking for IllegalStateExceptions thrown by the method
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void mockUser(Update update, Message message, User user) {
|
private void mockUser(Update update, Message message, User user) {
|
||||||
when(update.hasMessage()).thenReturn(true);
|
when(update.hasMessage()).thenReturn(true);
|
||||||
when(update.getMessage()).thenReturn(message);
|
when(update.getMessage()).thenReturn(message);
|
||||||
|
@ -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.objects.Reply;
|
||||||
import org.telegram.abilitybots.api.toggle.AbilityToggle;
|
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;
|
||||||
@ -41,7 +42,7 @@ public class DefaultBot extends AbilityBot {
|
|||||||
return getDefaultBuilder()
|
return getDefaultBuilder()
|
||||||
.name(DEFAULT)
|
.name(DEFAULT)
|
||||||
.info("dis iz default command")
|
.info("dis iz default command")
|
||||||
.reply(upd -> silent.send("reply", upd.getMessage().getChatId()), MESSAGE, update -> update.getMessage().getText().equals("must reply"))
|
.reply(Reply.of(upd -> silent.send("reply", upd.getMessage().getChatId()), MESSAGE, update -> update.getMessage().getText().equals("must reply")).enableStats("mustreply"))
|
||||||
.reply(upd -> silent.send("reply", upd.getCallbackQuery().getMessage().getChatId()), CALLBACK_QUERY)
|
.reply(upd -> silent.send("reply", upd.getCallbackQuery().getMessage().getChatId()), CALLBACK_QUERY)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@ -67,6 +68,7 @@ public class DefaultBot extends AbilityBot {
|
|||||||
.privacy(PUBLIC)
|
.privacy(PUBLIC)
|
||||||
.locality(USER)
|
.locality(USER)
|
||||||
.input(4)
|
.input(4)
|
||||||
|
.enableStats()
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,11 +5,13 @@ import org.junit.jupiter.api.AfterEach;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.telegram.abilitybots.api.db.DBContext;
|
import org.telegram.abilitybots.api.db.DBContext;
|
||||||
|
import org.telegram.abilitybots.api.objects.Flag;
|
||||||
import org.telegram.abilitybots.api.objects.Reply;
|
import org.telegram.abilitybots.api.objects.Reply;
|
||||||
import org.telegram.abilitybots.api.objects.ReplyFlow;
|
import org.telegram.abilitybots.api.objects.ReplyFlow;
|
||||||
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.telegrambots.meta.api.objects.Update;
|
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.polls.Poll;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
@ -106,6 +108,20 @@ public class ReplyFlowTest {
|
|||||||
assertFalse(db.<Long, Integer>getMap(STATES).containsKey(chatId), "User still has state after terminal reply");
|
assertFalse(db.<Long, Integer>getMap(STATES).containsKey(chatId), "User still has state after terminal reply");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void repliesHandlePollResponse() {
|
||||||
|
Update update = mock(Update.class);
|
||||||
|
when(update.hasPoll()).thenReturn(true);
|
||||||
|
when(update.hasMessage()).thenReturn(false);
|
||||||
|
|
||||||
|
Poll poll = mock(Poll.class);
|
||||||
|
when(poll.getId()).thenReturn("1");
|
||||||
|
when(update.getPoll()).thenReturn(poll);
|
||||||
|
|
||||||
|
// This should not be processed as a reply, so we wouldn't filter out (true)
|
||||||
|
assertTrue(bot.filterReply(update));
|
||||||
|
}
|
||||||
|
|
||||||
public static class ReplyFlowBot extends AbilityBot {
|
public static class ReplyFlowBot extends AbilityBot {
|
||||||
|
|
||||||
private ReplyFlowBot(String botToken, String botUsername, DBContext db) {
|
private ReplyFlowBot(String botToken, String botUsername, DBContext db) {
|
||||||
@ -139,7 +155,7 @@ public class ReplyFlowTest {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Predicate<Update> hasMessageWith(String msg) {
|
private Predicate<Update> hasMessageWith(String msg) {
|
||||||
return upd -> upd.getMessage().getText().equalsIgnoreCase(msg);
|
return upd -> Flag.MESSAGE.test(upd) && upd.getMessage().getText().equalsIgnoreCase(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ Usage
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots-chat-session-bot</artifactId>
|
<artifactId>telegrambots-chat-session-bot</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>Bots</artifactId>
|
<artifactId>Bots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>telegrambots-chat-session-bot</artifactId>
|
<artifactId>telegrambots-chat-session-bot</artifactId>
|
||||||
@ -84,7 +84,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots</artifactId>
|
<artifactId>telegrambots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
|
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
|
||||||
|
@ -16,12 +16,12 @@ Just import add the library to your project with one of these options:
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambotsextensions</artifactId>
|
<artifactId>telegrambotsextensions</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Using Gradle:
|
2. Using Gradle:
|
||||||
|
|
||||||
```gradle
|
```gradle
|
||||||
compile "org.telegram:telegrambotsextensions:4.8.1"
|
compile "org.telegram:telegrambotsextensions:4.9"
|
||||||
```
|
```
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>Bots</artifactId>
|
<artifactId>Bots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>telegrambotsextensions</artifactId>
|
<artifactId>telegrambotsextensions</artifactId>
|
||||||
@ -75,7 +75,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots</artifactId>
|
<artifactId>telegrambots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>Bots</artifactId>
|
<artifactId>Bots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>telegrambots-meta</artifactId>
|
<artifactId>telegrambots-meta</artifactId>
|
||||||
|
@ -10,14 +10,18 @@ import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
|
|||||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ruben Bermudez
|
* @author Ruben Bermudez
|
||||||
* @version 4.7
|
* @version 4.7
|
||||||
* Use this method to send a dice, which will have a random value from 1 to 6. On success, the sent Message is returned.
|
* Use this method to send an animated emoji that will display a random value. On success, the sent Message is returned.
|
||||||
* (Yes, we're aware of the “proper” singular of die. But it's awkward, and we decided to help it change. One dice at a time!)
|
|
||||||
*/
|
*/
|
||||||
public class SendDice extends BotApiMethod<Message> {
|
public class SendDice extends BotApiMethod<Message> {
|
||||||
|
private static final List<String> VALIDEMOJIS = Collections.unmodifiableList(Arrays.asList("\uD83C\uDFB2", "\uD83C\uDFAF", "\uD83C\uDFC0"));
|
||||||
|
|
||||||
public static final String PATH = "sendDice";
|
public static final String PATH = "sendDice";
|
||||||
|
|
||||||
private static final String CHATID_FIELD = "chat_id";
|
private static final String CHATID_FIELD = "chat_id";
|
||||||
@ -28,8 +32,12 @@ public class SendDice extends BotApiMethod<Message> {
|
|||||||
|
|
||||||
@JsonProperty(CHATID_FIELD)
|
@JsonProperty(CHATID_FIELD)
|
||||||
private String chatId; ///< Unique identifier for the target chat or username of the target channel (in the format @channelusername)
|
private String chatId; ///< Unique identifier for the target chat or username of the target channel (in the format @channelusername)
|
||||||
|
/**
|
||||||
|
* Emoji on which the dice throw animation is based. Currently, must be one of “🎲”, “🎯”, or “🏀”.
|
||||||
|
* Dice can have values 1-6 for “🎲” and “🎯”, and values 1-5 for “🏀”. Defauts to “🎲”
|
||||||
|
*/
|
||||||
@JsonProperty(EMOJI_FIELD)
|
@JsonProperty(EMOJI_FIELD)
|
||||||
private String emoji; ///< Optional. Emoji on which the dice throw animation is based. Currently, must be one of “🎲” or “🎯”. Defauts to “🎲”
|
private String emoji;
|
||||||
@JsonProperty(DISABLENOTIFICATION_FIELD)
|
@JsonProperty(DISABLENOTIFICATION_FIELD)
|
||||||
private Boolean disableNotification; ///< Optional. Sends the message silently. Users will receive a notification with no sound.
|
private Boolean disableNotification; ///< Optional. Sends the message silently. Users will receive a notification with no sound.
|
||||||
@JsonProperty(REPLYTOMESSAGEID_FIELD)
|
@JsonProperty(REPLYTOMESSAGEID_FIELD)
|
||||||
@ -121,8 +129,8 @@ public class SendDice extends BotApiMethod<Message> {
|
|||||||
if (chatId == null) {
|
if (chatId == null) {
|
||||||
throw new TelegramApiValidationException("ChatId parameter can't be empty", this);
|
throw new TelegramApiValidationException("ChatId parameter can't be empty", this);
|
||||||
}
|
}
|
||||||
if (emoji != null && !emoji.equals("\uD83C\uDFB2") && !emoji.equals("\uD83C\uDFAF")) {
|
if (emoji != null && !VALIDEMOJIS.contains(emoji)) {
|
||||||
throw new TelegramApiValidationException("Only \uD83C\uDFB2 and \uD83C\uDFAF are allowed in Emoji field ", this);
|
throw new TelegramApiValidationException("Only \uD83C\uDFB2, \uD83C\uDFAF or \uD83C\uDFC0 are allowed in Emoji field ", this);
|
||||||
}
|
}
|
||||||
if (replyMarkup != null) {
|
if (replyMarkup != null) {
|
||||||
replyMarkup.validate();
|
replyMarkup.validate();
|
||||||
|
@ -6,15 +6,14 @@ import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
|
|||||||
/**
|
/**
|
||||||
* @author Ruben Bermudez
|
* @author Ruben Bermudez
|
||||||
* @version 4.7
|
* @version 4.7
|
||||||
* This object represents a dice with random value from 1 to 6.
|
* This object represents an animated emoji that displays a random value.
|
||||||
* (Yes, we're aware of the “proper” singular of die. But it's awkward, and we decided to help it change. One dice at a time!)
|
|
||||||
*/
|
*/
|
||||||
public class Dice implements BotApiObject {
|
public class Dice implements BotApiObject {
|
||||||
private static final String VALUE_FIELD = "value";
|
private static final String VALUE_FIELD = "value";
|
||||||
private static final String EMOJI_FIELD = "emoji";
|
private static final String EMOJI_FIELD = "emoji";
|
||||||
|
|
||||||
@JsonProperty(VALUE_FIELD)
|
@JsonProperty(VALUE_FIELD)
|
||||||
private Integer value; ///< Value of the dice, 1-6
|
private Integer value; ///< Value of the dice, 1-6 for “🎲” and “🎯” base emoji, 1-5 for “🏀” base emoji
|
||||||
@JsonProperty(EMOJI_FIELD)
|
@JsonProperty(EMOJI_FIELD)
|
||||||
private String emoji; ///< Emoji on which the dice throw animation is based
|
private String emoji; ///< Emoji on which the dice throw animation is based
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ public class Message implements BotApiObject {
|
|||||||
private static final String POLL_FIELD = "poll";
|
private static final String POLL_FIELD = "poll";
|
||||||
private static final String REPLY_MARKUP_FIELD = "reply_markup";
|
private static final String REPLY_MARKUP_FIELD = "reply_markup";
|
||||||
private static final String DICE_FIELD = "dice";
|
private static final String DICE_FIELD = "dice";
|
||||||
|
private static final String VIABOT_FIELD = "via_bot";
|
||||||
|
|
||||||
@JsonProperty(MESSAGEID_FIELD)
|
@JsonProperty(MESSAGEID_FIELD)
|
||||||
private Integer messageId; ///< Integer Unique message identifier
|
private Integer messageId; ///< Integer Unique message identifier
|
||||||
@ -210,7 +211,8 @@ public class Message implements BotApiObject {
|
|||||||
private InlineKeyboardMarkup replyMarkup;
|
private InlineKeyboardMarkup replyMarkup;
|
||||||
@JsonProperty(DICE_FIELD)
|
@JsonProperty(DICE_FIELD)
|
||||||
private Dice dice; // Optional. Message is a dice with random value from 1 to 6
|
private Dice dice; // Optional. Message is a dice with random value from 1 to 6
|
||||||
|
@JsonProperty(VIABOT_FIELD)
|
||||||
|
private User viaBot; // Optional. Bot through which the message was sent
|
||||||
public Message() {
|
public Message() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -521,6 +523,14 @@ public class Message implements BotApiObject {
|
|||||||
return dice != null;
|
return dice != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public User getViaBot() {
|
||||||
|
return viaBot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasViaBot() {
|
||||||
|
return viaBot != null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasReplyMarkup() {
|
public boolean hasReplyMarkup() {
|
||||||
return replyMarkup != null;
|
return replyMarkup != null;
|
||||||
}
|
}
|
||||||
@ -579,6 +589,8 @@ public class Message implements BotApiObject {
|
|||||||
", forwardSenderName='" + forwardSenderName + '\'' +
|
", forwardSenderName='" + forwardSenderName + '\'' +
|
||||||
", poll=" + poll +
|
", poll=" + poll +
|
||||||
", replyMarkup=" + replyMarkup +
|
", replyMarkup=" + replyMarkup +
|
||||||
|
", dice=" + dice +
|
||||||
|
", viaBot=" + viaBot +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,10 @@ import org.telegram.telegrambots.meta.api.objects.inlinequery.inputmessageconten
|
|||||||
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
|
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
|
||||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ruben Bermudez
|
* @author Ruben Bermudez
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
@ -16,12 +20,15 @@ import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
|||||||
*/
|
*/
|
||||||
@JsonDeserialize
|
@JsonDeserialize
|
||||||
public class InlineQueryResultGif implements InlineQueryResult {
|
public class InlineQueryResultGif implements InlineQueryResult {
|
||||||
|
private static final List<String> VALIDTHUMBTYPES = Collections.unmodifiableList(Arrays.asList("image/jpeg", "image/gif", "video/mp4"));
|
||||||
|
|
||||||
private static final String TYPE_FIELD = "type";
|
private static final String TYPE_FIELD = "type";
|
||||||
private static final String ID_FIELD = "id";
|
private static final String ID_FIELD = "id";
|
||||||
private static final String GIFURL_FIELD = "gif_url";
|
private static final String GIFURL_FIELD = "gif_url";
|
||||||
private static final String GIFWIDTH_FIELD = "gif_width";
|
private static final String GIFWIDTH_FIELD = "gif_width";
|
||||||
private static final String GIFHEIGHT_FIELD = "gif_height";
|
private static final String GIFHEIGHT_FIELD = "gif_height";
|
||||||
private static final String THUMBURL_FIELD = "thumb_url";
|
private static final String THUMBURL_FIELD = "thumb_url";
|
||||||
|
private static final String THUMBMIMETYPE_FIELD = "thumb_mime_type";
|
||||||
private static final String TITLE_FIELD = "title";
|
private static final String TITLE_FIELD = "title";
|
||||||
private static final String CAPTION_FIELD = "caption";
|
private static final String CAPTION_FIELD = "caption";
|
||||||
private static final String INPUTMESSAGECONTENT_FIELD = "input_message_content";
|
private static final String INPUTMESSAGECONTENT_FIELD = "input_message_content";
|
||||||
@ -40,7 +47,9 @@ public class InlineQueryResultGif implements InlineQueryResult {
|
|||||||
@JsonProperty(GIFHEIGHT_FIELD)
|
@JsonProperty(GIFHEIGHT_FIELD)
|
||||||
private Integer gifHeight; ///< Optional. Height of the GIF
|
private Integer gifHeight; ///< Optional. Height of the GIF
|
||||||
@JsonProperty(THUMBURL_FIELD)
|
@JsonProperty(THUMBURL_FIELD)
|
||||||
private String thumbUrl; ///< Optional. URL of a static thumbnail for the result (jpeg or gif)
|
private String thumbUrl; ///< Optional. URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result
|
||||||
|
@JsonProperty(THUMBMIMETYPE_FIELD)
|
||||||
|
private String thumbUrlType; ///< Optional. MIME type of the thumbnail, must be one of “image/jpeg”, “image/gif”, or “video/mp4”
|
||||||
@JsonProperty(TITLE_FIELD)
|
@JsonProperty(TITLE_FIELD)
|
||||||
private String title; ///< Optional. Title for the result
|
private String title; ///< Optional. Title for the result
|
||||||
@JsonProperty(CAPTION_FIELD)
|
@JsonProperty(CAPTION_FIELD)
|
||||||
@ -107,6 +116,15 @@ public class InlineQueryResultGif implements InlineQueryResult {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getThumbUrlType() {
|
||||||
|
return thumbUrlType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InlineQueryResultGif setThumbUrlType(String thumbUrlType) {
|
||||||
|
this.thumbUrlType = thumbUrlType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
@ -169,6 +187,9 @@ public class InlineQueryResultGif implements InlineQueryResult {
|
|||||||
if (gifUrl == null || gifUrl.isEmpty()) {
|
if (gifUrl == null || gifUrl.isEmpty()) {
|
||||||
throw new TelegramApiValidationException("GifUrl parameter can't be empty", this);
|
throw new TelegramApiValidationException("GifUrl parameter can't be empty", this);
|
||||||
}
|
}
|
||||||
|
if (thumbUrlType != null && !VALIDTHUMBTYPES.contains(thumbUrlType)) {
|
||||||
|
throw new TelegramApiValidationException("ThumbUrlType parameter must be one of “image/jpeg”, “image/gif”, or “video/mp4”", this);
|
||||||
|
}
|
||||||
if (inputMessageContent != null) {
|
if (inputMessageContent != null) {
|
||||||
inputMessageContent.validate();
|
inputMessageContent.validate();
|
||||||
}
|
}
|
||||||
@ -186,6 +207,7 @@ public class InlineQueryResultGif implements InlineQueryResult {
|
|||||||
", gifWidth=" + gifWidth +
|
", gifWidth=" + gifWidth +
|
||||||
", gifHeight=" + gifHeight +
|
", gifHeight=" + gifHeight +
|
||||||
", thumbUrl='" + thumbUrl + '\'' +
|
", thumbUrl='" + thumbUrl + '\'' +
|
||||||
|
", thumbUrlType='" + thumbUrlType + '\'' +
|
||||||
", title='" + title + '\'' +
|
", title='" + title + '\'' +
|
||||||
", caption='" + caption + '\'' +
|
", caption='" + caption + '\'' +
|
||||||
", inputMessageContent=" + inputMessageContent +
|
", inputMessageContent=" + inputMessageContent +
|
||||||
|
@ -8,6 +8,10 @@ import org.telegram.telegrambots.meta.api.objects.inlinequery.result.InlineQuery
|
|||||||
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
|
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
|
||||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ruben Bermudez
|
* @author Ruben Bermudez
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
@ -17,11 +21,15 @@ import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
|||||||
*/
|
*/
|
||||||
@JsonDeserialize
|
@JsonDeserialize
|
||||||
public class InlineQueryResultCachedGif implements InlineQueryResult {
|
public class InlineQueryResultCachedGif implements InlineQueryResult {
|
||||||
|
private static final List<String> VALIDTHUMBTYPES = Collections.unmodifiableList(Arrays.asList("image/jpeg", "image/gif", "video/mp4"));
|
||||||
|
|
||||||
private static final String TYPE_FIELD = "type";
|
private static final String TYPE_FIELD = "type";
|
||||||
private static final String ID_FIELD = "id";
|
private static final String ID_FIELD = "id";
|
||||||
private static final String GIF_FILE_ID_FIELD = "gif_file_id";
|
private static final String GIF_FILE_ID_FIELD = "gif_file_id";
|
||||||
private static final String TITLE_FIELD = "title";
|
private static final String TITLE_FIELD = "title";
|
||||||
private static final String CAPTION_FIELD = "caption";
|
private static final String CAPTION_FIELD = "caption";
|
||||||
|
private static final String THUMBURL_FIELD = "thumb_url";
|
||||||
|
private static final String THUMBMIMETYPE_FIELD = "thumb_mime_type";
|
||||||
private static final String INPUTMESSAGECONTENT_FIELD = "input_message_content";
|
private static final String INPUTMESSAGECONTENT_FIELD = "input_message_content";
|
||||||
private static final String REPLY_MARKUP_FIELD = "reply_markup";
|
private static final String REPLY_MARKUP_FIELD = "reply_markup";
|
||||||
private static final String PARSEMODE_FIELD = "parse_mode";
|
private static final String PARSEMODE_FIELD = "parse_mode";
|
||||||
@ -42,6 +50,10 @@ public class InlineQueryResultCachedGif implements InlineQueryResult {
|
|||||||
private InlineKeyboardMarkup replyMarkup; ///< Optional. Inline keyboard attached to the message
|
private InlineKeyboardMarkup replyMarkup; ///< Optional. Inline keyboard attached to the message
|
||||||
@JsonProperty(PARSEMODE_FIELD)
|
@JsonProperty(PARSEMODE_FIELD)
|
||||||
private String parseMode; ///< Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
|
private String parseMode; ///< Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
|
||||||
|
@JsonProperty(THUMBURL_FIELD)
|
||||||
|
private String thumbUrl; ///< Optional. URL of the static (JPEG or GIF) or animated (MPEG4) thumbnail for the result
|
||||||
|
@JsonProperty(THUMBMIMETYPE_FIELD)
|
||||||
|
private String thumbUrlType;
|
||||||
|
|
||||||
public InlineQueryResultCachedGif() {
|
public InlineQueryResultCachedGif() {
|
||||||
super();
|
super();
|
||||||
@ -114,6 +126,24 @@ public class InlineQueryResultCachedGif implements InlineQueryResult {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getThumbUrl() {
|
||||||
|
return thumbUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InlineQueryResultCachedGif setThumbUrl(String thumbUrl) {
|
||||||
|
this.thumbUrl = thumbUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getThumbUrlType() {
|
||||||
|
return thumbUrlType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InlineQueryResultCachedGif setThumbUrlType(String thumbUrlType) {
|
||||||
|
this.thumbUrlType = thumbUrlType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validate() throws TelegramApiValidationException {
|
public void validate() throws TelegramApiValidationException {
|
||||||
if (id == null || id.isEmpty()) {
|
if (id == null || id.isEmpty()) {
|
||||||
@ -122,6 +152,9 @@ public class InlineQueryResultCachedGif implements InlineQueryResult {
|
|||||||
if (gifFileId == null || gifFileId.isEmpty()) {
|
if (gifFileId == null || gifFileId.isEmpty()) {
|
||||||
throw new TelegramApiValidationException("GifFileId parameter can't be empty", this);
|
throw new TelegramApiValidationException("GifFileId parameter can't be empty", this);
|
||||||
}
|
}
|
||||||
|
if (thumbUrlType != null && !VALIDTHUMBTYPES.contains(thumbUrlType)) {
|
||||||
|
throw new TelegramApiValidationException("ThumbUrlType parameter must be one of “image/jpeg”, “image/gif”, or “video/mp4”", this);
|
||||||
|
}
|
||||||
if (inputMessageContent != null) {
|
if (inputMessageContent != null) {
|
||||||
inputMessageContent.validate();
|
inputMessageContent.validate();
|
||||||
}
|
}
|
||||||
@ -141,6 +174,8 @@ public class InlineQueryResultCachedGif implements InlineQueryResult {
|
|||||||
", inputMessageContent=" + inputMessageContent +
|
", inputMessageContent=" + inputMessageContent +
|
||||||
", replyMarkup=" + replyMarkup +
|
", replyMarkup=" + replyMarkup +
|
||||||
", parseMode='" + parseMode + '\'' +
|
", parseMode='" + parseMode + '\'' +
|
||||||
|
", thumbUrl='" + thumbUrl + '\'' +
|
||||||
|
", thumbUrlType='" + thumbUrlType + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>Bots</artifactId>
|
<artifactId>Bots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>telegrambots-spring-boot-starter</artifactId>
|
<artifactId>telegrambots-spring-boot-starter</artifactId>
|
||||||
@ -79,7 +79,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots</artifactId>
|
<artifactId>telegrambots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>Bots</artifactId>
|
<artifactId>Bots</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>telegrambots</artifactId>
|
<artifactId>telegrambots</artifactId>
|
||||||
@ -95,7 +95,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.telegram</groupId>
|
<groupId>org.telegram</groupId>
|
||||||
<artifactId>telegrambots-meta</artifactId>
|
<artifactId>telegrambots-meta</artifactId>
|
||||||
<version>4.8.1</version>
|
<version>4.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
Loading…
Reference in New Issue
Block a user