import os import time import logging import threading import telebot from telebot import apihelper from groq import Groq import yt_dlp from flask import Flask, request from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import requests # --- 1. НАСТРОЙКИ --- logging.basicConfig(level=logging.INFO) app = Flask(__name__) BOT_TOKEN = os.environ.get("BOT_TOKEN") GROQ_KEY = os.environ.get("GROQ_KEY") SPACE_URL = os.environ.get("SPACE_URL") # --- УСИЛЕННАЯ СЕТЕВАЯ НАСТРОЙКА --- apihelper.CONNECT_TIMEOUT = 90 apihelper.READ_TIMEOUT = 90 # Создаем сессию с автоматическими повторами при ошибках SSL/сети def create_retry_session(): session = requests.Session() retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504]) adapter = HTTPAdapter(max_retries=retries) session.mount('https://', adapter) session.mount('http://', adapter) return session # Заставляем telebot использовать нашу защищенную сессию apihelper.CUSTOM_REQUEST_SENDER = lambda method, url, **kwargs: create_retry_session().request(method, url, **kwargs) bot = telebot.TeleBot(BOT_TOKEN, threaded=False) client = Groq(api_key=GROQ_KEY) BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # --- 2. ФУНКЦИИ ОБРАБОТКИ --- def translate_text(text): try: response = client.chat.completions.create( model="llama-3.3-70b-versatile", messages=[ {"role": "system", "content": "You are a direct translator from Dutch to Russian. No explanations."}, {"role": "user", "content": text} ], temperature=0.1 ) return response.choices[0].message.content except Exception as e: return f"[Ошибка перевода]: {e}" def transcribe_audio(file_path): try: with open(file_path, "rb") as f: result = client.audio.transcriptions.create( file=(os.path.basename(file_path), f.read()), model="whisper-large-v3", language="nl", response_format="text" ) return str(result) except Exception as e: return f"[Ошибка Whisper]: {e}" # --- 3. ФОНОВАЯ ЛОГИКА --- def run_async(func, *args, **kwargs): thr = threading.Thread(target=func, args=args, kwargs=kwargs) thr.start() def process_media_in_background(message): try: # Пытаемся отправить сообщение, игнорируя разовые ошибки сети try: status_msg = bot.reply_to(message, "⚡ Обрабатываю... (усиленное соединение)") except: status_msg = None if message.content_type == 'voice': file_id = message.voice.file_id ext = "ogg" elif message.content_type == 'video': file_id = message.video.file_id ext = "mp4" else: file_id = message.video_note.file_id ext = "mp4" file_info = bot.get_file(file_id) data = bot.download_file(file_info.file_path) path = os.path.join(BASE_DIR, f"temp_{file_id}.{ext}") with open(path, "wb") as f: f.write(data) text_nl = transcribe_audio(path) text_ru = translate_text(text_nl) final_text = f"🇳🇱 **NL:**\n{text_nl}\n\n🇷🇺 **RU:**\n{text_ru}" if status_msg: bot.edit_message_text(final_text, message.chat.id, status_msg.message_id) else: bot.send_message(message.chat.id, final_text) if os.path.exists(path): os.remove(path) except Exception as e: logging.error(f"Критическая ошибка: {e}") bot.send_message(message.chat.id, f"❌ Сетевая ошибка. Попробуй еще раз.") # --- 4. ОБРАБОТЧИКИ --- @bot.message_handler(commands=['start']) def start(message): bot.reply_to(message, "🤖 Бот усилен! Присылай медиа.") @bot.message_handler(content_types=['voice', 'video', 'video_note']) def handle_media(message): run_async(process_media_in_background, message) # --- 5. ВЕБХУК --- @app.route('/') def index(): return "Bot is running with SSL fix", 200 @app.route('/webhook', methods=['POST']) def webhook(): if request.headers.get('content-type') == 'application/json': json_string = request.get_data().decode('utf-8') update = telebot.types.Update.de_json(json_string) bot.process_new_updates([update]) return "ok", 200 return "forbidden", 403 @app.route('/setup') def setup(): try: if not SPACE_URL: return "Error: SPACE_URL missing", 500 clean_url = SPACE_URL.strip().rstrip('/') webhook_path = f"{clean_url}/webhook" bot.remove_webhook() time.sleep(2) bot.set_webhook(url=webhook_path, timeout=90) return f"✅ Соединение восстановлено! Вебхук: {webhook_path}", 200 except Exception as e: return f"❌ Ошибка при настройке: {e}", 500 if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)