Update main.py
Browse files
main.py
CHANGED
|
@@ -79,7 +79,6 @@ def load_db():
|
|
| 79 |
print("در حال تلاش برای خواندن دیتابیس کاربران از دیتاست هاگینگ فیس...")
|
| 80 |
if HF_TOKEN_DB:
|
| 81 |
try:
|
| 82 |
-
# دانلود دیتابیس از دیتاست خصوصی
|
| 83 |
file_path = hf_hub_download(
|
| 84 |
repo_id=DATASET_REPO,
|
| 85 |
filename=DB_FILE,
|
|
@@ -90,9 +89,8 @@ def load_db():
|
|
| 90 |
print("✅ دیتابیس با موفقیت از دیتاست هاگینگ فیس لود شد.")
|
| 91 |
return json.load(f)
|
| 92 |
except Exception as e:
|
| 93 |
-
print("⚠️ فایل دیتابیس در هاگینگ فیس یافت نشد یا خطایی رخ داد (ساخت دیتابیس جدید).
|
| 94 |
|
| 95 |
-
# اگر از دیتاست لود نشد، از لوکال بخوان
|
| 96 |
if os.path.exists(DB_FILE):
|
| 97 |
try:
|
| 98 |
with open(DB_FILE, "r", encoding="utf-8") as f:
|
|
@@ -102,7 +100,6 @@ def load_db():
|
|
| 102 |
return {}
|
| 103 |
|
| 104 |
def _upload_db_background():
|
| 105 |
-
"""تابع کمکی برای آپلود دیتابیس بدون درگیر کردن سرعت ربات"""
|
| 106 |
if HF_TOKEN_DB:
|
| 107 |
api = HfApi(token=HF_TOKEN_DB)
|
| 108 |
try:
|
|
@@ -118,24 +115,40 @@ def _upload_db_background():
|
|
| 118 |
def save_db(db_data):
|
| 119 |
with db_lock:
|
| 120 |
try:
|
| 121 |
-
# ذخیره فایل به صورت لوکال
|
| 122 |
with open(DB_FILE, "w", encoding="utf-8") as f:
|
| 123 |
json.dump(db_data, f, ensure_ascii=False, indent=4)
|
| 124 |
-
|
| 125 |
-
# استارت کردن یک Thread جدید برای آپلود به دیتاست تا ربات منتظر نماند
|
| 126 |
threading.Thread(target=_upload_db_background, daemon=True).start()
|
| 127 |
except Exception as e:
|
| 128 |
print("خطا در ذخیره دیتابیس:", e)
|
| 129 |
|
| 130 |
user_credits_db = load_db()
|
| 131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
def get_user_credits(chat_id):
|
| 133 |
-
# اطمینان از پاک بودن استرینگ از علائم مزاحم
|
| 134 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 135 |
today_str = datetime.date.today().isoformat()
|
| 136 |
|
| 137 |
if str_chat_id not in user_credits_db:
|
| 138 |
-
# ساخت کاربر جدید با مقادیر اولیه
|
| 139 |
user_credits_db[str_chat_id] = {
|
| 140 |
"is_premium": False,
|
| 141 |
"expire_date": None,
|
|
@@ -147,30 +160,29 @@ def get_user_credits(chat_id):
|
|
| 147 |
"tts": 5,
|
| 148 |
"file": 1,
|
| 149 |
"stt": 5,
|
| 150 |
-
"has_joined": False
|
|
|
|
|
|
|
|
|
|
| 151 |
}
|
| 152 |
save_db(user_credits_db)
|
| 153 |
|
| 154 |
user_data = user_credits_db[str_chat_id]
|
| 155 |
is_premium = user_data.get("is_premium", False)
|
| 156 |
|
| 157 |
-
# 🛡 بررسی انقضای اشتراک ماهانه کاربران ویژه 🛡
|
| 158 |
if is_premium and user_data.get("expire_date"):
|
| 159 |
try:
|
| 160 |
expire_date = datetime.datetime.fromisoformat(user_data["expire_date"])
|
| 161 |
if datetime.datetime.now() > expire_date:
|
| 162 |
-
# اگر زمان اشتراک تمام شده باشد، دوباره رایگان میشود
|
| 163 |
user_data["is_premium"] = False
|
| 164 |
user_data["expire_date"] = None
|
| 165 |
is_premium = False
|
| 166 |
except Exception:
|
| 167 |
pass
|
| 168 |
|
| 169 |
-
# 🔄 سیستم شارژ روزانه (فقط و فقط برای نسخه رایگان) 🔄
|
| 170 |
if not is_premium:
|
| 171 |
if user_data.get("last_reset") != today_str:
|
| 172 |
user_data["last_reset"] = today_str
|
| 173 |
-
# شارژ روزانه نسخه رایگان
|
| 174 |
user_data["chat"] = 10
|
| 175 |
user_data["image"] = 5
|
| 176 |
user_data["edit_image"] = 1
|
|
@@ -197,7 +209,7 @@ app = Flask(__name__)
|
|
| 197 |
|
| 198 |
@app.route('/')
|
| 199 |
def home():
|
| 200 |
-
return "ربات یکپارچه آلفا (نسخه پرو + مدیریت اشتراک نامحدود + د
|
| 201 |
|
| 202 |
def run_flask():
|
| 203 |
app.run(host="0.0.0.0", port=7860)
|
|
@@ -240,6 +252,12 @@ MAIN_KEYPAD_DICT = {
|
|
| 240 |
{"id": "buy_btn", "type": "Simple", "button_text": "خرید اشتراک 💎"}
|
| 241 |
]
|
| 242 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
{
|
| 244 |
"buttons":[
|
| 245 |
{"id": "transfer_btn", "type": "Simple", "button_text": "انتقال اکانت از برنامه به ربات"}
|
|
@@ -254,7 +272,6 @@ MAIN_KEYPAD_DICT = {
|
|
| 254 |
"resize_keyboard": True
|
| 255 |
}
|
| 256 |
|
| 257 |
-
# --- ⛔️ سیستم بررسی عضویت اجباری کانال (Force Join) ⛔️ ---
|
| 258 |
CHANNEL_USERNAME = "aialpha"
|
| 259 |
CHANNEL_GUID = None
|
| 260 |
|
|
@@ -271,7 +288,6 @@ JOIN_KEYPAD_DICT = {
|
|
| 271 |
|
| 272 |
async def check_channel_membership(client, user_id):
|
| 273 |
global CHANNEL_GUID
|
| 274 |
-
# جلوگیری از بلاک شدن خود ربات
|
| 275 |
if str(user_id) == str(BOT_GUID): return True
|
| 276 |
|
| 277 |
try:
|
|
@@ -293,7 +309,7 @@ async def check_channel_membership(client, user_id):
|
|
| 293 |
CHANNEL_GUID = getattr(res.exist.chat, 'object_guid', None)
|
| 294 |
|
| 295 |
if not CHANNEL_GUID:
|
| 296 |
-
return True
|
| 297 |
|
| 298 |
payload = {
|
| 299 |
"channel_guid": CHANNEL_GUID,
|
|
@@ -312,10 +328,9 @@ async def check_channel_membership(client, user_id):
|
|
| 312 |
|
| 313 |
return False
|
| 314 |
except Exception:
|
| 315 |
-
return False
|
| 316 |
|
| 317 |
|
| 318 |
-
# --- تابع ارسال منحصراً برای کیبورد پایین صفحه ---
|
| 319 |
async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
|
| 320 |
try:
|
| 321 |
if not use_keyboard:
|
|
@@ -335,7 +350,6 @@ async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
|
|
| 335 |
return None
|
| 336 |
|
| 337 |
|
| 338 |
-
# --- 🚨 تابع هوشمند دانلود فایل (با استفاده از UUID جهت جلوگیری از تداخل حریم خصوصی) 🚨 ---
|
| 339 |
async def helper_download_file(client, msg_obj):
|
| 340 |
errors =[]
|
| 341 |
file_id = None
|
|
@@ -348,7 +362,6 @@ async def helper_download_file(client, msg_obj):
|
|
| 348 |
elif isinstance(val, dict) and 'file_id' in val: file_id = val['file_id']
|
| 349 |
if file_id: break
|
| 350 |
|
| 351 |
-
# 🛡 استفاده از UUID به جای اعداد تصادفی برای تضمین ۱۰۰ درصدی عدم تداخل نام فایلها 🛡
|
| 352 |
temp_name = f"temp_dl_{uuid.uuid4().hex}.tmp"
|
| 353 |
|
| 354 |
if hasattr(client, "download_file"):
|
|
@@ -389,7 +402,6 @@ async def helper_download_file(client, msg_obj):
|
|
| 389 |
raise Exception("دانلود ناموفق. لاگ:\n" + "\n".join(errors))
|
| 390 |
|
| 391 |
|
| 392 |
-
# --- تنظیمات کلیدها ---
|
| 393 |
GEMINI_KEYS_STR1 = os.environ.get("GEMINI_API_KEYS1", "")
|
| 394 |
GEMINI_KEYS_STR2 = os.environ.get("GEMINI_API_KEYS2", "")
|
| 395 |
|
|
@@ -399,21 +411,13 @@ if GEMINI_KEYS_STR1:
|
|
| 399 |
if GEMINI_KEYS_STR2:
|
| 400 |
_raw_keys.extend(GEMINI_KEYS_STR2.split(","))
|
| 401 |
|
| 402 |
-
# حذف کلیدهای تکراری و خالی
|
| 403 |
GEMINI_KEYS = list(set([k.strip() for k in _raw_keys if k.strip()]))
|
| 404 |
print(f"✅ تعداد {len(GEMINI_KEYS)} کلید جیمینای با موفقیت شناسایی شد.")
|
| 405 |
|
| 406 |
-
# --- 🚀 سیستم چرخشی پیشرفته (Round-Robin) برای کلیدهای جیمینای ---
|
| 407 |
current_gemini_key_index = 0
|
| 408 |
gemini_key_lock = threading.Lock()
|
| 409 |
|
| 410 |
def get_next_gemini_keys(count=100):
|
| 411 |
-
"""
|
| 412 |
-
این تابع تضمین میکند که به ترتیب از کلیدها استفاده شود.
|
| 413 |
-
مثلاً درخواست اول کلیدهای ۱ تا ۱۰۰ را میگیرد.
|
| 414 |
-
درخواست دوم کلیدهای ۱۰۱ تا ۲۰۰ را میگیرد.
|
| 415 |
-
و وقتی به آخر لیست برسد، دوباره از اول شروع میکند.
|
| 416 |
-
"""
|
| 417 |
global current_gemini_key_index
|
| 418 |
with gemini_key_lock:
|
| 419 |
total_keys = len(GEMINI_KEYS)
|
|
@@ -435,25 +439,21 @@ HF_TOKENS =[k.strip() for k in HF_TOKENS_STR.split(",") if k.strip()]
|
|
| 435 |
bot_token = os.environ.get("RUBIKA_AUTH", "").strip()
|
| 436 |
|
| 437 |
|
| 438 |
-
# --- 🚨 تابع اختصاصی آپلود فایل به روبیکا (مجهز به سیستم Fallback هوشمند صوتی و Music) 🚨 ---
|
| 439 |
async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""):
|
| 440 |
abs_path = os.path.abspath(file_name)
|
| 441 |
error_logs =[]
|
| 442 |
|
| 443 |
api_file_type = "Image" if file_type in["photo", "Image", "image"] else "Voice" if file_type in["voice", "Voice", "audio"] else "File"
|
| 444 |
|
| 445 |
-
# اگر قرار است ویس ارسال شود اما فایل پسوند مناسب ندارد، برای جلوگیری از ارور فوراً به Music تبدیل میکنیم
|
| 446 |
if api_file_type == "Voice" and not abs_path.lower().endswith('.ogg'):
|
| 447 |
api_file_type = "Music"
|
| 448 |
|
| 449 |
-
# سیستم ۳ بار تلاش مجدد برای جلوگیری از قطعی سرور روبیکا
|
| 450 |
for attempt in range(3):
|
| 451 |
try:
|
| 452 |
url_request = f"https://botapi.rubika.ir/v3/{bot_token}/requestSendFile"
|
| 453 |
url_send = f"https://botapi.rubika.ir/v3/{bot_token}/sendFile"
|
| 454 |
|
| 455 |
async with aiohttp.ClientSession() as session:
|
| 456 |
-
# ۱. درخواست آدرس آپلود از روبیکا
|
| 457 |
async with session.post(url_request, json={"type": api_file_type}, timeout=20) as resp:
|
| 458 |
if resp.status != 200:
|
| 459 |
error_logs.append(f"Request HTTP {resp.status}")
|
|
@@ -465,17 +465,14 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
|
|
| 465 |
if req_data.get("status") == "OK":
|
| 466 |
upload_url = req_data.get("data", {}).get("upload_url")
|
| 467 |
|
| 468 |
-
# اگر آدرس آپلود با موفقیت دریافت شد
|
| 469 |
if upload_url:
|
| 470 |
with open(abs_path, "rb") as f:
|
| 471 |
form = aiohttp.FormData()
|
| 472 |
form.add_field('file', f, filename=os.path.basename(abs_path))
|
| 473 |
|
| 474 |
-
# ۲. ارسال فایل به لینک آپلود
|
| 475 |
async with session.post(upload_url, data=form, timeout=60) as up_resp:
|
| 476 |
if up_resp.status != 200:
|
| 477 |
error_logs.append(f"Upload HTTP {up_resp.status}")
|
| 478 |
-
# 🔴 اگر ارور 502 داد یعنی روبیکا فرمت ویس را پس زده است، پس تبدیل به حالت Music میکنیم
|
| 479 |
if up_resp.status == 502 and api_file_type == "Voice":
|
| 480 |
api_file_type = "Music"
|
| 481 |
await asyncio.sleep(1.5)
|
|
@@ -488,7 +485,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
|
|
| 488 |
await asyncio.sleep(1.5)
|
| 489 |
continue
|
| 490 |
|
| 491 |
-
# ۳. گرفتن file_id از پاسخی که سرور آپلود برمیگرداند
|
| 492 |
final_file_id = None
|
| 493 |
if up_data.get("status") == "OK" or up_data.get("status_det") == "OK":
|
| 494 |
if "data" in up_data and isinstance(up_data["data"], dict):
|
|
@@ -497,7 +493,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
|
|
| 497 |
final_file_id = up_data.get("file_id")
|
| 498 |
|
| 499 |
if final_file_id:
|
| 500 |
-
# ۴. ارسال نهایی پیام
|
| 501 |
send_payload = {
|
| 502 |
"chat_id": str(chat_id),
|
| 503 |
"file_id": str(final_file_id),
|
|
@@ -517,7 +512,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
|
|
| 517 |
else:
|
| 518 |
error_logs.append(f"SendFile API Error: {s_data}")
|
| 519 |
else:
|
| 520 |
-
# 🔴 اگر فرمت فایل نامعتبر بود، به جای ویس، به صورت موزیک (دارای دکمه پخش) ارسال کن
|
| 521 |
if up_data.get("status") == "INVALID_INPUT" and api_file_type == "Voice":
|
| 522 |
api_file_type = "Music"
|
| 523 |
error_logs.append(f"Upload API Error: {up_data}")
|
|
@@ -529,7 +523,6 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
|
|
| 529 |
error_logs.append(f"Raw HTTP Error: {str(e)[:100]}")
|
| 530 |
await asyncio.sleep(1.5)
|
| 531 |
|
| 532 |
-
# تلاش نهایی از طریق روبپای به عنوان راه جایگزین
|
| 533 |
try:
|
| 534 |
if hasattr(client, "send_file"):
|
| 535 |
await client.send_file(chat_id, abs_path)
|
|
@@ -567,7 +560,6 @@ processed_message_ids = set()
|
|
| 567 |
user_last_request_time = {}
|
| 568 |
|
| 569 |
|
| 570 |
-
# --- ۱. پردازش چت متنی و چندرسانهای ---
|
| 571 |
async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=None):
|
| 572 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 573 |
creds = get_user_credits(str_chat_id)
|
|
@@ -604,7 +596,6 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
|
|
| 604 |
history = history[-40:]
|
| 605 |
if history[0]["role"] == "model": history = history[1:]
|
| 606 |
|
| 607 |
-
# دریافت ۱۰۰ کلید به صورت چرخشی
|
| 608 |
keys_to_try = get_next_gemini_keys(100)
|
| 609 |
final_answer = None
|
| 610 |
|
|
@@ -622,7 +613,6 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
|
|
| 622 |
except (KeyError, IndexError): continue
|
| 623 |
except Exception: continue
|
| 624 |
|
| 625 |
-
# --- Fallback to Hugging Face Gemma 4 ---
|
| 626 |
if not final_answer and HF_TOKENS:
|
| 627 |
hf_messages =[]
|
| 628 |
for msg in history:
|
|
@@ -673,7 +663,6 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
|
|
| 673 |
await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", False)
|
| 674 |
return
|
| 675 |
|
| 676 |
-
# کسر اعتبار در دیتاست (اگر نامحدود نیست)
|
| 677 |
if not creds.get("is_premium"):
|
| 678 |
user_credits_db[str_chat_id]["chat"] -= 1
|
| 679 |
save_db(user_credits_db)
|
|
@@ -704,7 +693,6 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
|
|
| 704 |
await send_with_keyboard(client, chat_id, "❌ خطایی در ارسال پیام رخ داد.", False)
|
| 705 |
|
| 706 |
|
| 707 |
-
# --- ۲. پردازش ساخت عکس ---
|
| 708 |
async def process_image(client, chat_id, prompt):
|
| 709 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 710 |
creds = get_user_credits(str_chat_id)
|
|
@@ -718,7 +706,6 @@ async def process_image(client, chat_id, prompt):
|
|
| 718 |
gemini_sys_prompt = f"You are an expert AI image generation prompt engineer. Translate the following user input to English, and enhance it with high-quality, highly detailed, 4k resolution, cinematic lighting, and visually striking descriptive keywords. Return ONLY the final English prompt string.\nUser input: {prompt}"
|
| 719 |
|
| 720 |
if GEMINI_KEYS:
|
| 721 |
-
# دریافت ۱۰۰ کلید به صورت چرخشی
|
| 722 |
keys_to_try_gemini = get_next_gemini_keys(100)
|
| 723 |
async with aiohttp.ClientSession() as session:
|
| 724 |
for key in keys_to_try_gemini:
|
|
@@ -732,7 +719,6 @@ async def process_image(client, chat_id, prompt):
|
|
| 732 |
break
|
| 733 |
except Exception: continue
|
| 734 |
|
| 735 |
-
# Fallback to HF Router if Gemini fails
|
| 736 |
if enhanced_prompt == prompt and HF_TOKENS:
|
| 737 |
keys_to_try_hf = HF_TOKENS.copy()
|
| 738 |
random.shuffle(keys_to_try_hf)
|
|
@@ -758,7 +744,7 @@ async def process_image(client, chat_id, prompt):
|
|
| 758 |
if proc_msg:
|
| 759 |
msg_id = getattr(proc_msg, 'message_id', None)
|
| 760 |
if isinstance(proc_msg, dict): msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
|
| 761 |
-
if msg_id: await client.delete_messages(chat_id,
|
| 762 |
except Exception: pass
|
| 763 |
|
| 764 |
short_preview = enhanced_prompt[:150] + "..." if len(enhanced_prompt) > 150 else enhanced_prompt
|
|
@@ -787,7 +773,6 @@ async def process_image(client, chat_id, prompt):
|
|
| 787 |
|
| 788 |
if not generated_image: return await send_with_keyboard(client, chat_id, f"❌ عکس ساخته نشد.\n\n⚠️ خطا:\n{last_error_log[:200]}", True)
|
| 789 |
|
| 790 |
-
# کسر اعتبار (ساخت عکس محدود است حتی برای پرو)
|
| 791 |
user_credits_db[str_chat_id]["image"] -= 1
|
| 792 |
save_db(user_credits_db)
|
| 793 |
|
|
@@ -802,7 +787,7 @@ async def process_image(client, chat_id, prompt):
|
|
| 802 |
if os.path.exists(file_name): os.remove(file_name)
|
| 803 |
except Exception as e: await send_with_keyboard(client, chat_id, f"❌ خطا در ذخیره عکس:\n{str(e)[:150]}", True)
|
| 804 |
|
| 805 |
-
|
| 806 |
async def translate_text_aloha(prompt_text):
|
| 807 |
session_hash = ''.join(random.choices(string.ascii_lowercase + string.digits, k=11))
|
| 808 |
join_url = "https://hamed744-translate-tts-aloha.hf.space/gradio_api/queue/join"
|
|
@@ -814,12 +799,10 @@ async def translate_text_aloha(prompt_text):
|
|
| 814 |
|
| 815 |
try:
|
| 816 |
async with aiohttp.ClientSession() as session:
|
| 817 |
-
# پیوستن به صف ترجمه
|
| 818 |
async with session.post(join_url, json=payload, timeout=20) as resp:
|
| 819 |
if resp.status != 200:
|
| 820 |
return prompt_text
|
| 821 |
|
| 822 |
-
# دریافت دادهها به صورت جریانی (Stream)
|
| 823 |
data_url = f"https://hamed744-translate-tts-aloha.hf.space/gradio_api/queue/data?session_hash={session_hash}"
|
| 824 |
async with session.get(data_url, timeout=60) as resp:
|
| 825 |
async for line_bytes in resp.content:
|
|
@@ -838,7 +821,7 @@ async def translate_text_aloha(prompt_text):
|
|
| 838 |
|
| 839 |
return prompt_text
|
| 840 |
|
| 841 |
-
|
| 842 |
async def process_image_edit(client, chat_id, image_bytes, prompt):
|
| 843 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 844 |
creds = get_user_credits(str_chat_id)
|
|
@@ -850,7 +833,6 @@ async def process_image_edit(client, chat_id, image_bytes, prompt):
|
|
| 850 |
|
| 851 |
proc_msg = await send_with_keyboard(client, chat_id, "🪄 در حال ترجمه دستور شما توسط اسپیس و اعمال جادوی FLUX.2...\n(این فرآیند ممکن است کمی طول بکشد)", False)
|
| 852 |
|
| 853 |
-
# گرفتن ترجمه از اسپیس درخواستی
|
| 854 |
translated_prompt = await translate_text_aloha(prompt)
|
| 855 |
if not translated_prompt or translated_prompt.strip() == "":
|
| 856 |
translated_prompt = prompt
|
|
@@ -883,7 +865,6 @@ async def process_image_edit(client, chat_id, image_bytes, prompt):
|
|
| 883 |
if not generated_image:
|
| 884 |
return await send_with_keyboard(client, chat_id, f"❌ متأسفانه ویرایش عکس انجام نشد.\n\n⚠️ علت:\n{last_error_log[:200]}", True)
|
| 885 |
|
| 886 |
-
# کسر اعتبار (ویرایش عکس محدود است حتی برای پرو)
|
| 887 |
user_credits_db[str_chat_id]["edit_image"] -= 1
|
| 888 |
save_db(user_credits_db)
|
| 889 |
|
|
@@ -901,7 +882,6 @@ async def process_image_edit(client, chat_id, image_bytes, prompt):
|
|
| 901 |
await send_with_keyboard(client, chat_id, f"❌ خطا در ذخیره عکس ویرایش شده:\n{str(e)[:150]}", True)
|
| 902 |
|
| 903 |
|
| 904 |
-
# --- ۳. پردازش ساخت صدا ---
|
| 905 |
async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
|
| 906 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 907 |
creds = get_user_credits(str_chat_id)
|
|
@@ -938,19 +918,15 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
|
|
| 938 |
except Exception: pass
|
| 939 |
|
| 940 |
if audio_bytes:
|
| 941 |
-
# کسر اعتبار در دیتاست (اگر نامحدود نیست)
|
| 942 |
if not creds.get("is_premium"):
|
| 943 |
user_credits_db[str_chat_id]["tts"] -= 1
|
| 944 |
save_db(user_credits_db)
|
| 945 |
|
| 946 |
-
# فایل صوتی را فقط به صورت MP3 ذخیره میکنیم تا از مشکل 502 روبیکا جلوگیری شود
|
| 947 |
file_name_mp3 = f"audio_{uuid.uuid4().hex}.mp3"
|
| 948 |
|
| 949 |
with open(file_name_mp3, "wb") as f: f.write(audio_bytes)
|
| 950 |
|
| 951 |
await asyncio.sleep(1)
|
| 952 |
-
|
| 953 |
-
# ارسال فقط به صورت فایل دانلودشونده MP3 (حالت Voice حذف شد)
|
| 954 |
upload_result_file = await helper_upload_file(client, chat_id, file_name_mp3, "File", "✅ صدای شما با موفقیت آماده شد (فایل MP3):")
|
| 955 |
|
| 956 |
if upload_result_file is not True:
|
|
@@ -961,7 +937,6 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
|
|
| 961 |
except Exception: traceback.print_exc()
|
| 962 |
|
| 963 |
|
| 964 |
-
# --- ۳.۵. پردازش پادکست ---
|
| 965 |
async def process_podcast(client, chat_id, prompt):
|
| 966 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 967 |
creds = get_user_credits(str_chat_id)
|
|
@@ -1031,12 +1006,10 @@ async def process_podcast(client, chat_id, prompt):
|
|
| 1031 |
combined_audio += audio_segment
|
| 1032 |
except Exception as e: return await send_with_keyboard(client, chat_id, f"❌ خطا در پردازش صدا (آیا pydub و ffmpeg نصب است؟):\n{str(e)}", True)
|
| 1033 |
|
| 1034 |
-
# کسر اعتبار در دیتاست (اگر نامحدود نیست)
|
| 1035 |
if not creds.get("is_premium"):
|
| 1036 |
user_credits_db[str_chat_id]["podcast"] -= 1
|
| 1037 |
save_db(user_credits_db)
|
| 1038 |
|
| 1039 |
-
# فقط با فرمت MP3 خروجی میدهیم (بدون تبدیل OGG)
|
| 1040 |
file_name_mp3 = f"final_podcast_{uuid.uuid4().hex}.mp3"
|
| 1041 |
combined_audio.export(file_name_mp3, format="mp3")
|
| 1042 |
|
|
@@ -1048,8 +1021,6 @@ async def process_podcast(client, chat_id, prompt):
|
|
| 1048 |
except: pass
|
| 1049 |
|
| 1050 |
caption_file = f"🎧 فایل پادکست شما با فرمت MP3:\n\n💡 موضوع شما: {prompt}"
|
| 1051 |
-
|
| 1052 |
-
# ارسال فقط به صورت فایل MP3
|
| 1053 |
upload_result_file = await helper_upload_file(client, chat_id, file_name_mp3, "File", caption_file)
|
| 1054 |
|
| 1055 |
if upload_result_file is not True:
|
|
@@ -1058,7 +1029,6 @@ async def process_podcast(client, chat_id, prompt):
|
|
| 1058 |
if os.path.exists(file_name_mp3): os.remove(file_name_mp3)
|
| 1059 |
|
| 1060 |
|
| 1061 |
-
# --- ۴. پردازش تبدیل فایل صوتی/تصویری به متن ---
|
| 1062 |
async def process_stt(client, chat_id, audio_bytes, file_name):
|
| 1063 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1064 |
creds = get_user_credits(str_chat_id)
|
|
@@ -1072,7 +1042,6 @@ async def process_stt(client, chat_id, audio_bytes, file_name):
|
|
| 1072 |
mime_type, _ = mimetypes.guess_type(file_name)
|
| 1073 |
if not mime_type: mime_type = "audio/ogg"
|
| 1074 |
|
| 1075 |
-
# دریافت ۱۰۰ کلید به صورت چرخشی
|
| 1076 |
keys_to_try = get_next_gemini_keys(100)
|
| 1077 |
transcribed_text = None
|
| 1078 |
prompt = "لطفاً این فایل صوتی/تصویری را با دقت کامل گوش بده و صحبتهای داخل آن را کلمه به کلمه به متن تبدیل کن. هیچ توضیح اضافهای نده."
|
|
@@ -1080,7 +1049,7 @@ async def process_stt(client, chat_id, audio_bytes, file_name):
|
|
| 1080 |
async with aiohttp.ClientSession() as session:
|
| 1081 |
for key in keys_to_try:
|
| 1082 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 1083 |
-
payload = {"contents":
|
| 1084 |
try:
|
| 1085 |
async with session.post(url, json=payload, timeout=60) as response:
|
| 1086 |
if response.status == 200:
|
|
@@ -1097,7 +1066,6 @@ async def process_stt(client, chat_id, audio_bytes, file_name):
|
|
| 1097 |
except Exception: pass
|
| 1098 |
|
| 1099 |
if transcribed_text:
|
| 1100 |
-
# کسر اعتبار در دیتاست (اگر نامحدود نیست)
|
| 1101 |
if not creds.get("is_premium"):
|
| 1102 |
user_credits_db[str_chat_id]["stt"] -= 1
|
| 1103 |
save_db(user_credits_db)
|
|
@@ -1106,7 +1074,6 @@ async def process_stt(client, chat_id, audio_bytes, file_name):
|
|
| 1106 |
await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", True)
|
| 1107 |
|
| 1108 |
|
| 1109 |
-
# --- ۵. پردازش تحلیل فایل مستقل ---
|
| 1110 |
async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
| 1111 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1112 |
creds = get_user_credits(str_chat_id)
|
|
@@ -1120,14 +1087,13 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
|
| 1120 |
mime_type, _ = mimetypes.guess_type(file_name)
|
| 1121 |
if not mime_type: mime_type = "image/jpeg"
|
| 1122 |
|
| 1123 |
-
# دریافت ۱۰۰ کلید به صورت چرخشی
|
| 1124 |
keys_to_try = get_next_gemini_keys(100)
|
| 1125 |
final_answer = None
|
| 1126 |
|
| 1127 |
async with aiohttp.ClientSession() as session:
|
| 1128 |
for key in keys_to_try:
|
| 1129 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 1130 |
-
payload = {"contents":
|
| 1131 |
try:
|
| 1132 |
async with session.post(url, json=payload, timeout=45) as response:
|
| 1133 |
if response.status == 200:
|
|
@@ -1144,7 +1110,6 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
|
| 1144 |
except Exception: pass
|
| 1145 |
|
| 1146 |
if final_answer:
|
| 1147 |
-
# کسر اعتبار در دیتاست (اگر نامحدود نیست)
|
| 1148 |
if not creds.get("is_premium"):
|
| 1149 |
user_credits_db[str_chat_id]["file"] -= 1
|
| 1150 |
save_db(user_credits_db)
|
|
@@ -1153,12 +1118,10 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
|
| 1153 |
await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", True)
|
| 1154 |
|
| 1155 |
|
| 1156 |
-
# --- ۵.۵. پردازش ساخت مقاله و تبدیل به فایل (PDF & DOCX) ---
|
| 1157 |
async def process_create_file(client, chat_id, topic):
|
| 1158 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1159 |
creds = get_user_credits(str_chat_id)
|
| 1160 |
|
| 1161 |
-
# بررسی محدودیت بخش ساخت فایل (کسر از اعتبار پیام چت)
|
| 1162 |
if creds["chat"] <= 0:
|
| 1163 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار چت شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
| 1164 |
|
|
@@ -1182,7 +1145,6 @@ async def process_create_file(client, chat_id, topic):
|
|
| 1182 |
break
|
| 1183 |
except Exception: continue
|
| 1184 |
|
| 1185 |
-
# Fallback to Hugging Face
|
| 1186 |
if not article_text and HF_TOKENS:
|
| 1187 |
keys_to_try_hf = HF_TOKENS.copy()
|
| 1188 |
random.shuffle(keys_to_try_hf)
|
|
@@ -1220,7 +1182,6 @@ async def process_create_file(client, chat_id, topic):
|
|
| 1220 |
converter_url = "https://opera8-texttopdf.hf.space/"
|
| 1221 |
|
| 1222 |
async with aiohttp.ClientSession() as session:
|
| 1223 |
-
# دریافت خروجی PDF
|
| 1224 |
try:
|
| 1225 |
form_data_pdf = aiohttp.FormData()
|
| 1226 |
form_data_pdf.add_field('content', article_text)
|
|
@@ -1230,7 +1191,6 @@ async def process_create_file(client, chat_id, topic):
|
|
| 1230 |
pdf_bytes = await resp.read()
|
| 1231 |
except Exception as e: print("PDF creation error:", e)
|
| 1232 |
|
| 1233 |
-
# دریافت خروجی DOCX
|
| 1234 |
try:
|
| 1235 |
form_data_docx = aiohttp.FormData()
|
| 1236 |
form_data_docx.add_field('content', article_text)
|
|
@@ -1250,7 +1210,6 @@ async def process_create_file(client, chat_id, topic):
|
|
| 1250 |
if not pdf_bytes and not docx_bytes:
|
| 1251 |
return await send_with_keyboard(client, chat_id, "❌ متاسفانه در تبدیل متن به فایل خطایی رخ داد.", True)
|
| 1252 |
|
| 1253 |
-
# کسر اعتبار ساخت فایل از سهمیه "چت" کاربر در صورت غیر پرمیوم بودن
|
| 1254 |
if not creds.get("is_premium"):
|
| 1255 |
user_credits_db[str_chat_id]["chat"] -= 1
|
| 1256 |
save_db(user_credits_db)
|
|
@@ -1282,7 +1241,6 @@ async def process_create_file(client, chat_id, topic):
|
|
| 1282 |
await send_with_keyboard(client, chat_id, "❌ فایلها ساخته شدند اما روبیکا در ارسال آنها دچار مشکل شد.", True)
|
| 1283 |
|
| 1284 |
|
| 1285 |
-
# --- تنظیمات ربات روبیکا ---
|
| 1286 |
if not bot_token:
|
| 1287 |
print("خطا: توکن ربات روبیکا وارد نشده است!")
|
| 1288 |
else:
|
|
@@ -1292,13 +1250,10 @@ else:
|
|
| 1292 |
async def main_handler(client, update):
|
| 1293 |
global BOT_GUID
|
| 1294 |
|
| 1295 |
-
# 🔥 سیستم ضد رگبار و تخلیه صف (Backlog) سرور 🔥
|
| 1296 |
-
# در صورت هجوم پیامهای تلنبار شده سرور روبیکا، پیامها رد میشود
|
| 1297 |
if is_backlog_burst():
|
| 1298 |
return
|
| 1299 |
|
| 1300 |
try:
|
| 1301 |
-
# 🛡 دریافت آیدی یکتای ربات برای جلوگیری از لوپ 🛡
|
| 1302 |
if not BOT_GUID:
|
| 1303 |
try:
|
| 1304 |
me_info = await client.get_me()
|
|
@@ -1309,25 +1264,20 @@ else:
|
|
| 1309 |
|
| 1310 |
msg_obj = getattr(update, "message", None) or getattr(update, "new_message", None)
|
| 1311 |
|
| 1312 |
-
# --- استخراج دقیق شناسه فرستنده (برای جلوگیری از حرف زدن ربات با خودش) ---
|
| 1313 |
author_id = getattr(update, 'author_guid', None)
|
| 1314 |
if not author_id and msg_obj:
|
| 1315 |
author_id = msg_obj.get('author_object_guid') if isinstance(msg_obj, dict) else getattr(msg_obj, 'author_object_guid', None)
|
| 1316 |
|
| 1317 |
-
# ⛔️ حیاتیترین بخش: اگر نویسنده پیام خودِ ربات است، هرگز پردازش نشود!
|
| 1318 |
if BOT_GUID and author_id == BOT_GUID:
|
| 1319 |
return
|
| 1320 |
|
| 1321 |
-
# --- استخراج دقیق شناسه چت ---
|
| 1322 |
chat_id = getattr(update, 'object_guid', None) or getattr(update, 'author_guid', None) or getattr(update, "chat_id", None)
|
| 1323 |
if not chat_id: return
|
| 1324 |
|
| 1325 |
-
# استخراج آیدی پیام
|
| 1326 |
msg_id = getattr(update, "message_id", None)
|
| 1327 |
if not msg_id and msg_obj:
|
| 1328 |
msg_id = msg_obj.get("message_id") if isinstance(msg_obj, dict) else getattr(msg_obj, "message_id", None)
|
| 1329 |
|
| 1330 |
-
# 🛡 کلید ترکیبی ضد تداخل: آیدی چت + آیدی پیام 🛡
|
| 1331 |
unique_msg_key = f"{chat_id}_{msg_id}" if msg_id else None
|
| 1332 |
if unique_msg_key:
|
| 1333 |
if unique_msg_key in processed_message_ids: return
|
|
@@ -1336,21 +1286,22 @@ else:
|
|
| 1336 |
|
| 1337 |
current_time = time.time()
|
| 1338 |
|
| 1339 |
-
# 🛡 سیستم محدودکننده سرعت کاربر (Rate Limit) 🛡
|
| 1340 |
last_req_time = user_last_request_time.get(chat_id, 0)
|
| 1341 |
if current_time - last_req_time < 1.0:
|
| 1342 |
return
|
| 1343 |
user_last_request_time[chat_id] = current_time
|
| 1344 |
|
| 1345 |
-
# تشخیص محتوای متنی
|
| 1346 |
user_text = getattr(update, "text", "") or getattr(msg_obj, "text", "")
|
| 1347 |
user_text_str = str(user_text).strip() if user_text else ""
|
| 1348 |
user_text_lower = user_text_str.lower()
|
| 1349 |
|
| 1350 |
-
|
| 1351 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1352 |
|
| 1353 |
-
# 🛠 --- سیستم پنل مدیریت (بدون نیاز به لاگین) --- 🛠
|
| 1354 |
if user_text_lower.startswith(f"{ADMIN_CODE} pro=") or user_text_lower.startswith(f"{ADMIN_CODE}pro="):
|
| 1355 |
parts = user_text_str.split("=", 1)
|
| 1356 |
if len(parts) >= 2:
|
|
@@ -1368,7 +1319,10 @@ else:
|
|
| 1368 |
"tts": 5,
|
| 1369 |
"file": 1,
|
| 1370 |
"stt": 5,
|
| 1371 |
-
"has_joined": True
|
|
|
|
|
|
|
|
|
|
| 1372 |
}
|
| 1373 |
|
| 1374 |
user_credits_db[target_id]["is_premium"] = True
|
|
@@ -1437,10 +1391,12 @@ else:
|
|
| 1437 |
stt_rem = "نامحدود ∞" if is_prem else t_creds.get('stt', 0)
|
| 1438 |
image_rem = t_creds.get('image', 0)
|
| 1439 |
edit_image_rem = t_creds.get('edit_image', 0)
|
|
|
|
| 1440 |
|
| 1441 |
info_msg = f"""🔍 **اطلاعات کاربر `{target_id}`:**
|
| 1442 |
|
| 1443 |
🔹 **وضعیت:** {status_text}
|
|
|
|
| 1444 |
|
| 1445 |
📊 **سهمیه:**
|
| 1446 |
- چت: {chat_rem}
|
|
@@ -1455,7 +1411,6 @@ else:
|
|
| 1455 |
await send_with_keyboard(client, chat_id, f"❌ کاربری با شناسه `{target_id}` در دیتابیس یافت نشد.", False)
|
| 1456 |
return
|
| 1457 |
|
| 1458 |
-
# تشخیص فایل
|
| 1459 |
is_file = False
|
| 1460 |
file_name = f"unknown_file_{uuid.uuid4().hex[:6]}.jpg"
|
| 1461 |
|
|
@@ -1476,13 +1431,8 @@ else:
|
|
| 1476 |
file_name = file_attr.get('file_name', file_name) if isinstance(file_attr, dict) else file_name
|
| 1477 |
break
|
| 1478 |
|
| 1479 |
-
# ⛔️ سیستم قفل اجباری کانال (Force Join) - حالت اعتمادی (یک بار کلیک) ⛔️
|
| 1480 |
-
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1481 |
-
creds = get_user_credits(str_chat_id)
|
| 1482 |
-
|
| 1483 |
if user_text_str == "✅ عضو شدم":
|
| 1484 |
if not creds.get("has_joined", False):
|
| 1485 |
-
# با همان کلیک اول تایید میشود
|
| 1486 |
user_credits_db[str_chat_id]["has_joined"] = True
|
| 1487 |
save_db(user_credits_db)
|
| 1488 |
await send_with_keyboard(client, chat_id, "🎉 **عضویت شما با موفقیت تایید شد! خیلی خوش آمدید.**\n\nحالا میتوانید از تمامی امکانات ربات استفاده کنید.\nلطفاً یکی از گزینههای منو را انتخاب کنید:", True)
|
|
@@ -1500,15 +1450,19 @@ else:
|
|
| 1500 |
await client.send_message(chat_id, join_msg)
|
| 1501 |
return
|
| 1502 |
|
| 1503 |
-
if
|
| 1504 |
-
user_states[
|
| 1505 |
-
user_states[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1506 |
await send_with_keyboard(client, chat_id, "سلام! به ربات هوش مصنوعی آلفا خوش آمدید 🤖\n\nلطفاً برای شروع، از کیبورد پایین یکی از بخشها را انتخاب کنید:", True)
|
| 1507 |
return
|
| 1508 |
|
| 1509 |
-
# --- حساب کاربری ---
|
| 1510 |
if user_text_str in["/account", "حساب کاربری 👤"]:
|
| 1511 |
-
creds = get_user_credits(chat_id)
|
| 1512 |
is_prem = creds.get("is_premium", False)
|
| 1513 |
|
| 1514 |
if is_prem:
|
|
@@ -1538,11 +1492,15 @@ else:
|
|
| 1538 |
stt_rem = "نامحدود ∞" if is_prem else creds['stt']
|
| 1539 |
image_rem = creds['image']
|
| 1540 |
edit_image_rem = creds['edit_image']
|
|
|
|
|
|
|
| 1541 |
|
| 1542 |
account_profile = f"""👤 **اطلاعات حساب کاربری شما**
|
| 1543 |
|
| 1544 |
🔹 **شناسه یکتا:** `{chat_id}`
|
|
|
|
| 1545 |
🔹 **وضعیت اشتراک:** {status_text}{expire_info}
|
|
|
|
| 1546 |
|
| 1547 |
📊 **سهمیه باقیمانده شما:**
|
| 1548 |
- 💬 چت هوشمند: {chat_rem}
|
|
@@ -1557,7 +1515,58 @@ else:
|
|
| 1557 |
await send_with_keyboard(client, chat_id, account_profile, True)
|
| 1558 |
return
|
| 1559 |
|
| 1560 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1561 |
if user_text_str in["/buy", "خرید اشتراک 💎"]:
|
| 1562 |
buy_text = f"""💎 **خرید اشتراک ویژه آلفا پرو (یک ماهه)**
|
| 1563 |
|
|
@@ -1589,7 +1598,6 @@ else:
|
|
| 1589 |
await send_with_keyboard(client, chat_id, buy_text, True)
|
| 1590 |
return
|
| 1591 |
|
| 1592 |
-
# --- دکمه انتقال اکانت ---
|
| 1593 |
if user_text_str in["/transfer", "انتقال اکانت از برنامه به ربات"]:
|
| 1594 |
transfer_text = f"""🔄 **انتقال اکانت از برنامه به ربات**
|
| 1595 |
|
|
@@ -1605,55 +1613,128 @@ else:
|
|
| 1605 |
return
|
| 1606 |
|
| 1607 |
if user_text_str in["/chat", "💬 چت", "چت با هوش مصنوعی 🤖"]:
|
| 1608 |
-
user_states[
|
| 1609 |
-
user_states[
|
| 1610 |
await send_with_keyboard(client, chat_id, "💬 شما وارد بخش **چت با هوش مصنوعی** شدید.\n\nهر سوالی دارید بفرستید تا جواب بدم:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1611 |
return
|
| 1612 |
|
| 1613 |
if user_text_str in["/image", "🎨 عکس", "ساخت تصاویر🎨"]:
|
| 1614 |
-
user_states[
|
| 1615 |
await send_with_keyboard(client, chat_id, "🎨 شما وارد بخش **ساخت عکس پیشرفته** شدید.\n\nمتن خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1616 |
return
|
| 1617 |
|
| 1618 |
if user_text_str in["/edit_image", "ویرایش تصاویر 🪄"]:
|
| 1619 |
-
user_states[
|
| 1620 |
-
user_states[
|
| 1621 |
await send_with_keyboard(client, chat_id, "🪄 به بخش **ویرایش عکس (Flux.2)** خوش آمدید.\n\nلطفاً ابتدا عکسی که میخواهید ویرایش کنید را بفرستید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1622 |
return
|
| 1623 |
|
| 1624 |
if user_text_str in["/tts", "🎙️ صدا", "تبدیل متن به صدا🗣️"]:
|
| 1625 |
-
user_states[
|
| 1626 |
await send_with_keyboard(client, chat_id, "🎙️ شما وارد بخش **تبدیل متن به صدا** شدید.\n\nلطفاً متنی که میخواهید به صدا تبدیل شود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1627 |
return
|
| 1628 |
|
| 1629 |
if user_text_str in["/podcast", "📻 پادکست", "ساخت پادکست 🎙️"]:
|
| 1630 |
-
user_states[
|
| 1631 |
await send_with_keyboard(client, chat_id, "📻 شما وارد بخش **ساخت پادکست** شدید.\n\nلطفاً موضوع پادکست خود را بفرستید.\nمثال: درباره تاریخچه پیدایش قهوه با ۳ گوینده یک پادکست جذاب بساز . همچنین این قسمت متصل به مدل زبانی است و درخواست هارو قبل از ساخت درک میکنه. میتوانید مقاله کامل یک سایت بفرستید با تبلیغات یا هرچی، هوش مصنوعی متن مقاله رو استخراج و پادکست براتون میسازه . در توضیحات امکان مشخص کردن تعداد گوینده به همراه اسم شون نیز از سمت شما امکان پذیر است.\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1632 |
return
|
| 1633 |
|
| 1634 |
if user_text_str in["/file", "تحلیل فایل 📁"]:
|
| 1635 |
-
user_states[
|
| 1636 |
-
user_states[
|
| 1637 |
await send_with_keyboard(client, chat_id, "📁 شما وارد بخش **تحلیل فایل اختصاصی** شدید.\n\nلطفاً فایل خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1638 |
return
|
| 1639 |
|
| 1640 |
if user_text_str in["/stt", "فایل صوتی به متن 📝"]:
|
| 1641 |
-
user_states[
|
| 1642 |
await send_with_keyboard(client, chat_id, "📝 شما وارد بخش **تبدیل صدا به متن** شدید.\n\nلطفاً فایل خود (ویس، آهنگ، ویدیو و...) را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1643 |
return
|
| 1644 |
|
| 1645 |
if user_text_str in["/create_file", "ساخت فایل 📄"]:
|
| 1646 |
-
user_states[
|
| 1647 |
await send_with_keyboard(client, chat_id, "📄 شما وارد بخش **ساخت فایل** شدید.\n\nلطفاً موضوع مقالهای که میخواهید را کامل بفرستید.\nمثال: نحوه مدیریت زمان\n\nهوش مصنوعی یک مقاله کامل و طولانی نوشته و در نهایت فایل PDF و Word آن را به شما تحویل میدهد.\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1648 |
return
|
| 1649 |
|
| 1650 |
-
current_mode = user_states[
|
| 1651 |
|
| 1652 |
if current_mode is None:
|
| 1653 |
if is_file: pass
|
| 1654 |
elif user_text_str: await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا از کیبورد پایین، بخش مورد نظرتان را انتخاب کنید:", True)
|
| 1655 |
return
|
| 1656 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1657 |
elif current_mode == "chat":
|
| 1658 |
if is_file:
|
| 1659 |
await send_with_keyboard(client, chat_id, "📥 در حال دانلود فایل...", False)
|
|
@@ -1673,17 +1754,17 @@ else:
|
|
| 1673 |
await send_with_keyboard(client, chat_id, "📥 در حال دانلود عکس...", False)
|
| 1674 |
try:
|
| 1675 |
file_bytes = await helper_download_file(client, msg_obj)
|
| 1676 |
-
user_states[
|
| 1677 |
-
user_states[
|
| 1678 |
await send_with_keyboard(client, chat_id, "✅ عکس با موفقیت دریافت شد.\n\nحالا دستور خود را به صورت متنی تایپ کنید.\nمثال: یک کلاه قرمز روی سر این گربه بگذار.", False)
|
| 1679 |
except Exception as dl_err: await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت عکس!\n{str(dl_err)}", False)
|
| 1680 |
return
|
| 1681 |
|
| 1682 |
elif current_mode == "image_edit_waiting_for_prompt":
|
| 1683 |
if user_text_str:
|
| 1684 |
-
saved_bytes = user_states[
|
| 1685 |
-
user_states[
|
| 1686 |
-
user_states[
|
| 1687 |
asyncio.create_task(process_image_edit(client, chat_id, saved_bytes, user_text_str))
|
| 1688 |
else: await send_with_keyboard(client, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)
|
| 1689 |
return
|
|
@@ -1691,8 +1772,8 @@ else:
|
|
| 1691 |
elif current_mode == "tts_waiting_for_text":
|
| 1692 |
if user_text_str:
|
| 1693 |
if len(user_text_str) > 2500: return await send_with_keyboard(client, chat_id, "⚠️ لطفاً متنی کوتاهتر از 2500 کاراکتر بفرستید.", False)
|
| 1694 |
-
user_states[
|
| 1695 |
-
user_states[
|
| 1696 |
|
| 1697 |
speakers_menu = """✅ متن شما ذخیره شد.
|
| 1698 |
لطفاً **شماره** گوینده مورد نظر خود را بفرستید:
|
|
@@ -1714,8 +1795,8 @@ else:
|
|
| 1714 |
|
| 1715 |
if normalized_text.isdigit() and normalized_text in SPEAKERS:
|
| 1716 |
spk_name, spk_id = SPEAKERS[normalized_text]
|
| 1717 |
-
txt = user_states[
|
| 1718 |
-
user_states[
|
| 1719 |
asyncio.create_task(process_tts(client, chat_id, txt, spk_id, spk_name))
|
| 1720 |
else:
|
| 1721 |
await send_with_keyboard(client, chat_id, "❌ شماره نامعتبر است! لطفاً فقط یک عدد بین 1 تا 30 بفرستید.", False)
|
|
@@ -1740,18 +1821,18 @@ else:
|
|
| 1740 |
await send_with_keyboard(client, chat_id, "📥 در حال دریافت فایل...", False)
|
| 1741 |
try:
|
| 1742 |
file_bytes = await helper_download_file(client, msg_obj)
|
| 1743 |
-
user_states[
|
| 1744 |
-
user_states[
|
| 1745 |
-
user_states[
|
| 1746 |
await send_with_keyboard(client, chat_id, "✅ فایل با موفقیت دریافت شد.\n\nحالا لطفاً متنی بگویید **چگونه تحلیل شود؟**", False)
|
| 1747 |
except Exception as dl_err: await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت فایل!\n{str(dl_err)}", False)
|
| 1748 |
return
|
| 1749 |
|
| 1750 |
elif current_mode == "file_waiting_for_prompt":
|
| 1751 |
if user_text_str:
|
| 1752 |
-
saved_bytes = user_states[
|
| 1753 |
-
saved_name = user_states[
|
| 1754 |
-
user_states[
|
| 1755 |
asyncio.create_task(process_file_analysis(client, chat_id, saved_bytes, saved_name, user_text_str))
|
| 1756 |
else: await send_with_keyboard(client, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)
|
| 1757 |
return
|
|
@@ -1768,5 +1849,5 @@ else:
|
|
| 1768 |
if __name__ == "__main__":
|
| 1769 |
threading.Thread(target=run_flask, daemon=True).start()
|
| 1770 |
if bot_token:
|
| 1771 |
-
print("ربات آلفا پرو با سیستم اشتراک نامحدود + سپر امنیتی
|
| 1772 |
bot.run()
|
|
|
|
| 79 |
print("در حال تلاش برای خواندن دیتابیس کاربران از دیتاست هاگینگ فیس...")
|
| 80 |
if HF_TOKEN_DB:
|
| 81 |
try:
|
|
|
|
| 82 |
file_path = hf_hub_download(
|
| 83 |
repo_id=DATASET_REPO,
|
| 84 |
filename=DB_FILE,
|
|
|
|
| 89 |
print("✅ دیتابیس با موفقیت از دیتاست هاگینگ فیس لود شد.")
|
| 90 |
return json.load(f)
|
| 91 |
except Exception as e:
|
| 92 |
+
print("⚠️ فایل دیتابیس در هاگینگ فیس یافت نشد یا خطایی رخ داد (ساخت دیتابیس جدید).")
|
| 93 |
|
|
|
|
| 94 |
if os.path.exists(DB_FILE):
|
| 95 |
try:
|
| 96 |
with open(DB_FILE, "r", encoding="utf-8") as f:
|
|
|
|
| 100 |
return {}
|
| 101 |
|
| 102 |
def _upload_db_background():
|
|
|
|
| 103 |
if HF_TOKEN_DB:
|
| 104 |
api = HfApi(token=HF_TOKEN_DB)
|
| 105 |
try:
|
|
|
|
| 115 |
def save_db(db_data):
|
| 116 |
with db_lock:
|
| 117 |
try:
|
|
|
|
| 118 |
with open(DB_FILE, "w", encoding="utf-8") as f:
|
| 119 |
json.dump(db_data, f, ensure_ascii=False, indent=4)
|
|
|
|
|
|
|
| 120 |
threading.Thread(target=_upload_db_background, daemon=True).start()
|
| 121 |
except Exception as e:
|
| 122 |
print("خطا در ذخیره دیتابیس:", e)
|
| 123 |
|
| 124 |
user_credits_db = load_db()
|
| 125 |
|
| 126 |
+
# --- سیستم تولید و یافتن کد هدیه 8 رقمی یکتا ---
|
| 127 |
+
def get_or_create_referral_code(chat_id):
|
| 128 |
+
user_data = user_credits_db[chat_id]
|
| 129 |
+
if not user_data.get("referral_code"):
|
| 130 |
+
while True:
|
| 131 |
+
# فقط از اعداد برای تولید کد 8 رقمی استفاده میکنیم
|
| 132 |
+
new_code = ''.join(random.choices(string.digits, k=8))
|
| 133 |
+
exists = any(u.get("referral_code") == new_code for u in user_credits_db.values())
|
| 134 |
+
if not exists:
|
| 135 |
+
user_data["referral_code"] = new_code
|
| 136 |
+
save_db(user_credits_db)
|
| 137 |
+
break
|
| 138 |
+
return user_data["referral_code"]
|
| 139 |
+
|
| 140 |
+
def find_user_by_referral_code(code):
|
| 141 |
+
code = code.strip()
|
| 142 |
+
for uid, data in user_credits_db.items():
|
| 143 |
+
if data.get("referral_code", "") == code:
|
| 144 |
+
return uid
|
| 145 |
+
return None
|
| 146 |
+
|
| 147 |
def get_user_credits(chat_id):
|
|
|
|
| 148 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 149 |
today_str = datetime.date.today().isoformat()
|
| 150 |
|
| 151 |
if str_chat_id not in user_credits_db:
|
|
|
|
| 152 |
user_credits_db[str_chat_id] = {
|
| 153 |
"is_premium": False,
|
| 154 |
"expire_date": None,
|
|
|
|
| 160 |
"tts": 5,
|
| 161 |
"file": 1,
|
| 162 |
"stt": 5,
|
| 163 |
+
"has_joined": False,
|
| 164 |
+
"invited_count": 0,
|
| 165 |
+
"used_referral": False,
|
| 166 |
+
"referral_code": ""
|
| 167 |
}
|
| 168 |
save_db(user_credits_db)
|
| 169 |
|
| 170 |
user_data = user_credits_db[str_chat_id]
|
| 171 |
is_premium = user_data.get("is_premium", False)
|
| 172 |
|
|
|
|
| 173 |
if is_premium and user_data.get("expire_date"):
|
| 174 |
try:
|
| 175 |
expire_date = datetime.datetime.fromisoformat(user_data["expire_date"])
|
| 176 |
if datetime.datetime.now() > expire_date:
|
|
|
|
| 177 |
user_data["is_premium"] = False
|
| 178 |
user_data["expire_date"] = None
|
| 179 |
is_premium = False
|
| 180 |
except Exception:
|
| 181 |
pass
|
| 182 |
|
|
|
|
| 183 |
if not is_premium:
|
| 184 |
if user_data.get("last_reset") != today_str:
|
| 185 |
user_data["last_reset"] = today_str
|
|
|
|
| 186 |
user_data["chat"] = 10
|
| 187 |
user_data["image"] = 5
|
| 188 |
user_data["edit_image"] = 1
|
|
|
|
| 209 |
|
| 210 |
@app.route('/')
|
| 211 |
def home():
|
| 212 |
+
return "ربات یکپارچه آلفا (نسخه پرو + مدیریت اشتراک نامحدود + دعوت دوستان + سیستم ضد باگ) روشن است! 🚀"
|
| 213 |
|
| 214 |
def run_flask():
|
| 215 |
app.run(host="0.0.0.0", port=7860)
|
|
|
|
| 252 |
{"id": "buy_btn", "type": "Simple", "button_text": "خرید اشتراک 💎"}
|
| 253 |
]
|
| 254 |
},
|
| 255 |
+
{
|
| 256 |
+
"buttons":[
|
| 257 |
+
{"id": "invite_btn", "type": "Simple", "button_text": "دعوت دوستان 🎁"},
|
| 258 |
+
{"id": "referral_btn", "type": "Simple", "button_text": "ثبت کد هدیه 🎫"}
|
| 259 |
+
]
|
| 260 |
+
},
|
| 261 |
{
|
| 262 |
"buttons":[
|
| 263 |
{"id": "transfer_btn", "type": "Simple", "button_text": "انتقال اکانت از برنامه به ربات"}
|
|
|
|
| 272 |
"resize_keyboard": True
|
| 273 |
}
|
| 274 |
|
|
|
|
| 275 |
CHANNEL_USERNAME = "aialpha"
|
| 276 |
CHANNEL_GUID = None
|
| 277 |
|
|
|
|
| 288 |
|
| 289 |
async def check_channel_membership(client, user_id):
|
| 290 |
global CHANNEL_GUID
|
|
|
|
| 291 |
if str(user_id) == str(BOT_GUID): return True
|
| 292 |
|
| 293 |
try:
|
|
|
|
| 309 |
CHANNEL_GUID = getattr(res.exist.chat, 'object_guid', None)
|
| 310 |
|
| 311 |
if not CHANNEL_GUID:
|
| 312 |
+
return True
|
| 313 |
|
| 314 |
payload = {
|
| 315 |
"channel_guid": CHANNEL_GUID,
|
|
|
|
| 328 |
|
| 329 |
return False
|
| 330 |
except Exception:
|
| 331 |
+
return False
|
| 332 |
|
| 333 |
|
|
|
|
| 334 |
async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
|
| 335 |
try:
|
| 336 |
if not use_keyboard:
|
|
|
|
| 350 |
return None
|
| 351 |
|
| 352 |
|
|
|
|
| 353 |
async def helper_download_file(client, msg_obj):
|
| 354 |
errors =[]
|
| 355 |
file_id = None
|
|
|
|
| 362 |
elif isinstance(val, dict) and 'file_id' in val: file_id = val['file_id']
|
| 363 |
if file_id: break
|
| 364 |
|
|
|
|
| 365 |
temp_name = f"temp_dl_{uuid.uuid4().hex}.tmp"
|
| 366 |
|
| 367 |
if hasattr(client, "download_file"):
|
|
|
|
| 402 |
raise Exception("دانلود ناموفق. لاگ:\n" + "\n".join(errors))
|
| 403 |
|
| 404 |
|
|
|
|
| 405 |
GEMINI_KEYS_STR1 = os.environ.get("GEMINI_API_KEYS1", "")
|
| 406 |
GEMINI_KEYS_STR2 = os.environ.get("GEMINI_API_KEYS2", "")
|
| 407 |
|
|
|
|
| 411 |
if GEMINI_KEYS_STR2:
|
| 412 |
_raw_keys.extend(GEMINI_KEYS_STR2.split(","))
|
| 413 |
|
|
|
|
| 414 |
GEMINI_KEYS = list(set([k.strip() for k in _raw_keys if k.strip()]))
|
| 415 |
print(f"✅ تعداد {len(GEMINI_KEYS)} کلید جیمینای با موفقیت شناسایی شد.")
|
| 416 |
|
|
|
|
| 417 |
current_gemini_key_index = 0
|
| 418 |
gemini_key_lock = threading.Lock()
|
| 419 |
|
| 420 |
def get_next_gemini_keys(count=100):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 421 |
global current_gemini_key_index
|
| 422 |
with gemini_key_lock:
|
| 423 |
total_keys = len(GEMINI_KEYS)
|
|
|
|
| 439 |
bot_token = os.environ.get("RUBIKA_AUTH", "").strip()
|
| 440 |
|
| 441 |
|
|
|
|
| 442 |
async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""):
|
| 443 |
abs_path = os.path.abspath(file_name)
|
| 444 |
error_logs =[]
|
| 445 |
|
| 446 |
api_file_type = "Image" if file_type in["photo", "Image", "image"] else "Voice" if file_type in["voice", "Voice", "audio"] else "File"
|
| 447 |
|
|
|
|
| 448 |
if api_file_type == "Voice" and not abs_path.lower().endswith('.ogg'):
|
| 449 |
api_file_type = "Music"
|
| 450 |
|
|
|
|
| 451 |
for attempt in range(3):
|
| 452 |
try:
|
| 453 |
url_request = f"https://botapi.rubika.ir/v3/{bot_token}/requestSendFile"
|
| 454 |
url_send = f"https://botapi.rubika.ir/v3/{bot_token}/sendFile"
|
| 455 |
|
| 456 |
async with aiohttp.ClientSession() as session:
|
|
|
|
| 457 |
async with session.post(url_request, json={"type": api_file_type}, timeout=20) as resp:
|
| 458 |
if resp.status != 200:
|
| 459 |
error_logs.append(f"Request HTTP {resp.status}")
|
|
|
|
| 465 |
if req_data.get("status") == "OK":
|
| 466 |
upload_url = req_data.get("data", {}).get("upload_url")
|
| 467 |
|
|
|
|
| 468 |
if upload_url:
|
| 469 |
with open(abs_path, "rb") as f:
|
| 470 |
form = aiohttp.FormData()
|
| 471 |
form.add_field('file', f, filename=os.path.basename(abs_path))
|
| 472 |
|
|
|
|
| 473 |
async with session.post(upload_url, data=form, timeout=60) as up_resp:
|
| 474 |
if up_resp.status != 200:
|
| 475 |
error_logs.append(f"Upload HTTP {up_resp.status}")
|
|
|
|
| 476 |
if up_resp.status == 502 and api_file_type == "Voice":
|
| 477 |
api_file_type = "Music"
|
| 478 |
await asyncio.sleep(1.5)
|
|
|
|
| 485 |
await asyncio.sleep(1.5)
|
| 486 |
continue
|
| 487 |
|
|
|
|
| 488 |
final_file_id = None
|
| 489 |
if up_data.get("status") == "OK" or up_data.get("status_det") == "OK":
|
| 490 |
if "data" in up_data and isinstance(up_data["data"], dict):
|
|
|
|
| 493 |
final_file_id = up_data.get("file_id")
|
| 494 |
|
| 495 |
if final_file_id:
|
|
|
|
| 496 |
send_payload = {
|
| 497 |
"chat_id": str(chat_id),
|
| 498 |
"file_id": str(final_file_id),
|
|
|
|
| 512 |
else:
|
| 513 |
error_logs.append(f"SendFile API Error: {s_data}")
|
| 514 |
else:
|
|
|
|
| 515 |
if up_data.get("status") == "INVALID_INPUT" and api_file_type == "Voice":
|
| 516 |
api_file_type = "Music"
|
| 517 |
error_logs.append(f"Upload API Error: {up_data}")
|
|
|
|
| 523 |
error_logs.append(f"Raw HTTP Error: {str(e)[:100]}")
|
| 524 |
await asyncio.sleep(1.5)
|
| 525 |
|
|
|
|
| 526 |
try:
|
| 527 |
if hasattr(client, "send_file"):
|
| 528 |
await client.send_file(chat_id, abs_path)
|
|
|
|
| 560 |
user_last_request_time = {}
|
| 561 |
|
| 562 |
|
|
|
|
| 563 |
async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=None):
|
| 564 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 565 |
creds = get_user_credits(str_chat_id)
|
|
|
|
| 596 |
history = history[-40:]
|
| 597 |
if history[0]["role"] == "model": history = history[1:]
|
| 598 |
|
|
|
|
| 599 |
keys_to_try = get_next_gemini_keys(100)
|
| 600 |
final_answer = None
|
| 601 |
|
|
|
|
| 613 |
except (KeyError, IndexError): continue
|
| 614 |
except Exception: continue
|
| 615 |
|
|
|
|
| 616 |
if not final_answer and HF_TOKENS:
|
| 617 |
hf_messages =[]
|
| 618 |
for msg in history:
|
|
|
|
| 663 |
await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", False)
|
| 664 |
return
|
| 665 |
|
|
|
|
| 666 |
if not creds.get("is_premium"):
|
| 667 |
user_credits_db[str_chat_id]["chat"] -= 1
|
| 668 |
save_db(user_credits_db)
|
|
|
|
| 693 |
await send_with_keyboard(client, chat_id, "❌ خطایی در ارسال پیام رخ داد.", False)
|
| 694 |
|
| 695 |
|
|
|
|
| 696 |
async def process_image(client, chat_id, prompt):
|
| 697 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 698 |
creds = get_user_credits(str_chat_id)
|
|
|
|
| 706 |
gemini_sys_prompt = f"You are an expert AI image generation prompt engineer. Translate the following user input to English, and enhance it with high-quality, highly detailed, 4k resolution, cinematic lighting, and visually striking descriptive keywords. Return ONLY the final English prompt string.\nUser input: {prompt}"
|
| 707 |
|
| 708 |
if GEMINI_KEYS:
|
|
|
|
| 709 |
keys_to_try_gemini = get_next_gemini_keys(100)
|
| 710 |
async with aiohttp.ClientSession() as session:
|
| 711 |
for key in keys_to_try_gemini:
|
|
|
|
| 719 |
break
|
| 720 |
except Exception: continue
|
| 721 |
|
|
|
|
| 722 |
if enhanced_prompt == prompt and HF_TOKENS:
|
| 723 |
keys_to_try_hf = HF_TOKENS.copy()
|
| 724 |
random.shuffle(keys_to_try_hf)
|
|
|
|
| 744 |
if proc_msg:
|
| 745 |
msg_id = getattr(proc_msg, 'message_id', None)
|
| 746 |
if isinstance(proc_msg, dict): msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
|
| 747 |
+
if msg_id: await client.delete_messages(chat_id,[msg_id])
|
| 748 |
except Exception: pass
|
| 749 |
|
| 750 |
short_preview = enhanced_prompt[:150] + "..." if len(enhanced_prompt) > 150 else enhanced_prompt
|
|
|
|
| 773 |
|
| 774 |
if not generated_image: return await send_with_keyboard(client, chat_id, f"❌ عکس ساخته نشد.\n\n⚠️ خطا:\n{last_error_log[:200]}", True)
|
| 775 |
|
|
|
|
| 776 |
user_credits_db[str_chat_id]["image"] -= 1
|
| 777 |
save_db(user_credits_db)
|
| 778 |
|
|
|
|
| 787 |
if os.path.exists(file_name): os.remove(file_name)
|
| 788 |
except Exception as e: await send_with_keyboard(client, chat_id, f"❌ خطا در ذخیره عکس:\n{str(e)[:150]}", True)
|
| 789 |
|
| 790 |
+
|
| 791 |
async def translate_text_aloha(prompt_text):
|
| 792 |
session_hash = ''.join(random.choices(string.ascii_lowercase + string.digits, k=11))
|
| 793 |
join_url = "https://hamed744-translate-tts-aloha.hf.space/gradio_api/queue/join"
|
|
|
|
| 799 |
|
| 800 |
try:
|
| 801 |
async with aiohttp.ClientSession() as session:
|
|
|
|
| 802 |
async with session.post(join_url, json=payload, timeout=20) as resp:
|
| 803 |
if resp.status != 200:
|
| 804 |
return prompt_text
|
| 805 |
|
|
|
|
| 806 |
data_url = f"https://hamed744-translate-tts-aloha.hf.space/gradio_api/queue/data?session_hash={session_hash}"
|
| 807 |
async with session.get(data_url, timeout=60) as resp:
|
| 808 |
async for line_bytes in resp.content:
|
|
|
|
| 821 |
|
| 822 |
return prompt_text
|
| 823 |
|
| 824 |
+
|
| 825 |
async def process_image_edit(client, chat_id, image_bytes, prompt):
|
| 826 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 827 |
creds = get_user_credits(str_chat_id)
|
|
|
|
| 833 |
|
| 834 |
proc_msg = await send_with_keyboard(client, chat_id, "🪄 در حال ترجمه دستور شما توسط اسپیس و اعمال جادوی FLUX.2...\n(این فرآیند ممکن است کمی طول بکشد)", False)
|
| 835 |
|
|
|
|
| 836 |
translated_prompt = await translate_text_aloha(prompt)
|
| 837 |
if not translated_prompt or translated_prompt.strip() == "":
|
| 838 |
translated_prompt = prompt
|
|
|
|
| 865 |
if not generated_image:
|
| 866 |
return await send_with_keyboard(client, chat_id, f"❌ متأسفانه ویرایش عکس انجام نشد.\n\n⚠️ علت:\n{last_error_log[:200]}", True)
|
| 867 |
|
|
|
|
| 868 |
user_credits_db[str_chat_id]["edit_image"] -= 1
|
| 869 |
save_db(user_credits_db)
|
| 870 |
|
|
|
|
| 882 |
await send_with_keyboard(client, chat_id, f"❌ خطا در ذخیره عکس ویرایش شده:\n{str(e)[:150]}", True)
|
| 883 |
|
| 884 |
|
|
|
|
| 885 |
async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
|
| 886 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 887 |
creds = get_user_credits(str_chat_id)
|
|
|
|
| 918 |
except Exception: pass
|
| 919 |
|
| 920 |
if audio_bytes:
|
|
|
|
| 921 |
if not creds.get("is_premium"):
|
| 922 |
user_credits_db[str_chat_id]["tts"] -= 1
|
| 923 |
save_db(user_credits_db)
|
| 924 |
|
|
|
|
| 925 |
file_name_mp3 = f"audio_{uuid.uuid4().hex}.mp3"
|
| 926 |
|
| 927 |
with open(file_name_mp3, "wb") as f: f.write(audio_bytes)
|
| 928 |
|
| 929 |
await asyncio.sleep(1)
|
|
|
|
|
|
|
| 930 |
upload_result_file = await helper_upload_file(client, chat_id, file_name_mp3, "File", "✅ صدای شما با موفقیت آماده شد (فایل MP3):")
|
| 931 |
|
| 932 |
if upload_result_file is not True:
|
|
|
|
| 937 |
except Exception: traceback.print_exc()
|
| 938 |
|
| 939 |
|
|
|
|
| 940 |
async def process_podcast(client, chat_id, prompt):
|
| 941 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 942 |
creds = get_user_credits(str_chat_id)
|
|
|
|
| 1006 |
combined_audio += audio_segment
|
| 1007 |
except Exception as e: return await send_with_keyboard(client, chat_id, f"❌ خطا در پردازش صدا (آیا pydub و ffmpeg نصب است؟):\n{str(e)}", True)
|
| 1008 |
|
|
|
|
| 1009 |
if not creds.get("is_premium"):
|
| 1010 |
user_credits_db[str_chat_id]["podcast"] -= 1
|
| 1011 |
save_db(user_credits_db)
|
| 1012 |
|
|
|
|
| 1013 |
file_name_mp3 = f"final_podcast_{uuid.uuid4().hex}.mp3"
|
| 1014 |
combined_audio.export(file_name_mp3, format="mp3")
|
| 1015 |
|
|
|
|
| 1021 |
except: pass
|
| 1022 |
|
| 1023 |
caption_file = f"🎧 فایل پادکست شما با فرمت MP3:\n\n💡 موضوع شما: {prompt}"
|
|
|
|
|
|
|
| 1024 |
upload_result_file = await helper_upload_file(client, chat_id, file_name_mp3, "File", caption_file)
|
| 1025 |
|
| 1026 |
if upload_result_file is not True:
|
|
|
|
| 1029 |
if os.path.exists(file_name_mp3): os.remove(file_name_mp3)
|
| 1030 |
|
| 1031 |
|
|
|
|
| 1032 |
async def process_stt(client, chat_id, audio_bytes, file_name):
|
| 1033 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1034 |
creds = get_user_credits(str_chat_id)
|
|
|
|
| 1042 |
mime_type, _ = mimetypes.guess_type(file_name)
|
| 1043 |
if not mime_type: mime_type = "audio/ogg"
|
| 1044 |
|
|
|
|
| 1045 |
keys_to_try = get_next_gemini_keys(100)
|
| 1046 |
transcribed_text = None
|
| 1047 |
prompt = "لطفاً این فایل صوتی/تصویری را با دقت کامل گوش بده و صحبتهای داخل آن را کلمه به کلمه به متن تبدیل کن. هیچ توضیح اضافهای نده."
|
|
|
|
| 1049 |
async with aiohttp.ClientSession() as session:
|
| 1050 |
for key in keys_to_try:
|
| 1051 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 1052 |
+
payload = {"contents":[{"parts":[{"text": prompt}, {"inlineData": {"mimeType": mime_type, "data": base64_data}}]}], "generationConfig": {"temperature": 0.2}}
|
| 1053 |
try:
|
| 1054 |
async with session.post(url, json=payload, timeout=60) as response:
|
| 1055 |
if response.status == 200:
|
|
|
|
| 1066 |
except Exception: pass
|
| 1067 |
|
| 1068 |
if transcribed_text:
|
|
|
|
| 1069 |
if not creds.get("is_premium"):
|
| 1070 |
user_credits_db[str_chat_id]["stt"] -= 1
|
| 1071 |
save_db(user_credits_db)
|
|
|
|
| 1074 |
await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", True)
|
| 1075 |
|
| 1076 |
|
|
|
|
| 1077 |
async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
| 1078 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1079 |
creds = get_user_credits(str_chat_id)
|
|
|
|
| 1087 |
mime_type, _ = mimetypes.guess_type(file_name)
|
| 1088 |
if not mime_type: mime_type = "image/jpeg"
|
| 1089 |
|
|
|
|
| 1090 |
keys_to_try = get_next_gemini_keys(100)
|
| 1091 |
final_answer = None
|
| 1092 |
|
| 1093 |
async with aiohttp.ClientSession() as session:
|
| 1094 |
for key in keys_to_try:
|
| 1095 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 1096 |
+
payload = {"contents":[{"parts":[{"text": prompt}, {"inlineData": {"mimeType": mime_type, "data": base64_data}}]}], "generationConfig": {"temperature": 0.6}}
|
| 1097 |
try:
|
| 1098 |
async with session.post(url, json=payload, timeout=45) as response:
|
| 1099 |
if response.status == 200:
|
|
|
|
| 1110 |
except Exception: pass
|
| 1111 |
|
| 1112 |
if final_answer:
|
|
|
|
| 1113 |
if not creds.get("is_premium"):
|
| 1114 |
user_credits_db[str_chat_id]["file"] -= 1
|
| 1115 |
save_db(user_credits_db)
|
|
|
|
| 1118 |
await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", True)
|
| 1119 |
|
| 1120 |
|
|
|
|
| 1121 |
async def process_create_file(client, chat_id, topic):
|
| 1122 |
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1123 |
creds = get_user_credits(str_chat_id)
|
| 1124 |
|
|
|
|
| 1125 |
if creds["chat"] <= 0:
|
| 1126 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار چت شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
| 1127 |
|
|
|
|
| 1145 |
break
|
| 1146 |
except Exception: continue
|
| 1147 |
|
|
|
|
| 1148 |
if not article_text and HF_TOKENS:
|
| 1149 |
keys_to_try_hf = HF_TOKENS.copy()
|
| 1150 |
random.shuffle(keys_to_try_hf)
|
|
|
|
| 1182 |
converter_url = "https://opera8-texttopdf.hf.space/"
|
| 1183 |
|
| 1184 |
async with aiohttp.ClientSession() as session:
|
|
|
|
| 1185 |
try:
|
| 1186 |
form_data_pdf = aiohttp.FormData()
|
| 1187 |
form_data_pdf.add_field('content', article_text)
|
|
|
|
| 1191 |
pdf_bytes = await resp.read()
|
| 1192 |
except Exception as e: print("PDF creation error:", e)
|
| 1193 |
|
|
|
|
| 1194 |
try:
|
| 1195 |
form_data_docx = aiohttp.FormData()
|
| 1196 |
form_data_docx.add_field('content', article_text)
|
|
|
|
| 1210 |
if not pdf_bytes and not docx_bytes:
|
| 1211 |
return await send_with_keyboard(client, chat_id, "❌ متاسفانه در تبدیل متن به فایل خطایی رخ داد.", True)
|
| 1212 |
|
|
|
|
| 1213 |
if not creds.get("is_premium"):
|
| 1214 |
user_credits_db[str_chat_id]["chat"] -= 1
|
| 1215 |
save_db(user_credits_db)
|
|
|
|
| 1241 |
await send_with_keyboard(client, chat_id, "❌ فایلها ساخته شدند اما روبیکا در ارسال آنها دچار مشکل شد.", True)
|
| 1242 |
|
| 1243 |
|
|
|
|
| 1244 |
if not bot_token:
|
| 1245 |
print("خطا: توکن ربات روبیکا وارد نشده است!")
|
| 1246 |
else:
|
|
|
|
| 1250 |
async def main_handler(client, update):
|
| 1251 |
global BOT_GUID
|
| 1252 |
|
|
|
|
|
|
|
| 1253 |
if is_backlog_burst():
|
| 1254 |
return
|
| 1255 |
|
| 1256 |
try:
|
|
|
|
| 1257 |
if not BOT_GUID:
|
| 1258 |
try:
|
| 1259 |
me_info = await client.get_me()
|
|
|
|
| 1264 |
|
| 1265 |
msg_obj = getattr(update, "message", None) or getattr(update, "new_message", None)
|
| 1266 |
|
|
|
|
| 1267 |
author_id = getattr(update, 'author_guid', None)
|
| 1268 |
if not author_id and msg_obj:
|
| 1269 |
author_id = msg_obj.get('author_object_guid') if isinstance(msg_obj, dict) else getattr(msg_obj, 'author_object_guid', None)
|
| 1270 |
|
|
|
|
| 1271 |
if BOT_GUID and author_id == BOT_GUID:
|
| 1272 |
return
|
| 1273 |
|
|
|
|
| 1274 |
chat_id = getattr(update, 'object_guid', None) or getattr(update, 'author_guid', None) or getattr(update, "chat_id", None)
|
| 1275 |
if not chat_id: return
|
| 1276 |
|
|
|
|
| 1277 |
msg_id = getattr(update, "message_id", None)
|
| 1278 |
if not msg_id and msg_obj:
|
| 1279 |
msg_id = msg_obj.get("message_id") if isinstance(msg_obj, dict) else getattr(msg_obj, "message_id", None)
|
| 1280 |
|
|
|
|
| 1281 |
unique_msg_key = f"{chat_id}_{msg_id}" if msg_id else None
|
| 1282 |
if unique_msg_key:
|
| 1283 |
if unique_msg_key in processed_message_ids: return
|
|
|
|
| 1286 |
|
| 1287 |
current_time = time.time()
|
| 1288 |
|
|
|
|
| 1289 |
last_req_time = user_last_request_time.get(chat_id, 0)
|
| 1290 |
if current_time - last_req_time < 1.0:
|
| 1291 |
return
|
| 1292 |
user_last_request_time[chat_id] = current_time
|
| 1293 |
|
|
|
|
| 1294 |
user_text = getattr(update, "text", "") or getattr(msg_obj, "text", "")
|
| 1295 |
user_text_str = str(user_text).strip() if user_text else ""
|
| 1296 |
user_text_lower = user_text_str.lower()
|
| 1297 |
|
| 1298 |
+
str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
|
| 1299 |
+
|
| 1300 |
+
if str_chat_id not in user_states:
|
| 1301 |
+
user_states[str_chat_id] = {"mode": None, "text": "", "history":[], "file_bytes": None, "file_name": None}
|
| 1302 |
+
|
| 1303 |
+
creds = get_user_credits(str_chat_id)
|
| 1304 |
|
|
|
|
| 1305 |
if user_text_lower.startswith(f"{ADMIN_CODE} pro=") or user_text_lower.startswith(f"{ADMIN_CODE}pro="):
|
| 1306 |
parts = user_text_str.split("=", 1)
|
| 1307 |
if len(parts) >= 2:
|
|
|
|
| 1319 |
"tts": 5,
|
| 1320 |
"file": 1,
|
| 1321 |
"stt": 5,
|
| 1322 |
+
"has_joined": True,
|
| 1323 |
+
"invited_count": 0,
|
| 1324 |
+
"used_referral": False,
|
| 1325 |
+
"referral_code": ""
|
| 1326 |
}
|
| 1327 |
|
| 1328 |
user_credits_db[target_id]["is_premium"] = True
|
|
|
|
| 1391 |
stt_rem = "نامحدود ∞" if is_prem else t_creds.get('stt', 0)
|
| 1392 |
image_rem = t_creds.get('image', 0)
|
| 1393 |
edit_image_rem = t_creds.get('edit_image', 0)
|
| 1394 |
+
invs = t_creds.get('invited_count', 0)
|
| 1395 |
|
| 1396 |
info_msg = f"""🔍 **اطلاعات کاربر `{target_id}`:**
|
| 1397 |
|
| 1398 |
🔹 **وضعیت:** {status_text}
|
| 1399 |
+
🎁 **تعداد افراد دعوت شده:** {invs} نفر
|
| 1400 |
|
| 1401 |
📊 **سهمیه:**
|
| 1402 |
- چت: {chat_rem}
|
|
|
|
| 1411 |
await send_with_keyboard(client, chat_id, f"❌ کاربری با شناسه `{target_id}` در دیتابیس یافت نشد.", False)
|
| 1412 |
return
|
| 1413 |
|
|
|
|
| 1414 |
is_file = False
|
| 1415 |
file_name = f"unknown_file_{uuid.uuid4().hex[:6]}.jpg"
|
| 1416 |
|
|
|
|
| 1431 |
file_name = file_attr.get('file_name', file_name) if isinstance(file_attr, dict) else file_name
|
| 1432 |
break
|
| 1433 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1434 |
if user_text_str == "✅ عضو شدم":
|
| 1435 |
if not creds.get("has_joined", False):
|
|
|
|
| 1436 |
user_credits_db[str_chat_id]["has_joined"] = True
|
| 1437 |
save_db(user_credits_db)
|
| 1438 |
await send_with_keyboard(client, chat_id, "🎉 **عضویت شما با موفقیت تایید شد! خیلی خوش آمدید.**\n\nحالا میتوانید از تمامی امکانات ربات استفاده کنید.\nلطفاً یکی از گزینههای منو را انتخاب کنید:", True)
|
|
|
|
| 1450 |
await client.send_message(chat_id, join_msg)
|
| 1451 |
return
|
| 1452 |
|
| 1453 |
+
if user_text_lower.startswith("/start"):
|
| 1454 |
+
user_states[str_chat_id]["mode"] = None
|
| 1455 |
+
user_states[str_chat_id]["file_bytes"] = None
|
| 1456 |
+
await send_with_keyboard(client, chat_id, "سلام! به ربات هوش مصنوعی آلفا خوش آمدید 🤖\n\nلطفاً برای شروع، از کیبورد پایین یکی از بخشها را انتخاب کنید:", True)
|
| 1457 |
+
return
|
| 1458 |
+
|
| 1459 |
+
if user_text_str in["سلام", "لغو", "/cancel", "❌ لغو", "برگشت♻️"]:
|
| 1460 |
+
user_states[str_chat_id]["mode"] = None
|
| 1461 |
+
user_states[str_chat_id]["file_bytes"] = None
|
| 1462 |
await send_with_keyboard(client, chat_id, "سلام! به ربات هوش مصنوعی آلفا خوش آمدید 🤖\n\nلطفاً برای شروع، از کیبورد پایین یکی از بخشها را انتخاب کنید:", True)
|
| 1463 |
return
|
| 1464 |
|
|
|
|
| 1465 |
if user_text_str in["/account", "حساب کاربری 👤"]:
|
|
|
|
| 1466 |
is_prem = creds.get("is_premium", False)
|
| 1467 |
|
| 1468 |
if is_prem:
|
|
|
|
| 1492 |
stt_rem = "نامحدود ∞" if is_prem else creds['stt']
|
| 1493 |
image_rem = creds['image']
|
| 1494 |
edit_image_rem = creds['edit_image']
|
| 1495 |
+
invited_count = creds.get('invited_count', 0)
|
| 1496 |
+
my_code = get_or_create_referral_code(str_chat_id)
|
| 1497 |
|
| 1498 |
account_profile = f"""👤 **اطلاعات حساب کاربری شما**
|
| 1499 |
|
| 1500 |
🔹 **شناسه یکتا:** `{chat_id}`
|
| 1501 |
+
🎫 **کد هدیه شما:** `{my_code}`
|
| 1502 |
🔹 **وضعیت اشتراک:** {status_text}{expire_info}
|
| 1503 |
+
🎁 **تعداد افراد دعوت شده:** {invited_count} نفر
|
| 1504 |
|
| 1505 |
📊 **سهمیه باقیمانده شما:**
|
| 1506 |
- 💬 چت هوشمند: {chat_rem}
|
|
|
|
| 1515 |
await send_with_keyboard(client, chat_id, account_profile, True)
|
| 1516 |
return
|
| 1517 |
|
| 1518 |
+
# ===============================================
|
| 1519 |
+
# 🎁 سیستم جدید دعوت دوستان (دو سر سود) 🎁
|
| 1520 |
+
# ===============================================
|
| 1521 |
+
if user_text_str in["/invite", "دعوت دوستان 🎁"]:
|
| 1522 |
+
invites = creds.get("invited_count", 0)
|
| 1523 |
+
remains = 10 - (invites % 10)
|
| 1524 |
+
my_code = get_or_create_referral_code(str_chat_id)
|
| 1525 |
+
|
| 1526 |
+
invite_text = f"""🎁 **سیستم دعوت دوستان (دو سر سود)**
|
| 1527 |
+
|
| 1528 |
+
با دعوت دوستان خود به ربات آلفا، هم شما و هم دوستتان هدیه میگیرید!
|
| 1529 |
+
به دوست خود بگویید پس از ورو�� به ربات، دکمه **«ثبت کد هدیه 🎫»** را بزند و کد زیر را وارد کند.
|
| 1530 |
+
✨ **سود دوست شما:** در همان لحظه 10 تبدیل رایگان متن به صدا دریافت میکند.
|
| 1531 |
+
✨ **سود شما:** به آمار دعوتهایتان اضافه میشود و به ازای هر **10 نفر**، **3 روز اشتراک پرو نامحدود** میگیرید.
|
| 1532 |
+
|
| 1533 |
+
📊 **آمار شما:**
|
| 1534 |
+
- تعداد دعوتهای موفق: {invites} نفر
|
| 1535 |
+
- دعوتهای باقیمانده تا جایزه بعدی: {remains} نفر
|
| 1536 |
+
|
| 1537 |
+
کد هدیه اختصاصی شما:
|
| 1538 |
+
`{my_code}`
|
| 1539 |
+
|
| 1540 |
+
(متن زیر را کپی کرده و برای دوستانتان بفرستید 👇)"""
|
| 1541 |
+
await send_with_keyboard(client, chat_id, invite_text, True)
|
| 1542 |
+
|
| 1543 |
+
forward_text = f"""🤖 **ربات هوش مصنوعی آلفا پرو**
|
| 1544 |
+
|
| 1545 |
+
✨ با این ربات میتونی کارهای زیر رو به راحتی انجام بدی:
|
| 1546 |
+
💬 چت با پیشرفتهترین هوش مصنوعی
|
| 1547 |
+
🎨 ساخت و ویرایش حرفهای عکس
|
| 1548 |
+
🎙 ساخت پادکست اختصاصی
|
| 1549 |
+
🗣 تبدیل متن به صدا (30 گوینده مختلف)
|
| 1550 |
+
📝 تبدیل صدا و ویدیو به متن
|
| 1551 |
+
📁 تحلیل فایلها و ساخت مقاله
|
| 1552 |
+
|
| 1553 |
+
👇 اول وارد ربات زیر شو:
|
| 1554 |
+
@aialphabot
|
| 1555 |
+
|
| 1556 |
+
سپس دکمه **«ثبت کد هدیه 🎫»** را بزن و کد 8 رقمی زیر رو وارد کن تا همون اول **10 تا تبدیل صدا هدیه بگیری**:
|
| 1557 |
+
`{my_code}`"""
|
| 1558 |
+
await send_with_keyboard(client, chat_id, forward_text, False)
|
| 1559 |
+
return
|
| 1560 |
+
|
| 1561 |
+
if user_text_str in["/referral", "ثبت کد هدیه 🎫"]:
|
| 1562 |
+
if creds.get("used_referral", False):
|
| 1563 |
+
await send_with_keyboard(client, chat_id, "❌ شما قبلاً کد هدیه یک نفر را ثبت کردهاید و فقط یکبار مجاز به استفاده از این امکان هستید.", True)
|
| 1564 |
+
return
|
| 1565 |
+
user_states[str_chat_id]["mode"] = "waiting_for_referral_code"
|
| 1566 |
+
msg = "🎫 **ثبت کد هدیه**\n\nکد هدیه 8 رقمی (اعداد) که از دوست خود دریافت کردهاید را اینجا وارد کنید تا در همان لحظه **10 سهمیه تبدیل رایگان متن به صدا** هدیه بگیرید!\n\n(برای انصراف دکمه «برگشت♻️» را بزنید)"
|
| 1567 |
+
await send_with_keyboard(client, chat_id, msg, True)
|
| 1568 |
+
return
|
| 1569 |
+
|
| 1570 |
if user_text_str in["/buy", "خرید اشتراک 💎"]:
|
| 1571 |
buy_text = f"""💎 **خرید اشتراک ویژه آلفا پرو (یک ماهه)**
|
| 1572 |
|
|
|
|
| 1598 |
await send_with_keyboard(client, chat_id, buy_text, True)
|
| 1599 |
return
|
| 1600 |
|
|
|
|
| 1601 |
if user_text_str in["/transfer", "انتقال اکانت از برنامه به ربات"]:
|
| 1602 |
transfer_text = f"""🔄 **انتقال اکانت از برنامه به ربات**
|
| 1603 |
|
|
|
|
| 1613 |
return
|
| 1614 |
|
| 1615 |
if user_text_str in["/chat", "💬 چت", "چت با هوش مصنوعی 🤖"]:
|
| 1616 |
+
user_states[str_chat_id]["mode"] = "chat"
|
| 1617 |
+
user_states[str_chat_id]["history"] =[]
|
| 1618 |
await send_with_keyboard(client, chat_id, "💬 شما وارد بخش **چت با هوش مصنوعی** شدید.\n\nهر سوالی دارید بفرستید تا جواب بدم:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1619 |
return
|
| 1620 |
|
| 1621 |
if user_text_str in["/image", "🎨 عکس", "ساخت تصاویر🎨"]:
|
| 1622 |
+
user_states[str_chat_id]["mode"] = "image_waiting_for_text"
|
| 1623 |
await send_with_keyboard(client, chat_id, "🎨 شما وارد بخش **ساخت عکس پیشرفته** شدید.\n\nمتن خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1624 |
return
|
| 1625 |
|
| 1626 |
if user_text_str in["/edit_image", "ویرایش تصاویر 🪄"]:
|
| 1627 |
+
user_states[str_chat_id]["mode"] = "image_edit_waiting_for_image"
|
| 1628 |
+
user_states[str_chat_id]["file_bytes"] = None
|
| 1629 |
await send_with_keyboard(client, chat_id, "🪄 به بخش **ویرایش عکس (Flux.2)** خوش آمدید.\n\nلطفاً ابتدا عکسی که میخواهید ویرایش کنید را بفرستید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1630 |
return
|
| 1631 |
|
| 1632 |
if user_text_str in["/tts", "🎙️ صدا", "تبدیل متن به صدا🗣️"]:
|
| 1633 |
+
user_states[str_chat_id]["mode"] = "tts_waiting_for_text"
|
| 1634 |
await send_with_keyboard(client, chat_id, "🎙️ شما وارد بخش **تبدیل متن به صدا** شدید.\n\nلطفاً متنی که میخواهید به صدا تبدیل شود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1635 |
return
|
| 1636 |
|
| 1637 |
if user_text_str in["/podcast", "📻 پادکست", "ساخت پادکست 🎙️"]:
|
| 1638 |
+
user_states[str_chat_id]["mode"] = "podcast_waiting_for_topic"
|
| 1639 |
await send_with_keyboard(client, chat_id, "📻 شما وارد بخش **ساخت پادکست** شدید.\n\nلطفاً موضوع پادکست خود را بفرستید.\nمثال: درباره تاریخچه پیدایش قهوه با ۳ گوینده یک پادکست جذاب بساز . همچنین این قسمت متصل به مدل زبانی است و درخواست هارو قبل از ساخت درک میکنه. میتوانید مقاله کامل یک سایت بفرستید با تبلیغات یا هرچی، هوش مصنوعی متن مقاله رو استخراج و پادکست براتون میسازه . در توضیحات امکان مشخص کردن تعداد گوینده به همراه اسم شون نیز از سمت شما امکان پذیر است.\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1640 |
return
|
| 1641 |
|
| 1642 |
if user_text_str in["/file", "تحلیل فایل 📁"]:
|
| 1643 |
+
user_states[str_chat_id]["mode"] = "file_waiting_for_file"
|
| 1644 |
+
user_states[str_chat_id]["file_bytes"] = None
|
| 1645 |
await send_with_keyboard(client, chat_id, "📁 شما وارد بخش **تحلیل فایل اختصاصی** شدید.\n\nلطفاً فایل خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1646 |
return
|
| 1647 |
|
| 1648 |
if user_text_str in["/stt", "فایل صوتی به متن 📝"]:
|
| 1649 |
+
user_states[str_chat_id]["mode"] = "stt_waiting_for_audio"
|
| 1650 |
await send_with_keyboard(client, chat_id, "📝 شما وارد بخش **تبدیل صدا به متن** شدید.\n\nلطفاً فایل خود (ویس، آهنگ، ویدیو و...) را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1651 |
return
|
| 1652 |
|
| 1653 |
if user_text_str in["/create_file", "ساخت فایل 📄"]:
|
| 1654 |
+
user_states[str_chat_id]["mode"] = "create_file_waiting_for_topic"
|
| 1655 |
await send_with_keyboard(client, chat_id, "📄 شما وارد بخش **ساخت فایل** شدید.\n\nلطفاً موضوع مقالهای که میخواهید را کامل بفرستید.\nمثال: نحوه مدیریت زمان\n\nهوش مصنوعی یک مقاله کامل و طولانی نوشته و در نهایت فایل PDF و Word آن را به شما تحویل میدهد.\n\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1656 |
return
|
| 1657 |
|
| 1658 |
+
current_mode = user_states[str_chat_id].get("mode")
|
| 1659 |
|
| 1660 |
if current_mode is None:
|
| 1661 |
if is_file: pass
|
| 1662 |
elif user_text_str: await send_with_keyboard(client, chat_id, "⚠️ لطفاً ابتدا از کیبورد پایین، بخش مورد نظرتان را انتخاب کنید:", True)
|
| 1663 |
return
|
| 1664 |
|
| 1665 |
+
# ===============================================
|
| 1666 |
+
# بخش دریافت کد هدیه 8 رقمی از کاربر
|
| 1667 |
+
# ===============================================
|
| 1668 |
+
elif current_mode == "waiting_for_referral_code":
|
| 1669 |
+
if user_text_str:
|
| 1670 |
+
# تبدیل به اعداد انگلیسی در صورت استفاده از کیبورد فارسی
|
| 1671 |
+
normalized_code = to_english_digits(user_text_str).strip()
|
| 1672 |
+
|
| 1673 |
+
if not normalized_code.isdigit() or len(normalized_code) != 8:
|
| 1674 |
+
await send_with_keyboard(client, chat_id, "❌ کد وارد شده نامعتبر است. لطفاً یک کد 8 رقمی صحیح بفرستید.", False)
|
| 1675 |
+
return
|
| 1676 |
+
|
| 1677 |
+
inviter_id = find_user_by_referral_code(normalized_code)
|
| 1678 |
+
|
| 1679 |
+
if not inviter_id:
|
| 1680 |
+
await send_with_keyboard(client, chat_id, "❌ کد هدیه یافت نشد. لطفاً کد را با دقت بررسی کنید.", False)
|
| 1681 |
+
return
|
| 1682 |
+
|
| 1683 |
+
if str(inviter_id) == str(str_chat_id):
|
| 1684 |
+
await send_with_keyboard(client, chat_id, "❌ شما نمیتوانید کد خودتان را ثبت کنید!", False)
|
| 1685 |
+
return
|
| 1686 |
+
|
| 1687 |
+
user_states[str_chat_id]["mode"] = None
|
| 1688 |
+
|
| 1689 |
+
# 1. پاداش کاربر دعوت شده (اضافه شدن 10 تبدیل صدا)
|
| 1690 |
+
user_credits_db[str_chat_id]["used_referral"] = True
|
| 1691 |
+
user_credits_db[str_chat_id]["tts"] = user_credits_db[str_chat_id].get("tts", 0) + 10
|
| 1692 |
+
|
| 1693 |
+
# 2. پاداش شخص دعوت کننده
|
| 1694 |
+
user_credits_db[inviter_id]["invited_count"] = user_credits_db[inviter_id].get("invited_count", 0) + 1
|
| 1695 |
+
current_invites = user_credits_db[inviter_id]["invited_count"]
|
| 1696 |
+
|
| 1697 |
+
if current_invites > 0 and current_invites % 10 == 0:
|
| 1698 |
+
inviter_data = user_credits_db[inviter_id]
|
| 1699 |
+
inviter_data["is_premium"] = True
|
| 1700 |
+
now = datetime.datetime.now()
|
| 1701 |
+
if inviter_data.get("expire_date"):
|
| 1702 |
+
try:
|
| 1703 |
+
current_exp = datetime.datetime.fromisoformat(inviter_data["expire_date"])
|
| 1704 |
+
if current_exp > now:
|
| 1705 |
+
new_exp = current_exp + datetime.timedelta(days=3)
|
| 1706 |
+
else:
|
| 1707 |
+
new_exp = now + datetime.timedelta(days=3)
|
| 1708 |
+
except:
|
| 1709 |
+
new_exp = now + datetime.timedelta(days=3)
|
| 1710 |
+
else:
|
| 1711 |
+
new_exp = now + datetime.timedelta(days=3)
|
| 1712 |
+
|
| 1713 |
+
inviter_data["expire_date"] = new_exp.isoformat()
|
| 1714 |
+
inviter_data["chat"] = 999999
|
| 1715 |
+
inviter_data["image"] = 20
|
| 1716 |
+
inviter_data["edit_image"] = 10
|
| 1717 |
+
inviter_data["podcast"] = 999999
|
| 1718 |
+
inviter_data["tts"] = 999999
|
| 1719 |
+
inviter_data["file"] = 999999
|
| 1720 |
+
inviter_data["stt"] = 999999
|
| 1721 |
+
|
| 1722 |
+
save_db(user_credits_db)
|
| 1723 |
+
try:
|
| 1724 |
+
msg_text = f"🎉 **تبریک ویژه!**\nیک دوست کد هدیه شما را ثبت کرد.\nتعداد کل دعوتهای شما: {current_invites} نفر\n\n🎁 **هدیه شما:** ۳ روز اشتراک پرو نامحدود به حساب شما افزوده شد!"
|
| 1725 |
+
asyncio.create_task(send_with_keyboard(client, inviter_id, msg_text, True))
|
| 1726 |
+
except: pass
|
| 1727 |
+
else:
|
| 1728 |
+
save_db(user_credits_db)
|
| 1729 |
+
remains = 10 - (current_invites % 10)
|
| 1730 |
+
try:
|
| 1731 |
+
msg_text = f"🎉 **تبریک!**\nیک دوست کد هدیه شما را ثبت کرد.\nتعداد کل دعوتهای شما: {current_invites} نفر\n\n⏳ با دعوت {remains} نفر دیگر، ۳ روز اشتراک رایگان دریافت میکنید!"
|
| 1732 |
+
asyncio.create_task(send_with_keyboard(client, inviter_id, msg_text, True))
|
| 1733 |
+
except: pass
|
| 1734 |
+
|
| 1735 |
+
await send_with_keyboard(client, chat_id, "✅ کد هدیه با موفقیت ثبت شد!\n🎁 **10 سهمیه تبدیل رایگان متن به صدا** به حساب شما اضافه گردید.", True)
|
| 1736 |
+
return
|
| 1737 |
+
|
| 1738 |
elif current_mode == "chat":
|
| 1739 |
if is_file:
|
| 1740 |
await send_with_keyboard(client, chat_id, "📥 در حال دانلود فایل...", False)
|
|
|
|
| 1754 |
await send_with_keyboard(client, chat_id, "📥 در حال دانلود عکس...", False)
|
| 1755 |
try:
|
| 1756 |
file_bytes = await helper_download_file(client, msg_obj)
|
| 1757 |
+
user_states[str_chat_id]["file_bytes"] = file_bytes
|
| 1758 |
+
user_states[str_chat_id]["mode"] = "image_edit_waiting_for_prompt"
|
| 1759 |
await send_with_keyboard(client, chat_id, "✅ عکس با موفقیت دریافت شد.\n\nحالا دستور خود را به صورت متنی تایپ کنید.\nمثال: یک کلاه قرمز روی سر این گربه بگذار.", False)
|
| 1760 |
except Exception as dl_err: await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت عکس!\n{str(dl_err)}", False)
|
| 1761 |
return
|
| 1762 |
|
| 1763 |
elif current_mode == "image_edit_waiting_for_prompt":
|
| 1764 |
if user_text_str:
|
| 1765 |
+
saved_bytes = user_states[str_chat_id].get("file_bytes")
|
| 1766 |
+
user_states[str_chat_id]["mode"] = None
|
| 1767 |
+
user_states[str_chat_id]["file_bytes"] = None
|
| 1768 |
asyncio.create_task(process_image_edit(client, chat_id, saved_bytes, user_text_str))
|
| 1769 |
else: await send_with_keyboard(client, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)
|
| 1770 |
return
|
|
|
|
| 1772 |
elif current_mode == "tts_waiting_for_text":
|
| 1773 |
if user_text_str:
|
| 1774 |
if len(user_text_str) > 2500: return await send_with_keyboard(client, chat_id, "⚠️ لطفاً متنی کوتاهتر از 2500 کاراکتر بفرستید.", False)
|
| 1775 |
+
user_states[str_chat_id]["text"] = user_text_str
|
| 1776 |
+
user_states[str_chat_id]["mode"] = "tts_waiting_for_speaker"
|
| 1777 |
|
| 1778 |
speakers_menu = """✅ متن شما ذخیره شد.
|
| 1779 |
لطفاً **شماره** گوینده مورد نظر خود را بفرستید:
|
|
|
|
| 1795 |
|
| 1796 |
if normalized_text.isdigit() and normalized_text in SPEAKERS:
|
| 1797 |
spk_name, spk_id = SPEAKERS[normalized_text]
|
| 1798 |
+
txt = user_states[str_chat_id]["text"]
|
| 1799 |
+
user_states[str_chat_id]["mode"] = "tts_waiting_for_text"
|
| 1800 |
asyncio.create_task(process_tts(client, chat_id, txt, spk_id, spk_name))
|
| 1801 |
else:
|
| 1802 |
await send_with_keyboard(client, chat_id, "❌ شماره نامعتبر است! لطفاً فقط یک عدد بین 1 تا 30 بفرستید.", False)
|
|
|
|
| 1821 |
await send_with_keyboard(client, chat_id, "📥 در حال دریافت فایل...", False)
|
| 1822 |
try:
|
| 1823 |
file_bytes = await helper_download_file(client, msg_obj)
|
| 1824 |
+
user_states[str_chat_id]["file_bytes"] = file_bytes
|
| 1825 |
+
user_states[str_chat_id]["file_name"] = file_name
|
| 1826 |
+
user_states[str_chat_id]["mode"] = "file_waiting_for_prompt"
|
| 1827 |
await send_with_keyboard(client, chat_id, "✅ فایل با موفقیت دریافت شد.\n\nحالا لطفاً متنی بگویید **چگونه تحلیل شود؟**", False)
|
| 1828 |
except Exception as dl_err: await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت فایل!\n{str(dl_err)}", False)
|
| 1829 |
return
|
| 1830 |
|
| 1831 |
elif current_mode == "file_waiting_for_prompt":
|
| 1832 |
if user_text_str:
|
| 1833 |
+
saved_bytes = user_states[str_chat_id].get("file_bytes")
|
| 1834 |
+
saved_name = user_states[str_chat_id].get("file_name", "file.jpeg")
|
| 1835 |
+
user_states[str_chat_id]["mode"] = "file_waiting_for_file"
|
| 1836 |
asyncio.create_task(process_file_analysis(client, chat_id, saved_bytes, saved_name, user_text_str))
|
| 1837 |
else: await send_with_keyboard(client, chat_id, "⚠️ لطفاً درخواست خود را متنی بنویسید.", False)
|
| 1838 |
return
|
|
|
|
| 1849 |
if __name__ == "__main__":
|
| 1850 |
threading.Thread(target=run_flask, daemon=True).start()
|
| 1851 |
if bot_token:
|
| 1852 |
+
print("ربات آلفا پرو با سیستم اشتراک نامحدود + کد هدیه یکتا + سپر امنیتی روشن شد...")
|
| 1853 |
bot.run()
|