[ВОЛК] коррекция бота под повторные попытки
This commit is contained in:
+135
-47
@@ -4,6 +4,7 @@ import time
|
|||||||
import errno
|
import errno
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
import telebot
|
import telebot
|
||||||
|
from telebot import apihelper
|
||||||
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
|
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
import pymysql
|
import pymysql
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
@@ -159,6 +160,11 @@ for name, value in required_vars.items():
|
|||||||
logger.error(f"Требуется переменная окружения {name}")
|
logger.error(f"Требуется переменная окружения {name}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
# Настройка таймаутов для Telegram API
|
||||||
|
apihelper.READ_TIMEOUT = 120 # Таймаут на чтение ответа (увеличен для больших сообщений)
|
||||||
|
apihelper.CONNECT_TIMEOUT = 30 # Таймаут на подключение
|
||||||
|
apihelper.RETRY_ON_TIMEOUT = True # Автоматические повторные попытки при таймауте
|
||||||
|
|
||||||
# Создаем экземпляр бота
|
# Создаем экземпляр бота
|
||||||
bot = telebot.TeleBot(RESPONDER_BOT_TOKEN)
|
bot = telebot.TeleBot(RESPONDER_BOT_TOKEN)
|
||||||
|
|
||||||
@@ -802,44 +808,89 @@ def download_image(image_url):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def send_post_message(chat_id, text, image_url=None, reply_markup=None):
|
def send_post_message(chat_id, text, image_url=None, reply_markup=None):
|
||||||
"""Отправляет сообщение с изображением или текстом"""
|
"""Отправляет сообщение с изображением или текстом с повторными попытками при таймауте"""
|
||||||
logger.info(f"starting send_post_message")
|
logger.info(f"starting send_post_message")
|
||||||
try:
|
|
||||||
# Дополнительная обрезка текста
|
|
||||||
if len(text) > UNIFIED_MAX_LENGTH:
|
|
||||||
text = text[:UNIFIED_MAX_LENGTH - 3] + "..."
|
|
||||||
|
|
||||||
if image_url:
|
# Параметры для повторных попыток при таймауте
|
||||||
# Загружаем изображение
|
max_retries = 5
|
||||||
image = download_image(image_url)
|
retry_interval = 2
|
||||||
if image:
|
|
||||||
# Отправляем фото с подписью
|
# Дополнительная обрезка текста
|
||||||
bot.send_photo(
|
if len(text) > UNIFIED_MAX_LENGTH:
|
||||||
chat_id,
|
text = text[:UNIFIED_MAX_LENGTH - 3] + "..."
|
||||||
photo=image,
|
|
||||||
caption=text,
|
if image_url:
|
||||||
reply_markup=reply_markup,
|
# Загружаем изображение
|
||||||
parse_mode='HTML'
|
image = download_image(image_url)
|
||||||
)
|
if image:
|
||||||
return True
|
# Отправляем фото с подписью с повторными попытками
|
||||||
|
for attempt in range(1, max_retries + 1):
|
||||||
|
try:
|
||||||
|
bot.send_photo(
|
||||||
|
chat_id,
|
||||||
|
photo=image,
|
||||||
|
caption=text,
|
||||||
|
reply_markup=reply_markup,
|
||||||
|
parse_mode='HTML'
|
||||||
|
)
|
||||||
|
logger.info(f"Сообщение с изображением успешно отправлено (попытка {attempt})")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
error_str = str(e)
|
||||||
|
# Проверяем, является ли это таймаутом
|
||||||
|
if 'timeout' in error_str.lower() or 'timed out' in error_str.lower():
|
||||||
|
if attempt < max_retries:
|
||||||
|
logger.warning(f"Таймаут при отправке фото (попытка {attempt}/{max_retries}), повтор через {retry_interval} сек...")
|
||||||
|
time.sleep(retry_interval)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logger.error(f"Таймаут при отправке фото после {max_retries} попыток: {e}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# Для других ошибок не повторяем
|
||||||
|
logger.error(f"Ошибка отправки фото: {e}")
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
logger.warning(f"Не удалось загрузить изображение: {image_url}")
|
||||||
|
|
||||||
|
# Если изображение отсутствует или не загружено, отправляем текст с повторными попытками
|
||||||
|
for attempt in range(1, max_retries + 1):
|
||||||
|
try:
|
||||||
|
bot.send_message(
|
||||||
|
chat_id,
|
||||||
|
text,
|
||||||
|
reply_markup=reply_markup,
|
||||||
|
parse_mode='HTML'
|
||||||
|
)
|
||||||
|
logger.info(f"Текстовое сообщение успешно отправлено (попытка {attempt})")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
error_str = str(e)
|
||||||
|
# Проверяем, является ли это таймаутом
|
||||||
|
if 'timeout' in error_str.lower() or 'timed out' in error_str.lower():
|
||||||
|
if attempt < max_retries:
|
||||||
|
logger.warning(f"Таймаут при отправке сообщения (попытка {attempt}/{max_retries}), повтор через {retry_interval} сек...")
|
||||||
|
time.sleep(retry_interval)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logger.error(f"Таймаут при отправке сообщения после {max_retries} попыток: {e}")
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Не удалось загрузить изображение: {image_url}")
|
# Для других ошибок не повторяем
|
||||||
|
logger.error(f"Ошибка отправки сообщения: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
# Если изображение отсутствует или не загружено, отправляем текст
|
return False
|
||||||
bot.send_message(
|
|
||||||
chat_id,
|
|
||||||
text,
|
|
||||||
reply_markup=reply_markup,
|
|
||||||
parse_mode='HTML'
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Ошибка отправки сообщения: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def send_direct_message(user_id, message_text):
|
def send_direct_message(user_id, message_text):
|
||||||
"""Отправляет сообщение пользователю по ID с обработкой ошибок"""
|
"""Отправляет сообщение пользователю по ID с обработкой ошибок и повторными попытками при таймауте"""
|
||||||
logger.info(f"starting send_direct_message")
|
logger.info(f"starting send_direct_message")
|
||||||
|
|
||||||
|
# Параметры для повторных попыток при таймауте
|
||||||
|
max_retries = 5
|
||||||
|
retry_interval = 2
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Проверяем, что сообщение не пустое
|
# Проверяем, что сообщение не пустое
|
||||||
if not message_text or not message_text.strip():
|
if not message_text or not message_text.strip():
|
||||||
@@ -848,17 +899,35 @@ def send_direct_message(user_id, message_text):
|
|||||||
log_event("error", f"user_{user_id}", message=error_msg)
|
log_event("error", f"user_{user_id}", message=error_msg)
|
||||||
return False, error_msg
|
return False, error_msg
|
||||||
|
|
||||||
# Отправляем сообщение
|
# Отправляем сообщение с повторными попытками
|
||||||
bot.send_message(
|
for attempt in range(1, max_retries + 1):
|
||||||
user_id,
|
try:
|
||||||
message_text,
|
bot.send_message(
|
||||||
parse_mode='HTML'
|
user_id,
|
||||||
)
|
message_text,
|
||||||
|
parse_mode='HTML'
|
||||||
|
)
|
||||||
|
|
||||||
# Логируем успешную отправку
|
# Логируем успешную отправку
|
||||||
log_event("info", f"user_{user_id}", message=f"Сообщение отправлено: {message_text[:50]}...")
|
log_event("info", f"user_{user_id}", message=f"Сообщение отправлено: {message_text[:50]}...")
|
||||||
logger.info(f"Сообщение успешно отправлено пользователю {user_id}")
|
logger.info(f"Сообщение успешно отправлено пользователю {user_id} (попытка {attempt})")
|
||||||
return True, "Сообщение отправлено успешно"
|
return True, "Сообщение отправлено успешно"
|
||||||
|
except Exception as e:
|
||||||
|
error_str = str(e)
|
||||||
|
# Проверяем, является ли это таймаутом
|
||||||
|
if 'timeout' in error_str.lower() or 'timed out' in error_str.lower():
|
||||||
|
if attempt < max_retries:
|
||||||
|
logger.warning(f"Таймаут при отправке сообщения пользователю {user_id} (попытка {attempt}/{max_retries}), повтор через {retry_interval} сек...")
|
||||||
|
time.sleep(retry_interval)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
error_msg = f"Таймаут при отправке сообщения после {max_retries} попыток: {e}"
|
||||||
|
logger.error(error_msg)
|
||||||
|
log_event("error", f"user_{user_id}", message=error_msg)
|
||||||
|
return False, f"Таймаут при отправке сообщения. Попробуйте позже."
|
||||||
|
else:
|
||||||
|
# Для других ошибок выходим из цикла и обрабатываем дальше
|
||||||
|
break
|
||||||
|
|
||||||
except telebot.apihelper.ApiTelegramException as e:
|
except telebot.apihelper.ApiTelegramException as e:
|
||||||
error_msg = f"Ошибка Telegram API: {e}"
|
error_msg = f"Ошибка Telegram API: {e}"
|
||||||
@@ -963,12 +1032,31 @@ def handle_start(message):
|
|||||||
# Команда /start без параметров
|
# Команда /start без параметров
|
||||||
welcome_text = get_welcome_text()
|
welcome_text = get_welcome_text()
|
||||||
|
|
||||||
bot.send_message(
|
# Отправляем приветственное сообщение с повторными попытками при таймауте
|
||||||
message.chat.id,
|
max_retries = 5
|
||||||
welcome_text,
|
retry_interval = 2
|
||||||
reply_markup=create_main_keyboard(),
|
for attempt in range(1, max_retries + 1):
|
||||||
parse_mode='HTML'
|
try:
|
||||||
)
|
bot.send_message(
|
||||||
|
message.chat.id,
|
||||||
|
welcome_text,
|
||||||
|
reply_markup=create_main_keyboard(),
|
||||||
|
parse_mode='HTML'
|
||||||
|
)
|
||||||
|
logger.info(f"Приветственное сообщение отправлено (попытка {attempt})")
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
error_str = str(e)
|
||||||
|
if 'timeout' in error_str.lower() or 'timed out' in error_str.lower():
|
||||||
|
if attempt < max_retries:
|
||||||
|
logger.warning(f"Таймаут при отправке приветственного сообщения (попытка {attempt}/{max_retries}), повтор через {retry_interval} сек...")
|
||||||
|
time.sleep(retry_interval)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
logger.error(f"Таймаут при отправке приветственного сообщения после {max_retries} попыток: {e}")
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = f"Ошибка в обработке /start: {e}"
|
error_msg = f"Ошибка в обработке /start: {e}"
|
||||||
logger.error(error_msg)
|
logger.error(error_msg)
|
||||||
|
|||||||
Reference in New Issue
Block a user