From bf8ba844cf8245aee4f089e165c45ccadde8b38c Mon Sep 17 00:00:00 2001 From: Struchkov Mark Date: Tue, 19 Jul 2022 20:37:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=B7=D0=B0=D0=B3=D1=80?= =?UTF-8?q?=D1=83=D0=B7=D0=BA=D0=B8=20=D1=84=D0=BE=D1=82=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 4 +- telegram-core/pom.xml | 2 +- .../telegram/convert/MessageMailConvert.java | 47 ++++ .../domain/attachment/ContactAttachment.java | 71 ++++++ .../telegram/domain/attachment/Picture.java | 51 ++++ .../attachment/PictureGroupAttachment.java | 31 +++ .../attachment/TelegramAttachmentType.java | 4 +- .../domain/keyboard/InlineKeyBoard.java | 18 +- .../domain/keyboard/MarkupKeyBoard.java | 23 +- .../domain/keyboard/button/ContactButton.java | 27 +++ .../button/{ButtonUrl.java => UrlButton.java} | 8 +- .../{ButtonWebApp.java => WebAppButton.java} | 8 +- .../telegram/listen/TelegramSender.java | 226 ------------------ .../service/AttachmentServiceImpl.java | 35 ++- .../telegram/service/TelegramSender.java | 102 ++++++++ .../godfather/telegram/utils/Attachments.java | 47 ++++ .../telegram/utils/InlineKeyBoards.java | 14 +- .../telegram/utils/KeyBoardConvert.java | 152 ++++++++++++ 18 files changed, 610 insertions(+), 260 deletions(-) create mode 100644 telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/ContactAttachment.java create mode 100644 telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/Picture.java create mode 100644 telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/PictureGroupAttachment.java create mode 100644 telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ContactButton.java rename telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/{ButtonUrl.java => UrlButton.java} (70%) rename telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/{ButtonWebApp.java => WebAppButton.java} (70%) delete mode 100644 telegram-core/src/main/java/dev/struchkov/godfather/telegram/listen/TelegramSender.java create mode 100644 telegram-core/src/main/java/dev/struchkov/godfather/telegram/service/TelegramSender.java create mode 100644 telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/KeyBoardConvert.java diff --git a/pom.xml b/pom.xml index b4491c5..781b8ca 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ dev.struchkov.godfather telegram-bot - 0.0.15 + 0.0.17 pom @@ -33,7 +33,7 @@ UTF-8 UTF-8 - 0.0.12 + 0.0.14 6.1.0 3.10.1 diff --git a/telegram-core/pom.xml b/telegram-core/pom.xml index 50d49e3..8a725ec 100644 --- a/telegram-core/pom.xml +++ b/telegram-core/pom.xml @@ -5,7 +5,7 @@ dev.struchkov.godfather telegram-bot - 0.0.15 + 0.0.17 telegram-core diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/convert/MessageMailConvert.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/convert/MessageMailConvert.java index 05a74bd..36b9e6d 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/convert/MessageMailConvert.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/convert/MessageMailConvert.java @@ -2,10 +2,15 @@ package dev.struchkov.godfather.telegram.convert; import dev.struchkov.godfather.context.domain.content.Mail; import dev.struchkov.godfather.context.domain.content.attachment.Attachment; +import dev.struchkov.godfather.telegram.domain.attachment.ContactAttachment; import dev.struchkov.godfather.telegram.domain.attachment.DocumentAttachment; +import dev.struchkov.godfather.telegram.domain.attachment.Picture; +import dev.struchkov.godfather.telegram.domain.attachment.PictureGroupAttachment; +import org.telegram.telegrambots.meta.api.objects.Contact; import org.telegram.telegrambots.meta.api.objects.Document; import org.telegram.telegrambots.meta.api.objects.Message; import org.telegram.telegrambots.meta.api.objects.MessageEntity; +import org.telegram.telegrambots.meta.api.objects.PhotoSize; import java.time.Instant; import java.time.LocalDateTime; @@ -38,6 +43,8 @@ public final class MessageMailConvert { mail.setLastName(message.getChat().getLastName()); convertDocument(message.getDocument()).ifPresent(mail::addAttachment); + convertContact(message.getContact()).ifPresent(mail::addAttachment); + convertPhoto(message.getPhoto()).ifPresent(mail::addAttachment); final List entities = message.getEntities(); if (entities != null) { @@ -51,6 +58,46 @@ public final class MessageMailConvert { return mail; } + private static Optional convertPhoto(List photoSizes) { + if (photoSizes != null && !photoSizes.isEmpty()) { + final PictureGroupAttachment attachment = new PictureGroupAttachment(); + + final List pictures = photoSizes.stream() + .map(photoSize -> { + final Picture picture = new Picture(); + picture.setFileSize(photoSize.getFileSize()); + picture.setFileId(photoSize.getFileId()); + picture.setHeight(photoSize.getHeight()); + picture.setWeight(photoSize.getWidth()); + picture.setFileUniqueId(photoSize.getFileUniqueId()); + return picture; + }).toList(); + + attachment.setPictureSizes(pictures); + + return Optional.of(attachment); + } + return Optional.empty(); + } + + private static Optional convertContact(Contact contact) { + if (contact != null) { + final ContactAttachment attachment = new ContactAttachment(); + attachment.setPhoneNumber(contact.getPhoneNumber()); + attachment.setUserId(contact.getUserId()); + attachment.setFirstName(contact.getFirstName()); + attachment.setLastName(contact.getLastName()); + if (contact.getVCard() != null) { + attachment.setOwner(false); + attachment.setVCard(contact.getVCard()); + } else { + attachment.setOwner(true); + } + return Optional.of(attachment); + } + return Optional.empty(); + } + private static Optional convertDocument(Document document) { if (document != null) { final DocumentAttachment attachment = new DocumentAttachment(); diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/ContactAttachment.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/ContactAttachment.java new file mode 100644 index 0000000..c2ade6a --- /dev/null +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/ContactAttachment.java @@ -0,0 +1,71 @@ +package dev.struchkov.godfather.telegram.domain.attachment; + +import dev.struchkov.godfather.context.domain.content.attachment.Attachment; + +public class ContactAttachment extends Attachment { + + private String phoneNumber; + private String firstName; + private String lastName; + private Long userId; + private String vCard; + + /** + * если true, то контакт принадлежит отправившему телеграм аккаунту. + */ + private boolean owner; + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public boolean isOwner() { + return owner; + } + + public void setOwner(boolean owner) { + this.owner = owner; + } + + public String getVCard() { + return vCard; + } + + public void setVCard(String vCard) { + this.vCard = vCard; + } + + @Override + public String getType() { + return TelegramAttachmentType.CONTACT.name(); + } + +} diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/Picture.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/Picture.java new file mode 100644 index 0000000..7fbeb15 --- /dev/null +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/Picture.java @@ -0,0 +1,51 @@ +package dev.struchkov.godfather.telegram.domain.attachment; + +public class Picture { + + private String fileId; + private String fileUniqueId; + private Integer fileSize; + private Integer weight; + private Integer height; + + public String getFileId() { + return fileId; + } + + public void setFileId(String fileId) { + this.fileId = fileId; + } + + public String getFileUniqueId() { + return fileUniqueId; + } + + public void setFileUniqueId(String fileUniqueId) { + this.fileUniqueId = fileUniqueId; + } + + public Integer getFileSize() { + return fileSize; + } + + public void setFileSize(Integer fileSize) { + this.fileSize = fileSize; + } + + public Integer getWeight() { + return weight; + } + + public void setWeight(Integer weight) { + this.weight = weight; + } + + public Integer getHeight() { + return height; + } + + public void setHeight(Integer height) { + this.height = height; + } + +} diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/PictureGroupAttachment.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/PictureGroupAttachment.java new file mode 100644 index 0000000..be367d2 --- /dev/null +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/PictureGroupAttachment.java @@ -0,0 +1,31 @@ +package dev.struchkov.godfather.telegram.domain.attachment; + +import dev.struchkov.godfather.context.domain.content.attachment.Attachment; + +import java.util.Comparator; +import java.util.List; +import java.util.Optional; + +public class PictureGroupAttachment extends Attachment { + + private List pictures; + + public void setPictureSizes(List pictures) { + this.pictures = pictures; + } + + public List getPictureSizes() { + return pictures; + } + + public Optional getLargePicture() { + return pictures.stream() + .max(Comparator.comparingInt(Picture::getFileSize)); + } + + @Override + public String getType() { + return TelegramAttachmentType.PICTURE.name(); + } + +} diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/TelegramAttachmentType.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/TelegramAttachmentType.java index 0789133..71a4b66 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/TelegramAttachmentType.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/attachment/TelegramAttachmentType.java @@ -2,6 +2,8 @@ package dev.struchkov.godfather.telegram.domain.attachment; public enum TelegramAttachmentType { - DOCUMENT + DOCUMENT, + CONTACT, + PICTURE } diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/InlineKeyBoard.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/InlineKeyBoard.java index c89b9db..fc87c63 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/InlineKeyBoard.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/InlineKeyBoard.java @@ -1,15 +1,19 @@ package dev.struchkov.godfather.telegram.domain.keyboard; import dev.struchkov.godfather.context.domain.keyboard.KeyBoard; +import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton; import dev.struchkov.godfather.context.domain.keyboard.KeyBoardLine; import java.util.ArrayList; import java.util.List; +import static dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoardLine.simpleLine; + public class InlineKeyBoard implements KeyBoard { public static final String TYPE = "INLINE"; - protected List lines = new ArrayList<>(); + + protected List lines; public InlineKeyBoard(List lines) { this.lines = lines; @@ -23,8 +27,16 @@ public class InlineKeyBoard implements KeyBoard { return new Builder(); } - public static InlineKeyBoard inlineKeyBoard(KeyBoardLine keyBoardLine) { - return builder().line(keyBoardLine).build(); + public static InlineKeyBoard inlineKeyBoard(KeyBoardLine... keyBoardLine) { + final Builder builder = builder(); + for (KeyBoardLine boardLine : keyBoardLine) { + builder.line(boardLine); + } + return builder.build(); + } + + public static InlineKeyBoard inlineKeyBoard(KeyBoardButton... buttons) { + return builder().line(simpleLine(buttons)).build(); } public List getLines() { diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/MarkupKeyBoard.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/MarkupKeyBoard.java index bcd348d..6657ef2 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/MarkupKeyBoard.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/MarkupKeyBoard.java @@ -4,16 +4,17 @@ import dev.struchkov.godfather.context.domain.keyboard.KeyBoardLine; import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoard; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class MarkupKeyBoard extends SimpleKeyBoard { public static final String TYPE = "MARKUP"; - + private static final MarkupKeyBoard EMPTY = new MarkupKeyBoard(); /** * Скрыть меню после ответа или нет. */ - private boolean oneTime = true; + private boolean oneTime; /** * Изменяет размер клавиатуры по вертикали для оптимального соответствия (например, сделать клавиатуру меньше, если есть только два ряда кнопок). @@ -22,6 +23,10 @@ public class MarkupKeyBoard extends SimpleKeyBoard { private String inputFieldPlaceholder; + public MarkupKeyBoard() { + super(Collections.emptyList()); + } + private MarkupKeyBoard(Builder builder) { super(builder.lines); oneTime = builder.oneTime; @@ -29,10 +34,14 @@ public class MarkupKeyBoard extends SimpleKeyBoard { inputFieldPlaceholder = builder.inputFieldPlaceholder; } - public static Builder newBuilder() { + public static Builder markupBuilder() { return new Builder(); } + public static MarkupKeyBoard empty() { + return EMPTY; + } + public boolean isResizeKeyboard() { return resizeKeyboard; } @@ -50,6 +59,14 @@ public class MarkupKeyBoard extends SimpleKeyBoard { return TYPE; } + public boolean isEmpty() { + return lines.isEmpty(); + } + + public boolean isNotEmpty() { + return !lines.isEmpty(); + } + public static final class Builder { private List lines = new ArrayList<>(); private boolean oneTime = true; diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ContactButton.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ContactButton.java new file mode 100644 index 0000000..d7a03c2 --- /dev/null +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ContactButton.java @@ -0,0 +1,27 @@ +package dev.struchkov.godfather.telegram.domain.keyboard.button; + +import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton; + +/** + * Запрашивает у пользователя его контактный номер. + */ +public class ContactButton implements KeyBoardButton { + + public static final String TYPE = "CONTACT"; + + private final String label; + + public ContactButton(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } + + @Override + public String getType() { + return TYPE; + } + +} diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ButtonUrl.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/UrlButton.java similarity index 70% rename from telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ButtonUrl.java rename to telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/UrlButton.java index 28f815a..c45e839 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ButtonUrl.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/UrlButton.java @@ -2,20 +2,20 @@ package dev.struchkov.godfather.telegram.domain.keyboard.button; import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton; -public class ButtonUrl implements KeyBoardButton { +public class UrlButton implements KeyBoardButton { public static final String TYPE = "URL"; private String label; private String url; - public ButtonUrl(String label, String url) { + public UrlButton(String label, String url) { this.label = label; this.url = url; } - public static ButtonUrl buttonUrl(String label, String url) { - return new ButtonUrl(label, url); + public static UrlButton buttonUrl(String label, String url) { + return new UrlButton(label, url); } @Override diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ButtonWebApp.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/WebAppButton.java similarity index 70% rename from telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ButtonWebApp.java rename to telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/WebAppButton.java index 1a24a8c..a2368de 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/ButtonWebApp.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/domain/keyboard/button/WebAppButton.java @@ -2,20 +2,20 @@ package dev.struchkov.godfather.telegram.domain.keyboard.button; import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton; -public class ButtonWebApp implements KeyBoardButton { +public class WebAppButton implements KeyBoardButton { public static final String TYPE = "WEB_APP"; private final String label; private final String url; - public ButtonWebApp(String label, String url) { + public WebAppButton(String label, String url) { this.label = label; this.url = url; } - public static ButtonWebApp buttonWebApp(String label, String url) { - return new ButtonWebApp(label, url); + public static WebAppButton buttonWebApp(String label, String url) { + return new WebAppButton(label, url); } public String getUrl() { diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/listen/TelegramSender.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/listen/TelegramSender.java deleted file mode 100644 index e1e17a2..0000000 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/listen/TelegramSender.java +++ /dev/null @@ -1,226 +0,0 @@ -package dev.struchkov.godfather.telegram.listen; - -import dev.struchkov.godfather.context.domain.BoxAnswer; -import dev.struchkov.godfather.context.domain.keyboard.KeyBoard; -import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton; -import dev.struchkov.godfather.context.domain.keyboard.KeyBoardLine; -import dev.struchkov.godfather.context.domain.keyboard.button.SimpleButton; -import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoard; -import dev.struchkov.godfather.context.service.sender.SendType; -import dev.struchkov.godfather.context.service.sender.Sending; -import dev.struchkov.godfather.telegram.TelegramConnect; -import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard; -import dev.struchkov.godfather.telegram.domain.keyboard.MarkupKeyBoard; -import dev.struchkov.godfather.telegram.domain.keyboard.button.ButtonUrl; -import dev.struchkov.godfather.telegram.domain.keyboard.button.ButtonWebApp; -import dev.struchkov.godfather.telegram.service.SendPreProcessing; -import dev.struchkov.haiti.context.exception.ConvertException; -import dev.struchkov.haiti.utils.Inspector; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.telegram.telegrambots.meta.api.methods.send.SendMessage; -import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText; -import org.telegram.telegrambots.meta.api.objects.Message; -import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup; -import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard; -import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup; -import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton; -import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardButton; -import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardRow; -import org.telegram.telegrambots.meta.api.objects.webapp.WebAppInfo; -import org.telegram.telegrambots.meta.bots.AbsSender; -import org.telegram.telegrambots.meta.exceptions.TelegramApiException; -import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static dev.struchkov.haiti.utils.Inspector.isNotNull; - -/** - * TODO: Добавить описание класса. - * - * @author upagge [15/07/2019] - */ -public class TelegramSender implements Sending { - - private static final Logger log = LoggerFactory.getLogger(TelegramSender.class); - - private static final String ERROR_REPLACE_MESSAGE = "Bad Request: message to edit not found"; - - private final AbsSender absSender; - private Map map = new HashMap<>(); - - private SendPreProcessing sendPreProcessing; - - public TelegramSender(TelegramConnect telegramConnect) { - this.absSender = telegramConnect.getAdsSender(); - } - - public void setSendPreProcessing(SendPreProcessing sendPreProcessing) { - this.sendPreProcessing = sendPreProcessing; - } - - public void send(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) { - isNotNull(telegramId, boxAnswer); - try { - if (boxAnswer.isReplace() && map.containsKey(telegramId)) { - replaceMessage(telegramId, boxAnswer); - } else { - sendMessage(telegramId, boxAnswer); - } - } catch (TelegramApiRequestException e) { - log.error(e.getApiResponse()); - if (ERROR_REPLACE_MESSAGE.equals(e.getApiResponse())) { - sendMessage(telegramId, boxAnswer); - } - } catch (TelegramApiException e) { - log.error(e.getMessage()); - } - } - - private void replaceMessage(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) throws TelegramApiException { - final EditMessageText editMessageText = new EditMessageText(); - editMessageText.setChatId(String.valueOf(telegramId)); - editMessageText.setMessageId(map.get(telegramId)); - editMessageText.enableMarkdown(true); - editMessageText.setText(boxAnswer.getMessage()); - editMessageText.setReplyMarkup(convertInlineKeyBoard((InlineKeyBoard) boxAnswer.getKeyBoard())); - absSender.execute(editMessageText); - } - - private void sendMessage(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) { - final SendMessage sendMessage = new SendMessage(); - sendMessage.enableMarkdown(true); - sendMessage.setChatId(String.valueOf(telegramId)); - sendMessage.setText( - sendPreProcessing != null - ? sendPreProcessing.pretreatment(boxAnswer.getMessage()) - : boxAnswer.getMessage() - ); - sendMessage.setReplyMarkup(convertKeyBoard(boxAnswer.getKeyBoard())); - try { - final Message execute = absSender.execute(sendMessage); - - map.put(telegramId, execute.getMessageId()); - } catch (TelegramApiRequestException e) { - log.error(e.getApiResponse()); - } catch (TelegramApiException e) { - log.error(e.getMessage()); - } - } - - private ReplyKeyboard convertKeyBoard(KeyBoard keyBoard) { - if (keyBoard != null) { - switch (keyBoard.getType()) { - case InlineKeyBoard.TYPE: - return convertInlineKeyBoard((InlineKeyBoard) keyBoard); - case MarkupKeyBoard.TYPE: - return convertMarkupKeyBoard((MarkupKeyBoard) keyBoard); - case SimpleKeyBoard.TYPE: - return convertSimpleKeyBoard((SimpleKeyBoard) keyBoard); - } - } - return null; - } - - private ReplyKeyboard convertSimpleKeyBoard(SimpleKeyBoard keyBoard) { - final ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup(); - keyboardMarkup.setKeyboard( - keyBoard.getLines().stream() - .map(this::convertMarkupLine) - .toList() - ); - return keyboardMarkup; - } - - private ReplyKeyboard convertMarkupKeyBoard(MarkupKeyBoard keyBoard) { - if (keyBoard != null) { - final ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup(); - keyboardMarkup.setOneTimeKeyboard(keyBoard.isOneTime()); - keyboardMarkup.setInputFieldPlaceholder(keyBoard.getInputFieldPlaceholder()); - keyboardMarkup.setResizeKeyboard(keyBoard.isResizeKeyboard()); - keyboardMarkup.setKeyboard( - keyBoard.getLines().stream() - .map(this::convertMarkupLine) - .toList() - ); - return keyboardMarkup; - } - return null; - } - - private InlineKeyboardMarkup convertInlineKeyBoard(InlineKeyBoard keyBoard) { - if (keyBoard != null) { - final InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup(); - inlineKeyboardMarkup.setKeyboard( - keyBoard.getLines().stream() - .map(this::convertInlineLine) - .toList() - ); - return inlineKeyboardMarkup; - } - return null; - } - - private List convertInlineLine(KeyBoardLine line) { - return line.getButtons().stream().map(this::convertInlineButton).toList(); - } - - private KeyboardRow convertMarkupLine(KeyBoardLine line) { - final List buttons = line.getButtons().stream().map(this::convertMarkupButton).toList(); - return new KeyboardRow(buttons); - } - - private InlineKeyboardButton convertInlineButton(KeyBoardButton keyBoardButton) { - final InlineKeyboardButton button = new InlineKeyboardButton(); - switch (keyBoardButton.getType()) { - case SimpleButton.TYPE -> { - final SimpleButton simpleButton = (SimpleButton) keyBoardButton; - final String callbackData = simpleButton.getCallbackData(); - final String label = simpleButton.getLabel(); - button.setText(label); - button.setCallbackData(callbackData != null ? callbackData : label); - } - case ButtonUrl.TYPE -> { - final ButtonUrl buttonUrl = (ButtonUrl) keyBoardButton; - button.setUrl(buttonUrl.getUrl()); - button.setText(buttonUrl.getLabel()); - } - case ButtonWebApp.TYPE -> { - final ButtonWebApp buttonWebApp = (ButtonWebApp) keyBoardButton; - final WebAppInfo webAppInfo = WebAppInfo.builder().url(buttonWebApp.getUrl()).build(); - button.setWebApp(webAppInfo); - button.setText(buttonWebApp.getLabel()); - } - default -> throw new ConvertException("Ошибка преобразования кнопки"); - } - return button; - } - - private KeyboardButton convertMarkupButton(KeyBoardButton keyBoardButton) { - final KeyboardButton button = new KeyboardButton(); - switch (keyBoardButton.getType()) { - case SimpleButton.TYPE -> { - final SimpleButton simpleButton = (SimpleButton) keyBoardButton; - button.setText(simpleButton.getLabel()); - Inspector.isNull(simpleButton.getCallbackData(), ConvertException.supplier("CallbackData поддерживает только Inline клавитаура")); - } - case ButtonWebApp.TYPE -> { - final ButtonWebApp buttonWebApp = (ButtonWebApp) keyBoardButton; - final WebAppInfo webAppInfo = WebAppInfo.builder().url(buttonWebApp.getUrl()).build(); - button.setText(buttonWebApp.getLabel()); - button.setWebApp(webAppInfo); - } - default -> throw new ConvertException("Ошибка преобразования кнопки"); - } - return button; - } - - public SendType getType() { - return SendType.PRIVATE; - } - -} diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/service/AttachmentServiceImpl.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/service/AttachmentServiceImpl.java index 50428fe..9dd00e7 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/service/AttachmentServiceImpl.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/service/AttachmentServiceImpl.java @@ -2,6 +2,7 @@ package dev.struchkov.godfather.telegram.service; import dev.struchkov.godfather.telegram.TelegramConnect; import dev.struchkov.godfather.telegram.domain.attachment.DocumentAttachment; +import dev.struchkov.godfather.telegram.domain.attachment.Picture; import dev.struchkov.godfather.telegram.domain.files.ByteContainer; import dev.struchkov.godfather.telegram.domain.files.FileContainer; import org.apache.commons.io.FileUtils; @@ -78,14 +79,32 @@ public class AttachmentServiceImpl { return ByteContainer.empty(); } + public ByteContainer uploadBytes(@NotNull Picture picture) { + isNotNull(picture); + try { + final byte[] bytes = downloadBytes(picture); + return new ByteContainer(null, bytes); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return ByteContainer.empty(); + } + + private byte[] downloadBytes(Picture picture) throws TelegramApiException, IOException { + return telegramDownloadBytes(picture.getFileId()); + } + private byte[] downloadBytes(DocumentAttachment documentAttachment) throws TelegramApiException, IOException { - final org.telegram.telegrambots.meta.api.objects.File file = getFilePath(documentAttachment); - final URL url = new URL(file.getFileUrl(botToken)); - return IOUtils.toByteArray(url); + return telegramDownloadBytes(documentAttachment.getFileId()); + } + + private byte[] telegramDownloadBytes(String fileId) throws TelegramApiException, IOException { + final String fileUrl = getFileUrl(fileId); + return IOUtils.toByteArray(new URL(fileUrl)); } private File downloadFile(DocumentAttachment documentAttachment) throws IOException, TelegramApiException { - final org.telegram.telegrambots.meta.api.objects.File file = getFilePath(documentAttachment); + final String fileUrl = getFileUrl(documentAttachment.getFileId()); final StringBuilder filePath = new StringBuilder(); if (folderPathForFiles != null) { @@ -96,15 +115,15 @@ public class AttachmentServiceImpl { filePath.append(documentAttachment.getFileName()); final java.io.File localFile = new java.io.File(filePath.toString()); - final InputStream is = new URL(file.getFileUrl(botToken)).openStream(); + final InputStream is = new URL(fileUrl).openStream(); FileUtils.copyInputStreamToFile(is, localFile); return localFile; } - private org.telegram.telegrambots.meta.api.objects.File getFilePath(DocumentAttachment documentAttachment) throws TelegramApiException { + private String getFileUrl(String fileId) throws TelegramApiException { final GetFile getFile = new GetFile(); - getFile.setFileId(documentAttachment.getFileId()); - return absSender.execute(getFile); + getFile.setFileId(fileId); + return absSender.execute(getFile).getFileUrl(botToken); } } diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/service/TelegramSender.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/service/TelegramSender.java new file mode 100644 index 0000000..f1fc936 --- /dev/null +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/service/TelegramSender.java @@ -0,0 +1,102 @@ +package dev.struchkov.godfather.telegram.service; + +import dev.struchkov.godfather.context.domain.BoxAnswer; +import dev.struchkov.godfather.context.service.sender.SendType; +import dev.struchkov.godfather.context.service.sender.Sending; +import dev.struchkov.godfather.telegram.TelegramConnect; +import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.api.methods.updatingmessages.EditMessageText; +import org.telegram.telegrambots.meta.api.objects.Message; +import org.telegram.telegrambots.meta.bots.AbsSender; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; +import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException; + +import java.util.HashMap; +import java.util.Map; + +import static dev.struchkov.godfather.telegram.utils.KeyBoardConvert.convertInlineKeyBoard; +import static dev.struchkov.godfather.telegram.utils.KeyBoardConvert.convertKeyBoard; +import static dev.struchkov.haiti.utils.Inspector.isNotNull; + +public class TelegramSender implements Sending { + + private static final Logger log = LoggerFactory.getLogger(TelegramSender.class); + + private static final String ERROR_REPLACE_MESSAGE = "Bad Request: message to edit not found"; + + private final AbsSender absSender; + private Map map = new HashMap<>(); + + private SendPreProcessing sendPreProcessing; + + public TelegramSender(TelegramConnect telegramConnect) { + this.absSender = telegramConnect.getAdsSender(); + } + + public void setSendPreProcessing(SendPreProcessing sendPreProcessing) { + this.sendPreProcessing = sendPreProcessing; + } + + public void send(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) { + isNotNull(telegramId, boxAnswer); + if (boxAnswer.getMessage() != null && !boxAnswer.getMessage().isBlank()) { + try { + if (boxAnswer.isReplace() && map.containsKey(telegramId)) { + replaceMessage(telegramId, boxAnswer); + } else { + sendMessage(telegramId, boxAnswer); + } + } catch (TelegramApiRequestException e) { + log.error(e.getApiResponse()); + if (ERROR_REPLACE_MESSAGE.equals(e.getApiResponse())) { + sendMessage(telegramId, boxAnswer); + } + } catch (TelegramApiException e) { + log.error(e.getMessage()); + } + } else { + log.warn("Сообщение не было отправлено, так как текст сообщения был пустым"); + } + } + + private void replaceMessage(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) throws TelegramApiException { + final EditMessageText editMessageText = new EditMessageText(); + editMessageText.setChatId(String.valueOf(telegramId)); + editMessageText.setMessageId(map.get(telegramId)); + editMessageText.enableMarkdown(true); + editMessageText.setText(boxAnswer.getMessage()); + editMessageText.setReplyMarkup(convertInlineKeyBoard((InlineKeyBoard) boxAnswer.getKeyBoard())); + absSender.execute(editMessageText); + } + + private void sendMessage(@NotNull Long telegramId, @NotNull BoxAnswer boxAnswer) { + final SendMessage sendMessage = new SendMessage(); + sendMessage.enableMarkdown(true); + sendMessage.setChatId(String.valueOf(telegramId)); + sendMessage.setText( + sendPreProcessing != null + ? sendPreProcessing.pretreatment(boxAnswer.getMessage()) + : boxAnswer.getMessage() + ); + sendMessage.setReplyMarkup(convertKeyBoard(boxAnswer.getKeyBoard())); + try { + final Message execute = absSender.execute(sendMessage); + + map.put(telegramId, execute.getMessageId()); + } catch (TelegramApiRequestException e) { + log.error(e.getApiResponse()); + } catch (TelegramApiException e) { + log.error(e.getMessage()); + } + + } + + public SendType getType() { + return SendType.PRIVATE; + } + +} diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/Attachments.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/Attachments.java index e4e0706..2431693 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/Attachments.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/Attachments.java @@ -1,7 +1,10 @@ package dev.struchkov.godfather.telegram.utils; import dev.struchkov.godfather.context.domain.content.attachment.Attachment; +import dev.struchkov.godfather.telegram.domain.attachment.ContactAttachment; import dev.struchkov.godfather.telegram.domain.attachment.DocumentAttachment; +import dev.struchkov.godfather.telegram.domain.attachment.Picture; +import dev.struchkov.godfather.telegram.domain.attachment.PictureGroupAttachment; import dev.struchkov.godfather.telegram.domain.attachment.TelegramAttachmentType; import dev.struchkov.haiti.utils.Inspector; @@ -16,6 +19,29 @@ public final class Attachments { utilityClass(); } + public static Optional findFirstPictureGroup(Collection attachments) { + if (attachments != null) { + for (Attachment attachment : attachments) { + if (isPictureGroup(attachment)) { + return Optional.ofNullable((PictureGroupAttachment) attachment); + } + } + } + return Optional.empty(); + } + + public static Optional findFirstLargePicture(Collection attachments) { + if (attachments != null) { + for (Attachment attachment : attachments) { + if (isPictureGroup(attachment)) { + final PictureGroupAttachment pictureGroup = (PictureGroupAttachment) attachment; + return pictureGroup.getLargePicture(); + } + } + } + return Optional.empty(); + } + public static Optional findFirstDocument(Collection attachments) { if (attachments != null) { for (Attachment attachment : attachments) { @@ -27,6 +53,17 @@ public final class Attachments { return Optional.empty(); } + public static Optional findFirstContact(Collection attachments) { + if (attachments != null) { + for (Attachment attachment : attachments) { + if (isContact(attachment)) { + return Optional.ofNullable((ContactAttachment) attachment); + } + } + } + return Optional.empty(); + } + public static boolean hasDocument(Collection attachments) { Inspector.isNotNull(attachments); for (Attachment attachment : attachments) { @@ -42,4 +79,14 @@ public final class Attachments { return TelegramAttachmentType.DOCUMENT.name().equals(attachment.getType()); } + private static boolean isContact(Attachment attachment) { + Inspector.isNotNull(attachment); + return TelegramAttachmentType.CONTACT.name().equals(attachment.getType()); + } + + private static boolean isPictureGroup(Attachment attachment) { + Inspector.isNotNull(attachment); + return TelegramAttachmentType.PICTURE.name().equals(attachment.getType()); + } + } diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/InlineKeyBoards.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/InlineKeyBoards.java index b4f358a..d9e78c0 100644 --- a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/InlineKeyBoards.java +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/InlineKeyBoards.java @@ -15,10 +15,10 @@ import static dev.struchkov.haiti.utils.Exceptions.utilityClass; public final class InlineKeyBoards { - public static final SimpleButton YES_BUTTON = simpleButton("Да", "{\"button\": \"yes\"}"); - public static final SimpleButton NO_BUTTON = simpleButton("Нет", "{\"button\": \"no\"}"); + public static final SimpleButton YES_BUTTON = simpleButton("Да", "Да"); + public static final SimpleButton NO_BUTTON = simpleButton("Нет", "Нет"); - public InlineKeyBoards() { + private InlineKeyBoards() { utilityClass(); } @@ -27,10 +27,8 @@ public final class InlineKeyBoards { * * @return {@link SimpleKeyBoard} */ - public static InlineKeyBoard keyBoardYesNo() { - return InlineKeyBoard.inlineKeyBoard( - SimpleKeyBoardLine.builder().button(YES_BUTTON).button(NO_BUTTON).build() - ); + public static SimpleKeyBoardLine lineYesOrNo() { + return simpleLine(YES_BUTTON, NO_BUTTON); } /** @@ -122,7 +120,7 @@ public final class InlineKeyBoards { * @param buttons Список кнопок * @return {@link SimpleKeyBoard} */ - public static InlineKeyBoard verticalMenuButton(List buttons) { + public static InlineKeyBoard verticalMenuButton(KeyBoardButton... buttons) { final InlineKeyBoard.Builder keyBoard = InlineKeyBoard.builder(); for (KeyBoardButton simpleButton : buttons) { keyBoard.line(simpleLine(simpleButton)); diff --git a/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/KeyBoardConvert.java b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/KeyBoardConvert.java new file mode 100644 index 0000000..c59dc98 --- /dev/null +++ b/telegram-core/src/main/java/dev/struchkov/godfather/telegram/utils/KeyBoardConvert.java @@ -0,0 +1,152 @@ +package dev.struchkov.godfather.telegram.utils; + +import dev.struchkov.godfather.context.domain.keyboard.KeyBoard; +import dev.struchkov.godfather.context.domain.keyboard.KeyBoardButton; +import dev.struchkov.godfather.context.domain.keyboard.KeyBoardLine; +import dev.struchkov.godfather.context.domain.keyboard.button.SimpleButton; +import dev.struchkov.godfather.context.domain.keyboard.simple.SimpleKeyBoard; +import dev.struchkov.godfather.telegram.domain.keyboard.InlineKeyBoard; +import dev.struchkov.godfather.telegram.domain.keyboard.MarkupKeyBoard; +import dev.struchkov.godfather.telegram.domain.keyboard.button.ContactButton; +import dev.struchkov.godfather.telegram.domain.keyboard.button.UrlButton; +import dev.struchkov.godfather.telegram.domain.keyboard.button.WebAppButton; +import dev.struchkov.haiti.context.exception.ConvertException; +import dev.struchkov.haiti.utils.Exceptions; +import dev.struchkov.haiti.utils.Inspector; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboard; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardRemove; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardButton; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.KeyboardRow; +import org.telegram.telegrambots.meta.api.objects.webapp.WebAppInfo; + +import java.util.List; + +public final class KeyBoardConvert { + + private KeyBoardConvert() { + Exceptions.utilityClass(); + } + + public static ReplyKeyboard convertKeyBoard(KeyBoard keyBoard) { + if (keyBoard != null) { + switch (keyBoard.getType()) { + case InlineKeyBoard.TYPE: + return convertInlineKeyBoard((InlineKeyBoard) keyBoard); + case MarkupKeyBoard.TYPE: + return convertMarkupKeyBoard((MarkupKeyBoard) keyBoard); + case SimpleKeyBoard.TYPE: + return convertSimpleKeyBoard((SimpleKeyBoard) keyBoard); + } + } + return null; + } + + public static ReplyKeyboard convertSimpleKeyBoard(SimpleKeyBoard keyBoard) { + final ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup(); + keyboardMarkup.setKeyboard( + keyBoard.getLines().stream() + .map(KeyBoardConvert::convertMarkupLine) + .toList() + ); + return keyboardMarkup; + } + + public static ReplyKeyboard convertMarkupKeyBoard(MarkupKeyBoard keyBoard) { + if (keyBoard != null) { + if (keyBoard.isNotEmpty()) { + final ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup(); + keyboardMarkup.setOneTimeKeyboard(keyBoard.isOneTime()); + keyboardMarkup.setInputFieldPlaceholder(keyBoard.getInputFieldPlaceholder()); + keyboardMarkup.setResizeKeyboard(keyBoard.isResizeKeyboard()); + keyboardMarkup.setKeyboard( + keyBoard.getLines().stream() + .map(KeyBoardConvert::convertMarkupLine) + .toList() + ); + return keyboardMarkup; + } else { + final ReplyKeyboardRemove replyKeyboardRemove = new ReplyKeyboardRemove(); + replyKeyboardRemove.setRemoveKeyboard(true); + return replyKeyboardRemove; + } + } + return null; + } + + public static InlineKeyboardMarkup convertInlineKeyBoard(InlineKeyBoard keyBoard) { + if (keyBoard != null) { + final InlineKeyboardMarkup inlineKeyboardMarkup = new InlineKeyboardMarkup(); + inlineKeyboardMarkup.setKeyboard( + keyBoard.getLines().stream() + .map(KeyBoardConvert::convertInlineLine) + .toList() + ); + return inlineKeyboardMarkup; + } + return null; + } + + private static List convertInlineLine(KeyBoardLine line) { + return line.getButtons().stream().map(KeyBoardConvert::convertInlineButton).toList(); + } + + private static KeyboardRow convertMarkupLine(KeyBoardLine line) { + final List buttons = line.getButtons().stream().map(KeyBoardConvert::convertMarkupButton).toList(); + return new KeyboardRow(buttons); + } + + private static InlineKeyboardButton convertInlineButton(KeyBoardButton keyBoardButton) { + final InlineKeyboardButton button = new InlineKeyboardButton(); + switch (keyBoardButton.getType()) { + case SimpleButton.TYPE -> { + final SimpleButton simpleButton = (SimpleButton) keyBoardButton; + final String callbackData = simpleButton.getCallbackData(); + final String label = simpleButton.getLabel(); + button.setText(label); + button.setCallbackData(callbackData != null ? callbackData : label); + } + case UrlButton.TYPE -> { + final UrlButton urlButton = (UrlButton) keyBoardButton; + button.setUrl(urlButton.getUrl()); + button.setText(urlButton.getLabel()); + } + case WebAppButton.TYPE -> { + final WebAppButton webAppButton = (WebAppButton) keyBoardButton; + final WebAppInfo webAppInfo = WebAppInfo.builder().url(webAppButton.getUrl()).build(); + button.setWebApp(webAppInfo); + button.setText(webAppButton.getLabel()); + } + default -> throw new ConvertException("Ошибка преобразования кнопки"); + } + return button; + } + + private static KeyboardButton convertMarkupButton(KeyBoardButton keyBoardButton) { + final KeyboardButton button = new KeyboardButton(); + switch (keyBoardButton.getType()) { + case SimpleButton.TYPE -> { + final SimpleButton simpleButton = (SimpleButton) keyBoardButton; + button.setText(simpleButton.getLabel()); + Inspector.isNull(simpleButton.getCallbackData(), ConvertException.supplier("CallbackData поддерживает только Inline клавитаура")); + } + case WebAppButton.TYPE -> { + final WebAppButton webAppButton = (WebAppButton) keyBoardButton; + final WebAppInfo webAppInfo = WebAppInfo.builder().url(webAppButton.getUrl()).build(); + button.setText(webAppButton.getLabel()); + button.setWebApp(webAppInfo); + } + case ContactButton.TYPE -> { + final ContactButton contactButton = (ContactButton) keyBoardButton; + + button.setText(contactButton.getLabel()); + button.setRequestContact(true); + } + default -> throw new ConvertException("Ошибка преобразования кнопки"); + } + return button; + } + +}