Opera8 commited on
Commit
d3404b2
·
verified ·
1 Parent(s): 81db30a

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +58 -29
main.py CHANGED
@@ -18,7 +18,7 @@ app = Flask(__name__)
18
 
19
  @app.route('/')
20
  def home():
21
- return "ربات یکپارچه آلفا (نسخه پرو + دانلود فایل ۱۰۰٪ تضمینی) روشن است! 🚀"
22
 
23
  def run_flask():
24
  app.run(host="0.0.0.0", port=7860)
@@ -26,7 +26,7 @@ def run_flask():
26
 
27
  # --- ساختار کیبورد پایین صفحه (Chat Keypad) ---
28
  MAIN_KEYPAD_DICT = {
29
- "rows": [
30
  {
31
  "buttons":[
32
  {"id": "chat_btn", "type": "Simple", "button_text": "چت با هوش مصنوعی 🤖"}
@@ -158,9 +158,8 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
158
  abs_path = os.path.abspath(file_name)
159
  error_logs =[]
160
 
161
- api_file_type = "Image" if file_type in ["photo", "Image", "image"] else "Voice" if file_type in["voice", "Voice", "audio"] else "File"
162
 
163
- # --- تلاش اول: ارسال مستقیم از طریق API خام روبیکا (بهترین کیفیت) ---
164
  try:
165
  url_request = f"https://botapi.rubika.ir/v3/{bot_token}/requestSendFile"
166
  url_send = f"https://botapi.rubika.ir/v3/{bot_token}/sendFile"
@@ -171,7 +170,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
171
 
172
  if req_data.get("status") == "OK":
173
  data_dict = req_data.get("data", {})
174
- # دریافت آدرس آپلود و آیدی فایل
175
  upload_url = data_dict.get("upload_url")
176
  file_id = data_dict.get("id") or data_dict.get("file_id")
177
 
@@ -207,7 +205,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
207
  except Exception as e:
208
  error_logs.append(f"Raw HTTP Error: {e}")
209
 
210
- # --- تلاش دوم (پشتیبان تضمینی): استفاده از متد داخلی بدون آرگومان Caption ---
211
  try:
212
  if hasattr(client, "send_file"):
213
  await client.send_file(chat_id, abs_path)
@@ -220,7 +217,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
220
  return "\n".join(error_logs)
221
 
222
 
223
- # --- لیست تمام سرورهای تولید صدای شما ---
224
  WORKER_URLS =[
225
  "https://hamed744-ttspro.hf.space/generate",
226
  "https://hamed744-ttspro2.hf.space/generate",
@@ -249,8 +245,8 @@ SPEAKERS = {
249
  user_states = {}
250
 
251
 
252
- # --- ۱. پردازش چت متنی ---
253
- async def process_gemini(client, chat_id, prompt):
254
  if not GEMINI_KEYS:
255
  await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشده‌اند.", False)
256
  return
@@ -259,10 +255,40 @@ async def process_gemini(client, chat_id, prompt):
259
 
260
  history = user_states[chat_id].get("history",[])
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  if history and history[-1]["role"] == "user":
263
- history[-1]["parts"][0]["text"] += "\n" + prompt
 
264
  else:
265
- history.append({"role": "user", "parts":[{"text": prompt}]})
266
 
267
  # تغییر تاریخچه به ۴۰ مورد برای ذخیره کردن ۲۰ سوال و جواب (۲۰ پیام رفت و برگشت)
268
  if len(history) > 40:
@@ -279,7 +305,7 @@ async def process_gemini(client, chat_id, prompt):
279
  url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
280
  payload = {"contents": history, "generationConfig": {"temperature": 0.7, "maxOutputTokens": 8192}}
281
  try:
282
- async with session.post(url, json=payload, timeout=45) as response:
283
  if response.status == 200:
284
  data = await response.json()
285
  try:
@@ -302,7 +328,7 @@ async def process_gemini(client, chat_id, prompt):
302
  if not final_answer:
303
  if history and history[-1]["role"] == "user":
304
  history.pop()
305
- await send_with_keyboard(client, chat_id, "❌ متأسفانه پاسخی دریافت نشد. لطفاً دوباره تلاش کنید.", False)
306
  return
307
 
308
  history.append({"role": "model", "parts":[{"text": final_answer}]})
@@ -378,7 +404,6 @@ async def process_image(client, chat_id, prompt):
378
  await asyncio.sleep(1)
379
  caption_text = "🎨 تصویر شما آماده شد!\n(مدل: Z-Image-Turbo)"
380
 
381
- # آپلود مستقیم به سرور اصلی روبیکا
382
  upload_result = await helper_upload_file(client, chat_id, file_name, "Image", caption_text)
383
 
384
  if upload_result is not True:
@@ -428,7 +453,7 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
428
  if isinstance(proc_msg, dict):
429
  msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
430
  if msg_id:
431
- await client.delete_messages(chat_id, [msg_id])
432
  except Exception: pass
433
 
434
  if audio_bytes:
@@ -437,7 +462,6 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
437
 
438
  await asyncio.sleep(1)
439
 
440
- # آپلود مستقیم به سرور اصلی روبیکا
441
  upload_result = await helper_upload_file(client, chat_id, file_name, "Voice", "✅ پردازش صدای شما انجام شد.")
442
 
443
  if upload_result is not True:
@@ -459,23 +483,20 @@ async def process_stt(client, chat_id, audio_bytes, file_name):
459
 
460
  proc_msg = await send_with_keyboard(client, chat_id, "📝 در حال گوش دادن و پیاده‌سازی متن توسط جیمینای... (لطفاً صبور باشید)", False)
461
 
462
- # تبدیل مستقیم بایت‌های صوتی به Base64
463
  base64_data = base64.b64encode(audio_bytes).decode('utf-8')
464
 
465
- # حدس زدن فرمت برای ارسال به جیمینای
466
  mime_type, _ = mimetypes.guess_type(file_name)
467
  if not mime_type:
468
  if file_name.endswith(('.ogg', '.oga')): mime_type = "audio/ogg"
469
  elif file_name.endswith('.wav'): mime_type = "audio/wav"
470
  elif file_name.endswith('.mp3'): mime_type = "audio/mp3"
471
  elif file_name.endswith('.mp4'): mime_type = "video/mp4"
472
- else: mime_type = "audio/ogg" # فرمت پیش‌فرض و معمول برای ویس‌های روبیکا و تلگرام
473
 
474
  keys_to_try = GEMINI_KEYS.copy()
475
  random.shuffle(keys_to_try)
476
  transcribed_text = None
477
 
478
- # دستور متنی به جیمینای برای گرفتن دقیق‌ترین استخراج متن
479
  prompt = "لطفاً این فایل صوتی/تصویری را با دقت کامل گوش بده و صحبت‌های داخل آن را کلمه به کلمه به متن تبدیل کن. هیچ توضیح اضافه‌ای نده و فقط متن پیاده‌سازی شده را بفرست."
480
 
481
  async with aiohttp.ClientSession() as session:
@@ -510,7 +531,7 @@ async def process_stt(client, chat_id, audio_bytes, file_name):
510
  await send_with_keyboard(client, chat_id, f"❌ تبدیل فایل به متن ناموفق بود.\n(احتمالاً فرمت فایل پشتیبانی نمی‌شود یا فایل شما صوتی نیست)", True)
511
 
512
 
513
- # --- ۵. پردازش تحلیل هر نوع فایل با جیمینای ---
514
  async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
515
  if not GEMINI_KEYS:
516
  await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشده‌اند.", False)
@@ -526,7 +547,7 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
526
  elif file_name.endswith('.pdf'): mime_type = "application/pdf"
527
  elif file_name.endswith('.mp4'): mime_type = "video/mp4"
528
  elif file_name.endswith('.mp3'): mime_type = "audio/mp3"
529
- elif file_name.endswith('.ogg'): mime_type = "audio/ogg"
530
  elif file_name.endswith('.wav'): mime_type = "audio/wav"
531
  else: mime_type = "image/jpeg"
532
 
@@ -611,7 +632,7 @@ else:
611
 
612
  if user_text_str in["/chat", "💬 چت", "چت با هوش مصنوعی 🤖"]:
613
  user_states[chat_id] = {"mode": "chat", "text": "", "history":[]}
614
- await send_with_keyboard(client, chat_id, "💬 شما وارد بخش **چت با هوش مصنوعی** شدید.\n(حالا ربات سابقه گفتگو را به یاد می‌آورد)\n\nهر سوالی دارید بفرستید تا جواب بدم:\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
615
  return
616
 
617
  if user_text_str in["/image", "🎨 عکس", "ساخت تصاویر با هوش مصنوعی🎨"]:
@@ -626,7 +647,7 @@ else:
626
 
627
  if user_text_str in["/file", "تحلیل فایل با هوش مصنوعی 📁"]:
628
  user_states[chat_id] = {"mode": "file_waiting_for_file", "text": "", "history":[], "file_bytes": None, "file_name": None}
629
- await send_with_keyboard(client, chat_id, "📁 شما وارد بخش **تحلیل فایل** شدید.\n\nلطفاً هر نوع فایلی (عکس، ویدیو، PDF، داکیومنت و...) را که می‌خواهید بررسی شود ارسال کنید:\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
630
  return
631
 
632
  if user_text_str in["/stt", "تبدیل فایل صوتی به متن 📝"]:
@@ -641,9 +662,19 @@ else:
641
  elif user_text_str: await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا از کیبورد پایین، بخش مورد نظرتان را انتخاب کنید:", True)
642
  return
643
 
644
- # --- مسیریابی ---
645
  elif current_mode == "chat":
646
- if user_text_str: asyncio.create_task(process_gemini(client, chat_id, user_text_str))
 
 
 
 
 
 
 
 
 
 
647
  return
648
 
649
  elif current_mode == "image_waiting_for_text":
@@ -685,7 +716,6 @@ else:
685
  await send_with_keyboard(client, chat_id, "❌ شماره نامعتبر است! لطفاً فقط یک عدد بین 1 تا 30 بفرستید.", False)
686
  return
687
 
688
- # --- بخش STT (صدا به متن) آپدیت شده ---
689
  elif current_mode == "stt_waiting_for_audio":
690
  if not is_file:
691
  await send_with_keyboard(client, chat_id, "⚠️ لطفاً یک فایل (ویس، آهنگ، ویدیو و...) ارسال کنید.", False)
@@ -695,14 +725,13 @@ else:
695
  try:
696
  audio_bytes = await helper_download_file(client, msg_obj)
697
  user_states[chat_id]["mode"] = "stt_waiting_for_audio"
698
- # انتقال نام فایل به تابع جیمینای برای تشخیص فرمت ویس
699
  asyncio.create_task(process_stt(client, chat_id, audio_bytes, file_name))
700
  except Exception as dl_err:
701
  err_trace = traceback.format_exc()
702
  await send_with_keyboard(client, chat_id, f"❌ خطا در دانلود فایل!\n\n🔴 لاگ برنامه‌نویس:\n`{err_trace[-300:]}`\n{str(dl_err)}", False)
703
  return
704
 
705
- # --- بخش تحلیل فایل ---
706
  elif current_mode == "file_waiting_for_file":
707
  if not is_file:
708
  await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا یک فایل (تصویر، ویدیو، PDF و...) ارسال کنید.", False)
 
18
 
19
  @app.route('/')
20
  def home():
21
+ return "ربات یکپارچه آلفا (نسخه پرو + دانلود فایل ۱۰۰٪ تضمینی + چت چندرسانه‌ای) روشن است! 🚀"
22
 
23
  def run_flask():
24
  app.run(host="0.0.0.0", port=7860)
 
26
 
27
  # --- ساختار کیبورد پایین صفحه (Chat Keypad) ---
28
  MAIN_KEYPAD_DICT = {
29
+ "rows":[
30
  {
31
  "buttons":[
32
  {"id": "chat_btn", "type": "Simple", "button_text": "چت با هوش مصنوعی 🤖"}
 
158
  abs_path = os.path.abspath(file_name)
159
  error_logs =[]
160
 
161
+ api_file_type = "Image" if file_type in["photo", "Image", "image"] else "Voice" if file_type in["voice", "Voice", "audio"] else "File"
162
 
 
163
  try:
164
  url_request = f"https://botapi.rubika.ir/v3/{bot_token}/requestSendFile"
165
  url_send = f"https://botapi.rubika.ir/v3/{bot_token}/sendFile"
 
170
 
171
  if req_data.get("status") == "OK":
172
  data_dict = req_data.get("data", {})
 
173
  upload_url = data_dict.get("upload_url")
174
  file_id = data_dict.get("id") or data_dict.get("file_id")
175
 
 
205
  except Exception as e:
206
  error_logs.append(f"Raw HTTP Error: {e}")
207
 
 
208
  try:
209
  if hasattr(client, "send_file"):
210
  await client.send_file(chat_id, abs_path)
 
217
  return "\n".join(error_logs)
218
 
219
 
 
220
  WORKER_URLS =[
221
  "https://hamed744-ttspro.hf.space/generate",
222
  "https://hamed744-ttspro2.hf.space/generate",
 
245
  user_states = {}
246
 
247
 
248
+ # --- ۱. پردازش چت متنی و چندرسانه‌ای (ارتقا یافته) ---
249
+ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=None):
250
  if not GEMINI_KEYS:
251
  await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشده‌اند.", False)
252
  return
 
255
 
256
  history = user_states[chat_id].get("history",[])
257
 
258
+ # آماده‌سازی بخش‌های پیام کاربر (متن + فایل در صورت وجود)
259
+ new_parts =[]
260
+
261
+ if prompt:
262
+ new_parts.append({"text": prompt})
263
+ elif file_bytes:
264
+ new_parts.append({"text": "لطفاً این فایل را به دقت بررسی کن."})
265
+
266
+ if file_bytes and file_name:
267
+ base64_data = base64.b64encode(file_bytes).decode('utf-8')
268
+ mime_type, _ = mimetypes.guess_type(file_name)
269
+ if not mime_type:
270
+ if file_name.endswith(('.jpg', '.jpeg')): mime_type = "image/jpeg"
271
+ elif file_name.endswith('.png'): mime_type = "image/png"
272
+ elif file_name.endswith('.pdf'): mime_type = "application/pdf"
273
+ elif file_name.endswith('.mp4'): mime_type = "video/mp4"
274
+ elif file_name.endswith('.mp3'): mime_type = "audio/mp3"
275
+ elif file_name.endswith(('.ogg', '.oga')): mime_type = "audio/ogg"
276
+ elif file_name.endswith('.wav'): mime_type = "audio/wav"
277
+ else: mime_type = "image/jpeg"
278
+
279
+ new_parts.append({
280
+ "inlineData": {
281
+ "mimeType": mime_type,
282
+ "data": base64_data
283
+ }
284
+ })
285
+
286
+ # افزودن پیام جدید به سابقه
287
  if history and history[-1]["role"] == "user":
288
+ # اگر پیام قبلی هم از کاربر بود، پیام جدید (فایل یا متن) را به آن اضافه کن
289
+ history[-1]["parts"].extend(new_parts)
290
  else:
291
+ history.append({"role": "user", "parts": new_parts})
292
 
293
  # تغییر تاریخچه به ۴۰ مورد برای ذخیره کردن ۲۰ سوال و جواب (۲۰ پیام رفت و برگشت)
294
  if len(history) > 40:
 
305
  url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
306
  payload = {"contents": history, "generationConfig": {"temperature": 0.7, "maxOutputTokens": 8192}}
307
  try:
308
+ async with session.post(url, json=payload, timeout=60) as response:
309
  if response.status == 200:
310
  data = await response.json()
311
  try:
 
328
  if not final_answer:
329
  if history and history[-1]["role"] == "user":
330
  history.pop()
331
+ await send_with_keyboard(client, chat_id, "❌ متأسفانه پاسخی دریافت نشد. (شاید سایز فایل بیش از حد مجاز بوده است)", False)
332
  return
333
 
334
  history.append({"role": "model", "parts":[{"text": final_answer}]})
 
404
  await asyncio.sleep(1)
405
  caption_text = "🎨 تصویر شما آماده شد!\n(مدل: Z-Image-Turbo)"
406
 
 
407
  upload_result = await helper_upload_file(client, chat_id, file_name, "Image", caption_text)
408
 
409
  if upload_result is not True:
 
453
  if isinstance(proc_msg, dict):
454
  msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
455
  if msg_id:
456
+ await client.delete_messages(chat_id,[msg_id])
457
  except Exception: pass
458
 
459
  if audio_bytes:
 
462
 
463
  await asyncio.sleep(1)
464
 
 
465
  upload_result = await helper_upload_file(client, chat_id, file_name, "Voice", "✅ پردازش صدای شما انجام شد.")
466
 
467
  if upload_result is not True:
 
483
 
484
  proc_msg = await send_with_keyboard(client, chat_id, "📝 در حال گوش دادن و پیاده‌سازی متن توسط جیمینای... (لطفاً صبور باشید)", False)
485
 
 
486
  base64_data = base64.b64encode(audio_bytes).decode('utf-8')
487
 
 
488
  mime_type, _ = mimetypes.guess_type(file_name)
489
  if not mime_type:
490
  if file_name.endswith(('.ogg', '.oga')): mime_type = "audio/ogg"
491
  elif file_name.endswith('.wav'): mime_type = "audio/wav"
492
  elif file_name.endswith('.mp3'): mime_type = "audio/mp3"
493
  elif file_name.endswith('.mp4'): mime_type = "video/mp4"
494
+ else: mime_type = "audio/ogg"
495
 
496
  keys_to_try = GEMINI_KEYS.copy()
497
  random.shuffle(keys_to_try)
498
  transcribed_text = None
499
 
 
500
  prompt = "لطفاً این فایل صوتی/تصویری را با دقت کامل گوش بده و صحبت‌های داخل آن را کلمه به کلمه به متن تبدیل کن. هیچ توضیح اضافه‌ای نده و فقط متن پیاده‌سازی شده را بفرست."
501
 
502
  async with aiohttp.ClientSession() as session:
 
531
  await send_with_keyboard(client, chat_id, f"❌ تبدیل فایل به متن ناموفق بود.\n(احتمالاً فرمت فایل پشتیبانی نمی‌شود یا فایل شما صوتی نیست)", True)
532
 
533
 
534
+ # --- ۵. پردازش تحلیل فایل مستقل ---
535
  async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
536
  if not GEMINI_KEYS:
537
  await send_with_keyboard(client, chat_id, "❌ کلیدهای API جیمینای تنظیم نشده‌اند.", False)
 
547
  elif file_name.endswith('.pdf'): mime_type = "application/pdf"
548
  elif file_name.endswith('.mp4'): mime_type = "video/mp4"
549
  elif file_name.endswith('.mp3'): mime_type = "audio/mp3"
550
+ elif file_name.endswith(('.ogg', '.oga')): mime_type = "audio/ogg"
551
  elif file_name.endswith('.wav'): mime_type = "audio/wav"
552
  else: mime_type = "image/jpeg"
553
 
 
632
 
633
  if user_text_str in["/chat", "💬 چت", "چت با هوش مصنوعی 🤖"]:
634
  user_states[chat_id] = {"mode": "chat", "text": "", "history":[]}
635
+ await send_with_keyboard(client, chat_id, "💬 شما وارد بخش **چت با هوش مصنوعی** شدید.\n(حالا ربات سابقه گفتگو را به یاد می‌آورد)\n\nهر سوالی دارید بفرستید تا جواب بدم:\n💡 نکته: در همین بخش هم می‌توانید برای من عکس یا فایل ارسال کنید تا آن را بررسی کنم.\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
636
  return
637
 
638
  if user_text_str in["/image", "🎨 عکس", "ساخت تصاویر با هوش مصنوعی🎨"]:
 
647
 
648
  if user_text_str in["/file", "تحلیل فایل با هوش مصنوعی 📁"]:
649
  user_states[chat_id] = {"mode": "file_waiting_for_file", "text": "", "history":[], "file_bytes": None, "file_name": None}
650
+ await send_with_keyboard(client, chat_id, "📁 شما وارد بخش **تحلیل فایل اختصاصی** شدید.\n\nلطفاً هر نوع فایلی (عکس، ویدیو، PDF، داکیومنت و...) را که می‌خواهید بررسی شود ارسال کنید:\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
651
  return
652
 
653
  if user_text_str in["/stt", "تبدیل فایل صوتی به متن 📝"]:
 
662
  elif user_text_str: await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا از کیبورد پایین، بخش مورد نظرتان را انتخاب کنید:", True)
663
  return
664
 
665
+ # --- مسیریابی و هندل کردن حالت چت (ارتقا یافته برای پشتیبانی از ارسال فایل) ---
666
  elif current_mode == "chat":
667
+ if is_file:
668
+ await send_with_keyboard(client, chat_id, "📥 در حال دانلود فایل برای چت هوشمند...", False)
669
+ try:
670
+ file_bytes = await helper_download_file(client, msg_obj)
671
+ # اگر کاربر همراه عکس کپشن نوشته باشد ارسال می‌شود، در غیر اینصورت ربات متوجه می‌شود فایل فرستاده
672
+ asyncio.create_task(process_gemini(client, chat_id, user_text_str, file_bytes=file_bytes, file_name=file_name))
673
+ except Exception as dl_err:
674
+ err_trace = traceback.format_exc()
675
+ await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت فایل!\n\n🔴 لاگ برنامه‌نویس:\n`{err_trace[-300:]}`\n{str(dl_err)}", False)
676
+ elif user_text_str:
677
+ asyncio.create_task(process_gemini(client, chat_id, user_text_str))
678
  return
679
 
680
  elif current_mode == "image_waiting_for_text":
 
716
  await send_with_keyboard(client, chat_id, "❌ شماره نامعتبر است! لطفاً فقط یک عدد بین 1 تا 30 بفرستید.", False)
717
  return
718
 
 
719
  elif current_mode == "stt_waiting_for_audio":
720
  if not is_file:
721
  await send_with_keyboard(client, chat_id, "⚠️ لطفاً یک فایل (ویس، آهنگ، ویدیو و...) ارسال کنید.", False)
 
725
  try:
726
  audio_bytes = await helper_download_file(client, msg_obj)
727
  user_states[chat_id]["mode"] = "stt_waiting_for_audio"
 
728
  asyncio.create_task(process_stt(client, chat_id, audio_bytes, file_name))
729
  except Exception as dl_err:
730
  err_trace = traceback.format_exc()
731
  await send_with_keyboard(client, chat_id, f"❌ خطا در دانلود فایل!\n\n🔴 لاگ برنامه‌نویس:\n`{err_trace[-300:]}`\n{str(dl_err)}", False)
732
  return
733
 
734
+ # --- بخش تحلیل فایل اختصاصی ---
735
  elif current_mode == "file_waiting_for_file":
736
  if not is_file:
737
  await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا یک فایل (تصویر، ویدیو، PDF و...) ارسال کنید.", False)