diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/TelegramAdapter.java b/src/main/java/de/ph87/kleinanzeigen/telegram/TelegramAdapter.java index ff8d64b..3c2d33b 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/TelegramAdapter.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/TelegramAdapter.java @@ -7,10 +7,7 @@ import de.ph87.kleinanzeigen.telegram.chat.ChatDto; import de.ph87.kleinanzeigen.telegram.chat.ChatService; import de.ph87.kleinanzeigen.telegram.chat.message.MessageDto; import de.ph87.kleinanzeigen.telegram.chat.message.MessageService; -import de.ph87.kleinanzeigen.telegram.request.ChatRequestEnable; -import de.ph87.kleinanzeigen.telegram.request.ChatRequestUndo; -import de.ph87.kleinanzeigen.telegram.request.MessageRequestHide; -import de.ph87.kleinanzeigen.telegram.request.MessageRequestRemember; +import de.ph87.kleinanzeigen.telegram.request.*; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import lombok.NonNull; @@ -97,6 +94,12 @@ public class TelegramAdapter { messageService.undo(request); } + @Async + @EventListener(ChatRequestHelp.class) + public void onChatHelp(@NonNull final ChatRequestHelp request) { + chatService.help(request); + } + @Async @EventListener(MessageRequestHide.class) public void onMessageHide(@NonNull final MessageRequestHide request) { @@ -133,7 +136,7 @@ public class TelegramAdapter { private boolean mayDelete(final @NonNull MessageDto message) { if (message.needsToBeDeleted()) { - TlgMessage.of(message).ifPresent(tlgMessage -> { + TlgMessage.of(bot, message).ifPresent(tlgMessage -> { bot.delete(tlgMessage); messageService.markDeleted(tlgMessage); }); @@ -175,7 +178,7 @@ public class TelegramAdapter { } catch (TelegramApiException | JsonProcessingException e) { if (e.toString().endsWith("Bad Request: message to edit not found")) { log.info("Message has been deleted by User. Marking has hidden: {}", message); - TlgMessage.of(message).ifPresent(messageService::markDeleted); + TlgMessage.of(bot, message).ifPresent(messageService::markDeleted); } else if (e.toString().endsWith("Bad Request: message is not modified: specified new message content and reply markup are exactly the same as a current content and reply markup of the message")) { log.debug("Ignoring complaint from telegram-bot-api about unmodified message: {}", message); } else { diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/TelegramBot.java b/src/main/java/de/ph87/kleinanzeigen/telegram/TelegramBot.java index 94fdada..7c492ab 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/TelegramBot.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/TelegramBot.java @@ -2,14 +2,12 @@ package de.ph87.kleinanzeigen.telegram; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import de.ph87.kleinanzeigen.telegram.request.ChatRequestEnable; -import de.ph87.kleinanzeigen.telegram.request.ChatRequestUndo; -import de.ph87.kleinanzeigen.telegram.request.MessageRequestHide; -import de.ph87.kleinanzeigen.telegram.request.MessageRequestRemember; +import de.ph87.kleinanzeigen.telegram.request.*; import jakarta.annotation.PreDestroy; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.jpa.repository.JpaContext; import org.springframework.stereotype.Service; import org.telegram.telegrambots.bots.TelegramLongPollingBot; import org.telegram.telegrambots.meta.TelegramBotsApi; @@ -35,7 +33,9 @@ public class TelegramBot extends TelegramLongPollingBot { private final DefaultBotSession session; - public TelegramBot(final TelegramConfig config, final ObjectMapper objectMapper, final ApplicationEventPublisher publisher) throws TelegramApiException { + private final JpaContext jpaContext; + + public TelegramBot(final TelegramConfig config, final ObjectMapper objectMapper, final ApplicationEventPublisher publisher, final JpaContext jpaContext) throws TelegramApiException { super(config.getToken()); this.config = config; @@ -47,6 +47,7 @@ public class TelegramBot extends TelegramLongPollingBot { session = (DefaultBotSession) api.registerBot(this); log.info("Telegram bot registered."); this.objectMapper = objectMapper; + this.jpaContext = jpaContext; } @PreDestroy @@ -71,13 +72,14 @@ public class TelegramBot extends TelegramLongPollingBot { } private void handleMessage(@NonNull final Message message) { - final String command = message.getText().toLowerCase(Locale.ROOT).replaceAll("\\W+", ""); - switch (command) { - case "start" -> publisher.publishEvent(new ChatRequestEnable(message, true)); - case "undo" -> publisher.publishEvent(new ChatRequestUndo(message)); - case "stop" -> publisher.publishEvent(new ChatRequestEnable(message, false)); + final String[] command = message.getText().toLowerCase(Locale.ROOT).replaceAll("[^\\w\\s]+", "").replaceAll("\\s+", " ").split(" "); + switch (command[0]) { + case "start" -> publisher.publishEvent(new ChatRequestEnable(this, message, true)); + case "stop" -> publisher.publishEvent(new ChatRequestEnable(this, message, false)); + case "r", "undo", "rückgängig" -> publisher.publishEvent(new ChatRequestUndo(this, message)); + case "h", "hilfe", "help" -> publisher.publishEvent(new ChatRequestHelp(this, message)); } - delete(new TlgMessage(message)); + delete(new TlgMessage(this, message)); } private void handleCallback(@NonNull final CallbackQuery callback) { @@ -86,8 +88,8 @@ public class TelegramBot extends TelegramLongPollingBot { final InlineDto dto = objectMapper.readValue(callback.getData(), InlineDto.class); switch (dto.getCommand()) { case HIDE -> hide(message); - case REMEMBER -> publisher.publishEvent(new MessageRequestRemember(message, true)); - case UNREMEMBER -> publisher.publishEvent(new MessageRequestRemember(message, false)); + case REMEMBER -> publisher.publishEvent(new MessageRequestRemember(this, message, true)); + case UNREMEMBER -> publisher.publishEvent(new MessageRequestRemember(this, message, false)); } } catch (JsonProcessingException e) { log.error("Failed to read InlineDto.", e); @@ -95,7 +97,7 @@ public class TelegramBot extends TelegramLongPollingBot { } private void hide(final MaybeInaccessibleMessage message) { - final MessageRequestHide event = new MessageRequestHide(message); + final MessageRequestHide event = new MessageRequestHide(this, message); delete(event); publisher.publishEvent(event); } @@ -103,7 +105,7 @@ public class TelegramBot extends TelegramLongPollingBot { public void delete(@NonNull final TlgMessage tlgMessage) { try { log.info("Removing TlgMessage: tlgMessage={}", tlgMessage); - execute(new DeleteMessage(tlgMessage.chatId + "", tlgMessage.messageId)); + execute(new DeleteMessage(tlgMessage.chat.idStr, tlgMessage.id)); } catch (TelegramApiException e) { log.error("Failed to remove TlgMessage: tlgMessage={}", tlgMessage); } diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/TlgChat.java b/src/main/java/de/ph87/kleinanzeigen/telegram/TlgChat.java index b210e6d..128f159 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/TlgChat.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/TlgChat.java @@ -2,15 +2,34 @@ package de.ph87.kleinanzeigen.telegram; import lombok.NonNull; import lombok.ToString; +import org.telegram.telegrambots.meta.api.methods.BotApiMethod; import org.telegram.telegrambots.meta.api.objects.MaybeInaccessibleMessage; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; + +import java.io.Serializable; @ToString public class TlgChat { + public final TelegramBot bot; + public final long id; - public TlgChat(@NonNull final MaybeInaccessibleMessage message) { - this.id = message.getChatId(); + public final String idStr; + + public TlgChat(@NonNull final TelegramBot bot, final long id) { + this.bot = bot; + this.id = id; + this.idStr = this.id + ""; + } + + public TlgChat(@NonNull final TelegramBot bot, @NonNull final MaybeInaccessibleMessage message) { + this(bot, message.getChatId()); + } + + @NonNull + public > T execute(@NonNull final Method method) throws TelegramApiException { + return bot.execute(method); } } diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/TlgMessage.java b/src/main/java/de/ph87/kleinanzeigen/telegram/TlgMessage.java index f4bbb8c..a6606ef 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/TlgMessage.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/TlgMessage.java @@ -3,31 +3,39 @@ package de.ph87.kleinanzeigen.telegram; import de.ph87.kleinanzeigen.telegram.chat.message.MessageDto; import lombok.NonNull; import lombok.ToString; +import org.telegram.telegrambots.meta.api.methods.BotApiMethod; import org.telegram.telegrambots.meta.api.objects.MaybeInaccessibleMessage; +import org.telegram.telegrambots.meta.exceptions.TelegramApiException; +import java.io.Serializable; import java.util.Optional; @ToString public class TlgMessage { - public final long chatId; + public final TlgChat chat; - public final int messageId; + public final int id; - private TlgMessage(final long chatId, final int messageId) { - this.chatId = chatId; - this.messageId = messageId; + private TlgMessage(@NonNull final TelegramBot bot, final long chatId, final int id) { + this.chat = new TlgChat(bot, chatId); + this.id = id; } - public TlgMessage(@NonNull final MaybeInaccessibleMessage message) { - this(message.getChatId(), message.getMessageId()); + public TlgMessage(@NonNull final TelegramBot bot, @NonNull final MaybeInaccessibleMessage message) { + this(bot, message.getChatId(), message.getMessageId()); } - public static Optional of(@NonNull final MessageDto message) { + public static Optional of(@NonNull final TelegramBot bot, @NonNull final MessageDto message) { if (message.getTelegramMessageId() == null) { return Optional.empty(); } - return Optional.of(new TlgMessage(message.getChat().getId(), message.getTelegramMessageId())); + return Optional.of(new TlgMessage(bot, message.getChat().getId(), message.getTelegramMessageId())); + } + + @NonNull + public > T execute(@NonNull final Method method) throws TelegramApiException { + return chat.bot.execute(method); } } diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/chat/Chat.java b/src/main/java/de/ph87/kleinanzeigen/telegram/chat/Chat.java index 3b576db..d830168 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/chat/Chat.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/chat/Chat.java @@ -1,5 +1,6 @@ package de.ph87.kleinanzeigen.telegram.chat; +import jakarta.annotation.Nullable; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; @@ -22,6 +23,11 @@ public class Chat { @Column(nullable = false) private String name; + @Setter + @Column + @Nullable + private Long keyboardMessageId = null; + public Chat(final long id, final boolean enabled, @NonNull final String name) { this.id = id; this.enabled = enabled; diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/chat/ChatDto.java b/src/main/java/de/ph87/kleinanzeigen/telegram/chat/ChatDto.java index 3968837..c349a6c 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/chat/ChatDto.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/chat/ChatDto.java @@ -1,5 +1,6 @@ package de.ph87.kleinanzeigen.telegram.chat; +import jakarta.annotation.Nullable; import lombok.Data; @Data @@ -11,10 +12,14 @@ public class ChatDto { private final String name; + @Nullable + private final Long keyboardMessageId; + public ChatDto(final Chat chat) { this.id = chat.getId(); this.enabled = chat.isEnabled(); this.name = chat.getName(); + this.keyboardMessageId = chat.getKeyboardMessageId(); } } diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/chat/ChatService.java b/src/main/java/de/ph87/kleinanzeigen/telegram/chat/ChatService.java index 844707e..9e098ee 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/chat/ChatService.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/chat/ChatService.java @@ -2,11 +2,17 @@ package de.ph87.kleinanzeigen.telegram.chat; import de.ph87.kleinanzeigen.telegram.TelegramConfig; import de.ph87.kleinanzeigen.telegram.TlgChat; +import de.ph87.kleinanzeigen.telegram.request.ChatRequestHelp; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.telegram.telegrambots.meta.api.methods.send.SendMessage; +import org.telegram.telegrambots.meta.api.objects.replykeyboard.ReplyKeyboardMarkup; +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.exceptions.TelegramApiException; import java.util.List; @@ -45,6 +51,21 @@ public class ChatService { return chat; } + public void help(@NonNull final ChatRequestHelp request) { + final SendMessage send = new SendMessage(request.idStr, ""); + final KeyboardRow row0 = new KeyboardRow(List.of( + new KeyboardButton("Rückgängig"), + new KeyboardButton("Alles löschen") + )); + final List keyboard = List.of(row0); + send.setReplyMarkup(new ReplyKeyboardMarkup(keyboard)); + try { + request.execute(send); + } catch (TelegramApiException e) { + log.error("Failed to printHelp: request={}, error={}", request, e.toString()); + } + } + private void update(@NonNull final Chat chat, final boolean enabled, final @NonNull String username) { chat.setName(username); if (chat.isEnabled() != enabled) { diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/chat/message/MessageService.java b/src/main/java/de/ph87/kleinanzeigen/telegram/chat/message/MessageService.java index e082b6b..0863ee7 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/chat/message/MessageService.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/chat/message/MessageService.java @@ -86,7 +86,7 @@ public class MessageService { } private Optional find(final @NonNull TlgMessage tlgMessage) { - return messageRepository.findByChat_IdAndTelegramMessageId(tlgMessage.chatId, tlgMessage.messageId); + return messageRepository.findByChat_IdAndTelegramMessageId(tlgMessage.chat.id, tlgMessage.id); } private void publish(@NonNull final Message message) { diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestEnable.java b/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestEnable.java index c8eb7da..30a536f 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestEnable.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestEnable.java @@ -1,5 +1,6 @@ package de.ph87.kleinanzeigen.telegram.request; +import de.ph87.kleinanzeigen.telegram.TelegramBot; import de.ph87.kleinanzeigen.telegram.TlgChat; import lombok.Getter; import lombok.NonNull; @@ -13,8 +14,8 @@ public class ChatRequestEnable extends TlgChat { @NonNull private final String username; - public ChatRequestEnable(@NonNull final Message message, final boolean enable) { - super(message); + public ChatRequestEnable(@NonNull final TelegramBot bot, @NonNull final Message message, final boolean enable) { + super(bot, message); this.enable = enable; this.username = message.getFrom().getUserName() == null ? "" : message.getFrom().getUserName(); } diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestHelp.java b/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestHelp.java new file mode 100644 index 0000000..5e957d8 --- /dev/null +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestHelp.java @@ -0,0 +1,16 @@ +package de.ph87.kleinanzeigen.telegram.request; + +import de.ph87.kleinanzeigen.telegram.TelegramBot; +import de.ph87.kleinanzeigen.telegram.TlgChat; +import lombok.Getter; +import lombok.NonNull; +import org.telegram.telegrambots.meta.api.objects.Message; + +@Getter +public class ChatRequestHelp extends TlgChat { + + public ChatRequestHelp(@NonNull final TelegramBot bot, @NonNull final Message message) { + super(bot, message); + } + +} diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestUndo.java b/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestUndo.java index ffb5d72..fac4b72 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestUndo.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/request/ChatRequestUndo.java @@ -1,5 +1,6 @@ package de.ph87.kleinanzeigen.telegram.request; +import de.ph87.kleinanzeigen.telegram.TelegramBot; import de.ph87.kleinanzeigen.telegram.TlgChat; import lombok.Getter; import lombok.NonNull; @@ -8,8 +9,8 @@ import org.telegram.telegrambots.meta.api.objects.Message; @Getter public class ChatRequestUndo extends TlgChat { - public ChatRequestUndo(@NonNull final Message message) { - super(message); + public ChatRequestUndo(@NonNull final TelegramBot bot, @NonNull final Message message) { + super(bot, message); } } diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/request/MessageRequestHide.java b/src/main/java/de/ph87/kleinanzeigen/telegram/request/MessageRequestHide.java index e5aaea8..952403c 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/request/MessageRequestHide.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/request/MessageRequestHide.java @@ -1,5 +1,6 @@ package de.ph87.kleinanzeigen.telegram.request; +import de.ph87.kleinanzeigen.telegram.TelegramBot; import de.ph87.kleinanzeigen.telegram.TlgMessage; import lombok.Getter; import lombok.NonNull; @@ -8,8 +9,8 @@ import org.telegram.telegrambots.meta.api.objects.MaybeInaccessibleMessage; @Getter public class MessageRequestHide extends TlgMessage { - public MessageRequestHide(@NonNull final MaybeInaccessibleMessage message) { - super(message); + public MessageRequestHide(@NonNull final TelegramBot bot, @NonNull final MaybeInaccessibleMessage message) { + super(bot, message); } } diff --git a/src/main/java/de/ph87/kleinanzeigen/telegram/request/MessageRequestRemember.java b/src/main/java/de/ph87/kleinanzeigen/telegram/request/MessageRequestRemember.java index 85e160e..9850360 100644 --- a/src/main/java/de/ph87/kleinanzeigen/telegram/request/MessageRequestRemember.java +++ b/src/main/java/de/ph87/kleinanzeigen/telegram/request/MessageRequestRemember.java @@ -1,5 +1,6 @@ package de.ph87.kleinanzeigen.telegram.request; +import de.ph87.kleinanzeigen.telegram.TelegramBot; import de.ph87.kleinanzeigen.telegram.TlgMessage; import lombok.Getter; import lombok.NonNull; @@ -10,8 +11,8 @@ public class MessageRequestRemember extends TlgMessage { private final boolean remember; - public MessageRequestRemember(@NonNull final MaybeInaccessibleMessage message, final boolean remember) { - super(message); + public MessageRequestRemember(@NonNull final TelegramBot bot, @NonNull final MaybeInaccessibleMessage message, final boolean remember) { + super(bot, message); this.remember = remember; }