Opera8 commited on
Commit
3c50a88
·
verified ·
1 Parent(s): 9cdbc91

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +60 -152
main.py CHANGED
@@ -698,204 +698,112 @@ HF_TOKENS_STR = os.environ.get("HF_TOKENS", "")
698
  HF_TOKENS =[k.strip() for k in HF_TOKENS_STR.split(",") if k.strip()]
699
 
700
  # ==============================================================================
701
- # 🟢 پارت 11: آپلودر صبور، هوشمند و صنعتی (با ظرفیت 50 کارگر همزمان طبق درخواست)
702
  # ==============================================================================
703
  import asyncio
704
  import os
705
- import aiohttp
706
 
707
- # 🟢 ۱. مدیریت صف آپلود اصلی (ارتقا به ۵۰ کارگر)
708
  _upload_lock = None
709
- _shared_session = None
710
 
711
  def get_upload_lock():
712
  global _upload_lock
713
  if _upload_lock is None:
714
- # ظرفیت روی 50 تنظیم شد.
715
- _upload_lock = asyncio.Semaphore(2)
716
  return _upload_lock
717
 
718
- async def get_shared_session():
719
- global _shared_session
720
- if _shared_session is None or _shared_session.closed:
721
- connector = aiohttp.TCPConnector(limit=100, keepalive_timeout=60)
722
- _shared_session = aiohttp.ClientSession(connector=connector)
723
- return _shared_session
724
-
725
  async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""):
726
  abs_path = os.path.abspath(file_name)
727
  if not os.path.exists(abs_path):
728
  return "File Not Found"
729
 
730
- try:
731
- file_bytes = await asyncio.to_thread(sync_read_file, abs_path)
732
- except Exception as e:
733
- return f"File Read Error: {e}"
734
-
735
  error_logs = []
736
- bot_token = os.environ.get("RUBIKA_AUTH", "").strip()
737
 
 
738
  api_file_type = "Image" if file_type in ["photo", "Image", "image"] else "Voice" if file_type in ["voice", "Voice", "audio"] else file_type
739
  if api_file_type == "Voice" and not abs_path.lower().endswith('.ogg'):
740
  api_file_type = "Music"
741
  if api_file_type == "File" and abs_path.lower().endswith('.mp3'):
742
  api_file_type = "Music"
743
-
744
  async with get_upload_lock():
745
- session = await get_shared_session()
746
 
747
- # سیستم خواب تصاعدی: اگر روبیکا بلاک کرد، چقدر صبر کنیم؟
748
- backoff_time = 10
749
-
750
- # 🚀 فاز اصلی: استفاده از API پرسرعت روبیکا
751
- for attempt in range(12):
752
  try:
753
- # --- مرحله ۱: گرفتن لینک آپلود ---
754
- req_resp = await session.post(
755
- f"https://botapi.rubika.ir/v3/{bot_token}/requestSendFile",
756
- json={"type": api_file_type},
757
- timeout=aiohttp.ClientTimeout(total=20)
758
- )
759
- if req_resp.status != 200:
760
- error_logs.append(f"reqSend HTTP {req_resp.status}")
761
- await asyncio.sleep(3)
762
- continue
763
-
764
- req_data = await req_resp.json()
765
- if req_data.get("status") in ["TOO_REQUESTS", "TOO_REQ"]:
766
- error_logs.append(f"TOO_REQ (گرفتن لینک - صبر {backoff_time}s)")
767
- await asyncio.sleep(backoff_time)
768
- backoff_time += 5
769
- continue
770
-
771
- upload_url = req_data.get("data", {}).get("upload_url")
772
- if not upload_url:
773
- error_logs.append("لینک آپلود دریافت نشد")
774
- await asyncio.sleep(3)
775
- continue
776
-
777
- # --- مرحله ۲: آپلود فیزیکی فایل ---
778
- form = aiohttp.FormData()
779
- form.add_field('file', file_bytes, filename=os.path.basename(abs_path))
780
-
781
- up_resp = await session.post(
782
- upload_url,
783
- data=form,
784
- timeout=aiohttp.ClientTimeout(total=120)
785
- )
786
- if up_resp.status != 200:
787
- error_logs.append(f"Upload HTTP {up_resp.status}")
788
- await asyncio.sleep(3)
789
- continue
790
-
791
- up_data = await up_resp.json()
792
- if up_data.get("status") in ["TOO_REQUESTS", "TOO_REQ"]:
793
- error_logs.append(f"TOO_REQ (آپلود - صبر {backoff_time}s)")
794
- await asyncio.sleep(backoff_time)
795
- backoff_time += 5
796
- continue
797
-
798
- final_file_id = None
799
- if up_data.get("status") in ["OK", "OK_DET"]:
800
- if "data" in up_data and isinstance(up_data["data"], dict):
801
- final_file_id = up_data["data"].get("file_id") or up_data["data"].get("id")
802
- else:
803
- final_file_id = up_data.get("file_id")
804
- else:
805
- error_logs.append(f"Up Error: {up_data.get('status')}")
806
-
807
- if final_file_id:
808
- # --- مرحله ۳: ارسال فایل به کاربر ---
809
- send_payload = {
810
- "chat_id": str(chat_id),
811
- "file_id": str(final_file_id),
812
- "text": caption,
813
- "chat_keypad_type": "New",
814
- "chat_keypad": MAIN_KEYPAD_DICT
815
- }
816
- send_resp = await session.post(
817
- f"https://botapi.rubika.ir/v3/{bot_token}/sendFile",
818
- json=send_payload,
819
- timeout=aiohttp.ClientTimeout(total=20)
820
- )
821
- s_data = await send_resp.json()
822
-
823
- if s_data.get("status") == "OK":
824
- await asyncio.sleep(1)
825
  return True
826
- elif s_data.get("status") in ["TOO_REQUESTS", "TOO_REQ"]:
827
- error_logs.append(f"TOO_REQ (ارسال نهایی - صبر {backoff_time}s)")
828
- await asyncio.sleep(backoff_time)
829
- backoff_time += 5
830
- continue
831
- else:
832
- error_logs.append(f"Send Error: {s_data.get('status')}")
 
 
833
  else:
834
- if not final_file_id and "INVALID_INPUT" in str(up_data):
835
- api_file_type = "File"
836
- error_logs.append("تغییر اجباری نوع به File")
837
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
838
  except Exception as e:
839
- error_logs.append(f"تلاش {attempt+1} خطا: {str(e)[:25]}")
840
- await asyncio.sleep(3)
841
-
842
- # 🛡️ فاز دوم (Fallback امن)
843
- try:
844
- sent_success = False
845
- if api_file_type == "Image" and hasattr(client, "send_photo"):
846
- try:
847
- await client.send_photo(chat_id, photo=abs_path, caption=caption)
848
- sent_success = True
849
- except Exception as e:
850
- if "TOO_REQ" in str(e).upper():
851
- await asyncio.sleep(15)
852
- await client.send_photo(chat_id, photo=abs_path, caption=caption)
853
- sent_success = True
854
-
855
- elif api_file_type in ["Music", "Voice"] and hasattr(client, "send_music"):
856
- try:
857
- await client.send_music(chat_id, abs_path, caption=caption)
858
- sent_success = True
859
- except Exception as e:
860
- if "TOO_REQ" in str(e).upper():
861
- await asyncio.sleep(15)
862
- await client.send_music(chat_id, abs_path, caption=caption)
863
- sent_success = True
864
-
865
- if not sent_success:
866
- if hasattr(client, "send_document"):
867
- await client.send_document(chat_id, document=abs_path, caption=caption)
868
- sent_success = True
869
- elif hasattr(client, "send_file"):
870
- await client.send_file(chat_id, abs_path)
871
- sent_success = True
872
-
873
- if sent_success:
874
- return True
875
 
876
- except Exception as e:
877
- error_logs.append(f"Fallback Fail: {str(e)[:40]}")
 
 
 
 
 
 
878
 
879
- return "❌ خطا در آپلود:\n" + "\n".join(error_logs[-5:])
880
 
881
  # ==============================================================================
882
- # 🟢 ۲. تعریف کارگرهای پس‌زمینه عمومی (ارتقا به 50 کارگر اختصاصی)
883
  # ==============================================================================
884
- _general_upload_workers = asyncio.Semaphore(50) # ظرفیت 50 فایل همزمان در پس‌زمینه
885
 
886
  async def background_general_uploader(client, chat_id, file_name, file_type, caption_text, str_chat_id, credit_key=None):
887
  async with _general_upload_workers:
888
  try:
889
  res = await helper_upload_file(client, chat_id, file_name, file_type, caption_text)
890
  if res is not True:
 
891
  creds = get_user_credits(str_chat_id)
892
  if not creds.get("is_premium") and credit_key:
893
  user_credits_db[str_chat_id][credit_key] += 1
894
  save_db(user_credits_db)
895
  await send_with_keyboard(client, chat_id, f"❌ سرور ارسال گزارش داد:\nآپلود {file_type} انجام نشد و اعتبار شما برگشت داده شد.\n`{str(res)[:500]}`", True)
896
- except: pass
 
897
  finally:
898
- if os.path.exists(file_name): os.remove(file_name)
 
 
899
 
900
 
901
 
 
698
  HF_TOKENS =[k.strip() for k in HF_TOKENS_STR.split(",") if k.strip()]
699
 
700
  # ==============================================================================
701
+ # 🟢 پارت 11: آپلودر با استفاده انحصاری از کتابخانه رسمی روب‌پای (Rubpy)
702
  # ==============================================================================
703
  import asyncio
704
  import os
 
705
 
706
+ # 🟢 ۱. مدیریت صف آپلود
707
  _upload_lock = None
 
708
 
709
  def get_upload_lock():
710
  global _upload_lock
711
  if _upload_lock is None:
712
+ # برای اینکه کتابخانه کرش نکند، فایل‌ها را 2 تا 2 تا به کتابخانه می‌سپاریم
713
+ _upload_lock = asyncio.Semaphore(10)
714
  return _upload_lock
715
 
 
 
 
 
 
 
 
716
  async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""):
717
  abs_path = os.path.abspath(file_name)
718
  if not os.path.exists(abs_path):
719
  return "File Not Found"
720
 
 
 
 
 
 
721
  error_logs = []
 
722
 
723
+ # تشخیص نوع فایل
724
  api_file_type = "Image" if file_type in ["photo", "Image", "image"] else "Voice" if file_type in ["voice", "Voice", "audio"] else file_type
725
  if api_file_type == "Voice" and not abs_path.lower().endswith('.ogg'):
726
  api_file_type = "Music"
727
  if api_file_type == "File" and abs_path.lower().endswith('.mp3'):
728
  api_file_type = "Music"
729
+
730
  async with get_upload_lock():
731
+ backoff_time = 10 # زمان صبر اولیه در صورت برخورد به محدودیت
732
 
733
+ # ربات ۵ بار تلاش می‌کند تا کتابخانه کار را انجام دهد
734
+ for attempt in range(5):
 
 
 
735
  try:
736
+ if api_file_type == "Image":
737
+ if hasattr(client, "send_photo"):
738
+ try:
739
+ await client.send_photo(chat_id, photo=abs_path, caption=caption)
740
+ except TypeError:
741
+ await client.send_photo(chat_id, abs_path, caption=caption)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
742
  return True
743
+
744
+ elif api_file_type in ["Music", "Voice"]:
745
+ if hasattr(client, "send_music"):
746
+ try:
747
+ await client.send_music(chat_id, abs_path, caption=caption)
748
+ except TypeError:
749
+ await client.send_music(chat_id, music=abs_path, caption=caption)
750
+ return True
751
+
752
  else:
753
+ if hasattr(client, "send_document"):
754
+ try:
755
+ await client.send_document(chat_id, document=abs_path, caption=caption)
756
+ except TypeError:
757
+ await client.send_document(chat_id, abs_path, caption=caption)
758
+ return True
759
+ elif hasattr(client, "send_file"):
760
+ try:
761
+ await client.send_file(chat_id, file=abs_path)
762
+ except TypeError:
763
+ await client.send_file(chat_id, abs_path)
764
+ if caption:
765
+ await send_with_keyboard(client, chat_id, caption, True)
766
+ return True
767
+
768
+ error_logs.append("متد مناسب در کتابخانه یافت نشد.")
769
+ break # اگر متد کلاً وجود نداشت، از حلقه خارج می‌شویم
770
+
771
  except Exception as e:
772
+ err_str = str(e)
773
+ error_logs.append(f"تلاش {attempt+1} با کتابخانه: {err_str[:40]}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
774
 
775
+ # اگر کتابخانه ارور TOO_REQUESTS داد، صبر می‌کنیم
776
+ if "TOO_REQ" in err_str.upper() or "429" in err_str:
777
+ await asyncio.sleep(backoff_time)
778
+ backoff_time += 15 # دفعه بعد بیشتر صبر می‌کند
779
+ else:
780
+ await asyncio.sleep(4)
781
+
782
+ return "❌ خطا در آپلود با کتابخانه روب‌پای:\n" + "\n".join(error_logs[-3:])
783
 
 
784
 
785
  # ==============================================================================
786
+ # 🟢 ۲. تعریف کارگرهای پس‌زمینه عمومی (مشترک برای همه بخش‌ها)
787
  # ==============================================================================
788
+ _general_upload_workers = asyncio.Semaphore(10) # ظرفیت پردازش پس‌زمینه
789
 
790
  async def background_general_uploader(client, chat_id, file_name, file_type, caption_text, str_chat_id, credit_key=None):
791
  async with _general_upload_workers:
792
  try:
793
  res = await helper_upload_file(client, chat_id, file_name, file_type, caption_text)
794
  if res is not True:
795
+ # عودت اعتبار در صورت شکست قطعی آپلود
796
  creds = get_user_credits(str_chat_id)
797
  if not creds.get("is_premium") and credit_key:
798
  user_credits_db[str_chat_id][credit_key] += 1
799
  save_db(user_credits_db)
800
  await send_with_keyboard(client, chat_id, f"❌ سرور ارسال گزارش داد:\nآپلود {file_type} انجام نشد و اعتبار شما برگشت داده شد.\n`{str(res)[:500]}`", True)
801
+ except Exception as e:
802
+ pass
803
  finally:
804
+ if os.path.exists(file_name):
805
+ os.remove(file_name)
806
+
807
 
808
 
809