Files
pepper_bot/PepperBot/Application/Services/DealService.cs
T
2026-03-10 17:02:08 +03:00

134 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.Extensions.Logging;
using PepperBot.Application.Interfaces;
using PepperBot.Domain;
namespace PepperBot.Application.Services;
public class DealService
{
private readonly IPepperClient _pepperClient;
private readonly IDealRepository _repository;
private readonly ISubscriptionRepository _subscriptionRepository;
private readonly ITelegramNotifier _notifier;
private readonly ILogger<DealService> _logger;
private readonly IHealthMonitor _healthMonitor;
public DealService(
IPepperClient pepperClient,
IDealRepository repository,
ISubscriptionRepository subscriptionRepository,
ITelegramNotifier notifier,
ILogger<DealService> logger,
IHealthMonitor healthMonitor)
{
_pepperClient = pepperClient;
_repository = repository;
_subscriptionRepository = subscriptionRepository;
_notifier = notifier;
_logger = logger;
_healthMonitor = healthMonitor;
}
public async Task CheckAndNotifyAsync(CancellationToken cancellationToken)
{
var deals = await _pepperClient.GetLatestDealsAsync(cancellationToken);
_logger.LogInformation("Начата обработка полученных скидок: всего {DealCount}", deals.Count);
// Хелсчек: успешный запрос, вернувший более одной скидки (пусть и не новой)
if (deals.Count > 1)
{
_healthMonitor.ReportSuccess(DateTimeOffset.UtcNow);
_logger.LogDebug("HealthCheck: успешно получено более одной скидки ({DealCount})", deals.Count);
}
// Загружаем активные подписки один раз на проход
var subscriptions = await _subscriptionRepository.GetAllActiveAsync(cancellationToken);
_logger.LogInformation("Загружено активных подписок: {SubscriptionCount}", subscriptions.Count);
foreach (var deal in deals)
{
if (await _repository.ExistsAsync(deal.Id, cancellationToken))
{
_logger.LogDebug("Скидка уже есть в репозитории и будет пропущена: {DealId}", deal.Id);
continue;
}
_logger.LogInformation("Новая скидка: {Title} ({Id})", deal.Title, deal.Id);
await _repository.AddAsync(deal, cancellationToken);
// Общая рассылка в основной чат (как было раньше)
await _notifier.NotifyNewDealAsync(deal, cancellationToken);
if (subscriptions.Count == 0)
{
_logger.LogDebug("Активные подписки отсутствуют. Фильтрация по ключевым словам пропущена для скидки {DealId}", deal.Id);
continue;
}
var searchableText = $"{deal.Title} {deal.StoreName}";
foreach (var subscription in subscriptions)
{
if (!subscription.IsActive)
{
_logger.LogDebug("Подписка {SubscriptionId} неактивна и будет пропущена", subscription.Id);
continue;
}
var keywords = ParseKeywords(subscription.Keywords);
if (keywords.Count == 0)
{
_logger.LogDebug("У подписки {SubscriptionId} не удалось извлечь ключевые слова из строки: \"{RawKeywords}\"",
subscription.Id,
subscription.Keywords);
continue;
}
var isMatch = IsMatch(searchableText, keywords);
_logger.LogDebug(
"Результат фильтрации скидки {DealId} по подписке {SubscriptionId}: {IsMatch}. Текст: \"{Text}\"; ключевые слова: {Keywords}",
deal.Id,
subscription.Id,
isMatch,
searchableText,
string.Join(", ", keywords));
if (isMatch)
{
await _notifier.NotifyDealToChatAsync(deal, subscription.ChatId, cancellationToken);
}
}
}
}
private static List<string> ParseKeywords(string raw)
{
return raw
.Split(new[] { '-',',', ';', '\n', '\r', '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(k => k.Trim())
.Where(k => k.Length > 0)
.ToList();
}
private static bool IsMatch(string text, List<string> keywords)
{
if (keywords.Count == 0)
{
return false;
}
foreach (var keyword in keywords)
{
if (text.Contains(keyword, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}