Spaces:
Sleeping
Sleeping
| 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. ОБРАБОТЧИКИ --- | |
| def start(message): | |
| bot.reply_to(message, "🤖 Бот усилен! Присылай медиа.") | |
| def handle_media(message): | |
| run_async(process_media_in_background, message) | |
| # --- 5. ВЕБХУК --- | |
| def index(): | |
| return "Bot is running with SSL fix", 200 | |
| 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 | |
| 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) |