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