[ВОЛК] переключение на отправку изображения файлом
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
+50
-28
@@ -8,6 +8,7 @@ import json
|
||||
import re
|
||||
import httpx
|
||||
import traceback
|
||||
import io
|
||||
from datetime import datetime, timezone
|
||||
from dotenv import load_dotenv
|
||||
from formatter import get_event_text
|
||||
@@ -105,6 +106,24 @@ def log_telegram_error(response, context=""):
|
||||
except Exception as e:
|
||||
logger.error(f"{context} Ошибка при логировании информации об ошибке: {e}")
|
||||
|
||||
async def download_image(image_url, httpx_client):
|
||||
"""Скачивает изображение по URL и возвращает его содержимое в виде bytes"""
|
||||
try:
|
||||
logger.info(f"Скачивание изображения: {image_url}")
|
||||
download_start_time = time.time()
|
||||
|
||||
response = await httpx_client.get(image_url, timeout=httpx.Timeout(connect=10.0, read=60.0, write=30.0, pool=10.0))
|
||||
response.raise_for_status()
|
||||
|
||||
download_duration = time.time() - download_start_time
|
||||
image_data = response.content
|
||||
logger.info(f"Изображение скачано за {download_duration:.2f} секунд, размер: {len(image_data)} байт")
|
||||
|
||||
return image_data
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка при скачивании изображения {image_url}: {e}")
|
||||
raise
|
||||
|
||||
async def publish_to_tg(vk_post_id):
|
||||
"""Публикация одной записи по VK post ID"""
|
||||
logger.info(f"Запуск публикации для записи VK ID {vk_post_id}")
|
||||
@@ -151,6 +170,8 @@ async def publish_to_tg(vk_post_id):
|
||||
# Переменная для отслеживания успешности публикации
|
||||
message_id = None
|
||||
publication_successful = False
|
||||
# Флаг, указывающий, было ли отправлено изображение (True) или текстовое сообщение (False)
|
||||
message_has_image = False
|
||||
|
||||
try:
|
||||
# Проверяем наличие организационного хештега
|
||||
@@ -212,44 +233,40 @@ async def publish_to_tg(vk_post_id):
|
||||
logger.info(f"Длина URL изображения: {len(image_url)} символов")
|
||||
logger.info(f"Длина подписи: {len(text)} символов")
|
||||
|
||||
photo_payload = {
|
||||
'chat_id': CHANNEL_ID,
|
||||
'photo': image_url,
|
||||
'caption': text,
|
||||
'parse_mode': 'HTML',
|
||||
'disable_notification': PUBLISH_SILENTLY
|
||||
}
|
||||
# Скачиваем изображение
|
||||
try:
|
||||
image_data = await download_image(image_url, httpx_client)
|
||||
except Exception as download_error:
|
||||
logger.error(f"Ошибка при скачивании изображения для записи VK ID {vk_post_id}: {download_error}")
|
||||
raise # Пробрасываем ошибку, чтобы перейти к fallback
|
||||
|
||||
# Логируем время начала запроса
|
||||
request_start_time = time.time()
|
||||
logger.info(f"Начало запроса отправки фото в {datetime.now(timezone.utc).isoformat()}")
|
||||
|
||||
try:
|
||||
photo_response = await httpx_client.post(send_photo_url, json=photo_payload)
|
||||
request_duration = time.time() - request_start_time
|
||||
logger.info(f"Запрос отправки фото завершен за {request_duration:.2f} секунд")
|
||||
except httpx.TimeoutException as e:
|
||||
request_duration = time.time() - request_start_time
|
||||
logger.error(f"ТАЙМАУТ при отправке фото для записи VK ID {vk_post_id}")
|
||||
logger.error(f"Время до таймаута: {request_duration:.2f} секунд")
|
||||
logger.error(f"Тип исключения: {type(e).__name__}")
|
||||
logger.error(f"Сообщение об ошибке: {str(e)}")
|
||||
logger.error(f"Полная информация об исключении: {repr(e)}")
|
||||
logger.error(f"URL изображения: {image_url}")
|
||||
logger.error(f"Длина URL изображения: {len(image_url)} символов")
|
||||
if hasattr(e, 'request'):
|
||||
logger.error(f"Запрос, вызвавший таймаут: {e.request.method} {e.request.url if hasattr(e.request, 'url') else 'N/A'}")
|
||||
# Пытаемся получить информацию о таймауте из исключения
|
||||
if hasattr(e, 'timeout'):
|
||||
logger.error(f"Настройки таймаута: {e.timeout}")
|
||||
logger.error(f"Трассировка стека:\n{traceback.format_exc()}")
|
||||
raise # Пробрасываем таймаут наверх
|
||||
# Отправляем изображение как файл через multipart/form-data
|
||||
# Создаем BytesIO объект для файла
|
||||
image_file = io.BytesIO(image_data)
|
||||
files = {
|
||||
'photo': ('image.jpg', image_file, 'image/jpeg')
|
||||
}
|
||||
data = {
|
||||
'chat_id': CHANNEL_ID,
|
||||
'caption': text,
|
||||
'parse_mode': 'HTML',
|
||||
'disable_notification': str(PUBLISH_SILENTLY).lower()
|
||||
}
|
||||
|
||||
photo_response = await httpx_client.post(send_photo_url, files=files, data=data)
|
||||
request_duration = time.time() - request_start_time
|
||||
logger.info(f"Запрос отправки фото завершен за {request_duration:.2f} секунд")
|
||||
|
||||
if photo_response.status_code == 200:
|
||||
photo_result = photo_response.json()
|
||||
if photo_result.get('ok'):
|
||||
message_data = photo_result.get('result', {})
|
||||
message_id = message_data.get('message_id')
|
||||
message_has_image = True # Успешно отправили изображение
|
||||
else:
|
||||
# Ошибка в ответе API - логируем полную информацию
|
||||
log_telegram_error(photo_response, f"[Отправка фото для VK ID {vk_post_id}]")
|
||||
@@ -282,6 +299,7 @@ async def publish_to_tg(vk_post_id):
|
||||
raise # Пробрасываем таймаут наверх
|
||||
except Exception as e:
|
||||
logger.warning(f"Не удалось отправить изображение для записи VK ID {vk_post_id}: {e}. Отправляем текстовое сообщение.")
|
||||
message_has_image = False # Отправляем текстовое сообщение вместо изображения
|
||||
text_payload = {
|
||||
'chat_id': CHANNEL_ID,
|
||||
'text': text,
|
||||
@@ -326,6 +344,7 @@ async def publish_to_tg(vk_post_id):
|
||||
raise Exception(f"HTTP {text_response.status_code}: {text_response.text}")
|
||||
else:
|
||||
# Если это организационное сообщение или нет изображения, отправляем текстовое сообщение
|
||||
message_has_image = False # Отправляем текстовое сообщение
|
||||
text_payload = {
|
||||
'chat_id': CHANNEL_ID,
|
||||
'text': text,
|
||||
@@ -388,7 +407,10 @@ async def publish_to_tg(vk_post_id):
|
||||
edit_caption_url = f"https://api.telegram.org/bot{BOT_TOKEN}/editMessageCaption"
|
||||
edit_text_url = f"https://api.telegram.org/bot{BOT_TOKEN}/editMessageText"
|
||||
|
||||
if has_image and not is_org_message:
|
||||
# Используем message_has_image для определения типа сообщения
|
||||
# Если было отправлено изображение, редактируем caption, иначе - текст
|
||||
if message_has_image:
|
||||
# Сообщение с изображением - редактируем caption
|
||||
try:
|
||||
edit_caption_payload = {
|
||||
'chat_id': CHANNEL_ID,
|
||||
|
||||
Reference in New Issue
Block a user