[ВОЛК] переход на прямого httpx клиента для постинга в телеграм
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2025-12-21 18:44:34 +03:00
parent de7fc5ad8a
commit ebaa7e89e4
+166 -93
View File
@@ -4,10 +4,8 @@ import httpx
import asyncio
import time
import sys
import json
from datetime import datetime
from telegram import Bot
from telegram.request import HTTPXRequest
from telegram.error import TelegramError, RetryAfter, TimedOut
from dotenv import load_dotenv
# Загрузка переменных окружения
@@ -132,44 +130,54 @@ async def test_telegram_publish():
logger.info(final_text)
logger.info("=" * 80)
# Создаем httpx клиент и бота с отключенным HTTP/2
# Создаем httpx клиент для прямых запросов к Telegram Bot API
httpx_client = None
try:
# Создаём клиент БЕЗ HTTP/2
# Создаём клиент БЕЗ HTTP/2 с указанными параметрами
logger.info("Создание httpx клиента с отключенным HTTP/2...")
httpx_client = httpx.AsyncClient(
http2=False, # ← отключаем HTTP/2
timeout=20.0, # явный таймаут
follow_redirects=True
)
logger.info("httpx клиент успешно создан с http2=False")
logger.info("httpx клиент успешно создан с http2=False, timeout=20.0")
# Создаем HTTPXRequest с явным указанием HTTP/1.1 (отключаем HTTP/2)
# HTTPXRequest автоматически создаст httpx клиент с http2=False при http_version="1.1"
logger.info("Создание HTTPXRequest с http_version='1.1' (HTTP/2 отключен)...")
request = HTTPXRequest(http_version="1.1", connection_pool_size=8)
logger.info("HTTPXRequest создан с http_version='1.1'")
# Примечание: HTTPXRequest создаст свой собственный httpx клиент с http2=False
# Наш httpx_client будет закрыт в finally, но не используется Bot'ом
# Это нормально - главное, что HTTP/2 отключен через http_version="1.1"
# Создаем бота с отключенным HTTP/2
logger.info("Создание объекта Bot с отключенным HTTP/2...")
bot = Bot(token=POSTER_BOT_TOKEN, request=request)
logger.info("Объект Bot успешно создан с отключенным HTTP/2")
# Получаем информацию о боте
# Получаем информацию о боте через Telegram Bot API
try:
logger.info("Попытка получения информации о боте через bot.get_me()...")
logger.debug(f"Параметры запроса get_me(): нет параметров (метод без аргументов)")
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 TimedOut as e:
logger.info("=" * 80)
logger.info("ПОПЫТКА ПОЛУЧЕНИЯ ИНФОРМАЦИИ О БОТЕ")
logger.info("=" * 80)
get_me_url = f"https://api.telegram.org/bot{POSTER_BOT_TOKEN}/getMe"
logger.info(f"URL запроса: {get_me_url}")
logger.info(f"Метод: GET")
start_time = datetime.now()
response = await httpx_client.get(get_me_url)
end_time = datetime.now()
duration = (end_time - start_time).total_seconds()
logger.info(f"Статус ответа: {response.status_code}")
logger.info(f"Время запроса: {duration:.2f} секунд")
if response.status_code == 200:
bot_info = response.json()
if bot_info.get('ok'):
result = bot_info.get('result', {})
logger.info("=" * 80)
logger.info("ИНФОРМАЦИЯ О БОТЕ УСПЕШНО ПОЛУЧЕНА!")
logger.info("=" * 80)
logger.info(f"ID: {result.get('id')}")
logger.info(f"Username: @{result.get('username')}")
logger.info(f"First name: {result.get('first_name')}")
logger.info(f"Is bot: {result.get('is_bot')}")
logger.info("=" * 80)
else:
logger.error(f"Ошибка в ответе API: {bot_info}")
else:
logger.error(f"HTTP ошибка: {response.status_code}")
logger.error(f"Текст ответа: {response.text}")
except httpx.TimeoutException as e:
logger.error("=" * 80)
logger.error("ТАЙМАУТ при получении информации о боте!")
logger.error("=" * 80)
@@ -177,32 +185,14 @@ async def test_telegram_publish():
logger.error(f"Сообщение: {str(e)}")
logger.error(f"Все атрибуты ошибки: {vars(e)}")
logger.error(f"Полное представление: {repr(e)}")
logger.error(f"Параметры запроса:")
logger.error(f" Метод: bot.get_me()")
logger.error(f" Токен: {'*' * 20 if POSTER_BOT_TOKEN else 'НЕ ЗАДАН'}")
logger.error(f" Длина токена: {len(POSTER_BOT_TOKEN) if POSTER_BOT_TOKEN else 0}")
except RetryAfter as e:
except httpx.HTTPError 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)}")
except TelegramError as e:
logger.error("=" * 80)
logger.error("ОШИБКА TELEGRAM при получении информации о боте!")
logger.error("ОШИБКА HTTP при получении информации о боте!")
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" Метод: bot.get_me()")
logger.error(f" Токен: {'*' * 20 if POSTER_BOT_TOKEN else 'НЕ ЗАДАН'}")
logger.error(f" Длина токена: {len(POSTER_BOT_TOKEN) if POSTER_BOT_TOKEN else 0}")
logger.error(f" Первые 10 символов токена: {POSTER_BOT_TOKEN[:10] if POSTER_BOT_TOKEN and len(POSTER_BOT_TOKEN) >= 10 else 'N/A'}")
except Exception as e:
logger.error("=" * 80)
logger.error("НЕОЖИДАННАЯ ОШИБКА при получении информации о боте!")
@@ -211,18 +201,17 @@ async def test_telegram_publish():
logger.error(f"Сообщение: {str(e)}")
logger.error(f"Все атрибуты ошибки: {vars(e) if hasattr(e, '__dict__') else 'N/A'}")
logger.error(f"Полное представление: {repr(e)}")
logger.error(f"Параметры запроса:")
logger.error(f" Метод: bot.get_me()")
logger.error(f" Токен: {'*' * 20 if POSTER_BOT_TOKEN else 'НЕ ЗАДАН'}")
logger.error(f" Длина токена: {len(POSTER_BOT_TOKEN) if POSTER_BOT_TOKEN else 0}")
import traceback
logger.error(f"Трассировка стека:\n{traceback.format_exc()}")
# Публикуем тестовое сообщение
# Публикуем тестовое сообщение через Telegram Bot API
try:
logger.info("=" * 80)
logger.info("ПОПЫТКА ОТПРАВКИ ТЕСТОВОГО СООБЩЕНИЯ")
logger.info("=" * 80)
send_message_url = f"https://api.telegram.org/bot{POSTER_BOT_TOKEN}/sendMessage"
logger.info(f"URL запроса: {send_message_url}")
logger.info(f"Метод: POST")
logger.info(f"Параметры запроса:")
logger.info(f" chat_id: {CHANNEL_ID}")
logger.info(f" text_length: {len(final_text)}")
@@ -230,31 +219,130 @@ async def test_telegram_publish():
logger.info(f" disable_notification: {PUBLISH_SILENTLY}")
logger.info(f" disable_web_page_preview: True")
payload = {
'chat_id': CHANNEL_ID,
'text': final_text,
'parse_mode': 'HTML',
'disable_notification': PUBLISH_SILENTLY,
'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
)
response = await httpx_client.post(send_message_url, json=payload)
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)
logger.info(f"Статус ответа: {response.status_code}")
logger.info(f"Время запроса: {duration:.2f} секунд")
return True
except TimedOut as e:
if response.status_code == 200:
result = response.json()
if result.get('ok'):
message_data = result.get('result', {})
message_id = message_data.get('message_id')
chat_data = message_data.get('chat', {})
logger.info("=" * 80)
logger.info("СООБЩЕНИЕ УСПЕШНО ОТПРАВЛЕНО!")
logger.info("=" * 80)
logger.info(f"Message ID: {message_id}")
logger.info(f"Chat ID: {chat_data.get('id')}")
logger.info(f"Chat type: {chat_data.get('type')}")
logger.info(f"Chat title: {chat_data.get('title', 'N/A')}")
logger.info(f"Время отправки: {duration:.2f} секунд")
logger.info(f"Дата сообщения: {message_data.get('date')}")
logger.info("=" * 80)
# Редактируем сообщение, добавляя информацию о редактировании
try:
logger.info("=" * 80)
logger.info("ПОПЫТКА РЕДАКТИРОВАНИЯ СООБЩЕНИЯ")
logger.info("=" * 80)
edit_message_url = f"https://api.telegram.org/bot{POSTER_BOT_TOKEN}/editMessageText"
logger.info(f"URL запроса: {edit_message_url}")
logger.info(f"Метод: POST")
logger.info(f"Параметры запроса:")
logger.info(f" chat_id: {CHANNEL_ID}")
logger.info(f" message_id: {message_id}")
# Добавляем информацию о редактировании в конец сообщения
edited_text = f"{final_text}\n\n<i>Сообщение отредактировано через httpx клиент</i>"
logger.info(f" text_length (после редактирования): {len(edited_text)}")
logger.info(f" parse_mode: HTML")
edit_payload = {
'chat_id': CHANNEL_ID,
'message_id': message_id,
'text': edited_text,
'parse_mode': 'HTML',
'disable_web_page_preview': True
}
edit_start_time = datetime.now()
edit_response = await httpx_client.post(edit_message_url, json=edit_payload)
edit_end_time = datetime.now()
edit_duration = (edit_end_time - edit_start_time).total_seconds()
logger.info(f"Статус ответа: {edit_response.status_code}")
logger.info(f"Время запроса: {edit_duration:.2f} секунд")
if edit_response.status_code == 200:
edit_result = edit_response.json()
if edit_result.get('ok'):
logger.info("=" * 80)
logger.info("СООБЩЕНИЕ УСПЕШНО ОТРЕДАКТИРОВАНО!")
logger.info("=" * 80)
logger.info(f"Время редактирования: {edit_duration:.2f} секунд")
logger.info("=" * 80)
else:
logger.error(f"Ошибка в ответе API при редактировании: {edit_result}")
else:
logger.error(f"HTTP ошибка при редактировании: {edit_response.status_code}")
logger.error(f"Текст ответа: {edit_response.text}")
except httpx.TimeoutException 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" message_id: {message_id}")
logger.error(f" text_length: {len(edited_text)}")
except httpx.HTTPError as e:
logger.error("=" * 80)
logger.error("ОШИБКА HTTP ПРИ РЕДАКТИРОВАНИИ СООБЩЕНИЯ!")
logger.error("=" * 80)
logger.error(f"Тип ошибки: {type(e).__name__}")
logger.error(f"Сообщение: {str(e)}")
logger.error(f"Все атрибуты ошибки: {vars(e)}")
logger.error(f"Полное представление: {repr(e)}")
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 True
else:
logger.error(f"Ошибка в ответе API: {result}")
logger.error(f"Описание ошибки: {result.get('description', 'N/A')}")
logger.error(f"Код ошибки: {result.get('error_code', 'N/A')}")
return False
else:
logger.error(f"HTTP ошибка: {response.status_code}")
logger.error(f"Текст ответа: {response.text}")
return False
except httpx.TimeoutException as e:
logger.error("=" * 80)
logger.error("ТАЙМАУТ ПРИ ОТПРАВКЕ СООБЩЕНИЯ!")
logger.error("=" * 80)
@@ -268,29 +356,14 @@ async def test_telegram_publish():
logger.error(f" parse_mode: HTML")
return False
except RetryAfter as e:
except httpx.HTTPError 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("ОШИБКА HTTP ПРИ ОТПРАВКЕ СООБЩЕНИЯ!")
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: