Global Keyboard WIP

This commit is contained in:
Patrick Haßel 2024-07-30 09:15:40 +02:00
parent 13fa1939ad
commit 08cc0e1474
13 changed files with 125 additions and 41 deletions

View File

@ -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 {

View File

@ -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);
}

View File

@ -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 extends Serializable, Method extends BotApiMethod<T>> T execute(@NonNull final Method method) throws TelegramApiException {
return bot.execute(method);
}
}

View File

@ -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<TlgMessage> of(@NonNull final MessageDto message) {
public static Optional<TlgMessage> 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 extends Serializable, Method extends BotApiMethod<T>> T execute(@NonNull final Method method) throws TelegramApiException {
return chat.bot.execute(method);
}
}

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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<KeyboardRow> 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) {

View File

@ -86,7 +86,7 @@ public class MessageService {
}
private Optional<Message> 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) {

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}