132 lines
7.2 KiB
C#
132 lines
7.2 KiB
C#
![]() |
using DailyDigestWorker.Configuration; // Для TelegramClientSettings
|
|||
|
using Microsoft.Extensions.Options; // Для IOptions
|
|||
|
using TL; // Основное пространство имен WTelegramClient для типов Telegram API
|
|||
|
using WTelegram; // Для Client
|
|||
|
|
|||
|
namespace DailyDigestWorker.Services
|
|||
|
{
|
|||
|
public class TelegramChannelReader : ITelegramChannelReader // Реализуем интерфейс
|
|||
|
{
|
|||
|
private readonly ILogger<TelegramChannelReader> _logger;
|
|||
|
private readonly Client _client; // Наш Singleton WTelegramClient
|
|||
|
private readonly TelegramClientSettings _settings;
|
|||
|
private InputPeer? _targetPeer; // Кэшированный InputPeer канала
|
|||
|
|
|||
|
// Внедряем зависимости
|
|||
|
public TelegramChannelReader(
|
|||
|
ILogger<TelegramChannelReader> logger,
|
|||
|
Client client, // Внедряем WTelegramClient
|
|||
|
IOptions<TelegramClientSettings> settingsOptions)
|
|||
|
{
|
|||
|
_logger = logger;
|
|||
|
_client = client;
|
|||
|
_settings = settingsOptions.Value;
|
|||
|
}
|
|||
|
|
|||
|
public async Task<List<string>?> GetRecentNewsAsync(int maxAgeHours, int limit, CancellationToken cancellationToken)
|
|||
|
{
|
|||
|
_logger.LogInformation("Попытка чтения новостей из канала {ChannelUsername}...", _settings.TargetChannelUsername);
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
_logger.LogDebug("Шаг 1: Проверка/выполнение авторизации пользователя...");
|
|||
|
// Добавляем try-catch вокруг LoginUserIfNeeded для более детального логгирования
|
|||
|
User? currentUser = null;
|
|||
|
try
|
|||
|
{
|
|||
|
currentUser = await _client.LoginUserIfNeeded(); // Может запросить ввод в консоль!
|
|||
|
}
|
|||
|
catch (Exception loginEx)
|
|||
|
{
|
|||
|
_logger.LogError(loginEx, "Ошибка во время выполнения LoginUserIfNeeded.");
|
|||
|
return null; // Выходим, если логин не удался
|
|||
|
}
|
|||
|
|
|||
|
if (currentUser == null)
|
|||
|
{
|
|||
|
_logger.LogError("Авторизация не удалась (LoginUserIfNeeded вернул null или выбросил исключение).");
|
|||
|
return null;
|
|||
|
}
|
|||
|
_logger.LogInformation("Шаг 1 Успех: Авторизация как {UserFirstName} (ID: {UserId})", currentUser.first_name, currentUser.id);
|
|||
|
|
|||
|
|
|||
|
// 2. Найти канал (получить InputPeer) - кэшируем результат
|
|||
|
if (_targetPeer == null)
|
|||
|
{
|
|||
|
_logger.LogDebug("Шаг 2: Поиск InputPeer для канала {ChannelUsername}...", _settings.TargetChannelUsername);
|
|||
|
var resolved = await _client.Contacts_ResolveUsername(_settings.TargetChannelUsername);
|
|||
|
if (resolved?.UserOrChat is Channel channel)
|
|||
|
{
|
|||
|
_targetPeer = channel.ToInputPeer();
|
|||
|
_logger.LogInformation("Шаг 2 Успех: Найден InputPeer для канала '{ChannelTitle}' (ID: {ChannelId})", channel.title, channel.id);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_logger.LogError("Шаг 2 Ошибка: Не удалось найти канал по юзернейму {ChannelUsername} или это не канал. Resolved: {@Resolved}", _settings.TargetChannelUsername, resolved);
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_logger.LogDebug("Шаг 2: Используется кэшированный InputPeer для канала.");
|
|||
|
}
|
|||
|
|
|||
|
// 3. Получить историю сообщений
|
|||
|
_logger.LogDebug("Шаг 3: Запрос истории сообщений (limit={Limit})...", limit);
|
|||
|
var history = await _client.Messages_GetHistory(_targetPeer, limit: limit);
|
|||
|
if (history == null)
|
|||
|
{
|
|||
|
_logger.LogWarning("Шаг 3 Ошибка: Не удалось получить историю сообщений (результат null).");
|
|||
|
return null;
|
|||
|
}
|
|||
|
_logger.LogInformation("Шаг 3 Успех: Получено {Count} сообщений/элементов в истории.", history.Messages.Length);
|
|||
|
|
|||
|
|
|||
|
// 4. Отфильтровать сообщения по дате и извлечь текст
|
|||
|
_logger.LogDebug("Шаг 4: Фильтрация сообщений новее {CutoffDateUtc} UTC...", DateTime.UtcNow.AddHours(-maxAgeHours));
|
|||
|
var newsTexts = new List<string>();
|
|||
|
var cutoffDate = DateTime.UtcNow.AddHours(-maxAgeHours);
|
|||
|
|
|||
|
foreach (var msgBase in history.Messages)
|
|||
|
{
|
|||
|
if (msgBase is Message message)
|
|||
|
{
|
|||
|
if (message.Date >= cutoffDate)
|
|||
|
{
|
|||
|
if (!string.IsNullOrWhiteSpace(message.message))
|
|||
|
{
|
|||
|
newsTexts.Add(message.message);
|
|||
|
// Уменьшим детальность этого лога, чтобы не засорять вывод
|
|||
|
// _logger.LogDebug(" + Добавлено сообщение от {MessageDate:yyyy-MM-dd HH:mm} UTC (ID: {MessageId})", message.Date, message.id);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_logger.LogDebug("Достигнуто сообщение старше {CutoffDateUtc} UTC, остановка фильтрации.", cutoffDate);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
_logger.LogInformation("Шаг 4 Успех: Найдено {Count} новостных сообщений за последние {Hours} часов.", newsTexts.Count, maxAgeHours);
|
|||
|
|
|||
|
newsTexts.Reverse();
|
|||
|
return newsTexts;
|
|||
|
}
|
|||
|
// ... (остальные catch блоки без изменений) ...
|
|||
|
catch (RpcException e)
|
|||
|
{
|
|||
|
_logger.LogError(e, "Ошибка Telegram API ({ErrorCode}): {ErrorMessage}", e.Code, e.Message);
|
|||
|
if (e.Code == 420)
|
|||
|
{
|
|||
|
_logger.LogWarning("Получен FloodWait на {Seconds} секунд. Пропускаем цикл чтения новостей.", e.X);
|
|||
|
}
|
|||
|
return null;
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
_logger.LogError(ex, "Неожиданная ошибка при чтении новостей из Telegram канала.");
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|