- Улучшенная проверка на дубли для telegram

This commit is contained in:
2025-08-20 15:33:53 +03:00
parent 47e1adfed7
commit 073fa11127
2 changed files with 176 additions and 23 deletions

View File

@@ -31,17 +31,7 @@ class TelegramNewsClient:
if message.text:
# Если указан топик, фильтруем только сообщения из этого топика
if self.config['topic_id']:
is_in_topic = False
# В Telegram топиках все сообщения имеют reply_to_msg_id равный ID первого сообщения топика
if hasattr(message, 'reply_to_msg_id') and message.reply_to_msg_id:
# Сообщение принадлежит топику если его reply_to_msg_id равен topic_id
if message.reply_to_msg_id == self.config['topic_id']:
is_in_topic = True
# Также проверяем, если само сообщение является первым сообщением топика
elif message.id == self.config['topic_id']:
is_in_topic = True
is_in_topic = self._is_message_in_topic(message, self.config['topic_id'])
self.logger.debug(f"Сообщение ID {message.id}, reply_to_msg_id={getattr(message, 'reply_to_msg_id', None)}, нужен топик {self.config['topic_id']}, в топике: {is_in_topic}")
@@ -57,9 +47,82 @@ class TelegramNewsClient:
if title:
titles.append(title)
self.logger.debug(f"Извлечено {len(titles)} заголовков из Telegram сообщений")
self.logger.info(f"Извлечено {len(titles)} заголовков из Telegram сообщений: {titles[:5]}{'...' if len(titles) > 5 else ''}")
return messages, titles
def _is_message_in_topic(self, message, topic_id):
"""Проверка принадлежности сообщения к топику с улучшенной логикой"""
# Само сообщение является первым сообщением топика
if message.id == topic_id:
return True
# Проверяем прямой ответ на сообщение топика
if hasattr(message, 'reply_to_msg_id') and message.reply_to_msg_id:
if message.reply_to_msg_id == topic_id:
return True
# Дополнительная проверка: может быть это ответ на ответ в топике
# В некоторых случаях Telegram API может показывать вложенную структуру
try:
# Получаем информацию о сообщении, на которое отвечали
reply_to = message.reply_to
if reply_to and hasattr(reply_to, 'reply_to_msg_id'):
# Рекурсивно проверяем цепочку ответов
current_reply_id = reply_to.reply_to_msg_id
depth = 0
while current_reply_id and depth < 10: # Ограничиваем глубину для безопасности
if current_reply_id == topic_id:
return True
# В реальном случае здесь нужно было бы получать сообщение по ID
# Но это может быть слишком дорого по API запросам
break
except Exception as e:
self.logger.debug(f"Ошибка при проверке вложенной структуры ответов: {e}")
return False
def _check_duplicate_news(self, topic_title, tg_titles, tg_messages):
"""Улучшенная проверка дубликатов новостей с детальным логированием"""
# Проверяем точное совпадение с заголовками
title_exists = topic_title in tg_titles
if title_exists:
self.logger.debug(f"Найдено точное совпадение заголовка: '{topic_title}'")
return True
# Проверяем частичные совпадения в заголовках (нормализованные)
normalized_topic = topic_title.lower().strip()
for existing_title in tg_titles:
normalized_existing = existing_title.lower().strip()
if normalized_topic == normalized_existing:
self.logger.debug(f"Найдено нормализованное совпадение заголовка: '{topic_title}' == '{existing_title}'")
return True
# Проверяем наличие заголовка как части структурированного сообщения
# Ищем точное совпадение в формате "### Заголовок\t"
formatted_title = f"### {topic_title}\t"
for message in tg_messages:
if message and formatted_title in message:
self.logger.debug(f"Найдено совпадение форматированного заголовка в сообщении: '{formatted_title}'")
return True
# Дополнительная проверка: ищем заголовок в начале сообщений
for message in tg_messages:
if message:
message_lines = message.strip().split('\n')
if message_lines:
first_line = message_lines[0].strip()
# Убираем префиксы и сравниваем
import re
cleaned_first_line = re.sub(r'^[#*\s\t]+', '', first_line)
cleaned_first_line = re.sub(r'\t.*$', '', cleaned_first_line).strip()
if cleaned_first_line.lower() == normalized_topic:
self.logger.debug(f"Найдено совпадение в первой строке сообщения: '{cleaned_first_line}' == '{topic_title}'")
return True
self.logger.debug(f"Новость '{topic_title}' не найдена среди {len(tg_titles)} существующих заголовков")
return False
def _extract_title_from_message(self, message_text):
"""Извлечение заголовка из текста сообщения"""
import re
@@ -180,14 +243,14 @@ class TelegramNewsClient:
# Фильтруем новости для публикации
list_for_public = []
for topic_id, topic_title in news_list:
# Проверяем по заголовкам и по полному тексту сообщений
title_exists = any(topic_title == title for title in tg_titles)
text_contains = any(topic_title in (msg or '') for msg in tg_messages)
# Улучшенная проверка дубликатов
is_duplicate = self._check_duplicate_news(topic_title, tg_titles, tg_messages)
if not title_exists and not text_contains:
if not is_duplicate:
list_for_public.append((topic_id, topic_title))
self.logger.debug(f"Новость '{topic_title}' добавлена в список для публикации")
else:
self.logger.debug(f"Новость '{topic_title}' уже есть в Telegram (title_exists={title_exists}, text_contains={text_contains})")
self.logger.debug(f"Новость '{topic_title}' уже существует в Telegram, пропускаем")
if not list_for_public:
self.logger.warning("Новостей для публикации в Telegram нет")