Opera8 commited on
Commit
0cf1ae0
·
verified ·
1 Parent(s): 0a06215

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +177 -153
main.py CHANGED
@@ -614,22 +614,19 @@ HF_TOKENS =[k.strip() for k in HF_TOKENS_STR.split(",") if k.strip()]
614
  # ==============================================================================
615
  async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""):
616
  abs_path = os.path.abspath(file_name)
617
- error_logs = []
618
 
619
- api_file_type = "Image" if file_type in["photo", "Image", "image"] else "Voice" if file_type in ["voice", "Voice", "audio"] else file_type
620
 
621
- # روبیکا فرمت‌های خاصی را قبول می‌کند.
622
  if api_file_type == "Voice" and not abs_path.lower().endswith('.ogg'):
623
  api_file_type = "Music"
624
  if api_file_type == "File" and abs_path.lower().endswith('.mp3'):
625
  api_file_type = "Music"
626
 
627
- # --- فاز اول (فوق سریع): استفاده از متدهای اختصاصی rubpy ---
628
- for attempt in range(10):
629
  try:
630
  sent_success = False
631
-
632
- # تلاش برای ارسال عکس
633
  if api_file_type == "Image" and hasattr(client, "send_photo"):
634
  try:
635
  await client.send_photo(chat_id, photo=abs_path, caption=caption)
@@ -638,7 +635,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
638
  await client.send_photo(chat_id, abs_path, caption=caption)
639
  sent_success = True
640
 
641
- # تلاش برای ارسال ویس
642
  elif api_file_type == "Voice" and hasattr(client, "send_voice"):
643
  try:
644
  await client.send_voice(chat_id, abs_path, caption=caption)
@@ -647,7 +643,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
647
  await client.send_voice(chat_id, file=abs_path, caption=caption)
648
  sent_success = True
649
 
650
- # تلاش برای ارسال موزیک
651
  elif api_file_type == "Music" and hasattr(client, "send_music"):
652
  try:
653
  await client.send_music(chat_id, abs_path, caption=caption)
@@ -656,8 +651,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
656
  await client.send_music(chat_id, music=abs_path, caption=caption)
657
  sent_success = True
658
 
659
- # *** سیستم ضد بمب اتم فاز 1 ***
660
- # اگر هیچکدام از متدهای بالا وجود نداشت یا به هر دلیلی ارسال نشد، حتما به عنوان فایل (سند) بفرست تا معطل نشود
661
  if not sent_success:
662
  if hasattr(client, "send_document"):
663
  try:
@@ -679,28 +672,34 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
679
  return True
680
 
681
  except Exception as e:
682
- err_msg = str(e)[:150]
683
- error_logs.append(f"Rubpy Send Error: {err_msg}")
684
-
685
- if "502" in err_msg or "timeout" in err_msg.lower() or "time" in err_msg.lower():
686
- await asyncio.sleep(4)
687
  else:
688
- await asyncio.sleep(2)
689
 
690
- # --- فاز دوم (سنگر آخر): آپلود دستی (Raw HTTP) در صورت مسدودی کامل روب‌پای ---
691
- for attempt in range(15):
692
  try:
693
  url_request = f"https://botapi.rubika.ir/v3/{bot_token}/requestSendFile"
694
  url_send = f"https://botapi.rubika.ir/v3/{bot_token}/sendFile"
695
 
696
  async with aiohttp.ClientSession() as session:
697
- async with session.post(url_request, json={"type": api_file_type}, timeout=30) as resp:
698
  if resp.status != 200:
699
- error_logs.append(f"Request HTTP {resp.status}")
700
- await asyncio.sleep(2)
701
  continue
702
 
703
  req_data = await resp.json()
 
 
 
 
 
 
 
704
  if req_data.get("status") == "OK":
705
  upload_url = req_data.get("data", {}).get("upload_url")
706
  if upload_url:
@@ -709,28 +708,24 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
709
  form.add_field('file', f, filename=os.path.basename(abs_path))
710
  async with session.post(upload_url, data=form, timeout=300) as up_resp:
711
  if up_resp.status != 200:
712
- error_logs.append(f"Upload HTTP {up_resp.status}")
713
- if up_resp.status in[502, 503, 500]:
714
- await asyncio.sleep(3)
715
- else:
716
- await asyncio.sleep(1.5)
717
  continue
718
 
719
  try:
720
  up_data = await up_resp.json()
721
- except Exception as json_err:
722
- error_logs.append(f"JSON Decode Error: {json_err}")
723
- await asyncio.sleep(2)
724
  continue
725
 
 
 
 
 
726
  final_file_id = None
727
 
728
- # *** سیستم ضد بمب اتم فاز 2 ***
729
- # دور زدن ارور روبیکا: اگر روبیکا به فرمت فایل گیر داد، سریعاً نوع را به File تغییر بده تا بدون بررسی فرمت آپلود کند!
730
  if up_data.get("status") == "INVALID_INPUT" and "format" in str(up_data).lower():
731
  api_file_type = "File"
732
- error_logs.append(f"Format Blocked! Downgrading type to File.")
733
- await asyncio.sleep(1)
734
  continue
735
 
736
  if up_data.get("status") == "OK" or up_data.get("status_det") == "OK":
@@ -747,34 +742,26 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
747
  "chat_keypad_type": "New",
748
  "chat_keypad": MAIN_KEYPAD_DICT
749
  }
750
- async with session.post(url_send, json=send_payload, timeout=30) as send_resp:
751
- if send_resp.status != 200:
752
- error_logs.append(f"Send HTTP {send_resp.status}")
753
- await asyncio.sleep(2)
754
- continue
755
-
756
  s_data = await send_resp.json()
757
- if s_data.get("status") == "OK": return True
758
- else: error_logs.append(f"SendFile API Error: {s_data}")
 
 
 
759
  else:
760
  if up_data.get("status") == "INVALID_INPUT" and api_file_type in ["Voice", "Music"]:
761
- api_file_type = "File" # دور زدن گیر دادن روبیکا
762
- error_logs.append(f"Upload API Error: {up_data}")
763
- else: error_logs.append(f"Missing upload_url in Response: {req_data}")
764
- else: error_logs.append(f"Request API Error: {req_data}")
765
  except Exception as e:
766
- error_logs.append(f"Raw HTTP Error: {str(e)[:100]}")
767
- await asyncio.sleep(2.5)
768
 
769
  return "\n".join(error_logs[-6:])
770
 
771
  # ==============================================================================
772
  # 🟢 پارت 12: توابع تغییر صدا و لیست گویندگان
773
  # ==============================================================================
774
- # ==================================================================
775
- # لیست‌های اولیه ربات
776
- # ==================================================================
777
- WORKER_URLS =["https://opera8-ttspro.hf.space/generate"]
778
 
