This commit is contained in:
+281
-88
@@ -4,9 +4,8 @@ import asyncio
|
|||||||
import pymysql
|
import pymysql
|
||||||
import time
|
import time
|
||||||
import html
|
import html
|
||||||
|
import httpx
|
||||||
from datetime import datetime, timezone, timedelta
|
from datetime import datetime, timezone, timedelta
|
||||||
from telegram import Bot, InlineKeyboardMarkup, InlineKeyboardButton
|
|
||||||
from telegram.error import TelegramError, RetryAfter, TimedOut
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from formatter import get_event_text
|
from formatter import get_event_text
|
||||||
|
|
||||||
@@ -61,6 +60,13 @@ file_handler = RetryFileHandler(LOG_FILE, encoding='utf-8')
|
|||||||
file_handler.setFormatter(formatter)
|
file_handler.setFormatter(formatter)
|
||||||
logger.addHandler(file_handler)
|
logger.addHandler(file_handler)
|
||||||
|
|
||||||
|
# Класс для обработки RetryAfter (FloodWait 429)
|
||||||
|
class RetryAfterException(Exception):
|
||||||
|
"""Исключение для обработки FloodWait (429) от Telegram API"""
|
||||||
|
def __init__(self, retry_after):
|
||||||
|
self.retry_after = retry_after
|
||||||
|
super().__init__(f"RetryAfter: {retry_after}")
|
||||||
|
|
||||||
def format_tags(tags_str):
|
def format_tags(tags_str):
|
||||||
"""Форматирование тегов с добавлением #"""
|
"""Форматирование тегов с добавлением #"""
|
||||||
if not tags_str:
|
if not tags_str:
|
||||||
@@ -84,7 +90,7 @@ def prepare_text(text):
|
|||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
async def tg_post_event(bot, event_data):
|
async def tg_post_event(httpx_client, event_data):
|
||||||
"""Публикация одного события"""
|
"""Публикация одного события"""
|
||||||
try:
|
try:
|
||||||
# Форматирование текста
|
# Форматирование текста
|
||||||
@@ -148,18 +154,48 @@ async def tg_post_event(bot, event_data):
|
|||||||
logger.info(f"Текст для публикации: {initial_text[:200]}..." if len(initial_text) > 200 else f"Текст для публикации: {initial_text}")
|
logger.info(f"Текст для публикации: {initial_text[:200]}..." if len(initial_text) > 200 else f"Текст для публикации: {initial_text}")
|
||||||
|
|
||||||
# Публикация первоначального сообщения без ссылок
|
# Публикация первоначального сообщения без ссылок
|
||||||
|
send_photo_url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendPhoto"
|
||||||
|
send_message_url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
|
||||||
|
|
||||||
if has_image:
|
if has_image:
|
||||||
try:
|
try:
|
||||||
logger.info(f"Попытка отправки фото для события {event_data['number']}: chat_id={CHANNEL_ID}, caption_length={len(initial_text)}, image_url_length={len(image_url)}")
|
logger.info(f"Попытка отправки фото для события {event_data['number']}: chat_id={CHANNEL_ID}, caption_length={len(initial_text)}, image_url_length={len(image_url)}")
|
||||||
message = await bot.send_photo(
|
photo_payload = {
|
||||||
chat_id=CHANNEL_ID,
|
'chat_id': CHANNEL_ID,
|
||||||
photo=image_url,
|
'photo': image_url,
|
||||||
caption=initial_text,
|
'caption': initial_text,
|
||||||
parse_mode="HTML",
|
'parse_mode': 'HTML',
|
||||||
disable_notification=PUBLISH_SILENTLY
|
'disable_notification': PUBLISH_SILENTLY
|
||||||
)
|
}
|
||||||
logger.info(f"Фото успешно отправлено для события {event_data['number']}, message_id={message.message_id}")
|
photo_response = await httpx_client.post(send_photo_url, json=photo_payload)
|
||||||
except TimedOut as e:
|
|
||||||
|
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')
|
||||||
|
logger.info(f"Фото успешно отправлено для события {event_data['number']}, message_id={message_id}")
|
||||||
|
else:
|
||||||
|
# Ошибка в ответе API - пробуем отправить текстовое сообщение
|
||||||
|
error_code = photo_result.get('error_code')
|
||||||
|
if error_code == 429:
|
||||||
|
# FloodWait - пробрасываем как RetryAfter
|
||||||
|
retry_after = photo_result.get('parameters', {}).get('retry_after', 60)
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"API error: {photo_result.get('description', 'Unknown error')}")
|
||||||
|
else:
|
||||||
|
if photo_response.status_code == 429:
|
||||||
|
# FloodWait
|
||||||
|
retry_after = 60
|
||||||
|
try:
|
||||||
|
error_data = photo_response.json()
|
||||||
|
retry_after = error_data.get('parameters', {}).get('retry_after', 60)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"HTTP {photo_response.status_code}: {photo_response.text}")
|
||||||
|
|
||||||
|
except httpx.TimeoutException as e:
|
||||||
logger.error(f"ТАЙМАУТ при отправке изображения для события номер {event_data['number']}")
|
logger.error(f"ТАЙМАУТ при отправке изображения для события номер {event_data['number']}")
|
||||||
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
@@ -172,24 +208,51 @@ async def tg_post_event(bot, event_data):
|
|||||||
logger.error(f" caption_length: {len(initial_text)}")
|
logger.error(f" caption_length: {len(initial_text)}")
|
||||||
logger.error(f" parse_mode: HTML")
|
logger.error(f" parse_mode: HTML")
|
||||||
raise
|
raise
|
||||||
except TelegramError as e:
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
if error_msg.startswith("RetryAfter:"):
|
||||||
|
retry_after = int(error_msg.split(":")[1])
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
logger.warning(f"Не удалось отправить изображение для события номер {event_data['number']}: {e}. Отправляем текстовое сообщение.")
|
logger.warning(f"Не удалось отправить изображение для события номер {event_data['number']}: {e}. Отправляем текстовое сообщение.")
|
||||||
logger.error(f"Полная информация об ошибке Telegram при отправке изображения для события {event_data['number']}:")
|
logger.error(f"Полная информация об ошибке Telegram при отправке изображения для события {event_data['number']}:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
logger.error(f" Сообщение: {str(e)}")
|
logger.error(f" Сообщение: {str(e)}")
|
||||||
logger.error(f" Все атрибуты ошибки: {vars(e)}")
|
logger.error(f" Все атрибуты ошибки: {vars(e) if hasattr(e, '__dict__') else 'N/A'}")
|
||||||
logger.error(f" Полное представление: {repr(e)}")
|
logger.error(f" Полное представление: {repr(e)}")
|
||||||
logger.info(f"Попытка отправки текстового сообщения вместо фото для события {event_data['number']}")
|
logger.info(f"Попытка отправки текстового сообщения вместо фото для события {event_data['number']}")
|
||||||
try:
|
try:
|
||||||
message = await bot.send_message(
|
text_payload = {
|
||||||
chat_id=CHANNEL_ID,
|
'chat_id': CHANNEL_ID,
|
||||||
text=initial_text,
|
'text': initial_text,
|
||||||
parse_mode="HTML",
|
'parse_mode': 'HTML',
|
||||||
disable_notification=PUBLISH_SILENTLY,
|
'disable_notification': PUBLISH_SILENTLY,
|
||||||
disable_web_page_preview=True # Отключаем предпросмотр ссылок
|
'disable_web_page_preview': True
|
||||||
)
|
}
|
||||||
logger.info(f"Текстовое сообщение успешно отправлено для события {event_data['number']}, message_id={message.message_id}")
|
text_response = await httpx_client.post(send_message_url, json=text_payload)
|
||||||
except TimedOut as e:
|
|
||||||
|
if text_response.status_code == 200:
|
||||||
|
text_result = text_response.json()
|
||||||
|
if text_result.get('ok'):
|
||||||
|
message_data = text_result.get('result', {})
|
||||||
|
message_id = message_data.get('message_id')
|
||||||
|
logger.info(f"Текстовое сообщение успешно отправлено для события {event_data['number']}, message_id={message_id}")
|
||||||
|
else:
|
||||||
|
error_code = text_result.get('error_code')
|
||||||
|
if error_code == 429:
|
||||||
|
retry_after = text_result.get('parameters', {}).get('retry_after', 60)
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"API error: {text_result.get('description', 'Unknown error')}")
|
||||||
|
else:
|
||||||
|
if text_response.status_code == 429:
|
||||||
|
retry_after = 60
|
||||||
|
try:
|
||||||
|
error_data = text_response.json()
|
||||||
|
retry_after = error_data.get('parameters', {}).get('retry_after', 60)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"HTTP {text_response.status_code}: {text_response.text}")
|
||||||
|
except httpx.TimeoutException as e:
|
||||||
logger.error(f"ТАЙМАУТ при отправке текстового сообщения для события номер {event_data['number']}")
|
logger.error(f"ТАЙМАУТ при отправке текстового сообщения для события номер {event_data['number']}")
|
||||||
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
@@ -201,18 +264,46 @@ async def tg_post_event(bot, event_data):
|
|||||||
logger.error(f" text_length: {len(initial_text)}")
|
logger.error(f" text_length: {len(initial_text)}")
|
||||||
logger.error(f" parse_mode: HTML")
|
logger.error(f" parse_mode: HTML")
|
||||||
raise
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
if error_msg.startswith("RetryAfter:"):
|
||||||
|
raise
|
||||||
|
raise
|
||||||
else:
|
else:
|
||||||
logger.info(f"Попытка отправки текстового сообщения для события {event_data['number']}: chat_id={CHANNEL_ID}, text_length={len(initial_text)}")
|
logger.info(f"Попытка отправки текстового сообщения для события {event_data['number']}: chat_id={CHANNEL_ID}, text_length={len(initial_text)}")
|
||||||
try:
|
try:
|
||||||
message = await bot.send_message(
|
text_payload = {
|
||||||
chat_id=CHANNEL_ID,
|
'chat_id': CHANNEL_ID,
|
||||||
text=initial_text,
|
'text': initial_text,
|
||||||
parse_mode="HTML",
|
'parse_mode': 'HTML',
|
||||||
disable_notification=PUBLISH_SILENTLY,
|
'disable_notification': PUBLISH_SILENTLY,
|
||||||
disable_web_page_preview=True # Отключаем предпросмотр ссылок
|
'disable_web_page_preview': True
|
||||||
)
|
}
|
||||||
logger.info(f"Текстовое сообщение успешно отправлено для события {event_data['number']}, message_id={message.message_id}")
|
text_response = await httpx_client.post(send_message_url, json=text_payload)
|
||||||
except TimedOut as e:
|
|
||||||
|
if text_response.status_code == 200:
|
||||||
|
text_result = text_response.json()
|
||||||
|
if text_result.get('ok'):
|
||||||
|
message_data = text_result.get('result', {})
|
||||||
|
message_id = message_data.get('message_id')
|
||||||
|
logger.info(f"Текстовое сообщение успешно отправлено для события {event_data['number']}, message_id={message_id}")
|
||||||
|
else:
|
||||||
|
error_code = text_result.get('error_code')
|
||||||
|
if error_code == 429:
|
||||||
|
retry_after = text_result.get('parameters', {}).get('retry_after', 60)
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"API error: {text_result.get('description', 'Unknown error')}")
|
||||||
|
else:
|
||||||
|
if text_response.status_code == 429:
|
||||||
|
retry_after = 60
|
||||||
|
try:
|
||||||
|
error_data = text_response.json()
|
||||||
|
retry_after = error_data.get('parameters', {}).get('retry_after', 60)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"HTTP {text_response.status_code}: {text_response.text}")
|
||||||
|
except httpx.TimeoutException as e:
|
||||||
logger.error(f"ТАЙМАУТ при отправке текстового сообщения для события номер {event_data['number']}")
|
logger.error(f"ТАЙМАУТ при отправке текстового сообщения для события номер {event_data['number']}")
|
||||||
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
@@ -225,9 +316,6 @@ async def tg_post_event(bot, event_data):
|
|||||||
logger.error(f" parse_mode: HTML")
|
logger.error(f" parse_mode: HTML")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
# Получаем ID сообщения для использования в ссылке подписки
|
|
||||||
message_id = message.message_id
|
|
||||||
|
|
||||||
# Формируем финальный текст с ссылками
|
# Формируем финальный текст с ссылками
|
||||||
if USE_SUBSCRIPTION_BOT:
|
if USE_SUBSCRIPTION_BOT:
|
||||||
links_line = f'🔎 <a href="{DESC_PREFIX}{number}/">Инфо</a> | 📌 <a href="{PZK_PREFIX}{number}/">Иду</a> | 🔜 <a href="https://t.me/{RESPONDER_BOT_NAME}?start=event_{message_id}">Подписка</a>'
|
links_line = f'🔎 <a href="{DESC_PREFIX}{number}/">Инфо</a> | 📌 <a href="{PZK_PREFIX}{number}/">Иду</a> | 🔜 <a href="https://t.me/{RESPONDER_BOT_NAME}?start=event_{message_id}">Подписка</a>'
|
||||||
@@ -239,16 +327,42 @@ async def tg_post_event(bot, event_data):
|
|||||||
|
|
||||||
# Редактируем сообщение, добавляя ссылки
|
# Редактируем сообщение, добавляя ссылки
|
||||||
logger.info(f"Попытка редактирования сообщения для события {event_data['number']}: message_id={message_id}, final_text_length={len(final_text)}")
|
logger.info(f"Попытка редактирования сообщения для события {event_data['number']}: message_id={message_id}, final_text_length={len(final_text)}")
|
||||||
|
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:
|
if has_image:
|
||||||
try:
|
try:
|
||||||
await bot.edit_message_caption(
|
edit_caption_payload = {
|
||||||
chat_id=CHANNEL_ID,
|
'chat_id': CHANNEL_ID,
|
||||||
message_id=message_id,
|
'message_id': message_id,
|
||||||
caption=final_text,
|
'caption': final_text,
|
||||||
parse_mode="HTML"
|
'parse_mode': 'HTML'
|
||||||
)
|
}
|
||||||
logger.info(f"Подпись успешно отредактирована для события {event_data['number']}")
|
edit_caption_response = await httpx_client.post(edit_caption_url, json=edit_caption_payload)
|
||||||
except TimedOut as e:
|
|
||||||
|
if edit_caption_response.status_code == 200:
|
||||||
|
edit_result = edit_caption_response.json()
|
||||||
|
if edit_result.get('ok'):
|
||||||
|
logger.info(f"Подпись успешно отредактирована для события {event_data['number']}")
|
||||||
|
else:
|
||||||
|
# Ошибка при редактировании подписи - пробуем редактировать текст
|
||||||
|
error_code = edit_result.get('error_code')
|
||||||
|
if error_code == 429:
|
||||||
|
retry_after = edit_result.get('parameters', {}).get('retry_after', 60)
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"API error: {edit_result.get('description', 'Unknown error')}")
|
||||||
|
else:
|
||||||
|
if edit_caption_response.status_code == 429:
|
||||||
|
retry_after = 60
|
||||||
|
try:
|
||||||
|
error_data = edit_caption_response.json()
|
||||||
|
retry_after = error_data.get('parameters', {}).get('retry_after', 60)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"HTTP {edit_caption_response.status_code}: {edit_caption_response.text}")
|
||||||
|
|
||||||
|
except httpx.TimeoutException as e:
|
||||||
logger.error(f"ТАЙМАУТ при редактировании подписи для события номер {event_data['number']}")
|
logger.error(f"ТАЙМАУТ при редактировании подписи для события номер {event_data['number']}")
|
||||||
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
@@ -261,24 +375,48 @@ async def tg_post_event(bot, event_data):
|
|||||||
logger.error(f" caption_length: {len(final_text)}")
|
logger.error(f" caption_length: {len(final_text)}")
|
||||||
logger.error(f" parse_mode: HTML")
|
logger.error(f" parse_mode: HTML")
|
||||||
raise
|
raise
|
||||||
except TelegramError as e:
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
if error_msg.startswith("RetryAfter:"):
|
||||||
|
raise
|
||||||
logger.warning(f"Не удалось отредактировать подпись для события номер {event_data['number']}: {e}. Пробуем отредактировать текстовое сообщение.")
|
logger.warning(f"Не удалось отредактировать подпись для события номер {event_data['number']}: {e}. Пробуем отредактировать текстовое сообщение.")
|
||||||
logger.error(f"Полная информация об ошибке Telegram при редактировании подписи для события {event_data['number']}:")
|
logger.error(f"Полная информация об ошибке Telegram при редактировании подписи для события {event_data['number']}:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
logger.error(f" Сообщение: {str(e)}")
|
logger.error(f" Сообщение: {str(e)}")
|
||||||
logger.error(f" Все атрибуты ошибки: {vars(e)}")
|
logger.error(f" Все атрибуты ошибки: {vars(e) if hasattr(e, '__dict__') else 'N/A'}")
|
||||||
logger.error(f" Полное представление: {repr(e)}")
|
logger.error(f" Полное представление: {repr(e)}")
|
||||||
logger.info(f"Попытка редактирования текста вместо подписи для события {event_data['number']}")
|
logger.info(f"Попытка редактирования текста вместо подписи для события {event_data['number']}")
|
||||||
try:
|
try:
|
||||||
await bot.edit_message_text(
|
edit_text_payload = {
|
||||||
chat_id=CHANNEL_ID,
|
'chat_id': CHANNEL_ID,
|
||||||
message_id=message_id,
|
'message_id': message_id,
|
||||||
text=final_text,
|
'text': final_text,
|
||||||
parse_mode="HTML",
|
'parse_mode': 'HTML',
|
||||||
disable_web_page_preview=True # Отключаем предпросмотр ссылок
|
'disable_web_page_preview': True
|
||||||
)
|
}
|
||||||
logger.info(f"Текст успешно отредактирован для события {event_data['number']}")
|
edit_text_response = await httpx_client.post(edit_text_url, json=edit_text_payload)
|
||||||
except TimedOut as e:
|
|
||||||
|
if edit_text_response.status_code == 200:
|
||||||
|
edit_result = edit_text_response.json()
|
||||||
|
if edit_result.get('ok'):
|
||||||
|
logger.info(f"Текст успешно отредактирован для события {event_data['number']}")
|
||||||
|
else:
|
||||||
|
error_code = edit_result.get('error_code')
|
||||||
|
if error_code == 429:
|
||||||
|
retry_after = edit_result.get('parameters', {}).get('retry_after', 60)
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"API error: {edit_result.get('description', 'Unknown error')}")
|
||||||
|
else:
|
||||||
|
if edit_text_response.status_code == 429:
|
||||||
|
retry_after = 60
|
||||||
|
try:
|
||||||
|
error_data = edit_text_response.json()
|
||||||
|
retry_after = error_data.get('parameters', {}).get('retry_after', 60)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"HTTP {edit_text_response.status_code}: {edit_text_response.text}")
|
||||||
|
except httpx.TimeoutException as e:
|
||||||
logger.error(f"ТАЙМАУТ при редактировании текста для события номер {event_data['number']}")
|
logger.error(f"ТАЙМАУТ при редактировании текста для события номер {event_data['number']}")
|
||||||
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
@@ -291,17 +429,43 @@ async def tg_post_event(bot, event_data):
|
|||||||
logger.error(f" text_length: {len(final_text)}")
|
logger.error(f" text_length: {len(final_text)}")
|
||||||
logger.error(f" parse_mode: HTML")
|
logger.error(f" parse_mode: HTML")
|
||||||
raise
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
if error_msg.startswith("RetryAfter:"):
|
||||||
|
raise
|
||||||
|
raise
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
await bot.edit_message_text(
|
edit_text_payload = {
|
||||||
chat_id=CHANNEL_ID,
|
'chat_id': CHANNEL_ID,
|
||||||
message_id=message_id,
|
'message_id': message_id,
|
||||||
text=final_text,
|
'text': final_text,
|
||||||
parse_mode="HTML",
|
'parse_mode': 'HTML',
|
||||||
disable_web_page_preview=True # Отключаем предпросмотр ссылок
|
'disable_web_page_preview': True
|
||||||
)
|
}
|
||||||
logger.info(f"Текст успешно отредактирован для события {event_data['number']}")
|
edit_text_response = await httpx_client.post(edit_text_url, json=edit_text_payload)
|
||||||
except TimedOut as e:
|
|
||||||
|
if edit_text_response.status_code == 200:
|
||||||
|
edit_result = edit_text_response.json()
|
||||||
|
if edit_result.get('ok'):
|
||||||
|
logger.info(f"Текст успешно отредактирован для события {event_data['number']}")
|
||||||
|
else:
|
||||||
|
error_code = edit_result.get('error_code')
|
||||||
|
if error_code == 429:
|
||||||
|
retry_after = edit_result.get('parameters', {}).get('retry_after', 60)
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"API error: {edit_result.get('description', 'Unknown error')}")
|
||||||
|
else:
|
||||||
|
if edit_text_response.status_code == 429:
|
||||||
|
retry_after = 60
|
||||||
|
try:
|
||||||
|
error_data = edit_text_response.json()
|
||||||
|
retry_after = error_data.get('parameters', {}).get('retry_after', 60)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
raise Exception(f"RetryAfter:{retry_after}")
|
||||||
|
raise Exception(f"HTTP {edit_text_response.status_code}: {edit_text_response.text}")
|
||||||
|
except httpx.TimeoutException as e:
|
||||||
logger.error(f"ТАЙМАУТ при редактировании текста для события номер {event_data['number']}")
|
logger.error(f"ТАЙМАУТ при редактировании текста для события номер {event_data['number']}")
|
||||||
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
@@ -317,17 +481,7 @@ async def tg_post_event(bot, event_data):
|
|||||||
|
|
||||||
return message_id # Возвращаем только message_id
|
return message_id # Возвращаем только message_id
|
||||||
|
|
||||||
except RetryAfter as e:
|
except httpx.TimeoutException as e:
|
||||||
# Обработка ошибки FloodWait (429)
|
|
||||||
logger.error(f"Получена ошибка FloodWait (429) при публикации события номер {event_data['number']}: {e}")
|
|
||||||
logger.error(f"Необходимо подождать {e.retry_after} секунд перед следующей попыткой")
|
|
||||||
logger.error(f"Полная информация об ошибке RetryAfter для события {event_data['number']}:")
|
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
|
||||||
logger.error(f" Сообщение: {str(e)}")
|
|
||||||
logger.error(f" Все атрибуты ошибки: {vars(e)}")
|
|
||||||
logger.error(f" Полное представление: {repr(e)}")
|
|
||||||
raise # Пробрасываем исключение выше для обработки на уровне цикла
|
|
||||||
except TimedOut as e:
|
|
||||||
logger.error(f"ТАЙМАУТ при публикации события номер {event_data['number']}")
|
logger.error(f"ТАЙМАУТ при публикации события номер {event_data['number']}")
|
||||||
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
logger.error(f"Полная диагностическая информация об ошибке TimedOut:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
@@ -341,12 +495,23 @@ async def tg_post_event(bot, event_data):
|
|||||||
logger.error(f" initial_text_length: {len(initial_text) if 'initial_text' in locals() else 'N/A'}")
|
logger.error(f" initial_text_length: {len(initial_text) if 'initial_text' in locals() else 'N/A'}")
|
||||||
logger.error(f" final_text_length: {len(final_text) if 'final_text' in locals() else 'N/A'}")
|
logger.error(f" final_text_length: {len(final_text) if 'final_text' in locals() else 'N/A'}")
|
||||||
return None
|
return None
|
||||||
except TelegramError as e:
|
except Exception as e:
|
||||||
|
error_msg = str(e)
|
||||||
|
if error_msg.startswith("RetryAfter:"):
|
||||||
|
# Обработка ошибки FloodWait (429)
|
||||||
|
retry_after = int(error_msg.split(":")[1])
|
||||||
|
logger.error(f"Получена ошибка FloodWait (429) при публикации события номер {event_data['number']}")
|
||||||
|
logger.error(f"Необходимо подождать {retry_after} секунд перед следующей попыткой")
|
||||||
|
logger.error(f"Полная информация об ошибке RetryAfter для события {event_data['number']}:")
|
||||||
|
logger.error(f" Тип ошибки: RetryAfter")
|
||||||
|
logger.error(f" Сообщение: {error_msg}")
|
||||||
|
logger.error(f" retry_after: {retry_after}")
|
||||||
|
raise RetryAfterException(retry_after)
|
||||||
logger.error(f"Ошибка Telegram при публикации события номер {event_data['number']}: {e}")
|
logger.error(f"Ошибка Telegram при публикации события номер {event_data['number']}: {e}")
|
||||||
logger.error(f"Полная информация об ошибке Telegram для события {event_data['number']}:")
|
logger.error(f"Полная информация об ошибке Telegram для события {event_data['number']}:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: {type(e).__name__}")
|
||||||
logger.error(f" Сообщение: {str(e)}")
|
logger.error(f" Сообщение: {str(e)}")
|
||||||
logger.error(f" Все атрибуты ошибки: {vars(e)}")
|
logger.error(f" Все атрибуты ошибки: {vars(e) if hasattr(e, '__dict__') else 'N/A'}")
|
||||||
logger.error(f" Полное представление: {repr(e)}")
|
logger.error(f" Полное представление: {repr(e)}")
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -402,8 +567,16 @@ async def tg_post_event_by_id(id_event):
|
|||||||
return
|
return
|
||||||
|
|
||||||
old_message_id = event.get('tg_message_id') # Сохраняем старый ID сообщения
|
old_message_id = event.get('tg_message_id') # Сохраняем старый ID сообщения
|
||||||
bot = Bot(token=BOT_TOKEN)
|
# Создаем httpx клиент с отключенным HTTP/2
|
||||||
tg_message_id = await tg_post_event(bot, event) # Получаем новый message_id
|
httpx_client = httpx.AsyncClient(
|
||||||
|
http2=False,
|
||||||
|
timeout=20.0,
|
||||||
|
follow_redirects=True
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
tg_message_id = await tg_post_event(httpx_client, event) # Получаем новый message_id
|
||||||
|
finally:
|
||||||
|
await httpx_client.aclose()
|
||||||
|
|
||||||
if tg_message_id:
|
if tg_message_id:
|
||||||
# Используем UTC время для записи в базу данных
|
# Используем UTC время для записи в базу данных
|
||||||
@@ -430,13 +603,25 @@ async def tg_post_event_by_id(id_event):
|
|||||||
else:
|
else:
|
||||||
logger.error(f"Не удалось опубликовать событие ID {id_event}")
|
logger.error(f"Не удалось опубликовать событие ID {id_event}")
|
||||||
|
|
||||||
except RetryAfter as e:
|
except Exception as e:
|
||||||
logger.error(f"Полная информация об ошибке RetryAfter в tg_post_event_by_id для события ID {id_event}:")
|
# Проверяем, не RetryAfter ли это
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
error_msg = str(e)
|
||||||
logger.error(f" Сообщение: {str(e)}")
|
if error_msg.startswith("RetryAfter:") or (hasattr(e, 'retry_after')):
|
||||||
logger.error(f" Все атрибуты ошибки: {vars(e)}")
|
retry_after = getattr(e, 'retry_after', int(error_msg.split(":")[1]) if ":" in error_msg else 60)
|
||||||
logger.error(f" Полное представление: {repr(e)}")
|
logger.error(f"Полная информация об ошибке RetryAfter в tg_post_event_by_id для события ID {id_event}:")
|
||||||
raise e
|
logger.error(f" Тип ошибки: RetryAfter")
|
||||||
|
logger.error(f" Сообщение: {error_msg}")
|
||||||
|
logger.error(f" retry_after: {retry_after}")
|
||||||
|
logger.error(f" Полное представление: {repr(e)}")
|
||||||
|
raise RetryAfterException(retry_after)
|
||||||
|
# Если это не RetryAfter, обрабатываем как обычную ошибку
|
||||||
|
if "RetryAfter" not in error_msg:
|
||||||
|
logger.error(f"Ошибка при публикации: {e}")
|
||||||
|
logger.error(f"Полная информация об ошибке в tg_post_event_by_id для события ID {id_event}:")
|
||||||
|
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)}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка при публикации: {e}")
|
logger.error(f"Ошибка при публикации: {e}")
|
||||||
logger.error(f"Полная информация об ошибке в tg_post_event_by_id для события ID {id_event}:")
|
logger.error(f"Полная информация об ошибке в tg_post_event_by_id для события ID {id_event}:")
|
||||||
@@ -497,14 +682,22 @@ async def tg_post_all_events():
|
|||||||
if event_count < len(events):
|
if event_count < len(events):
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|
||||||
except RetryAfter as e:
|
except RetryAfterException as e:
|
||||||
logger.error(f"Прерываем публикацию из-за ошибки FloodWait. Ожидание: {e.retry_after} секунд")
|
logger.error(f"Прерываем публикацию из-за ошибки FloodWait. Ожидание: {e.retry_after} секунд")
|
||||||
logger.error(f"Полная информация об ошибке RetryAfter в tg_post_all_events для события ID {event['id_event']}:")
|
logger.error(f"Полная информация об ошибке RetryAfter в tg_post_all_events для события ID {event['id_event']}:")
|
||||||
logger.error(f" Тип ошибки: {type(e).__name__}")
|
logger.error(f" Тип ошибки: RetryAfter")
|
||||||
logger.error(f" Сообщение: {str(e)}")
|
logger.error(f" Сообщение: {str(e)}")
|
||||||
logger.error(f" Все атрибуты ошибки: {vars(e)}")
|
logger.error(f" retry_after: {e.retry_after}")
|
||||||
logger.error(f" Полное представление: {repr(e)}")
|
logger.error(f" Полное представление: {repr(e)}")
|
||||||
break
|
break
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Ошибка при публикации события ID {event['id_event']}: {e}")
|
||||||
|
logger.error(f"Полная информация об ошибке в tg_post_all_events для события ID {event['id_event']}:")
|
||||||
|
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)}")
|
||||||
|
# Продолжаем публикацию следующих событий, несмотря на ошибку
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка при публикации события ID {event['id_event']}: {e}")
|
logger.error(f"Ошибка при публикации события ID {event['id_event']}: {e}")
|
||||||
logger.error(f"Полная информация об ошибке в tg_post_all_events для события ID {event['id_event']}:")
|
logger.error(f"Полная информация об ошибке в tg_post_all_events для события ID {event['id_event']}:")
|
||||||
|
|||||||
Reference in New Issue
Block a user