#!/usr/bin/env python3 import os, sys, warnings # ========== FORCE FFMPEG PATH (NO WARNING) ========== FFMPEG_DIR = r"C:\Users\inter\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-8.1.1-full_build\bin" os.environ["PATH"] = FFMPEG_DIR + os.pathsep + os.environ.get("PATH", "") os.environ["PYDUB_FFMPEG"] = os.path.join(FFMPEG_DIR, "ffmpeg.exe") warnings.filterwarnings("ignore", category=RuntimeWarning, module="pydub.utils") # Monkey-patch pydub's which() from pydub.utils import which _original_which = which def _forced_which(prog): if prog in ('ffmpeg', 'avconv'): return os.environ["PYDUB_FFMPEG"] return _original_which(prog) import pydub.utils pydub.utils.which = _forced_which import pydub pydub.AudioSegment.converter = os.environ["PYDUB_FFMPEG"] # Other imports import json, time, asyncio, threading from http.server import HTTPServer, BaseHTTPRequestHandler from telegram import Update from telegram.ext import Application, MessageHandler, filters, ContextTypes import speech_recognition as sr # ==================== CONFIG ==================== TELEGRAM_TOKEN = "REPLACE WITH YOUR BOT TOKEN" ALLOWED_CHAT_ID = 000000000 #REPLACE WITH YOUR CHAT ID HTTP_PORT = 8082 command_queue = [] queue_lock = threading.Lock() result = None result_event = threading.Event() # ==================== HTTP SERVER ==================== class CommandHandler(BaseHTTPRequestHandler): def log_message(self, format, *args): pass def do_GET(self): if self.path == '/get_command': self.send_response(200) self.send_header('Content-Type', 'application/json') self.end_headers() with queue_lock: if command_queue: cmd = command_queue.pop(0) self.wfile.write(json.dumps(cmd).encode()) print(f"Served: {cmd}") else: self.wfile.write(json.dumps({"action": None}).encode()) else: self.send_response(404) def do_POST(self): if self.path == '/post_response': length = int(self.headers.get('Content-Length', 0)) raw = self.rfile.read(length) try: data_str = raw.decode('utf-8').strip().rstrip('\x00') global result result = json.loads(data_str) result_event.set() print(f"Result: {result}") except Exception as e: print(f"POST error: {e}") self.send_response(200) self.end_headers() else: self.send_response(404) def start_http_server(): server = HTTPServer(('127.0.0.1', HTTP_PORT), CommandHandler) print(f"✅ HTTP server on {HTTP_PORT}") server.serve_forever() # ==================== AUDIO ==================== def transcribe_audio(wav_path): recognizer = sr.Recognizer() with sr.AudioFile(wav_path) as src: recognizer.adjust_for_ambient_noise(src, 0.5) audio = recognizer.record(src) try: return recognizer.recognize_google(audio).lower() except: return "" def parse_command(text): text = text.lower().strip() if "close all" in text: return {"action": "CLOSE_ALL"} if "balance" in text: return {"action": "BALANCE"} action = None if text.startswith("buy"): action = "BUY" text = text[3:].strip() elif text.startswith("sell"): action = "SELL" text = text[4:].strip() else: return None # ✅ DEFAULT LOT SIZE = 0.001 (micro lot, ~$117 for EURUSD) volume = 0.001 words = text.split() for i, w in enumerate(words): if w == "half": volume = 0.5 words.pop(i) break elif w in ["one", "a"]: volume = 1.0 words.pop(i) break else: try: volume = float(w) words.pop(i) break except: pass sym_text = " ".join(words) m = {"gold": "XAUUSD", "euro": "EURUSD", "pound": "GBPUSD", "silver": "XAGUSD", "oil": "USOIL"} symbol = "EURUSD" for k, v in m.items(): if k in sym_text: symbol = v break return {"action": action, "symbol": symbol, "volume": volume} def cleanup(*files): for f in files: if os.path.exists(f): try: os.remove(f) except: pass async def handle_voice(update, context): if update.effective_chat.id != ALLOWED_CHAT_ID: await update.message.reply_text("Unauthorized") return await update.message.reply_text("🎤 Processing...") voice = await update.message.voice.get_file() ogg, wav = "temp.ogg", "temp.wav" try: await voice.download_to_drive(ogg) audio = pydub.AudioSegment.from_ogg(ogg) audio = audio.set_frame_rate(16000).set_channels(1) audio.export(wav, format="wav") text = transcribe_audio(wav) if not text: await update.message.reply_text("❌ Could not understand") return await update.message.reply_text(f"📝 Heard: {text}") cmd = parse_command(text) if not cmd: await update.message.reply_text("❌ Invalid command. Example: 'buy 0.001 euro'") return with queue_lock: command_queue.append(cmd) await update.message.reply_text("⏳ Sending to MT5...") global result result = None result_event.clear() if result_event.wait(timeout=10): if result and result.get("status") == "success": msg = f"✅ Success!\nTicket: {result['ticket']}\nPrice: {result['price']}" else: msg = f"❌ Error: {result.get('message') if result else 'Unknown'}" else: msg = "⏰ No response from MT5. Is EA running?" await update.message.reply_text(msg) except Exception as e: await update.message.reply_text(f"❌ {str(e)[:100]}") finally: cleanup(ogg, wav) async def error_handler(update, context): print(f"Telegram error: {context.error}") def main(): threading.Thread(target=start_http_server, daemon=True).start() app = Application.builder().token(TELEGRAM_TOKEN).build() app.add_handler(MessageHandler(filters.VOICE, handle_voice)) app.add_error_handler(error_handler) print("✅ Telegram bot polling...") app.run_polling() if __name__ == "__main__": main()