Fix chat interactions

This commit is contained in:
2025-02-16 20:37:00 +03:00
parent ed09bcc549
commit 8af75a64f5
9 changed files with 31 additions and 45 deletions
@@ -2,7 +2,7 @@ package ru.cathub.telegabot.model;
public enum TextRole {
DEFAULT("Ты книжный ассистент в Telegram-боте. Отвечай кратко, используй эмоджи, разметку Markdown (*для\n" +
" выделения*, _для наклонного_)"),
" выделения*, _для наклонного_). Отвечай ТОЛЬКО на русском языке. Дополнительно проверь что ответ точно на Русском языке."),
REVIEWER("Анализируй текст как профессиональный редактор"),
RECOMMENDER("Рекомендуй книги на основе предпочтений");
@@ -10,6 +10,7 @@ import ru.cathub.telegabot.model.BookCreationCache;
import ru.cathub.telegabot.model.TextRole;
import ru.cathub.telegabot.repository.BookRepository;
import ru.cathub.telegabot.model.BotUser;
import ru.cathub.telegabot.repository.UserRepository;
import ru.cathub.telegabot.service.*;
import ru.cathub.telegabot.utils.Constants;
@@ -20,6 +21,7 @@ import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import static ru.cathub.telegabot.model.BookEditStateCache.BookEditState.*;
import static ru.cathub.telegabot.utils.BookFormatUtils.escapeNonMarkdown;
import static ru.cathub.telegabot.utils.Constants.*;
@Service
@@ -32,6 +34,7 @@ public class BookCreationServiceImpl implements BookCreationService {
private final BookRepository bookRepository;
private final BookCommonService bookCommonService;
private final OpenRouterService openRouterService;
private final UserRepository userRepository;
@Override
public void handleNewAddRequest(BotUser user, String text) {
@@ -39,13 +42,13 @@ public class BookCreationServiceImpl implements BookCreationService {
BookCreationCache newCache = new BookCreationCache();
newCache.setCreationState(BookCreationCache.CreationState.ADDING_TITLE);
bookCacheService.updateCache(user.getId(), newCache);
telegramClientService.sendMessageWithMarkdown(user, "*Введите название книги: \uD83D\uDCDA*", null);
}
}
@Transactional
@Override
@Transactional
public void handleExistingAddCache(BotUser user, String text) {
BookCreationCache cache = bookCacheService.getCache(user.getId());
@@ -80,7 +83,7 @@ public class BookCreationServiceImpl implements BookCreationService {
bookCacheService.updateCache(user.getId(), cache);
telegramClientService.sendMessage(user, "📅 Введите дату прочтения (в формате ДД.ММ.ГГГГ):");
}
case ADDING_DATE -> {
Date readDate = parseDate(text.trim());
cache.setReadDate(readDate);
@@ -88,49 +91,36 @@ public class BookCreationServiceImpl implements BookCreationService {
// Создаем и сохраняем книгу
Book book = createBookFromCache(cache, user);
bookRepository.save(book);
// Очищаем кэш
bookCacheService.clearCache(user.getId());
// Отправляем подтверждение
String message = String.format("✅ Книга успешно добавлена\\!\n\n%s",
bookCommonService.formatBookDetails(book));
String message = String.format("✅ Книга успешно добавлена\\!\n\n%s", bookCommonService.formatBookDetails(book));
// Формируем статистику
LocalDate today = LocalDate.now();
LocalDate endOfYear = LocalDate.of(today.getYear(), 12, 31);
long weeksLeft = ChronoUnit.WEEKS.between(today, endOfYear);
int target = user.getBooksToRead() != null ? user.getBooksToRead() : 0;
int read = user.getBooks() != null ? user.getBooks().size() : 0;
BotUser freshUser = userRepository.findById(user.getId()).orElseThrow();
int target = freshUser.getBooksToRead() != null ? freshUser.getBooksToRead() : 0;
int read = freshUser.getBooks() != null ? freshUser.getBooks().size() : 0;
int left = target - read;
String stats = String.format(
"\n\n📊 *Статистика:*\n" +
"⏳ До конца года: %d недель\n" +
"🎯 Цель: %d книг\n" +
"✅ Прочитано: %d\n" +
"📖 Осталось: %d",
weeksLeft, target, read, left > 0 ? left : 0
);
String stats = String.format("\n\n📊 *Статистика:*\n" + "⏳ До конца года: %d недель\n" + "🎯 Цель: %d книг\n" + "✅ Прочитано: %d\n" + "📖 Осталось: %d", weeksLeft, target, read, left > 0 ? left : 0);
telegramClientService.sendMessageWithMarkdown(user, message + stats);
bookRepository.save(book);
// Генерируем и отправляем поздравление
try {
String prompt = String.format("Придумай креативное поздравление с прочтением книги \"%s\". " +
"Учитывай что пользователь поставил оценку %d/10. ",
cache.getTitle(), cache.getRating());
String congrat = openRouterService.getChatResponse(
prompt,
TextRole.DEFAULT
);
String prompt = String.format("Придумай креативное поздравление с прочтением книги \"%s\" от автора \"%s\". " + "Учитывай что пользователь поставил оценку %d/10. ", cache.getTitle(),cache.getAuthor(), cache.getRating());
telegramClientService.sendMessageWithMarkdown(user, "🎉 *Поздравляю с прочтением!*\n\n" + congrat);
String congrat = openRouterService.getChatResponse(prompt, TextRole.DEFAULT);
log.info("Congratulation generated: {}", congrat);
telegramClientService.sendMessageWithMarkdown(user, "🎉 *Поздравляю с прочтением\\!*\n\n" + escapeNonMarkdown(congrat));
} catch (Exception e) {
log.error("Error generating congratulation for user {}", user.getId(), e);
telegramClientService.sendMessage(user, "📚 Спасибо за добавление книги!");
@@ -145,8 +135,7 @@ public class BookCreationServiceImpl implements BookCreationService {
} catch (NumberFormatException e) {
log.error("Invalid rating format for user {}", user.getId(), e);
telegramClientService.sendMessage(user, "❌ Ошибка: рейтинг должен быть числом от 0 до 10");
}
catch (ParseException e) {
} catch (ParseException e) {
log.error("Invalid date format for user {}", user.getId(), e);
telegramClientService.sendMessage(user, "❌ Ошибка: дата должна быть в формате ДД.ММ.ГГГГ");
} catch (Exception e) {
@@ -171,12 +160,6 @@ public class BookCreationServiceImpl implements BookCreationService {
}
private Book createBookFromCache(BookCreationCache cache, BotUser user) {
return Book.builder()
.title(cache.getTitle())
.author(cache.getAuthor())
.rating(cache.getRating())
.readDate(cache.getReadDate())
.botUser(user)
.build();
return Book.builder().title(cache.getTitle()).author(cache.getAuthor()).rating(cache.getRating()).readDate(cache.getReadDate()).botUser(user).build();
}
}
@@ -77,7 +77,7 @@ public class TelegramClientServiceImps implements TelegramClientService {
return telegramClient.execute(message);
} catch (TelegramApiException e) {
//logger.error("Ошибка отправки сообщения", e);
throw new RuntimeException(e);
throw new RuntimeException(e);
}
}
@@ -30,6 +30,10 @@ public class BookFormatUtils {
return text.replaceAll("([_*\\[\\]()~`>#+=|{}.!-])", "\\\\$1");
}
public static String escapeNonMarkdown(String text) {
return text.replaceAll("([().!-])", "\\\\$1");
}
public static String formatDate(Date date) {
if (date == null) {
return "Не указана";
+1 -1
View File
@@ -33,7 +33,7 @@ logging.level.org.springframework.cache=INFO
# OpenRouter AI
openrouter.api.url=https://openrouter.ai/api/v1
openrouter.api.model=deepseek/deepseek-r1-distill-qwen-32b
openrouter.api.model=qwen/qwen-2.5-72b-instruct
# Для безопасности лучше установить через переменную окружения:
@@ -12,7 +12,6 @@ import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@TestPropertySource(locations = "classpath:application.properties")
@Disabled
class TelegramBotApplicationTests {
@Value("${bot.token}")
@@ -38,7 +38,7 @@ class OpenRouterServiceIntegrationTest {
when(restTemplate.postForEntity(anyString(), any(), eq(Map.class)))
.thenReturn(new ResponseEntity<>(mockResponse, HttpStatus.OK));
String response = openRouterService.getChatResponse("Test message");
String response = openRouterService.getSimpleResponse("Test message");
assertEquals("Test response", response);
}
@@ -48,6 +48,6 @@ class OpenRouterServiceIntegrationTest {
.thenThrow(new RestClientException("API error"));
assertThrows(OpenRouterException.class,
() -> openRouterService.getChatResponse("Test message"));
() -> openRouterService.getSimpleResponse("Test message"));
}
}
@@ -28,7 +28,7 @@ class OpenRouterServiceLiveTest {
assumeTrue(openRouterConfig.getKey() != null && !openRouterConfig.getKey().isBlank(),
"OPENROUTER_API_KEY not set");
String response = openRouterService.getChatResponse("Hello in Russian");
String response = openRouterService.getSimpleResponse("Hello in Russian");
assertNotNull(response);
assertFalse(response.isBlank());
@@ -53,7 +53,7 @@ class OpenRouterServiceTest {
when(restTemplate.postForEntity(anyString(), any(), eq(Map.class)))
.thenReturn(new ResponseEntity<>(mockResponse, HttpStatus.OK));
String response = openRouterService.getChatResponse("Test message");
String response = openRouterService.getSimpleResponse("Test message");
assertEquals("Test response", response);
}
@@ -63,6 +63,6 @@ class OpenRouterServiceTest {
.thenThrow(new RestClientException("API error"));
assertThrows(OpenRouterException.class,
() -> openRouterService.getChatResponse("Test message"));
() -> openRouterService.getSimpleResponse("Test message"));
}
}