initial commit

This commit is contained in:
2021-08-10 23:22:25 +03:00
commit 18465ada30
42 changed files with 1647 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
package ru.penkrat.stbf.impl.pengrad;
import static lombok.AccessLevel.PROTECTED;
import java.util.Optional;
import com.pengrad.telegrambot.model.CallbackQuery;
import com.pengrad.telegrambot.model.Contact;
import com.pengrad.telegrambot.model.Message;
import com.pengrad.telegrambot.model.Update;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import ru.penkrat.stbf.api.BotRequest;
@RequiredArgsConstructor
public class BotRequestImpl implements BotRequest {
@Getter(PROTECTED)
private final Update update;
@Override
public Optional<String> getMessageText() {
if (update.message() != null) {
return Optional.ofNullable(update.message().text());
}
return Optional.empty();
}
@Override
public Optional<String> getPhoneNumber() {
return Optional.of(update)
.map(Update::message)
.map(Message::contact)
.map(Contact::phoneNumber);
}
@Override
public Optional<String> getCallbackData() {
return Optional.of(update)
.map(Update::callbackQuery)
.map(CallbackQuery::data);
}
@Override
public Optional<String> getCallbackMessageText() {
return Optional.of(update)
.map(Update::callbackQuery)
.map(CallbackQuery::message)
.map(Message::text);
}
@Override
public Long getChatId() {
return Optional.of(update)
.map(Update::callbackQuery)
.map(CallbackQuery::message)
.orElseGet(() -> update.message()).chat().id();
}
}

View File