779
  SPEAKERS = {
780
  "1": ("شهاب (مرد)", "Charon"), "2": ("آوا (زن)", "Zephyr"), "3": ("نوید (مرد)", "Achird"),
@@ -791,80 +778,100 @@ SPEAKERS = {
791
 
792
  user_states = {}
793
 
794
- # ==================================================================
795
- # توابع تغییر صدا و کلون کردن
796
- # ==================================================================
797
  async def process_standard_vc_job(client, chat_id, src_bytes, ref_bytes, job_type_name, credit_type):
798
  str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
799
  creds = get_user_credits(str_chat_id)
800
 
801
- proc_msg = await send_with_keyboard(client, chat_id, f"⏳ در حال آماده‌سازی فایل‌ها...\n(مدل: {job_type_name})", False)
802
 
803
- async with aiohttp.ClientSession() as session:
804
- form = aiohttp.FormData()
805
- form.add_field('source_audio', src_bytes, filename='src.wav', content_type='audio/wav')
806
- form.add_field('ref_audio', ref_bytes, filename='ref.wav', content_type='audio/wav')
807
-
808
- try:
809
- async with session.post(f"{VC_BASE_URL}/upload", data=form, timeout=43200) as resp:
810
- if resp.status != 200:
811
- return await send_with_keyboard(client, chat_id, f"❌ خطا در ارسال فایل‌ها (کد {resp.status})", True)
812
- data = await resp.json()
813
- job_id = data.get("job_id")
814
- total_chunks = data.get("total_chunks", 1)
815
- chunks = data.get("chunks",[])
816
- except Exception as e:
817
- return await send_with_keyboard(client, chat_id, f"❌ خطا در اتصال به سرور:\n{str(e)[:100]}", True)
 
 
 
 
 
 
 
 
 
 
 
818
 
819
- await send_with_keyboard(client, chat_id, "✅ فایل‌ها ارسال شد. در حال پردازش و تغییر صدا...\n(لطفا چند دقیقه صبور باشید)", False)
820
-
821
- final_filename = None
822
- for _ in range(10000):
823
- await asyncio.sleep(4)
 
 
 
 
824
  payload_check = {"job_id": job_id, "total_chunks": total_chunks, "chunks": chunks}
825
  try:
826
- async with session.post(f"{VC_BASE_URL}/check_status", json=payload_check, timeout=20) as c_resp:
827
  if c_resp.status == 200:
828
  c_data = await c_resp.json()
829
  if c_data.get("status") == "completed":
830
  final_filename = c_data.get("filename")
831
  break
832
  elif c_data.get("status") in ["failed", "error"]:
833
- return await send_with_keyboard(client, chat_id, "❌ خطای سرور در حین پردازش صدا.", True)
834
  except Exception:
835
  pass
836
 
837
  if not final_filename:
838
- return await send_with_keyboard(client, chat_id, "❌ پردازش بیش از حد طول کشید و متوقف شد.", True)
839
 
840
  download_url = f"{VC_BASE_URL}/download/{final_filename}"
841
  await send_with_keyboard(client, chat_id, "📥 پردازش تمام شد! در حال دانلود نتیجه...", False)
842
- try:
843
- async with session.get(download_url, timeout=43200) as d_resp:
844
- if d_resp.status == 200:
845
- result_bytes = await d_resp.read()
846
- else:
847
- return await send_with_keyboard(client, chat_id, "❌ خطا در دریافت فایل نهایی از سرور.", True)
848
- except Exception:
849
- return await send_with_keyboard(client, chat_id, "❌ خطا در اتصال هنگام دانلود خروجی.", True)
 
 
 
 
 
 
 
850
 
851
  file_name_mp3 = f"vc_standard_{uuid.uuid4().hex[:6]}.mp3"
852
  await asyncio.to_thread(sync_write_file, file_name_mp3, result_bytes)
853
 
854
  upload_result = False
855
- for up_att in range(3):
 
856
  res = await helper_upload_file(client, chat_id, file_name_mp3, "Music", f"🎙️ {job_type_name} شما آماده است!")
857
  if res is True:
858
  upload_result = True
859
  break
860
- await asyncio.sleep(4)
861
 
862
  if upload_result is True:
863
  if not creds.get("is_premium"):
864
  user_credits_db[str_chat_id][credit_type] -= 1
865
  save_db(user_credits_db)
866
  else:
867
- await send_with_keyboard(client, chat_id, "❌ فایل پردازش شد اما امکان ارسال در روبیکا فراهم نشد.", True)
868
 
869
  if os.path.exists(file_name_mp3): os.remove(file_name_mp3)
870
 
@@ -872,37 +879,48 @@ async def process_legacy_vc_job(client, chat_id, src_bytes, model_url, pitch, mo
872
  str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
873
  creds = get_user_credits(str_chat_id)
874
 
875
- proc_msg = await send_with_keyboard(client, chat_id, f"⏳ در حال آماده‌سازی فایل‌ها...\n(مدل: {model_name})", False)
876
 
877
- async with aiohttp.ClientSession() as session:
878
- form = aiohttp.FormData()
879
- form.add_field('audio_file', src_bytes, filename='input.wav', content_type='audio/wav')
880
- form.add_field('model_url', model_url)
881
- form.add_field('pitch', str(pitch))
882
- form.add_field('algo', 'rmvpe+')
883
- form.add_field('index_inf', '0.75')
884
- form.add_field('res_filter', '3')
885
- form.add_field('env_ratio', '0.25')
886
- form.add_field('protect', '0.33')
887
- form.add_field('denoise', 'false')
888
- form.add_field('reverb', 'false')
889
-
890
- try:
891
- async with session.post(f"{LEGACY_BASE_URL}/upload", data=form, timeout=43200) as resp:
892
- if resp.status != 200:
893
- return await send_with_keyboard(client, chat_id, f"❌ خطا در ارسال فایل‌ها (کد {resp.status})", True)
894
- data = await resp.json()
895
- job_id = data.get("job_id")
896
- except Exception as e:
897
- return await send_with_keyboard(client, chat_id, f"❌ خطا در اتصال به سرور:\n{str(e)[:100]}", True)
 
 
 
 
 
 
 
898
 
899
- await send_with_keyboard(client, chat_id, "✅ فایل ارسال شد. در حال پردازش و تغییر صدای شما...\n(لطفا چند دقیقه صبور باشید)", False)
900
-
901
- final_filename = None
902
- for _ in range(10000):
 
 
 
 
903
  await asyncio.sleep(5)
904
  try:
905
- async with session.get(f"{LEGACY_BASE_URL}/status/{job_id}", timeout=20) as c_resp:
906
  if c_resp.status == 200:
907
  c_data = await c_resp.json()
908
  if c_data.get("status") == "completed":
@@ -918,32 +936,39 @@ async def process_legacy_vc_job(client, chat_id, src_bytes, model_url, pitch, mo
918
 
919
  download_url = f"{LEGACY_BASE_URL}/download/{final_filename}"
920
  await send_with_keyboard(client, chat_id, "📥 پردازش تمام شد! در حال دانلود نتیجه...", False)
921
- try:
922
- async with session.get(download_url, timeout=43200) as d_resp:
923
- if d_resp.status == 200:
924
- result_bytes = await d_resp.read()
925
- else:
926
- return await send_with_keyboard(client, chat_id, "❌ خطا در دریافت فایل نهایی از سرور.", True)
927
- except Exception:
928
- return await send_with_keyboard(client, chat_id, "❌ خطا در اتصال هنگام دانلود خروجی.", True)
 
 
 
 
 
 
 
929
 
930
  file_name_mp3 = f"vc_legacy_{uuid.uuid4().hex[:6]}.mp3"
931
  await asyncio.to_thread(sync_write_file, file_name_mp3, result_bytes)
932
 
933
  upload_result = False
934
- for up_att in range(3):
935
  res = await helper_upload_file(client, chat_id, file_name_mp3, "Music", f"🎙️ صدای خروجی با مدل {model_name} آماده است!")
936
  if res is True:
937
  upload_result = True
938
  break
939
- await asyncio.sleep(4)
940
 
941
  if upload_result is True:
942
  if not creds.get("is_premium"):
943
  user_credits_db[str_chat_id]["voice_conv"] -= 1
944
  save_db(user_credits_db)
945
  else:
946
- await send_with_keyboard(client, chat_id, "❌ فایل پردازش شد اما امکان ارسال در روبیکا فراهم نشد.", True)
947
 
948
  if os.path.exists(file_name_mp3): os.remove(file_name_mp3)
949
 
@@ -1133,7 +1158,7 @@ async def process_image(client, chat_id, prompt, size_choice="1"):
1133
  async with aiohttp.ClientSession() as session:
1134
  for key in keys_to_try_gemini:
1135
  url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
1136
- payload = {"contents": [{"parts":[{"text": gemini_sys_prompt}]}], "generationConfig": {"temperature": 0.7}}
1137
  try:
1138
  async with session.post(url, json=payload, timeout=20) as response:
1139
  if response.status == 200:
@@ -1186,9 +1211,9 @@ async def process_image(client, chat_id, prompt, size_choice="1"):
1186
  proc_msg = await send_with_keyboard(client, chat_id, f"🎨 در حال طراحی عکس...\n\n📏 **ابعاد:** {size_name}\n📝 **پرامپت ساخته شده:**\n`{short_preview}`\n\n(ممکن است چند ثانیه زمان ببرد)", False)
1187
 
1188
  generated_image = None
1189
- last_error_log = "هیچ اتصالی برقرار نشد."
1190
 
1191
- for attempt in range(5):
 
1192
  keys_to_try = HF_TOKENS.copy()
1193
  random.shuffle(keys_to_try)
1194
  for token in keys_to_try:
@@ -1202,10 +1227,12 @@ async def process_image(client, chat_id, prompt, size_choice="1"):
1202
  )
1203
  break
1204
  except Exception as e:
1205
- last_error_log = str(e)
 
 
1206
  continue
1207
  if generated_image: break
1208
- await asyncio.sleep(2)
1209
 
1210
  try:
1211
  if proc_msg:
@@ -1215,7 +1242,7 @@ async def process_image(client, chat_id, prompt, size_choice="1"):
1215
  except Exception: pass
1216
 
1217
  if not generated_image:
1218
- return await send_with_keyboard(client, chat_id, f"❌ عکس ساخته نشد.\n\n⚠️ خطا:\n{last_error_log[:200]}", True)
1219
 
1220
  try:
1221
  file_name = f"image_{uuid.uuid4().hex}.jpg"
@@ -1224,26 +1251,25 @@ async def process_image(client, chat_id, prompt, size_choice="1"):
1224
  caption_text = f"🎨 تصویر شما با پرامپت هوشمند آماده شد!\n\n📏 ابعاد تصویر: {size_name}\n✨ ایده اولیه: {prompt}"
1225
 
1226
  upload_result = False
1227
- error_log_img = ""
1228
- for up_att in range(3):
1229
  res = await helper_upload_file(client, chat_id, file_name, "Image", caption_text)
1230
  if res is True:
1231
  upload_result = True
1232
  break
1233
  else:
1234
- error_log_img = res
1235
- await asyncio.sleep(4)
1236
 
1237
  if upload_result is True:
1238
  if not creds.get("is_premium"):
1239
  user_credits_db[str_chat_id]["image"] -= 1
1240
  save_db(user_credits_db)
1241
  else:
1242
- await send_with_keyboard(client, chat_id, f"❌ عکس ساخته شد اما آپلود در روبیکا با خطا مواجه شد:\n`{str(error_log_img)[:800]}`", True)
1243
 
1244
  if os.path.exists(file_name): os.remove(file_name)
1245
  except Exception as e:
1246
- await send_with_keyboard(client, chat_id, f"❌ خطا در ذخیره و ارسال عکس:\n{str(e)[:150]}", True)
1247
 
1248
  # ==============================================================================
1249
  # 🟢 پارت 15: توابع ترجمه و ویرایش عکس با هوش مصنوعی (Flux.2)
@@ -1370,9 +1396,9 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
1370
  headers = {"User-Agent": "Mozilla/5.0", "Content-Type": "application/json"}
1371
 
1372
  audio_bytes = None
1373
- last_error = "پاسخی دریافت نشد"
1374
 
1375
- for attempt in range(10):
 
1376
  workers = WORKER_URLS.copy()
1377
  random.shuffle(workers)
1378
  async with aiohttp.ClientSession(headers=headers, timeout=aiohttp.ClientTimeout(total=600)) as session:
@@ -1384,13 +1410,12 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
1384
  if 'audio' in content_type or response.content_length > 1000:
1385
  audio_bytes = await response.read()
1386
  break
1387
- else: last_error = "فایل نامعتبر"
1388
- else: last_error = f"ارور ({response.status})"
1389
- except Exception as e:
1390
- last_error = f"خطا: {str(e)}"
1391
  continue
1392
  if audio_bytes: break
1393
- await asyncio.sleep(2)
1394
 
1395
  try:
1396
  if proc_msg:
@@ -1405,26 +1430,25 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
1405
  await asyncio.sleep(1)
1406
 
1407
  upload_result_file = False
1408
- error_log_tts = ""
1409
- for up_att in range(3):
1410
  res = await helper_upload_file(client, chat_id, file_name_mp3, "Music", "✅ صدای شما با موفقیت آماده شد (فایل MP3):")
1411
  if res is True:
1412
  upload_result_file = True
1413
  break
1414
  else:
1415
- error_log_tts = res
1416
- await asyncio.sleep(4)
1417
 
1418
  if upload_result_file is True:
1419
  if not creds.get("is_premium"):
1420
  user_credits_db[str_chat_id]["tts"] -= 1
1421
  save_db(user_credits_db)
1422
  else:
1423
- await send_with_keyboard(client, chat_id, f"❌ فایل صدا ساخته شد اما سرور روبیکا اجازه آپلود نداد:\n`{str(error_log_tts)[:800]}`", True)
1424
 
1425
  if os.path.exists(file_name_mp3): os.remove(file_name_mp3)
1426
  else:
1427
- await send_with_keyboard(client, chat_id, f"❌ سرورها درگیر هستند.\nدلیل: {last_error}", True)
1428
  except Exception: traceback.print_exc()
1429
 
1430
  # ==============================================================================
 
614
  # ==============================================================================
615
  async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""):
616
  abs_path = os.path.abspath(file_name)
617
+ error_logs =[]
618
 
619
+ api_file_type = "Image" if file_type in ["photo", "Image", "image"] else "Voice" if file_type in ["voice", "Voice", "audio"] else file_type
620
 
 
621
  if api_file_type == "Voice" and not abs_path.lower().endswith('.ogg'):
622
  api_file_type = "Music"
623
  if api_file_type == "File" and abs_path.lower().endswith('.mp3'):
624
  api_file_type = "Music"
625
 
626
+ # --- فاز اول (تلاش با متدهای روب‌پای تا 15 بار) ---
627
+ for attempt in range(15):
628
  try:
629
  sent_success = False
 
 
630
  if api_file_type == "Image" and hasattr(client, "send_photo"):
631
  try:
632
  await client.send_photo(chat_id, photo=abs_path, caption=caption)
 
635
  await client.send_photo(chat_id, abs_path, caption=caption)
636
  sent_success = True
637
 
 
638
  elif api_file_type == "Voice" and hasattr(client, "send_voice"):
639
  try:
640
  await client.send_voice(chat_id, abs_path, caption=caption)
 
643
  await client.send_voice(chat_id, file=abs_path, caption=caption)
644
  sent_success = True
645
 
 
646
  elif api_file_type == "Music" and hasattr(client, "send_music"):
647
  try:
648
  await client.send_music(chat_id, abs_path, caption=caption)
 
651
  await client.send_music(chat_id, music=abs_path, caption=caption)
652
  sent_success = True
653
 
 
 
654
  if not sent_success:
655
  if hasattr(client, "send_document"):
656
  try:
 
672
  return True
673
 
674
  except Exception as e:
675
+ err_msg = str(e)
676
+ error_logs.append(f"Rubpy Error: {err_msg[:50]}")
677
+ # سیستم ضد اسپم روبیکا: اگر ارور محدودیت درخواست داد، ۱۵ ثانیه صبر کن!
678
+ if "TOO_REQUESTS" in err_msg or "429" in err_msg or "502" in err_msg or "timeout" in err_msg.lower():
679
+ await asyncio.sleep(15)
680
  else:
681
+ await asyncio.sleep(4)
682
 
683
+ # --- فاز دوم (سنگر آخر: آپلود دستی تا 30 بار پافشاری شدید) ---
684
+ for attempt in range(30):
685
  try:
686
  url_request = f"https://botapi.rubika.ir/v3/{bot_token}/requestSendFile"
687
  url_send = f"https://botapi.rubika.ir/v3/{bot_token}/sendFile"
688
 
689
  async with aiohttp.ClientSession() as session:
690
+ async with session.post(url_request, json={"type": api_file_type}, timeout=60) as resp:
691
  if resp.status != 200:
692
+ await asyncio.sleep(5)
 
693
  continue
694
 
695
  req_data = await resp.json()
696
+
697
+ # 🛑 هندل کردن دقیق ارور رباتیک TOO_REQUESTS
698
+ if req_data.get("status") == "TOO_REQUESTS":
699
+ error_logs.append("Hit TOO_REQUESTS on requestSendFile. Sleeping 15s...")
700
+ await asyncio.sleep(15)
701
+ continue
702
+
703
  if req_data.get("status") == "OK":
704
  upload_url = req_data.get("data", {}).get("upload_url")
705
  if upload_url:
 
708
  form.add_field('file', f, filename=os.path.basename(abs_path))
709
  async with session.post(upload_url, data=form, timeout=300) as up_resp:
710
  if up_resp.status != 200:
711
+ await asyncio.sleep(5)
 
 
 
 
712
  continue
713
 
714
  try:
715
  up_data = await up_resp.json()
716
+ except Exception:
717
+ await asyncio.sleep(3)
 
718
  continue
719
 
720
+ if up_data.get("status") == "TOO_REQUESTS":
721
+ await asyncio.sleep(15)
722
+ continue
723
+
724
  final_file_id = None
725
 
 
 
726
  if up_data.get("status") == "INVALID_INPUT" and "format" in str(up_data).lower():
727
  api_file_type = "File"
728
+ await asyncio.sleep(2)
 
729
  continue
730
 
731
  if up_data.get("status") == "OK" or up_data.get("status_det") == "OK":
 
742
  "chat_keypad_type": "New",
743
  "chat_keypad": MAIN_KEYPAD_DICT
744
  }
745
+ async with session.post(url_send, json=send_payload, timeout=60) as send_resp:
 
 
 
 
 
746
  s_data = await send_resp.json()
747
+ if s_data.get("status") == "TOO_REQUESTS":
748
+ await asyncio.sleep(15)
749
+ continue
750
+ if s_data.get("status") == "OK":
751
+ return True
752
  else:
753
  if up_data.get("status") == "INVALID_INPUT" and api_file_type in ["Voice", "Music"]:
754
+ api_file_type = "File"
 
 
 
755
  except Exception as e:
756
+ error_logs.append(f"Raw HTTP Error: {str(e)[:50]}")
757
+ await asyncio.sleep(5)
758
 
759
  return "\n".join(error_logs[-6:])
760
 
761
  # ==============================================================================
762
  # 🟢 پارت 12: توابع تغییر صدا و لیست گویندگان
763
  # ==============================================================================
764
+ WORKER_URLS = ["https://opera8-ttspro.hf.space/generate"]
 
 
 
765
 
766
  SPEAKERS = {
767
  "1": ("شهاب (مرد)", "Charon"), "2": ("آوا (زن)", "Zephyr"), "3": ("نوید (مرد)", "Achird"),
 
778
 
779
  user_states = {}
780
 
 
 
 
781
  async def process_standard_vc_job(client, chat_id, src_bytes, ref_bytes, job_type_name, credit_type):
782
  str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
783
  creds = get_user_credits(str_chat_id)
784
 
785
+ await send_with_keyboard(client, chat_id, f"⏳ در حال آماده‌سازی فایل‌ها...\n(مدل: {job_type_name})", False)
786
 
787
+ job_id = None
788
+ total_chunks = 1
789
+ chunks =[]
790
+
791
+ # 🛑 پافشاری ۳۰ بار برای آپلود به سرور تغییر صدا (ضد ارور 429)
792
+ for attempt in range(30):
793
+ async with aiohttp.ClientSession() as session:
794
+ # فرم باید در هر تلاش از نو ساخته شود
795
+ form = aiohttp.FormData()
796
+ form.add_field('source_audio', src_bytes, filename='src.wav', content_type='audio/wav')
797
+ form.add_field('ref_audio', ref_bytes, filename='ref.wav', content_type='audio/wav')
798
+ try:
799
+ async with session.post(f"{VC_BASE_URL}/upload", data=form, timeout=120) as resp:
800
+ if resp.status == 429: # شلوغی سرور اسپیس
801
+ await asyncio.sleep(15)
802
+ continue
803
+ if resp.status == 200:
804
+ data = await resp.json()
805
+ job_id = data.get("job_id")
806
+ total_chunks = data.get("total_chunks", 1)
807
+ chunks = data.get("chunks",[])
808
+ break
809
+ else:
810
+ await asyncio.sleep(5)
811
+ except Exception:
812
+ await asyncio.sleep(5)
813
 
814
+ if not job_id:
815
+ return await send_with_keyboard(client, chat_id, "❌ پردازش ناموفق بود. ترافیک ربات بسیار بالاست، لطفا چند دقیقه دیگر مجدداً تلاش کنید.", True)
816
+
817
+ await send_with_keyboard(client, chat_id, "✅ فایل‌ها ارسال شد. در حال پردازش و تغییر صدا...\n(لطفا چند دقیقه صبور باشید)", False)
818
+
819
+ final_filename = None
820
+ async with aiohttp.ClientSession() as session:
821
+ for _ in range(1000): # حلقه بی‌نهایت چک کردن استتوس
822
+ await asyncio.sleep(5)
823
  payload_check = {"job_id": job_id, "total_chunks": total_chunks, "chunks": chunks}
824
  try:
825
+ async with session.post(f"{VC_BASE_URL}/check_status", json=payload_check, timeout=30) as c_resp:
826
  if c_resp.status == 200:
827
  c_data = await c_resp.json()
828
  if c_data.get("status") == "completed":
829
  final_filename = c_data.get("filename")
830
  break
831
  elif c_data.get("status") in ["failed", "error"]:
832
+ return await send_with_keyboard(client, chat_id, "❌ خطای داخلی سرور در حین ساخت صدا رخ داد.", True)
833
  except Exception:
834
  pass
835
 
836
  if not final_filename:
837
+ return await send_with_keyboard(client, chat_id, "❌ پردازش بیش از حد طول کشید.", True)
838
 
839
  download_url = f"{VC_BASE_URL}/download/{final_filename}"
840
  await send_with_keyboard(client, chat_id, "📥 پردازش تمام شد! در حال دانلود نتیجه...", False)
841
+
842
+ result_bytes = None
843
+ for attempt in range(30):
844
+ try:
845
+ async with session.get(download_url, timeout=120) as d_resp:
846
+ if d_resp.status == 200:
847
+ result_bytes = await d_resp.read()
848
+ break
849
+ elif d_resp.status == 429:
850
+ await asyncio.sleep(10)
851
+ except Exception:
852
+ await asyncio.sleep(5)
853
+
854
+ if not result_bytes:
855
+ return await send_with_keyboard(client, chat_id, "❌ خطا در دریافت فایل نهایی از سرور.", True)
856
 
857
  file_name_mp3 = f"vc_standard_{uuid.uuid4().hex[:6]}.mp3"
858
  await asyncio.to_thread(sync_write_file, file_name_mp3, result_bytes)
859
 
860
  upload_result = False
861
+ # پافشاری بسیار بالا برای آپلود نهایی به روبیکا
862
+ for up_att in range(15):
863
  res = await helper_upload_file(client, chat_id, file_name_mp3, "Music", f"🎙️ {job_type_name} شما آماده است!")
864
  if res is True:
865
  upload_result = True
866
  break
867
+ await asyncio.sleep(5)
868
 
869
  if upload_result is True:
870
  if not creds.get("is_premium"):
871
  user_credits_db[str_chat_id][credit_type] -= 1
872
  save_db(user_credits_db)
873
  else:
874
+ await send_with_keyboard(client, chat_id, "❌ فایل با موفقیت پردازش شد اما ارسال آن به دلیل شلوغی سرور روبیکا با مشکل مواجه شد.", True)
875
 
876
  if os.path.exists(file_name_mp3): os.remove(file_name_mp3)
877
 
 
879
  str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
880
  creds = get_user_credits(str_chat_id)
881
 
882
+ await send_with_keyboard(client, chat_id, f"⏳ در حال آماده‌سازی فایل‌ها...\n(مدل: {model_name})", False)
883
 
884
+ job_id = None
885
+ # 🛑 پافشاری ۳۰ بار
886
+ for attempt in range(30):
887
+ async with aiohttp.ClientSession() as session:
888
+ form = aiohttp.FormData()
889
+ form.add_field('audio_file', src_bytes, filename='input.wav', content_type='audio/wav')
890
+ form.add_field('model_url', model_url)
891
+ form.add_field('pitch', str(pitch))
892
+ form.add_field('algo', 'rmvpe+')
893
+ form.add_field('index_inf', '0.75')
894
+ form.add_field('res_filter', '3')
895
+ form.add_field('env_ratio', '0.25')
896
+ form.add_field('protect', '0.33')
897
+ form.add_field('denoise', 'false')
898
+ form.add_field('reverb', 'false')
899
+ try:
900
+ async with session.post(f"{LEGACY_BASE_URL}/upload", data=form, timeout=120) as resp:
901
+ if resp.status == 429:
902
+ await asyncio.sleep(15)
903
+ continue
904
+ if resp.status == 200:
905
+ data = await resp.json()
906
+ job_id = data.get("job_id")
907
+ break
908
+ else:
909
+ await asyncio.sleep(5)
910
+ except Exception:
911
+ await asyncio.sleep(5)
912
 
913
+ if not job_id:
914
+ return await send_with_keyboard(client, chat_id, "❌ ترافیک سرور بسیار بالاست. لطفا چند دقیقه دیگر امتحان کنید.", True)
915
+
916
+ await send_with_keyboard(client, chat_id, "✅ فایل ارسال شد. در حال پردازش و تغییر صدای شما...\n(لطفا چند دقیقه صبور باشید)", False)
917
+
918
+ final_filename = None
919
+ async with aiohttp.ClientSession() as session:
920
+ for _ in range(1000):
921
  await asyncio.sleep(5)
922
  try:
923
+ async with session.get(f"{LEGACY_BASE_URL}/status/{job_id}", timeout=30) as c_resp:
924
  if c_resp.status == 200:
925
  c_data = await c_resp.json()
926
  if c_data.get("status") == "completed":
 
936
 
937
  download_url = f"{LEGACY_BASE_URL}/download/{final_filename}"
938
  await send_with_keyboard(client, chat_id, "📥 پردازش تمام شد! در حال دانلود نتیجه...", False)
939
+
940
+ result_bytes = None
941
+ for attempt in range(30):
942
+ try:
943
+ async with session.get(download_url, timeout=120) as d_resp:
944
+ if d_resp.status == 200:
945
+ result_bytes = await d_resp.read()
946
+ break
947
+ elif d_resp.status == 429:
948
+ await asyncio.sleep(10)
949
+ except Exception:
950
+ await asyncio.sleep(5)
951
+
952
+ if not result_bytes:
953
+ return await send_with_keyboard(client, chat_id, "❌ خطا در دریافت فایل نهایی از سرور.", True)
954
 
955
  file_name_mp3 = f"vc_legacy_{uuid.uuid4().hex[:6]}.mp3"
956
  await asyncio.to_thread(sync_write_file, file_name_mp3, result_bytes)
957
 
958
  upload_result = False
959
+ for up_att in range(15):
960
  res = await helper_upload_file(client, chat_id, file_name_mp3, "Music", f"🎙️ صدای خروجی با مدل {model_name} آماده است!")
961
  if res is True:
962
  upload_result = True
963
  break
964
+ await asyncio.sleep(5)
965
 
966
  if upload_result is True:
967
  if not creds.get("is_premium"):
968
  user_credits_db[str_chat_id]["voice_conv"] -= 1
969
  save_db(user_credits_db)
970
  else:
971
+ await send_with_keyboard(client, chat_id, "❌ فایل پردازش شد اما ترافیک روبیکا اجازه آپلود نداد.", True)
972
 
973
  if os.path.exists(file_name_mp3): os.remove(file_name_mp3)
974
 
 
1158
  async with aiohttp.ClientSession() as session:
1159
  for key in keys_to_try_gemini:
1160
  url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
1161
+ payload = {"contents":[{"parts":[{"text": gemini_sys_prompt}]}], "generationConfig": {"temperature": 0.7}}
1162
  try:
1163
  async with session.post(url, json=payload, timeout=20) as response:
1164
  if response.status == 200:
 
1211
  proc_msg = await send_with_keyboard(client, chat_id, f"🎨 در حال طراحی عکس...\n\n📏 **ابعاد:** {size_name}\n📝 **پرامپت ساخته شده:**\n`{short_preview}`\n\n(ممکن است چند ثانیه زمان ببرد)", False)
1212
 
1213
  generated_image = None
 
1214
 
1215
+ # پافشاری ۳۰ بار روی ساخت عکس
1216
+ for attempt in range(30):
1217
  keys_to_try = HF_TOKENS.copy()
1218
  random.shuffle(keys_to_try)
1219
  for token in keys_to_try:
 
1227
  )
1228
  break
1229
  except Exception as e:
1230
+ err_str = str(e).lower()
1231
+ if "429" in err_str or "too many" in err_str:
1232
+ await asyncio.sleep(10)
1233
  continue
1234
  if generated_image: break
1235
+ await asyncio.sleep(5)
1236
 
1237
  try:
1238
  if proc_msg:
 
1242
  except Exception: pass
1243
 
1244
  if not generated_image:
1245
+ return await send_with_keyboard(client, chat_id, f"❌ سرورهای ساخت عکس به شدت شلوغ هستند. لطفاً مجدداً امتحان کنید.", True)
1246
 
1247
  try:
1248
  file_name = f"image_{uuid.uuid4().hex}.jpg"
 
1251
  caption_text = f"🎨 تصویر شما با پرامپت هوشمند آماده شد!\n\n📏 ابعاد تصویر: {size_name}\n✨ ایده اولیه: {prompt}"
1252
 
1253
  upload_result = False
1254
+ # پافشاری ۱۵ بار روی ارسال عکس به روبیکا
1255
+ for up_att in range(15):
1256
  res = await helper_upload_file(client, chat_id, file_name, "Image", caption_text)
1257
  if res is True:
1258
  upload_result = True
1259
  break
1260
  else:
1261
+ await asyncio.sleep(5)
 
1262
 
1263
  if upload_result is True:
1264
  if not creds.get("is_premium"):
1265
  user_credits_db[str_chat_id]["image"] -= 1
1266
  save_db(user_credits_db)
1267
  else:
1268
+ await send_with_keyboard(client, chat_id, f"❌ عکس با موفقیت ساخته شد اما روبیکا به دلیل ترافیک بالا اجازه ارسال نداد.", True)
1269
 
1270
  if os.path.exists(file_name): os.remove(file_name)
1271
  except Exception as e:
1272
+ pass
1273
 
1274
  # ==============================================================================
1275
  # 🟢 پارت 15: توابع ترجمه و ویرایش عکس با هوش مصنوعی (Flux.2)
 
1396
  headers = {"User-Agent": "Mozilla/5.0", "Content-Type": "application/json"}
1397
 
1398
  audio_bytes = None
 
1399
 
1400
+ # پافشاری بسیار بالا (۳۰ بار) برای سرورهای تولید صدا
1401
+ for attempt in range(30):
1402
  workers = WORKER_URLS.copy()
1403
  random.shuffle(workers)
1404
  async with aiohttp.ClientSession(headers=headers, timeout=aiohttp.ClientTimeout(total=600)) as session:
 
1410
  if 'audio' in content_type or response.content_length > 1000:
1411
  audio_bytes = await response.read()
1412
  break
1413
+ elif response.status == 429: # مسدودیت موقت
1414
+ await asyncio.sleep(10)
1415
+ except Exception:
 
1416
  continue
1417
  if audio_bytes: break
1418
+ await asyncio.sleep(5)
1419
 
1420
  try:
1421
  if proc_msg:
 
1430
  await asyncio.sleep(1)
1431
 
1432
  upload_result_file = False
1433
+ # پافشاری بالا روی ارسال فایل در روبیکا
1434
+ for up_att in range(15):
1435
  res = await helper_upload_file(client, chat_id, file_name_mp3, "Music", "✅ صدای شما با موفقیت آماده شد (فایل MP3):")
1436
  if res is True:
1437
  upload_result_file = True
1438
  break
1439
  else:
1440
+ await asyncio.sleep(5)
 
1441
 
1442
  if upload_result_file is True:
1443
  if not creds.get("is_premium"):
1444
  user_credits_db[str_chat_id]["tts"] -= 1
1445
  save_db(user_credits_db)
1446
  else:
1447
+ await send_with_keyboard(client, chat_id, f"❌ صدای شما ساخته شد اما شلوغی سرور روبیکا مانع ارسال آن شد.", True)
1448
 
1449
  if os.path.exists(file_name_mp3): os.remove(file_name_mp3)
1450
  else:
1451
+ await send_with_keyboard(client, chat_id, f"❌ سرورها درگیر هستند. لطفا دقایقی دیگر مجددا امتحان کنید.", True)
1452
  except Exception: traceback.print_exc()
1453
 
1454
  # ==============================================================================