import os import logging import asyncio import time import sys from datetime import datetime from telegram import Bot from telegram.error import TelegramError, RetryAfter, TimedOut from dotenv import load_dotenv # Загрузка переменных окружения load_dotenv() # Настройки из переменных окружения POSTER_BOT_TOKEN = os.getenv('POSTER_BOT_TOKEN') RESPONDER_BOT_NAME = os.getenv('RESPONDER_BOT_NAME') CHANNEL_ID = os.getenv('CHANNEL_ID') DESC_PREFIX = os.getenv('DESC_PREFIX', '') PZK_PREFIX = os.getenv('PZK_PREFIX', '') MAX_CAPTION_LENGTH = int(os.getenv('MAX_CAPTION_LENGTH', 1000)) MAX_TEXT_LENGTH = int(os.getenv('MAX_TEXT_LENGTH', 4000)) PUBLISH_SILENTLY = os.getenv('PUBLISH_SILENTLY', 'false').lower() in ('true', '1', 'yes', 'on') USE_SUBSCRIPTION_BOT = os.getenv('USE_SUBSCRIPTION_BOT', 'true').lower() in ('true', '1', 'yes', 'on') # Настройка логирования LOG_FILE = 'volk_telegram_testing.log' logger = logging.getLogger('VOLK_TG_Test') logger.setLevel(logging.DEBUG) formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S') # Консольный обработчик console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) console_handler.setFormatter(formatter) logger.addHandler(console_handler) # Файловый обработчик с повторными попытками class RetryFileHandler(logging.FileHandler): def emit(self, record): for _ in range(5): try: super().emit(record) return except (IOError, PermissionError): time.sleep(0.5) print(f"Failed to write to log file after 5 attempts: {record.msg}") file_handler = RetryFileHandler(LOG_FILE, encoding='utf-8') file_handler.setLevel(logging.DEBUG) file_handler.setFormatter(formatter) logger.addHandler(file_handler) async def test_telegram_publish(): """Тестовая публикация сообщения в Telegram""" logger.info("=" * 80) logger.info("НАЧАЛО ТЕСТОВОЙ ПУБЛИКАЦИИ В TELEGRAM") logger.info("=" * 80) # Логируем загруженные параметры logger.info("Загруженные параметры из .env:") logger.info(f" POSTER_BOT_TOKEN: {'*' * 20 if POSTER_BOT_TOKEN else 'НЕ ЗАДАН'}") logger.info(f" RESPONDER_BOT_NAME: {RESPONDER_BOT_NAME}") logger.info(f" CHANNEL_ID: {CHANNEL_ID}") logger.info(f" DESC_PREFIX: {DESC_PREFIX}") logger.info(f" PZK_PREFIX: {PZK_PREFIX}") logger.info(f" MAX_CAPTION_LENGTH: {MAX_CAPTION_LENGTH}") logger.info(f" MAX_TEXT_LENGTH: {MAX_TEXT_LENGTH}") logger.info(f" PUBLISH_SILENTLY: {PUBLISH_SILENTLY}") logger.info(f" USE_SUBSCRIPTION_BOT: {USE_SUBSCRIPTION_BOT}") # Проверка обязательных параметров if not POSTER_BOT_TOKEN: logger.error("ОШИБКА: POSTER_BOT_TOKEN не задан в .env") return False if not CHANNEL_ID: logger.error("ОШИБКА: CHANNEL_ID не задан в .env") return False # Формируем тестовое сообщение test_number = "TEST001" test_tags = "#тест #volk_testing" test_unit_name = "Тестовая площадка" test_name = "Тестовое событие для проверки публикации" test_about = "Это тестовое сообщение для проверки работы публикации в Telegram. " * 5 # Формируем базовый текст base_text = f"{test_tags}\n{test_unit_name}\n{test_name}" base_text_length = len(base_text) # Формируем строку ссылок placeholder_message_id = '1234567890' if USE_SUBSCRIPTION_BOT: links_line = f'🔎 Инфо | 📌 Иду | 🔜 Подписка' else: links_line = f'🔎 Инфо' links_line_length = len(links_line) # Определяем максимальную длину max_length = MAX_CAPTION_LENGTH # Используем caption для теста # Вычисляем доступную длину для текста available_length = max_length - base_text_length - links_line_length - 3 if available_length < 0: available_length = 0 # Обрезаем about до доступной длины if len(test_about) > available_length: test_about = test_about[:available_length-3] + "..." # Формируем финальный текст final_text = f"{base_text}\n\n{test_about}\n\n{links_line}" # Логируем детали сообщения logger.info("=" * 80) logger.info("ДЕТАЛИ ТЕСТОВОГО СООБЩЕНИЯ:") logger.info("=" * 80) logger.info(f"Длина base_text: {base_text_length} символов") logger.info(f"Длина test_about: {len(test_about)} символов") logger.info(f"Длина links_line: {links_line_length} символов") logger.info(f"Максимальная длина (max_length): {max_length} символов") logger.info(f"Доступная длина для about: {available_length} символов") logger.info(f"Длина final_text: {len(final_text)} символов") logger.info(f"Используется изображение: НЕТ") logger.info("=" * 80) logger.info("ТЕКСТ СООБЩЕНИЯ:") logger.info("=" * 80) logger.info(final_text) logger.info("=" * 80) # Создаем бота try: logger.info("Создание объекта Bot...") bot = Bot(token=POSTER_BOT_TOKEN) logger.info("Объект Bot успешно создан") # Получаем информацию о боте try: bot_info = await bot.get_me() logger.info(f"Информация о боте:") logger.info(f" ID: {bot_info.id}") logger.info(f" Username: @{bot_info.username}") logger.info(f" First name: {bot_info.first_name}") logger.info(f" Is bot: {bot_info.is_bot}") except Exception as e: logger.warning(f"Не удалось получить информацию о боте: {e}") except Exception as e: logger.error(f"ОШИБКА при создании объекта Bot: {e}") logger.error(f" Тип ошибки: {type(e).__name__}") logger.error(f" Все атрибуты: {vars(e)}") return False # Публикуем тестовое сообщение try: logger.info("=" * 80) logger.info("ПОПЫТКА ОТПРАВКИ ТЕСТОВОГО СООБЩЕНИЯ") logger.info("=" * 80) logger.info(f"Параметры запроса:") logger.info(f" chat_id: {CHANNEL_ID}") logger.info(f" text_length: {len(final_text)}") logger.info(f" parse_mode: HTML") logger.info(f" disable_notification: {PUBLISH_SILENTLY}") logger.info(f" disable_web_page_preview: True") start_time = datetime.now() message = await bot.send_message( chat_id=CHANNEL_ID, text=final_text, parse_mode="HTML", disable_notification=PUBLISH_SILENTLY, disable_web_page_preview=True ) end_time = datetime.now() duration = (end_time - start_time).total_seconds() logger.info("=" * 80) logger.info("СООБЩЕНИЕ УСПЕШНО ОТПРАВЛЕНО!") logger.info("=" * 80) logger.info(f"Message ID: {message.message_id}") logger.info(f"Chat ID: {message.chat.id}") logger.info(f"Chat type: {message.chat.type}") logger.info(f"Chat title: {message.chat.title if hasattr(message.chat, 'title') else 'N/A'}") logger.info(f"Время отправки: {duration:.2f} секунд") logger.info(f"Дата сообщения: {message.date}") logger.info("=" * 80) return True except TimedOut as e: logger.error("=" * 80) logger.error("ТАЙМАУТ ПРИ ОТПРАВКЕ СООБЩЕНИЯ!") logger.error("=" * 80) logger.error(f"Тип ошибки: {type(e).__name__}") logger.error(f"Сообщение: {str(e)}") logger.error(f"Все атрибуты ошибки: {vars(e)}") logger.error(f"Полное представление: {repr(e)}") logger.error(f"Параметры запроса:") logger.error(f" chat_id: {CHANNEL_ID}") logger.error(f" text_length: {len(final_text)}") logger.error(f" parse_mode: HTML") return False except RetryAfter as e: logger.error("=" * 80) logger.error("ОШИБКА FLOODWAIT (429) ПРИ ОТПРАВКЕ СООБЩЕНИЯ!") logger.error("=" * 80) logger.error(f"Тип ошибки: {type(e).__name__}") logger.error(f"Сообщение: {str(e)}") logger.error(f"Необходимо подождать: {e.retry_after} секунд") logger.error(f"Все атрибуты ошибки: {vars(e)}") logger.error(f"Полное представление: {repr(e)}") return False except TelegramError as e: logger.error("=" * 80) logger.error("ОШИБКА TELEGRAM ПРИ ОТПРАВКЕ СООБЩЕНИЯ!") logger.error("=" * 80) logger.error(f"Тип ошибки: {type(e).__name__}") logger.error(f"Сообщение: {str(e)}") logger.error(f"Все атрибуты ошибки: {vars(e)}") logger.error(f"Полное представление: {repr(e)}") logger.error(f"Параметры запроса:") logger.error(f" chat_id: {CHANNEL_ID}") logger.error(f" text_length: {len(final_text)}") logger.error(f" parse_mode: HTML") return False except Exception as e: logger.error("=" * 80) logger.error("НЕОЖИДАННАЯ ОШИБКА ПРИ ОТПРАВКЕ СООБЩЕНИЯ!") logger.error("=" * 80) logger.error(f"Тип ошибки: {type(e).__name__}") logger.error(f"Сообщение: {str(e)}") logger.error(f"Все атрибуты ошибки: {vars(e) if hasattr(e, '__dict__') else 'N/A'}") logger.error(f"Полное представление: {repr(e)}") import traceback logger.error(f"Трассировка стека:\n{traceback.format_exc()}") return False async def main(): """Главная функция""" try: success = await test_telegram_publish() if success: logger.info("=" * 80) logger.info("ТЕСТ ЗАВЕРШЕН УСПЕШНО") logger.info("=" * 80) sys.exit(0) else: logger.error("=" * 80) logger.error("ТЕСТ ЗАВЕРШЕН С ОШИБКОЙ") logger.error("=" * 80) sys.exit(1) except KeyboardInterrupt: logger.warning("Прервано пользователем") sys.exit(1) except Exception as e: logger.error(f"Критическая ошибка: {e}") import traceback logger.error(f"Трассировка стека:\n{traceback.format_exc()}") sys.exit(1) if __name__ == "__main__": asyncio.run(main())