@@ -0,0 +1,151 @@
package ru.penkrat.stbf.impl.pengrad;
import java.lang.reflect.Field;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.gson.internal.reflect.ReflectionAccessor;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
import com.pengrad.telegrambot.model.request.InlineKeyboardMarkup;
import com.pengrad.telegrambot.model.request.KeyboardButton;
import com.pengrad.telegrambot.model.request.ParseMode;
import com.pengrad.telegrambot.model.request.ReplyKeyboardMarkup;
import com.pengrad.telegrambot.request.DeleteMessage;
import com.pengrad.telegrambot.request.EditMessageText;
import com.pengrad.telegrambot.request.SendDocument;
import com.pengrad.telegrambot.request.SendMessage;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import ru.penkrat.stbf.api.BotResponse;
import ru.penkrat.stbf.api.Screen;
@Slf4j
@RequiredArgsConstructor
public class BotResponseImpl implements BotResponse {
private final Update update;
private final TelegramBot telegramBot;
@Override
public void send(Screen screen) {
log.debug("Send message: \n============\n{}\n============", screen.getText().trim());
SendMessage sendMessage = new SendMessage(chatId(), screen.getText().trim())
.parseMode(screen.getScreenProperties().isParseModeHtml() ? ParseMode.HTML : ParseMode.MarkdownV2)
.disableWebPagePreview(screen.getScreenProperties().isDisableWebPagePreview())
.disableNotification(screen.getScreenProperties().isDisableNotification());
if (screen.getKeyboard() instanceof KeyboardImpl) {
KeyboardImpl kk = (KeyboardImpl) screen.getKeyboard();
KeyboardButton[][] keyboard = kk.getKeyboard();
InlineKeyboardButton[][] inlineKeyboard = kk.getInlineKeyboard();
if (inlineKeyboard != null && inlineKeyboard.length > 0) {
logKeyboard(inlineKeyboard);
sendMessage = sendMessage.replyMarkup(new InlineKeyboardMarkup(inlineKeyboard));
} else if (keyboard != null && keyboard.length > 0) {
logKeyboard(keyboard);
sendMessage = sendMessage.replyMarkup(new ReplyKeyboardMarkup(keyboard));
} else {
log.debug("No keyboard");
}
}
telegramBot.execute(sendMessage);
}
@Override
public void sendFile(String filename, byte[] data) {
telegramBot.execute(new SendDocument(chatId(), data).fileName(filename));
}
@Override
@Deprecated
public void editMessage(String text) {
telegramBot.execute(new EditMessageText(chatId(), messageId(), text)
.parseMode(ParseMode.HTML)
.disableWebPagePreview(true));
}
@Override
public void edit(Screen screen) {
EditMessageText editMessage = new EditMessageText(chatId(), messageId(), screen.getText())
.parseMode(screen.getScreenProperties().isParseModeHtml() ? ParseMode.HTML : ParseMode.MarkdownV2)
.disableWebPagePreview(screen.getScreenProperties().isDisableWebPagePreview());
if (screen.getKeyboard() instanceof KeyboardImpl) {
KeyboardImpl kk = (KeyboardImpl) screen.getKeyboard();
InlineKeyboardButton[][] inlineKeyboard = kk.getInlineKeyboard();
if (inlineKeyboard != null && inlineKeyboard.length > 0) {
logKeyboard(inlineKeyboard);
editMessage = editMessage.replyMarkup(new InlineKeyboardMarkup(inlineKeyboard));
} else {
log.debug("No keyboard");
}
}
telegramBot.execute(editMessage);
}
@Override
public void deleteMessage() {
telegramBot.execute(new DeleteMessage(chatId(), messageId()));
}
private Long chatId() {
if (update.callbackQuery() != null) {
return update.callbackQuery().message().chat().id();
}
return update.message().chat().id();
}
private Integer messageId() {
if (update.callbackQuery() != null) {
return update.callbackQuery().message().messageId();
}
return update.message().messageId();
}
private void logKeyboard(KeyboardButton[][] keyboard) {
if (log.isDebugEnabled()) {
for (int i = 0; i < keyboard.length; i++) {
if (keyboard[i].length > 0) {
String row = Stream.of(keyboard[i]).map(this::getText).collect(Collectors.joining(" | "));
log.debug("Keyboard: {}", row);
}
}
}
}
private void logKeyboard(InlineKeyboardButton[][] keyboard) {
if (log.isDebugEnabled()) {
for (int i = 0; i < keyboard.length; i++) {
if (keyboard[i].length > 0) {
String row = Stream.of(keyboard[i]).map(this::getText).collect(Collectors.joining(" | "));
log.debug("Inline keyboard: {}", row);
}
}
}
}
@SneakyThrows
private String getText(KeyboardButton btn) {
Field text = KeyboardButton.class.getDeclaredField("text");
ReflectionAccessor.getInstance().makeAccessible(text);
return String.valueOf(text.get(btn));
}
@SneakyThrows
private String getText(InlineKeyboardButton btn) {
Field text = InlineKeyboardButton.class.getDeclaredField("text");
ReflectionAccessor.getInstance().makeAccessible(text);
return String.valueOf(text.get(btn));
}
}

View File

@@ -0,0 +1,16 @@
package ru.penkrat.stbf.impl.pengrad;
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
import com.pengrad.telegrambot.model.request.KeyboardButton;
import lombok.Value;
import ru.penkrat.stbf.api.Keyboard;
@Value
class KeyboardImpl implements Keyboard {
private KeyboardButton[][] keyboard;
private InlineKeyboardButton[][] inlineKeyboard;
}

View File

