commit
bd5c5a2f41
17
Bots.ipr
17
Bots.ipr
@ -22,10 +22,10 @@
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="telegrambots-abilities" />
|
||||
<module name="telegrambots-extensions" />
|
||||
<module name="telegrambots-meta" />
|
||||
<module name="telegrambots-extensions" />
|
||||
<module name="telegrambots" />
|
||||
<module name="telegrambots-abilities" />
|
||||
<module name="telegrambots-chat-session-bot" />
|
||||
<module name="telegrambots-spring-boot-starter" />
|
||||
</profile>
|
||||
@ -2021,6 +2021,19 @@
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/telegram/telegrambots-meta/4.2/telegrambots-meta-4.2-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.telegram:telegrambots-meta:4.5">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/telegram/telegrambots-meta/4.5/telegrambots-meta-4.5.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$PROJECT_DIR$/telegrambots-meta/telegrambots-meta-4.5-javadoc.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/telegram/telegrambots-meta/4.5/telegrambots-meta-4.5-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/telegrambots-meta/telegrambots-meta-4.5-sources.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/telegram/telegrambots-meta/4.5/telegrambots-meta-4.5-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
<library name="Maven: org.telegram:telegrambots:3.5">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/telegram/telegrambots/3.5/telegrambots-3.5.jar!/" />
|
||||
|
@ -27,16 +27,16 @@ Just import add the library to your project with one of these options:
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambots:4.5"
|
||||
compile "org.telegram:telegrambots:4.6"
|
||||
```
|
||||
|
||||
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.5)
|
||||
3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.5)
|
||||
2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.6)
|
||||
3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.6)
|
||||
|
||||
In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`.
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
### <a id="4.6"></a>4.6 ###
|
||||
1. Update Api version [4.6](https://core.telegram.org/bots/api-changelog#january-23-2020)
|
||||
|
||||
### <a id="4.5"></a>4.5 ###
|
||||
1. Update Api version [4.5](https://core.telegram.org/bots/api-changelog#december-31-2019)
|
||||
2. Fixes: #697, #710
|
||||
|
@ -11,13 +11,13 @@ First you need ot get the library and add it to your project. There are few poss
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
```
|
||||
* With **Gradle**:
|
||||
|
||||
```groovy
|
||||
compile group: 'org.telegram', name: 'telegrambots', version: '4.5'
|
||||
compile group: 'org.telegram', name: 'telegrambots', version: '4.6'
|
||||
```
|
||||
|
||||
2. Don't like **Maven Central Repository**? It can also be taken from [Jitpack](https://jitpack.io/#rubenlagus/TelegramBots).
|
||||
|
@ -9,7 +9,7 @@ As with any Java project, you will need to set your dependencies.
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-abilities</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
```
|
||||
* **Gradle**
|
||||
|
@ -63,12 +63,10 @@ Reply saidLeft = Reply.of(upd -> silent.send("Sir, I have gone left.", getChatId
|
||||
hasMessageWith("go left or else"));
|
||||
```
|
||||
Now, after your naughty bot retaliates, the user can say "go left or else" to force the bot to go left. Awesome, our logic now looks like this:
|
||||
<div align="center">
|
||||
|
||||
![Alt text](./img/replyflow_diagram.svg)
|
||||
<img src="./img/replyflow_diagram.svg">
|
||||
|
||||
</div>
|
||||
<p align="center">
|
||||
[[/abilities/img/replyflow_diagram.svg|Diagram]]
|
||||
</p>
|
||||
|
||||
## Complete Example
|
||||
```java
|
||||
|
2
pom.xml
2
pom.xml
@ -7,7 +7,7 @@
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
|
||||
<modules>
|
||||
<module>telegrambots</module>
|
||||
|
@ -18,19 +18,19 @@ Usage
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-abilities</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
**Gradle**
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambots-abilities:4.5"
|
||||
compile "org.telegram:telegrambots-abilities:4.6"
|
||||
```
|
||||
|
||||
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.5)
|
||||
**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.6)
|
||||
|
||||
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.5)
|
||||
**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.6)
|
||||
|
||||
Motivation
|
||||
----------
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots-abilities</artifactId>
|
||||
@ -84,7 +84,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
@ -15,7 +15,7 @@ Usage
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-chat-session-bot</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots-chat-session-bot</artifactId>
|
||||
@ -84,7 +84,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 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>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambotsextensions</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
2. Using Gradle:
|
||||
|
||||
```gradle
|
||||
compile "org.telegram:telegrambotsextensions:4.5"
|
||||
compile "org.telegram:telegrambotsextensions:4.6"
|
||||
```
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambotsextensions</artifactId>
|
||||
@ -75,7 +75,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots-meta</artifactId>
|
||||
|
@ -2,14 +2,16 @@ package org.telegram.telegrambots.meta.api.methods.polls;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
|
||||
import org.telegram.telegrambots.meta.api.objects.Message;
|
||||
import org.telegram.telegrambots.meta.api.objects.ApiResponse;
|
||||
import org.telegram.telegrambots.meta.api.objects.Message;
|
||||
import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard;
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -29,6 +31,11 @@ public class SendPoll extends BotApiMethod<Message> {
|
||||
private static final String CHATID_FIELD = "chat_id";
|
||||
private static final String QUESTION_FIELD = "question";
|
||||
private static final String OPTIONS_FIELD = "options";
|
||||
private static final String ISANONYMOUS_FIELD = "is_anonymous";
|
||||
private static final String TYPE_FIELD = "type";
|
||||
private static final String ALLOWMULTIPLEANSWERS_FIELD = "allows_multiple_answers";
|
||||
private static final String CORRECTOPTIONID_FIELD = "correct_option_id";
|
||||
private static final String ISCLOSED_FIELD = "is_closed";
|
||||
private static final String DISABLENOTIFICATION_FIELD = "disable_notification";
|
||||
private static final String REPLYTOMESSAGEID_FIELD = "reply_to_message_id";
|
||||
private static final String REPLYMARKUP_FIELD = "reply_markup";
|
||||
@ -38,18 +45,30 @@ public class SendPoll extends BotApiMethod<Message> {
|
||||
* A native poll can't be sent to a private chat.
|
||||
*/
|
||||
@JsonProperty(CHATID_FIELD)
|
||||
private String chatId;
|
||||
private String chatId; ///< Unique identifier for the target chat or username of the target channel (in the format @channelusername)
|
||||
@JsonProperty(QUESTION_FIELD)
|
||||
private String question; ///< Poll question, 1-255 characters
|
||||
@JsonProperty(OPTIONS_FIELD)
|
||||
private List<String> options; ///< List of answer options, 1-10 strings 1-100 characters each
|
||||
private List<String> options = new ArrayList<>(); ///< List of answer options, 2-10 strings 1-100 characters each
|
||||
@JsonProperty(ISANONYMOUS_FIELD)
|
||||
private Boolean isAnonymous; ///< Optional True, if the poll needs to be anonymous, defaults to True
|
||||
@JsonProperty(TYPE_FIELD)
|
||||
private String type; ///< Optional Poll type, “quiz” or “regular”, defaults to “regular”
|
||||
@JsonProperty(ALLOWMULTIPLEANSWERS_FIELD)
|
||||
private Boolean allowMultipleAnswers; ///< Optional True, if the poll allows multiple answers, ignored for polls in quiz mode, defaults to False
|
||||
@JsonProperty(CORRECTOPTIONID_FIELD)
|
||||
private Integer correctOptionId; ///< Optional 0-based identifier of the correct answer option, required for polls in quiz mode
|
||||
@JsonProperty(ISCLOSED_FIELD)
|
||||
private Boolean isClosed; ///< Optional Pass True, if the poll needs to be immediately closed
|
||||
@JsonProperty(DISABLENOTIFICATION_FIELD)
|
||||
private Boolean disableNotification; ///< Optional. Sends the message silently. Users will receive a notification with no sound.
|
||||
@JsonProperty(REPLYTOMESSAGEID_FIELD)
|
||||
private Integer replyToMessageId; ///< Optional. If the message is a reply, ID of the original message
|
||||
@JsonProperty(REPLYMARKUP_FIELD)
|
||||
@JsonDeserialize()
|
||||
private ReplyKeyboard replyMarkup; ///< Optional. JSON-serialized object for a custom reply keyboard
|
||||
|
||||
|
||||
public SendPoll() {
|
||||
super();
|
||||
}
|
||||
@ -132,6 +151,51 @@ public class SendPoll extends BotApiMethod<Message> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getAnonymous() {
|
||||
return isAnonymous;
|
||||
}
|
||||
|
||||
public SendPoll setAnonymous(Boolean anonymous) {
|
||||
isAnonymous = anonymous;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public SendPoll setType(String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getAllowMultipleAnswers() {
|
||||
return allowMultipleAnswers;
|
||||
}
|
||||
|
||||
public SendPoll setAllowMultipleAnswers(Boolean allowMultipleAnswers) {
|
||||
this.allowMultipleAnswers = allowMultipleAnswers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Integer getCorrectOptionId() {
|
||||
return correctOptionId;
|
||||
}
|
||||
|
||||
public SendPoll setCorrectOptionId(Integer correctOptionId) {
|
||||
this.correctOptionId = correctOptionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Boolean getClosed() {
|
||||
return isClosed;
|
||||
}
|
||||
|
||||
public SendPoll setClosed(Boolean closed) {
|
||||
isClosed = closed;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return PATH;
|
||||
@ -141,7 +205,8 @@ public class SendPoll extends BotApiMethod<Message> {
|
||||
public Message deserializeResponse(String answer) throws TelegramApiRequestException {
|
||||
try {
|
||||
ApiResponse<Message> result = OBJECT_MAPPER.readValue(answer,
|
||||
new TypeReference<ApiResponse<Message>>(){});
|
||||
new TypeReference<ApiResponse<Message>>() {
|
||||
});
|
||||
if (result.getOk()) {
|
||||
return result.getResult();
|
||||
} else {
|
||||
@ -160,39 +225,40 @@ public class SendPoll extends BotApiMethod<Message> {
|
||||
if (question == null || question.isEmpty()) {
|
||||
throw new TelegramApiValidationException("Question parameter can't be empty", this);
|
||||
}
|
||||
if (options == null || options.isEmpty()) {
|
||||
throw new TelegramApiValidationException("Options parameter can't be empty", this);
|
||||
if (options == null || options.size() < 2 || options.size() > 10) {
|
||||
throw new TelegramApiValidationException("Options parameter must be between 2 and 10 item", this);
|
||||
}
|
||||
if (options.parallelStream().anyMatch(x -> x.isEmpty() || x.length() > 100)) {
|
||||
throw new TelegramApiValidationException("Options parameter values must be between 1 and 100 chars length", this);
|
||||
}
|
||||
if (replyMarkup != null) {
|
||||
replyMarkup.validate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof SendPoll)) {
|
||||
return false;
|
||||
}
|
||||
SendPoll sendMessage = (SendPoll) o;
|
||||
return Objects.equals(chatId, sendMessage.chatId)
|
||||
&& Objects.equals(disableNotification, sendMessage.disableNotification)
|
||||
&& Objects.equals(question, sendMessage.question)
|
||||
&& Objects.equals(options, sendMessage.options)
|
||||
&& Objects.equals(replyMarkup, sendMessage.replyMarkup)
|
||||
&& Objects.equals(replyToMessageId, sendMessage.replyToMessageId)
|
||||
;
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof SendPoll)) return false;
|
||||
SendPoll sendPoll = (SendPoll) o;
|
||||
return Objects.equals(chatId, sendPoll.chatId) &&
|
||||
Objects.equals(question, sendPoll.question) &&
|
||||
Objects.equals(options, sendPoll.options) &&
|
||||
Objects.equals(isAnonymous, sendPoll.isAnonymous) &&
|
||||
Objects.equals(type, sendPoll.type) &&
|
||||
Objects.equals(allowMultipleAnswers, sendPoll.allowMultipleAnswers) &&
|
||||
Objects.equals(correctOptionId, sendPoll.correctOptionId) &&
|
||||
Objects.equals(isClosed, sendPoll.isClosed) &&
|
||||
Objects.equals(disableNotification, sendPoll.disableNotification) &&
|
||||
Objects.equals(replyToMessageId, sendPoll.replyToMessageId) &&
|
||||
Objects.equals(replyMarkup, sendPoll.replyMarkup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(
|
||||
chatId,
|
||||
disableNotification,
|
||||
options,
|
||||
replyMarkup,
|
||||
replyToMessageId,
|
||||
question);
|
||||
return Objects.hash(chatId, question, options, isAnonymous, type, allowMultipleAnswers, correctOptionId,
|
||||
isClosed, disableNotification, replyToMessageId, replyMarkup);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -201,6 +267,11 @@ public class SendPoll extends BotApiMethod<Message> {
|
||||
"chatId='" + chatId + '\'' +
|
||||
", question='" + question + '\'' +
|
||||
", options=" + options +
|
||||
", isAnonymous=" + isAnonymous +
|
||||
", type='" + type + '\'' +
|
||||
", allowMultipleAnswers=" + allowMultipleAnswers +
|
||||
", correctOptionId=" + correctOptionId +
|
||||
", isClosed=" + isClosed +
|
||||
", disableNotification=" + disableNotification +
|
||||
", replyToMessageId=" + replyToMessageId +
|
||||
", replyMarkup=" + replyMarkup +
|
||||
|
@ -17,6 +17,7 @@ public class MessageEntity implements BotApiObject {
|
||||
private static final String LENGTH_FIELD = "length";
|
||||
private static final String URL_FIELD = "url";
|
||||
private static final String USER_FIELD = "user";
|
||||
private static final String LANGUAGE_FIELD = "language";
|
||||
/**
|
||||
* Type of the entity. One of
|
||||
* mention (@username),
|
||||
@ -46,6 +47,8 @@ public class MessageEntity implements BotApiObject {
|
||||
private String url; ///< Optional. For “text_link” only, url that will be opened after user taps on the text
|
||||
@JsonProperty(USER_FIELD)
|
||||
private User user; ///< Optional. For “text_mention” only, the mentioned user
|
||||
@JsonProperty(LANGUAGE_FIELD)
|
||||
private String language; ///< Optional. For “pre” only, the programming language of the entity text
|
||||
@JsonIgnore
|
||||
private String text; ///< Text present in the entity. Computed from offset and length
|
||||
|
||||
@ -77,6 +80,10 @@ public class MessageEntity implements BotApiObject {
|
||||
return user;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
protected void computeText(String message) {
|
||||
if (message != null) {
|
||||
text = message.substring(offset, offset + length);
|
||||
@ -89,8 +96,10 @@ public class MessageEntity implements BotApiObject {
|
||||
"type='" + type + '\'' +
|
||||
", offset=" + offset +
|
||||
", length=" + length +
|
||||
", url=" + url +
|
||||
", url='" + url + '\'' +
|
||||
", user=" + user +
|
||||
", language='" + language + '\'' +
|
||||
", text='" + text + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import org.telegram.telegrambots.meta.api.objects.inlinequery.InlineQuery;
|
||||
import org.telegram.telegrambots.meta.api.objects.payments.PreCheckoutQuery;
|
||||
import org.telegram.telegrambots.meta.api.objects.payments.ShippingQuery;
|
||||
import org.telegram.telegrambots.meta.api.objects.polls.Poll;
|
||||
import org.telegram.telegrambots.meta.api.objects.polls.PollAnswer;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
@ -28,6 +29,7 @@ public class Update implements BotApiObject {
|
||||
private static final String SHIPPING_QUERY_FIELD = "shipping_query";
|
||||
private static final String PRE_CHECKOUT_QUERY_FIELD = "pre_checkout_query";
|
||||
private static final String POLL_FIELD = "poll";
|
||||
private static final String POLLANSWER_FIELD = "poll_answer";
|
||||
|
||||
@JsonProperty(UPDATEID_FIELD)
|
||||
private Integer updateId;
|
||||
@ -51,6 +53,15 @@ public class Update implements BotApiObject {
|
||||
private PreCheckoutQuery preCheckoutQuery; ///< Optional. New incoming pre-checkout query. Contains full information about checkout
|
||||
@JsonProperty(POLL_FIELD)
|
||||
private Poll poll; ///< Optional. New poll state. Bots receive only updates about polls, which are sent by the bot.
|
||||
/**
|
||||
* Optional.
|
||||
* A user changed their answer in a non-anonymous poll.
|
||||
*
|
||||
* @apiNote Bots receive new votes only in polls that were sent by the bot itself.
|
||||
*/
|
||||
@JsonProperty(POLLANSWER_FIELD)
|
||||
private PollAnswer pollAnswer;
|
||||
|
||||
|
||||
public Update() {
|
||||
super();
|
||||
@ -100,6 +111,10 @@ public class Update implements BotApiObject {
|
||||
return poll;
|
||||
}
|
||||
|
||||
public PollAnswer getPollAnswer() {
|
||||
return pollAnswer;
|
||||
}
|
||||
|
||||
public boolean hasMessage() {
|
||||
return message != null;
|
||||
}
|
||||
@ -140,6 +155,10 @@ public class Update implements BotApiObject {
|
||||
return poll != null;
|
||||
}
|
||||
|
||||
public boolean hasPollAnswer() {
|
||||
return pollAnswer != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Update{" +
|
||||
@ -153,6 +172,8 @@ public class Update implements BotApiObject {
|
||||
", editedChannelPost=" + editedChannelPost +
|
||||
", shippingQuery=" + shippingQuery +
|
||||
", preCheckoutQuery=" + preCheckoutQuery +
|
||||
", poll=" + poll +
|
||||
", pollAnswer=" + pollAnswer +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.telegram.telegrambots.meta.api.objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
|
||||
|
||||
import java.util.Objects;
|
||||
@ -19,6 +18,9 @@ public class User implements BotApiObject {
|
||||
private static final String LASTNAME_FIELD = "last_name";
|
||||
private static final String USERNAME_FIELD = "username";
|
||||
private static final String LANGUAGECODE_FIELD = "language_code";
|
||||
private static final String CANJOINGROUPS_FIELD = "can_join_groups";
|
||||
private static final String CANREADALLGROUPMESSAGES_FIELD = "can_read_all_group_messages";
|
||||
private static final String SUPPORTINLINEQUERIES_FIELD = "supports_inline_queries";
|
||||
|
||||
@JsonProperty(ID_FIELD)
|
||||
private Integer id; ///< Unique identifier for this user or bot
|
||||
@ -32,6 +34,12 @@ public class User implements BotApiObject {
|
||||
private String userName; ///< Optional. User‘s or bot’s username
|
||||
@JsonProperty(LANGUAGECODE_FIELD)
|
||||
private String languageCode; ///< Optional. IETF language tag of the user's language
|
||||
@JsonProperty(CANJOINGROUPS_FIELD)
|
||||
private Boolean canJoinGroups; ///< Optional. True, if the bot can be invited to groups. Returned only in getMe.
|
||||
@JsonProperty(CANREADALLGROUPMESSAGES_FIELD)
|
||||
private Boolean canReadAllGroupMessages; ///< Optional. True, if privacy mode is disabled for the bot. Returned only in getMe.
|
||||
@JsonProperty(SUPPORTINLINEQUERIES_FIELD)
|
||||
private Boolean supportInlineQueries; ///< Optional. True, if the bot supports inline queries. Returned only in getMe.
|
||||
|
||||
public User() {
|
||||
super();
|
||||
@ -70,6 +78,18 @@ public class User implements BotApiObject {
|
||||
return isBot;
|
||||
}
|
||||
|
||||
public Boolean getCanJoinGroups() {
|
||||
return canJoinGroups;
|
||||
}
|
||||
|
||||
public Boolean getCanReadAllGroupMessages() {
|
||||
return canReadAllGroupMessages;
|
||||
}
|
||||
|
||||
public Boolean getSupportInlineQueries() {
|
||||
return supportInlineQueries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@ -80,12 +100,16 @@ public class User implements BotApiObject {
|
||||
Objects.equals(isBot, user.isBot) &&
|
||||
Objects.equals(lastName, user.lastName) &&
|
||||
Objects.equals(userName, user.userName) &&
|
||||
Objects.equals(languageCode, user.languageCode);
|
||||
Objects.equals(languageCode, user.languageCode) &&
|
||||
Objects.equals(canJoinGroups, user.canJoinGroups) &&
|
||||
Objects.equals(canReadAllGroupMessages, user.canReadAllGroupMessages) &&
|
||||
Objects.equals(supportInlineQueries, user.supportInlineQueries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, firstName, isBot, lastName, userName, languageCode);
|
||||
return Objects.hash(id, firstName, isBot, lastName, userName, languageCode,
|
||||
canJoinGroups, canReadAllGroupMessages, supportInlineQueries);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -97,6 +121,9 @@ public class User implements BotApiObject {
|
||||
", lastName='" + lastName + '\'' +
|
||||
", userName='" + userName + '\'' +
|
||||
", languageCode='" + languageCode + '\'' +
|
||||
", canJoinGroups=" + canJoinGroups +
|
||||
", canReadAllGroupMessages=" + canReadAllGroupMessages +
|
||||
", supportInlineQueries=" + supportInlineQueries +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
@ -15,7 +16,12 @@ public class Poll implements BotApiObject {
|
||||
private static final String ID_FIELD = "id";
|
||||
private static final String QUESTION_FIELD = "question";
|
||||
private static final String OPTIONS_FIELD = "options";
|
||||
private static final String TOTALVOTERCOUNT_FIELD = "total_voter_count";
|
||||
private static final String ISCLOSED_FIELD = "is_closed";
|
||||
private static final String ISANONYMOUS_FIELD = "is_anonymous";
|
||||
private static final String TYPE_FIELD = "type";
|
||||
private static final String ALLOWSMULTIPLEANSWERS_FIELD = "allows_multiple_answers";
|
||||
private static final String CORRECTOPTIONID_FIELD = "correct_option_id";
|
||||
|
||||
@JsonProperty(ID_FIELD)
|
||||
private String id; ///< Unique poll identifier
|
||||
@ -23,8 +29,24 @@ public class Poll implements BotApiObject {
|
||||
private String question; ///< Poll question, 1-255 characters
|
||||
@JsonProperty(OPTIONS_FIELD)
|
||||
private List<PollOption> options; ///< List of poll options
|
||||
@JsonProperty(TOTALVOTERCOUNT_FIELD)
|
||||
private Integer totalVoterCount; ///< Total number of users that voted in the poll
|
||||
@JsonProperty(ISCLOSED_FIELD)
|
||||
private Boolean isClosed; ///< True, if the poll is closed
|
||||
@JsonProperty(ISANONYMOUS_FIELD)
|
||||
private Boolean isAnonymous; ///< True, if the poll is closed
|
||||
@JsonProperty(TYPE_FIELD)
|
||||
private String type; ///< Poll type, currently can be “regular” or “quiz”
|
||||
@JsonProperty(ALLOWSMULTIPLEANSWERS_FIELD)
|
||||
private Boolean allowMultipleAnswers; ///< True, if the poll allows multiple answers
|
||||
/**
|
||||
* Optional. 0-based identifier of the correct answer option.
|
||||
*
|
||||
* @apiNote Available only for polls in the quiz mode,
|
||||
* which are closed or was sent (not forwarded) to the private chat with the bot.
|
||||
*/
|
||||
@JsonProperty(CORRECTOPTIONID_FIELD)
|
||||
private Integer correctOptionId; ///< True, if the poll allows multiple answers
|
||||
|
||||
public Poll() {
|
||||
}
|
||||
@ -61,13 +83,79 @@ public class Poll implements BotApiObject {
|
||||
isClosed = closed;
|
||||
}
|
||||
|
||||
public Integer getTotalVoterCount() {
|
||||
return totalVoterCount;
|
||||
}
|
||||
|
||||
public void setTotalVoterCount(Integer totalVoterCount) {
|
||||
this.totalVoterCount = totalVoterCount;
|
||||
}
|
||||
|
||||
public Boolean getAnonymous() {
|
||||
return isAnonymous;
|
||||
}
|
||||
|
||||
public void setAnonymous(Boolean anonymous) {
|
||||
isAnonymous = anonymous;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Boolean getAllowMultipleAnswers() {
|
||||
return allowMultipleAnswers;
|
||||
}
|
||||
|
||||
public void setAllowMultipleAnswers(Boolean allowMultipleAnswers) {
|
||||
this.allowMultipleAnswers = allowMultipleAnswers;
|
||||
}
|
||||
|
||||
public Integer getCorrectOptionId() {
|
||||
return correctOptionId;
|
||||
}
|
||||
|
||||
public void setCorrectOptionId(Integer correctOptionId) {
|
||||
this.correctOptionId = correctOptionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Poll)) return false;
|
||||
Poll poll = (Poll) o;
|
||||
return Objects.equals(id, poll.id) &&
|
||||
Objects.equals(question, poll.question) &&
|
||||
Objects.equals(options, poll.options) &&
|
||||
Objects.equals(totalVoterCount, poll.totalVoterCount) &&
|
||||
Objects.equals(isClosed, poll.isClosed) &&
|
||||
Objects.equals(isAnonymous, poll.isAnonymous) &&
|
||||
Objects.equals(type, poll.type) &&
|
||||
Objects.equals(allowMultipleAnswers, poll.allowMultipleAnswers) &&
|
||||
Objects.equals(correctOptionId, poll.correctOptionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, question, options, totalVoterCount, isClosed, isAnonymous, type, allowMultipleAnswers, correctOptionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Poll{" +
|
||||
"id='" + id + '\'' +
|
||||
", question='" + question + '\'' +
|
||||
", options=" + options +
|
||||
", totalVoterCount=" + totalVoterCount +
|
||||
", isClosed=" + isClosed +
|
||||
", isAnonymous=" + isAnonymous +
|
||||
", type='" + type + '\'' +
|
||||
", allowMultipleAnswers=" + allowMultipleAnswers +
|
||||
", correctOptionId=" + correctOptionId +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
package org.telegram.telegrambots.meta.api.objects.polls;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
|
||||
import org.telegram.telegrambots.meta.api.objects.User;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 4.6
|
||||
*
|
||||
* This object represents an answer of a user in a non-anonymous poll.
|
||||
*/
|
||||
public class PollAnswer implements BotApiObject {
|
||||
private static final String POLLID_FIELD = "poll_id";
|
||||
private static final String USER_FIELD = "user";
|
||||
private static final String OPTIONIDS_FIELD = "option_ids";
|
||||
|
||||
@JsonProperty(POLLID_FIELD)
|
||||
private String pollId; ///< Unique poll identifier
|
||||
@JsonProperty(USER_FIELD)
|
||||
private User user; ///< The user, who changed the answer to the poll
|
||||
@JsonProperty(OPTIONIDS_FIELD)
|
||||
private List<Integer> optionIds; ///< 0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.
|
||||
|
||||
public PollAnswer() {
|
||||
}
|
||||
|
||||
public String getPollId() {
|
||||
return pollId;
|
||||
}
|
||||
|
||||
public void setPollId(String pollId) {
|
||||
this.pollId = pollId;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public List<Integer> getOptionIds() {
|
||||
return optionIds;
|
||||
}
|
||||
|
||||
public void setOptionIds(List<Integer> optionIds) {
|
||||
this.optionIds = optionIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PollAnswer)) return false;
|
||||
PollAnswer that = (PollAnswer) o;
|
||||
return Objects.equals(pollId, that.pollId) &&
|
||||
Objects.equals(user, that.user) &&
|
||||
Objects.equals(optionIds, that.optionIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(pollId, user, optionIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PollAnswer{" +
|
||||
"pollId='" + pollId + '\'' +
|
||||
", user=" + user +
|
||||
", optionIds=" + optionIds +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import org.telegram.telegrambots.meta.api.interfaces.InputBotApiObject;
|
||||
import org.telegram.telegrambots.meta.api.interfaces.Validable;
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
||||
@ -11,18 +10,21 @@ import java.util.Objects;
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* @brief This object represents one button of the reply keyboard. For simple text buttons String
|
||||
*
|
||||
* This object represents one button of the reply keyboard. For simple text buttons String
|
||||
* can be used instead of this object to specify text of the button.
|
||||
* @note Optional fields are mutually exclusive.
|
||||
* @note request_contact and request_location options will only work in Telegram versions released
|
||||
* @apiNote Optional fields are mutually exclusive.
|
||||
* @apiNote request_contact and request_location options will only work in Telegram versions released
|
||||
* after 9 April, 2016. Older clients will ignore them.
|
||||
* @date 10 of April of 2016
|
||||
* @apiNote request_poll option will only work in Telegram versions released after 1X January, 2020.
|
||||
* Older clients will receive unsupported message.
|
||||
*/
|
||||
public class KeyboardButton implements InputBotApiObject, Validable {
|
||||
|
||||
private static final String TEXT_FIELD = "text";
|
||||
private static final String REQUEST_CONTACT_FIELD = "request_contact";
|
||||
private static final String REQUEST_LOCATION_FIELD = "request_location";
|
||||
private static final String REQUEST_POLL_FIELD = "request_poll";
|
||||
/**
|
||||
* Text of the button.
|
||||
* If none of the optional fields are used, it will be sent to the bot as a message when the button is pressed
|
||||
@ -43,6 +45,13 @@ public class KeyboardButton implements InputBotApiObject, Validable {
|
||||
*/
|
||||
@JsonProperty(REQUEST_LOCATION_FIELD)
|
||||
private Boolean requestLocation;
|
||||
/**
|
||||
* Optional.
|
||||
* If specified, the user will be asked to create a poll and send it to the bot when the button is pressed.
|
||||
* Available in private chats only
|
||||
*/
|
||||
@JsonProperty(REQUEST_POLL_FIELD)
|
||||
private KeyboardButtonPollType requestPoll;
|
||||
|
||||
public KeyboardButton() {
|
||||
super();
|
||||
@ -80,6 +89,15 @@ public class KeyboardButton implements InputBotApiObject, Validable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public KeyboardButtonPollType getRequestPoll() {
|
||||
return requestPoll;
|
||||
}
|
||||
|
||||
public KeyboardButton setRequestPoll(KeyboardButtonPollType requestPoll) {
|
||||
this.requestPoll = requestPoll;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (text == null || text.isEmpty()) {
|
||||
@ -88,6 +106,12 @@ public class KeyboardButton implements InputBotApiObject, Validable {
|
||||
if (requestContact != null && requestLocation != null && requestContact && requestLocation) {
|
||||
throw new TelegramApiValidationException("Cant request contact and location at the same time", this);
|
||||
}
|
||||
if (requestContact != null && requestPoll != null && requestContact) {
|
||||
throw new TelegramApiValidationException("Cant request contact and poll at the same time", this);
|
||||
}
|
||||
if (requestLocation != null && requestPoll != null && requestLocation) {
|
||||
throw new TelegramApiValidationException("Cant request location and poll at the same time", this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -99,6 +123,7 @@ public class KeyboardButton implements InputBotApiObject, Validable {
|
||||
KeyboardButton keyboardButton = (KeyboardButton) o;
|
||||
return Objects.equals(requestContact, keyboardButton.requestContact)
|
||||
&& Objects.equals(requestLocation, keyboardButton.requestLocation)
|
||||
&& Objects.equals(requestPoll, keyboardButton.requestPoll)
|
||||
&& Objects.equals(text, keyboardButton.text)
|
||||
;
|
||||
}
|
||||
@ -108,6 +133,7 @@ public class KeyboardButton implements InputBotApiObject, Validable {
|
||||
return Objects.hash(
|
||||
requestContact,
|
||||
requestLocation,
|
||||
requestPoll,
|
||||
text);
|
||||
}
|
||||
|
||||
@ -117,6 +143,7 @@ public class KeyboardButton implements InputBotApiObject, Validable {
|
||||
"text=" + text +
|
||||
", requestContact=" + requestContact +
|
||||
", requestLocation=" + requestLocation +
|
||||
", requestPoll=" + requestPoll +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
package org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
|
||||
import org.telegram.telegrambots.meta.api.interfaces.Validable;
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 4.6
|
||||
*
|
||||
* This object represents type of a poll, which is allowed to be created and sent when the corresponding button is pressed.
|
||||
*/
|
||||
public class KeyboardButtonPollType implements BotApiObject, Validable {
|
||||
private static final String TYPE_FIELD = "type";
|
||||
|
||||
/**
|
||||
* Optional.
|
||||
*
|
||||
* If quiz is passed, the user will be allowed to create only polls in the quiz mode.
|
||||
* If regular is passed, only regular polls will be allowed.
|
||||
* Otherwise, the user will be allowed to create a poll of any type.
|
||||
*/
|
||||
@JsonProperty(TYPE_FIELD)
|
||||
private String type;
|
||||
|
||||
public KeyboardButtonPollType() {
|
||||
}
|
||||
|
||||
public KeyboardButtonPollType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws TelegramApiValidationException {
|
||||
if (type == null || type.isEmpty()) {
|
||||
throw new TelegramApiValidationException("Type parameter can't be empty", this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof KeyboardButtonPollType)) return false;
|
||||
KeyboardButtonPollType that = (KeyboardButtonPollType) o;
|
||||
return Objects.equals(type, that.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KeyboardButtonPollType{" +
|
||||
"type='" + type + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -17,35 +17,34 @@
|
||||
|
||||
package org.telegram.telegrambots.meta.exceptions;
|
||||
|
||||
import org.telegram.telegrambots.meta.api.interfaces.InputBotApiObject;
|
||||
import org.telegram.telegrambots.meta.api.interfaces.BotApiObject;
|
||||
import org.telegram.telegrambots.meta.api.methods.PartialBotApiMethod;
|
||||
|
||||
/**
|
||||
* @author Ruben Bermudez
|
||||
* @version 1.0
|
||||
* @brief Exception from method validations
|
||||
* @date 16 of September of 2016
|
||||
* Exception from method validations
|
||||
*/
|
||||
public class TelegramApiValidationException extends TelegramApiException {
|
||||
private PartialBotApiMethod method;
|
||||
private InputBotApiObject object;
|
||||
private BotApiObject object;
|
||||
|
||||
public TelegramApiValidationException(String message, PartialBotApiMethod method) {
|
||||
super(message);
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public TelegramApiValidationException(String message, InputBotApiObject object) {
|
||||
public TelegramApiValidationException(String message, BotApiObject object) {
|
||||
super(message);
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public PartialBotApiMethod getMethod() {
|
||||
return method;
|
||||
public BotApiObject getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
public InputBotApiObject getObject() {
|
||||
return object;
|
||||
public PartialBotApiMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots-spring-boot-starter</artifactId>
|
||||
@ -78,7 +78,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>Bots</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>telegrambots</artifactId>
|
||||
@ -95,7 +95,7 @@
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots-meta</artifactId>
|
||||
<version>4.5</version>
|
||||
<version>4.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
|
Loading…
Reference in New Issue
Block a user