268 lines
12 KiB
Python
268 lines
12 KiB
Python
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<b>{test_name}</b>"
|
|
base_text_length = len(base_text)
|
|
|
|
# Формируем строку ссылок
|
|
placeholder_message_id = '1234567890'
|
|
if USE_SUBSCRIPTION_BOT:
|
|
links_line = f'🔎 <a href="{DESC_PREFIX}{test_number}/">Инфо</a> | 📌 <a href="{PZK_PREFIX}{test_number}/">Иду</a> | 🔜 <a href="https://t.me/{RESPONDER_BOT_NAME}?start=event_{placeholder_message_id}">Подписка</a>'
|
|
else:
|
|
links_line = f'🔎 <a href="{DESC_PREFIX}{test_number}/">Инфо</a>'
|
|
|
|
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())
|