Opera8 commited on
Commit
ae50d23
·
verified ·
1 Parent(s): c29619c

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +74 -53
main.py CHANGED
@@ -5,6 +5,7 @@ import aiohttp
5
  import traceback
6
  import asyncio
7
  import base64
 
8
  from flask import Flask
9
  from rubpy.bot import BotClient, filters
10
 
@@ -17,7 +18,7 @@ app = Flask(__name__)
17
 
18
  @app.route('/')
19
  def home():
20
- return "ربات یکپارچه آلفا (نسخه پرو با تحلیل فایل و STT) روشن است! 🚀"
21
 
22
  def run_flask():
23
  app.run(host="0.0.0.0", port=7860)
@@ -64,11 +65,9 @@ MAIN_KEYPAD_DICT = {
64
  # --- تابع ارسال منحصراً برای کیبورد پایین صفحه ---
65
  async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
66
  if not use_keyboard:
67
- # ارسال پیام متنی خالص بدون دستکاری کیبورد
68
  msg = await client.send_message(chat_id, text)
69
  return msg
70
 
71
- # ارسال تهاجمی: دور زدن محدودیت‌های rubpy
72
  try:
73
  payload = {
74
  "chat_id": chat_id,
@@ -85,7 +84,6 @@ async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
85
  except Exception as standard_err:
86
  pass
87
 
88
- # اگر تمامی روش‌ها شکست خورد، فقط پیام ارسال شود
89
  msg = await client.send_message(chat_id, text)
90
  return msg
91
 
@@ -126,16 +124,14 @@ HF_TOKENS = [k.strip() for k in HF_TOKENS_STR.split(",") if k.strip()]
126
  user_states = {}
127
 
128
 
129
- # --- ۱. پردازش چت متنی در پس‌زمینه (با حذف پیام پردازش) ---
130
  async def process_gemini(client, chat_id, prompt):
131
  if not GEMINI_KEYS:
132
  await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشده‌اند.", False)
133
  return
134
 
135
- # ارسال پیام موقت "در حال پردازش..."
136
  proc_msg = await send_with_keyboard(client, chat_id, "🧠 در حال پردازش...", False)
137
 
138
- # استخراج تاریخچه مکالمات کاربر
139
  history = user_states[chat_id].get("history", [])
140
 
141
  if history and history[-1]["role"] == "user":
@@ -170,7 +166,6 @@ async def process_gemini(client, chat_id, prompt):
170
  except Exception as e:
171
  continue
172
 
173
- # 🔴 پاک کردن پیام موقت "در حال پردازش..."
174
  try:
175
  if proc_msg:
176
  msg_id = getattr(proc_msg, 'message_id', None)
@@ -178,8 +173,7 @@ async def process_gemini(client, chat_id, prompt):
178
  msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
179
  if msg_id:
180
  await client.delete_messages(chat_id, [msg_id])
181
- except Exception as e:
182
- print(f"Failed to delete processing msg: {e}")
183
 
184
  if not final_answer:
185
  if history and history[-1]["role"] == "user":
@@ -215,14 +209,14 @@ async def process_gemini(client, chat_id, prompt):
215
  try:
216
  await send_with_keyboard(client, chat_id, chunk, False)
217
  await asyncio.sleep(2.5)
218
- except Exception as send_err:
219
  await asyncio.sleep(2.5)
220
 
221
- except Exception as e:
222
  await send_with_keyboard(client, chat_id, "❌ خطایی در ارسال پیام رخ داد.", False)
223
 
224
 
225
- # --- ۲. پردازش ساخت عکس در پس‌زمینه ---
226
  async def process_image(client, chat_id, prompt):
227
  if not HF_TOKENS:
228
  await send_with_keyboard(client, chat_id, "❌ توکن‌های هاگینگ فیس تنظیم نشده‌اند.", False)
@@ -245,7 +239,6 @@ async def process_image(client, chat_id, prompt):
245
  last_error_log = str(e)
246
  continue
247
 
248
- # پاک کردن پیام موقت
249
  try:
250
  if proc_msg:
251
  msg_id = getattr(proc_msg, 'message_id', None)
@@ -285,11 +278,11 @@ async def process_image(client, chat_id, prompt):
285
  if os.path.exists(file_name):
286
  os.remove(file_name)
287
 
288
- except Exception as e:
289
  await send_with_keyboard(client, chat_id, "❌ خطایی در فرآیند ذخیره عکس رخ داد.", True)
290
 
291
 
292
- # --- ۳. پردازش ساخت صدا در پس‌زمینه (TTS) ---
293
  async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
294
  try:
295
  proc_msg = await send_with_keyboard(client, chat_id, f"⏳ در حال ساخت صدا با «{speaker_name}»...\n(لطفاً صبور باشید)", False)
@@ -324,7 +317,6 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
324
  last_error = f"خطا در ارتباط: {str(e)}"
325
  continue
326
 
327
- # پاک کردن پیام موقت
328
  try:
329
  if proc_msg:
330
  msg_id = getattr(proc_msg, 'message_id', None)
@@ -361,11 +353,11 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
361
  else:
362
  await send_with_keyboard(client, chat_id, f"❌ سرورها درگیر هستند.\nدلیل: {last_error}", True)
363
 
364
- except Exception as e:
365
  traceback.print_exc()
366
 
367
 
368
- # --- ۴. پردازش تبدیل فایل صوتی به متن (STT) ---
369
  async def process_stt(client, chat_id, audio_bytes):
370
  if not HF_TOKENS:
371
  await send_with_keyboard(client, chat_id, "❌ توکن‌های هاگینگ فیس تنظیم نشده‌اند.", False)
@@ -381,7 +373,6 @@ async def process_stt(client, chat_id, audio_bytes):
381
 
382
  for token in keys_to_try:
383
  try:
384
- # استفاده از مدل قدرتمند ویسپر برای تبدیل صدا به متن (پشتیبانی عالی از فارسی)
385
  hf_client = AsyncInferenceClient(provider="hf-inference", api_key=token)
386
  response = await hf_client.automatic_speech_recognition(audio_bytes, model="openai/whisper-large-v3-turbo")
387
  transcribed_text = response.text
@@ -390,7 +381,6 @@ async def process_stt(client, chat_id, audio_bytes):
390
  last_error_log = str(e)
391
  continue
392
 
393
- # پاک کردن پیام موقت
394
  try:
395
  if proc_msg:
396
  msg_id = getattr(proc_msg, 'message_id', None)
@@ -403,20 +393,31 @@ async def process_stt(client, chat_id, audio_bytes):
403
  if transcribed_text:
404
  await send_with_keyboard(client, chat_id, f"📝 **متن استخراج شده:**\n\n{transcribed_text}", True)
405
  else:
406
- await send_with_keyboard(client, chat_id, f"❌ متأسفانه تبدیل صدا به متن ناموفق بود.\n\n⚠️ دلیل: {last_error_log[:150]}", True)
407
 
408
 
409
- # --- ۵. پردازش تحلیل فایل (عکس) با جیمینای ---
410
- async def process_file_analysis(client, chat_id, file_bytes, prompt):
411
  if not GEMINI_KEYS:
412
  await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشده‌اند.", False)
413
  return
414
 
415
- proc_msg = await send_with_keyboard(client, chat_id, "👁️ در حال تحلیل و بررسی فایل...", False)
416
 
417
- # تبدیل فایل به base64 برای ارسال به جیمینای
418
  base64_data = base64.b64encode(file_bytes).decode('utf-8')
419
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  keys_to_try = GEMINI_KEYS.copy()
421
  random.shuffle(keys_to_try)
422
  final_answer = None
@@ -428,7 +429,7 @@ async def process_file_analysis(client, chat_id, file_bytes, prompt):
428
  "contents": [{
429
  "parts": [
430
  {"text": prompt},
431
- {"inlineData": {"mimeType": "image/jpeg", "data": base64_data}}
432
  ]
433
  }],
434
  "generationConfig": {"temperature": 0.6, "maxOutputTokens": 8192}
@@ -444,10 +445,9 @@ async def process_file_analysis(client, chat_id, file_bytes, prompt):
444
  continue
445
  else:
446
  continue
447
- except Exception as e:
448
  continue
449
 
450
- # پاک کردن پیام موقت
451
  try:
452
  if proc_msg:
453
  msg_id = getattr(proc_msg, 'message_id', None)
@@ -460,7 +460,7 @@ async def process_file_analysis(client, chat_id, file_bytes, prompt):
460
  if final_answer:
461
  await send_with_keyboard(client, chat_id, f"💡 **نتیجه تحلیل:**\n\n{final_answer}", True)
462
  else:
463
- await send_with_keyboard(client, chat_id, "❌ متأسفانه در حال حاضر پاسخی برای این ��ایل دریافت نشد.", True)
464
 
465
 
466
  # --- تنظیمات ربات روبیکا ---
@@ -474,27 +474,45 @@ else:
474
  @bot.on_update(filters.private)
475
  async def main_handler(client, update):
476
  try:
477
- # استخراج اطلاعات پیام
478
  user_text = getattr(update, "text", "") or getattr(getattr(update, "message", None), "text", "") or getattr(getattr(update, "new_message", None), "text", "")
479
  user_text_str = str(user_text).strip() if user_text else ""
480
 
481
- # بررسی وجود فایل پیوست در پیام
482
  is_file = False
 
483
  msg_obj = getattr(update, "message", None) or getattr(update, "new_message", None)
 
484
  if msg_obj:
485
- if getattr(msg_obj, "file_inline", None) or getattr(msg_obj, "photo", None) or getattr(msg_obj, "voice", None) or getattr(msg_obj, "audio", None) or getattr(msg_obj, "document", None):
486
- is_file = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
 
488
  chat_id = getattr(update, "chat_id", None) or getattr(update, "author_guid", None) or getattr(update, "object_guid", None)
489
  if not chat_id:
490
  return
491
 
492
  if chat_id not in user_states:
493
- user_states[chat_id] = {"mode": None, "text": "", "history": [], "file_bytes": None}
494
 
495
- # مدیریت کامندهای لغو/شروع از دکمه‌ها یا چت
496
  if user_text_str in ["/start", "سلام", "لغو", "/cancel", "❌ لغو", "برگشت♻️"]:
497
- user_states[chat_id] = {"mode": None, "text": "", "history": [], "file_bytes": None}
498
  menu = (
499
  "سلام! به ربات هوشمند آلفا خوش آمدید 🤖\n\n"
500
  "لطفاً برای شروع، از کیبورد پایین یکی از بخش‌ها را انتخاب کنید:"
@@ -518,20 +536,20 @@ else:
518
  return
519
 
520
  if user_text_str in ["/file", "تحلیل فایل با هوش مصنوعی 📁"]:
521
- user_states[chat_id] = {"mode": "file_waiting_for_file", "text": "", "history": [], "file_bytes": None}
522
- await send_with_keyboard(client, chat_id, "📁 شما وارد بخش **تحلیل فایل** شدید.\n\nلطفاً فایل (ترجیحاً عکس) خود را ارسال کنید:\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
523
  return
524
 
525
  if user_text_str in ["/stt", "تبدیل فایل صوتی به متن 📝"]:
526
  user_states[chat_id] = {"mode": "stt_waiting_for_audio", "text": "", "history": []}
527
- await send_with_keyboard(client, chat_id, "📝 شما وارد بخش **تبدیل صدا به متن** شدید.\n\nلطفاً فایل صوتی (آهنگ یا ویس) خود را فوروارد یا ارسال کنید:\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
528
  return
529
 
530
  current_mode = user_states[chat_id].get("mode")
531
 
532
  if current_mode is None:
533
  if is_file:
534
- pass # اگر حالت مشخص نیست فایل را نادیده بگیر
535
  elif user_text_str:
536
  await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا از کیبورد پایین، بخش مورد نظرتان را انتخاب کنید:", True)
537
  return
@@ -586,45 +604,48 @@ else:
586
  # --- بخش جدید: STT (تبدیل صدا به متن) ---
587
  elif current_mode == "stt_waiting_for_audio":
588
  if not is_file:
589
- await send_with_keyboard(client, chat_id, "⚠️ لطفاً فقط یک فایل صوتی (ویس یا موزیک) ارسال کنید.", False)
590
  return
591
 
592
- await send_with_keyboard(client, chat_id, "📥 در حال دانلود فایل صوتی...", False)
593
  try:
594
  audio_bytes = await client.download(msg_obj)
595
- user_states[chat_id]["mode"] = "stt_waiting_for_audio" # آماده برای فایل بعدی
596
  asyncio.create_task(process_stt(client, chat_id, audio_bytes))
597
- except Exception as e:
598
- await send_with_keyboard(client, chat_id, f"❌ خطا در دانلود فایل! لطفاً دوباره تلاش کنید.", False)
599
  return
600
 
601
  # --- بخش جدید: تحلیل فایل با هوش مصنوعی ---
602
  elif current_mode == "file_waiting_for_file":
603
  if not is_file:
604
- await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا یک عکس/فایل ارسال کنید.", False)
605
  return
606
 
607
  await send_with_keyboard(client, chat_id, "📥 در حال دریافت فایل...", False)
608
  try:
609
  file_bytes = await client.download(msg_obj)
610
  user_states[chat_id]["file_bytes"] = file_bytes
 
611
  user_states[chat_id]["mode"] = "file_waiting_for_prompt"
612
- await send_with_keyboard(client, chat_id, "✅ فایل با موفقیت دریافت شد.\n\nحالا لطفاً بگویید **چگونه تحلیل شود؟** (مثلاً: متن داخل این عکس را استخراج کن، یا بگو در این عکس چیست؟)", False)
613
- except Exception as e:
614
- await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت فایل! لطفاً دوباره تلاش کنید.", False)
615
  return
616
 
617
  elif current_mode == "file_waiting_for_prompt":
618
  if user_text_str:
619
  saved_bytes = user_states[chat_id].get("file_bytes")
620
- user_states[chat_id]["mode"] = "file_waiting_for_file" # آماده برای فایل بعدی
 
621
  user_states[chat_id]["file_bytes"] = None
622
- asyncio.create_task(process_file_analysis(client, chat_id, saved_bytes, user_text_str))
 
623
  else:
624
  await send_with_keyboard(client, chat_id, "⚠️ لطفاً درخواست خود را به صورت متنی بنویسید.", False)
625
  return
626
 
627
- except Exception as e:
628
  traceback.print_exc()
629
 
630
  if __name__ == "__main__":
 
5
  import traceback
6
  import asyncio
7
  import base64
8
+ import mimetypes
9
  from flask import Flask
10
  from rubpy.bot import BotClient, filters
11
 
 
18
 
19
  @app.route('/')
20
  def home():
21
+ return "ربات یکپارچه آلفا (نسخه پرو با پشتیبانی کامل تمام فایل‌ها) روشن است! 🚀"
22
 
23
  def run_flask():
24
  app.run(host="0.0.0.0", port=7860)
 
65
  # --- تابع ارسال منحصراً برای کیبورد پایین صفحه ---
66
  async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
67
  if not use_keyboard:
 
68
  msg = await client.send_message(chat_id, text)
69
  return msg
70
 
 
71
  try:
72
  payload = {
73
  "chat_id": chat_id,
 
84
  except Exception as standard_err:
85
  pass
86
 
 
87
  msg = await client.send_message(chat_id, text)
88
  return msg
89
 
 
124
  user_states = {}
125
 
126
 
127
+ # --- ۱. پردازش چت متنی در پس‌زمینه ---
128
  async def process_gemini(client, chat_id, prompt):
129
  if not GEMINI_KEYS:
130
  await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشده‌اند.", False)
131
  return
132
 
 
133
  proc_msg = await send_with_keyboard(client, chat_id, "🧠 در حال پردازش...", False)
134
 
 
135
  history = user_states[chat_id].get("history", [])
136
 
137
  if history and history[-1]["role"] == "user":
 
166
  except Exception as e:
167
  continue
168
 
 
169
  try:
170
  if proc_msg:
171
  msg_id = getattr(proc_msg, 'message_id', None)
 
173
  msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
174
  if msg_id:
175
  await client.delete_messages(chat_id, [msg_id])
176
+ except Exception: pass
 
177
 
178
  if not final_answer:
179
  if history and history[-1]["role"] == "user":
 
209
  try:
210
  await send_with_keyboard(client, chat_id, chunk, False)
211
  await asyncio.sleep(2.5)
212
+ except Exception:
213
  await asyncio.sleep(2.5)
214
 
215
+ except Exception:
216
  await send_with_keyboard(client, chat_id, "❌ خطایی در ارسال پیام رخ داد.", False)
217
 
218
 
219
+ # --- ۲. پردازش ساخت عکس ---
220
  async def process_image(client, chat_id, prompt):
221
  if not HF_TOKENS:
222
  await send_with_keyboard(client, chat_id, "❌ توکن‌های هاگینگ فیس تنظیم نشده‌اند.", False)
 
239
  last_error_log = str(e)
240
  continue
241
 
 
242
  try:
243
  if proc_msg:
244
  msg_id = getattr(proc_msg, 'message_id', None)
 
278
  if os.path.exists(file_name):
279
  os.remove(file_name)
280
 
281
+ except Exception:
282
  await send_with_keyboard(client, chat_id, "❌ خطایی در فرآیند ذخیره عکس رخ داد.", True)
283
 
284
 
285
+ # --- ۳. پردازش ساخت صدا ---
286
  async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
287
  try:
288
  proc_msg = await send_with_keyboard(client, chat_id, f"⏳ در حال ساخت صدا با «{speaker_name}»...\n(لطفاً صبور باشید)", False)
 
317
  last_error = f"خطا در ارتباط: {str(e)}"
318
  continue
319
 
 
320
  try:
321
  if proc_msg:
322
  msg_id = getattr(proc_msg, 'message_id', None)
 
353
  else:
354
  await send_with_keyboard(client, chat_id, f"❌ سرورها درگیر هستند.\nدلیل: {last_error}", True)
355
 
356
+ except Exception:
357
  traceback.print_exc()
358
 
359
 
360
+ # --- ۴. پردازش تبدیل فایل صوتی/تصویری به متن (STT) ---
361
  async def process_stt(client, chat_id, audio_bytes):
362
  if not HF_TOKENS:
363
  await send_with_keyboard(client, chat_id, "❌ توکن‌های هاگینگ فیس تنظیم نشده‌اند.", False)
 
373
 
374
  for token in keys_to_try:
375
  try:
 
376
  hf_client = AsyncInferenceClient(provider="hf-inference", api_key=token)
377
  response = await hf_client.automatic_speech_recognition(audio_bytes, model="openai/whisper-large-v3-turbo")
378
  transcribed_text = response.text
 
381
  last_error_log = str(e)
382
  continue
383
 
 
384
  try:
385
  if proc_msg:
386
  msg_id = getattr(proc_msg, 'message_id', None)
 
393
  if transcribed_text:
394
  await send_with_keyboard(client, chat_id, f"📝 **متن استخراج شده:**\n\n{transcribed_text}", True)
395
  else:
396
+ await send_with_keyboard(client, chat_id, f"❌ متأسفانه تبدیل فایل به متن ناموفق بود.\n\n⚠️ دلیل: {last_error_log[:150]}", True)
397
 
398
 
399
+ # --- ۵. پردازش تحلیل هر نوع فایل با جیمینای ---
400
+ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
401
  if not GEMINI_KEYS:
402
  await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشده‌اند.", False)
403
  return
404
 
405
+ proc_msg = await send_with_keyboard(client, chat_id, "👁️ در حال تحلیل و بررسی فایل با هوش مصنوعی...", False)
406
 
 
407
  base64_data = base64.b64encode(file_bytes).decode('utf-8')
408
 
409
+ # حدس زدن هوشمند فرمت فایل برای جیمینای
410
+ mime_type, _ = mimetypes.guess_type(file_name)
411
+ if not mime_type:
412
+ if file_name.endswith(('.jpg', '.jpeg')): mime_type = "image/jpeg"
413
+ elif file_name.endswith('.png'): mime_type = "image/png"
414
+ elif file_name.endswith('.pdf'): mime_type = "application/pdf"
415
+ elif file_name.endswith('.mp4'): mime_type = "video/mp4"
416
+ elif file_name.endswith('.mp3'): mime_type = "audio/mp3"
417
+ elif file_name.endswith('.ogg'): mime_type = "audio/ogg"
418
+ elif file_name.endswith('.wav'): mime_type = "audio/wav"
419
+ else: mime_type = "image/jpeg"
420
+
421
  keys_to_try = GEMINI_KEYS.copy()
422
  random.shuffle(keys_to_try)
423
  final_answer = None
 
429
  "contents": [{
430
  "parts": [
431
  {"text": prompt},
432
+ {"inlineData": {"mimeType": mime_type, "data": base64_data}}
433
  ]
434
  }],
435
  "generationConfig": {"temperature": 0.6, "maxOutputTokens": 8192}
 
445
  continue
446
  else:
447
  continue
448
+ except Exception:
449
  continue
450
 
 
451
  try:
452
  if proc_msg:
453
  msg_id = getattr(proc_msg, 'message_id', None)
 
460
  if final_answer:
461
  await send_with_keyboard(client, chat_id, f"💡 **نتیجه تحلیل:**\n\n{final_answer}", True)
462
  else:
463
+ await send_with_keyboard(client, chat_id, "❌ متأسفانه در حال حاضر پاسخی برای این فایل دریافت نشد (شاید فرمت فایل پشتیبانی نمی‌شود).", True)
464
 
465
 
466
  # --- تنظیمات ربات روبیکا ---
 
474
  @bot.on_update(filters.private)
475
  async def main_handler(client, update):
476
  try:
 
477
  user_text = getattr(update, "text", "") or getattr(getattr(update, "message", None), "text", "") or getattr(getattr(update, "new_message", None), "text", "")
478
  user_text_str = str(user_text).strip() if user_text else ""
479
 
480
+ # --- سیستم پیشرفته تشخیص فایل فراگیر ---
481
  is_file = False
482
+ file_name = "unknown_file.jpg"
483
  msg_obj = getattr(update, "message", None) or getattr(update, "new_message", None)
484
+
485
  if msg_obj:
486
+ # بررسی متغیرهای مختلف (کلاس)
487
+ for attr in ['file', 'file_inline', 'photo', 'voice', 'audio', 'document', 'video']:
488
+ file_attr = getattr(msg_obj, attr, None)
489
+ if file_attr:
490
+ is_file = True
491
+ if hasattr(file_attr, 'file_name'):
492
+ file_name = file_attr.file_name
493
+ break
494
+
495
+ # بررسی متغیرهای مختلف (دیکشنری) - برای پشتیبانی از نسخه‌های مختلف rubpy
496
+ if not is_file and hasattr(msg_obj, 'to_dict'):
497
+ msg_dict = msg_obj.to_dict()
498
+ for attr in ['file', 'file_inline', 'photo', 'voice', 'audio', 'document', 'video']:
499
+ if attr in msg_dict:
500
+ is_file = True
501
+ file_attr = msg_dict.get(attr, {})
502
+ if isinstance(file_attr, dict) and 'file_name' in file_attr:
503
+ file_name = file_attr['file_name']
504
+ break
505
 
506
  chat_id = getattr(update, "chat_id", None) or getattr(update, "author_guid", None) or getattr(update, "object_guid", None)
507
  if not chat_id:
508
  return
509
 
510
  if chat_id not in user_states:
511
+ user_states[chat_id] = {"mode": None, "text": "", "history": [], "file_bytes": None, "file_name": None}
512
 
513
+ # مدیریت منو
514
  if user_text_str in ["/start", "سلام", "لغو", "/cancel", "❌ لغو", "برگشت♻️"]:
515
+ user_states[chat_id] = {"mode": None, "text": "", "history": [], "file_bytes": None, "file_name": None}
516
  menu = (
517
  "سلام! به ربات هوشمند آلفا خوش آمدید 🤖\n\n"
518
  "لطفاً برای شروع، از کیبورد پایین یکی از بخش‌ها را انتخاب کنید:"
 
536
  return
537
 
538
  if user_text_str in ["/file", "تحلیل فایل با هوش مصنوعی 📁"]:
539
+ user_states[chat_id] = {"mode": "file_waiting_for_file", "text": "", "history": [], "file_bytes": None, "file_name": None}
540
+ await send_with_keyboard(client, chat_id, "📁 شما وارد بخش **تحلیل فایل** شدید.\n\nلطفاً هر نوع فایلی (عکس، ویدیو، PDF، داکیومنت و...) را که می‌خواهید بررسی شود ارسال کنید:\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
541
  return
542
 
543
  if user_text_str in ["/stt", "تبدیل فایل صوتی به متن 📝"]:
544
  user_states[chat_id] = {"mode": "stt_waiting_for_audio", "text": "", "history": []}
545
+ await send_with_keyboard(client, chat_id, "📝 شما وارد بخش **تبدیل صدا به متن** شدید.\n\nلطفاً فایل خود (ویس، آهنگ، ویدیو و...) را فوروارد یا ارسال کنید:\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
546
  return
547
 
548
  current_mode = user_states[chat_id].get("mode")
549
 
550
  if current_mode is None:
551
  if is_file:
552
+ pass
553
  elif user_text_str:
554
  await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا از کیبورد پایین، بخش مورد نظرتان را انتخاب کنید:", True)
555
  return
 
604
  # --- بخش جدید: STT (تبدیل صدا به متن) ---
605
  elif current_mode == "stt_waiting_for_audio":
606
  if not is_file:
607
+ await send_with_keyboard(client, chat_id, "⚠️ لطفاً یک فایل (ویس، آهنگ، ویدیو و...) ارسال کنید.", False)
608
  return
609
 
610
+ await send_with_keyboard(client, chat_id, "📥 در حال دانلود فایل...", False)
611
  try:
612
  audio_bytes = await client.download(msg_obj)
613
+ user_states[chat_id]["mode"] = "stt_waiting_for_audio"
614
  asyncio.create_task(process_stt(client, chat_id, audio_bytes))
615
+ except Exception:
616
+ await send_with_keyboard(client, chat_id, "❌ خطا در دانلود فایل! لطفاً دوباره تلاش کنید.", False)
617
  return
618
 
619
  # --- بخش جدید: تحلیل فایل با هوش مصنوعی ---
620
  elif current_mode == "file_waiting_for_file":
621
  if not is_file:
622
+ await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا یک فایل (تصویر، ویدیو، PDF و...) ارسال کنید.", False)
623
  return
624
 
625
  await send_with_keyboard(client, chat_id, "📥 در حال دریافت فایل...", False)
626
  try:
627
  file_bytes = await client.download(msg_obj)
628
  user_states[chat_id]["file_bytes"] = file_bytes
629
+ user_states[chat_id]["file_name"] = file_name
630
  user_states[chat_id]["mode"] = "file_waiting_for_prompt"
631
+ await send_with_keyboard(client, chat_id, "✅ فایل با موفقیت دریافت شد.\n\nحالا لطفاً به صورت متنی بگویید **چگونه تحلیل شود؟**\n(مثلاً: متن این فایل را استخراج کن، یا بگو محتوای آن چیست؟)", False)
632
+ except Exception:
633
+ await send_with_keyboard(client, chat_id, "❌ خطا در دریافت فایل! لطفاً دوباره تلاش کنید.", False)
634
  return
635
 
636
  elif current_mode == "file_waiting_for_prompt":
637
  if user_text_str:
638
  saved_bytes = user_states[chat_id].get("file_bytes")
639
+ saved_name = user_states[chat_id].get("file_name", "file.jpeg")
640
+ user_states[chat_id]["mode"] = "file_waiting_for_file"
641
  user_states[chat_id]["file_bytes"] = None
642
+ user_states[chat_id]["file_name"] = None
643
+ asyncio.create_task(process_file_analysis(client, chat_id, saved_bytes, saved_name, user_text_str))
644
  else:
645
  await send_with_keyboard(client, chat_id, "⚠️ لطفاً درخواست خود را به صورت متنی بنویسید.", False)
646
  return
647
 
648
+ except Exception:
649
  traceback.print_exc()
650
 
651
  if __name__ == "__main__":