@@ -0,0 +1,149 @@
package ru.penkrat.stbf.impl.pengrad;
import com.pengrad.telegrambot.model.request.InlineKeyboardButton;
import com.pengrad.telegrambot.model.request.KeyboardButton;
import ru.penkrat.stbf.api.Action;
import ru.penkrat.stbf.api.Keyboard;
import ru.penkrat.stbf.api.KeyboardBuilder;
public class PengradKeyboardBuilder implements KeyboardBuilder {
private KeyboardButton[][] keyboard;
private InlineKeyboardButton[][] inlineKeyboard;
public static Keyboard singleKey(Action action) {
return KeyboardBuilder.newKeyboard().add(action).build();
}
@Override
public Keyboard build() {
return new KeyboardImpl(keyboard, inlineKeyboard);
}
public KeyboardBuilder addGetContact(String text) {
put(new KeyboardButton(text).requestContact(true));
return self();
}
public KeyboardBuilder add(String text) {
put(new KeyboardButton(text));
return self();
}
@Override
public KeyboardBuilder add(Action action) {
put(action);
return self();
}
public KeyboardBuilder row(KeyboardButton... buttons) {
for (int i = 0; i < buttons.length; i++) {
put(buttons[i]);
}
nextRow();
return self();
}
@Override
public KeyboardBuilder row(Action... buttons) {
for (int i = 0; i < buttons.length; i++) {
put(buttons[i]);
}
nextRow();
return self();
}
@Override
public KeyboardBuilder column(Action... buttons) {
for (int i = 0; i < buttons.length; i++) {
put(buttons[i]);
if (buttons[i].isInline()) {
nextRowI();
} else {
nextRow();
}
}
return self();
}
public KeyboardBuilder addNl(String text) {
add(text);
nextRow();
return self();
}
public PengradKeyboardBuilder add(String text, String data) {
put(new InlineKeyboardButton(text).callbackData(data));
return self();
}
public KeyboardBuilder addNl(String text, String data) {
add(text, data);
nextRowI();
return self();
}
private void nextRow() {
KeyboardButton[][] n = new KeyboardButton[keyboard.length + 1][];
System.arraycopy(keyboard, 0, n, 0, keyboard.length);
keyboard = n;
keyboard[keyboard.length - 1] = new KeyboardButton[] {};
}
private void nextRowI() {
InlineKeyboardButton[][] n = new InlineKeyboardButton[inlineKeyboard.length + 1][];
System.arraycopy(inlineKeyboard, 0, n, 0, inlineKeyboard.length);
inlineKeyboard = n;
inlineKeyboard[inlineKeyboard.length - 1] = new InlineKeyboardButton[] {};
}
protected PengradKeyboardBuilder self() {
return this;
}
private void put(Action action) {
if (action.isInline()) {
put(new InlineKeyboardButton(action.getText()).callbackData(action.getCallbackData()));
} else {
put(new KeyboardButton(action.getText()).requestContact(action.isRequestContact()));
}
}
private void put(KeyboardButton btn) {
if (keyboard == null) {
keyboard = new KeyboardButton[][] {
new KeyboardButton[] { btn }
};
} else {
KeyboardButton[] k = keyboard[keyboard.length - 1];
KeyboardButton[] n = new KeyboardButton[k.length + 1];
System.arraycopy(k, 0, n, 0, k.length);
n[k.length] = btn;
keyboard[keyboard.length - 1] = n;
}
}
private void put(InlineKeyboardButton btn) {
if (inlineKeyboard == null) {
inlineKeyboard = new InlineKeyboardButton[][] {
new InlineKeyboardButton[] { btn }
};
} else {
InlineKeyboardButton[] k = inlineKeyboard[inlineKeyboard.length - 1];
InlineKeyboardButton[] n = new InlineKeyboardButton[k.length + 1];
System.arraycopy(k, 0, n, 0, k.length);
n[k.length] = btn;
inlineKeyboard[inlineKeyboard.length - 1] = n;
}
}
@Override
public KeyboardBuilder newInstance() {
return new PengradKeyboardBuilder();
}
}

View File

@@ -0,0 +1,35 @@
package ru.penkrat.stbf.impl.pengrad;
import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.UpdatesListener;
import com.pengrad.telegrambot.model.Update;
import lombok.extern.slf4j.Slf4j;
import ru.penkrat.stbf.api.CommandChain;
@Slf4j
public class PengradTelegramBot extends TelegramBot implements AutoCloseable {
public PengradTelegramBot(String botToken, CommandChain commandChain) {
super(botToken);
this.setUpdatesListener(updates -> {
for (Update update : updates) {
try {
commandChain.processCommand(
new BotRequestImpl(update),
new BotResponseImpl(update, this));
} catch (Exception e) {
log.error("Bot Error:", e);
}
}
return UpdatesListener.CONFIRMED_UPDATES_ALL;
});
}
@Override
public void close() throws Exception {
removeGetUpdatesListener();
log.debug("Bot closed.");
}
}

View File

@@ -0,0 +1 @@
ru.penkrat.stbf.impl.pengrad.PengradKeyboardBuilder