Update main.py
Browse files
main.py
CHANGED
|
@@ -23,9 +23,9 @@ from pydub import AudioSegment
|
|
| 23 |
# --- کد مدیریت برای ارتقای کاربران بدون نیاز به لاگین ---
|
| 24 |
ADMIN_CODE = "3011"
|
| 25 |
|
| 26 |
-
# --- ثبت زمان روشن شدن ربات
|
| 27 |
-
#
|
| 28 |
-
BOT_STARTUP_TIME = time.time()
|
| 29 |
|
| 30 |
# متغیر سراسری برای ذخیره آیدی خود ربات (جلوگیری از جواب دادن ربات به خودش)
|
| 31 |
BOT_GUID = None
|
|
@@ -38,7 +38,7 @@ db_lock = threading.Lock()
|
|
| 38 |
|
| 39 |
# --- الگوریتم تبدیل تاریخ میلادی به شمسی (بدون نیاز به نصب کتابخانه) ---
|
| 40 |
def gregorian_to_jalali(gy, gm, gd):
|
| 41 |
-
g_d_m =
|
| 42 |
gy2 = (gy + 1) if (gm > 2) else gy
|
| 43 |
days = 355666 + (365 * gy) + ((gy2 + 3) // 4) - ((gy2 + 99) // 100) + ((gy2 + 399) // 400) + gd + g_d_m[gm - 1]
|
| 44 |
jy = -1595 + (33 * (days // 12053))
|
|
@@ -185,43 +185,43 @@ def run_flask():
|
|
| 185 |
|
| 186 |
# --- ساختار کیبورد آپدیت شده ---
|
| 187 |
MAIN_KEYPAD_DICT = {
|
| 188 |
-
"rows":
|
| 189 |
{
|
| 190 |
-
"buttons":
|
| 191 |
{"id": "chat_btn", "type": "Simple", "button_text": "چت با هوش مصنوعی 🤖"}
|
| 192 |
]
|
| 193 |
},
|
| 194 |
{
|
| 195 |
-
"buttons":
|
| 196 |
{"id": "img_btn", "type": "Simple", "button_text": "ساخت تصاویر🎨"},
|
| 197 |
{"id": "edit_img_btn", "type": "Simple", "button_text": "ویرایش تصاویر 🪄"}
|
| 198 |
]
|
| 199 |
},
|
| 200 |
{
|
| 201 |
-
"buttons":
|
| 202 |
{"id": "podcast_btn", "type": "Simple", "button_text": "ساخت پادکست 🎙️"},
|
| 203 |
{"id": "tts_btn", "type": "Simple", "button_text": "تبدیل متن به صدا🗣️"}
|
| 204 |
]
|
| 205 |
},
|
| 206 |
{
|
| 207 |
-
"buttons":
|
| 208 |
{"id": "stt_btn", "type": "Simple", "button_text": "فایل صوتی به متن 📝"},
|
| 209 |
{"id": "file_btn", "type": "Simple", "button_text": "تحلیل فایل 📁"}
|
| 210 |
]
|
| 211 |
},
|
| 212 |
{
|
| 213 |
-
"buttons":
|
| 214 |
{"id": "account_btn", "type": "Simple", "button_text": "حساب کاربری 👤"},
|
| 215 |
{"id": "buy_btn", "type": "Simple", "button_text": "خرید اشتراک 💎"}
|
| 216 |
]
|
| 217 |
},
|
| 218 |
{
|
| 219 |
-
"buttons":
|
| 220 |
{"id": "transfer_btn", "type": "Simple", "button_text": "انتقال اکانت از برنامه به ربات"}
|
| 221 |
]
|
| 222 |
},
|
| 223 |
{
|
| 224 |
-
"buttons":
|
| 225 |
{"id": "cancel_btn", "type": "Simple", "button_text": "برگشت♻️"}
|
| 226 |
]
|
| 227 |
}
|
|
@@ -251,10 +251,10 @@ async def send_with_keyboard(client, chat_id, text, use_keyboard=True):
|
|
| 251 |
|
| 252 |
# --- 🚨 تابع هوشمند دانلود فایل (با استفاده از UUID جهت جلوگیری از تداخل حریم خصوصی) 🚨 ---
|
| 253 |
async def helper_download_file(client, msg_obj):
|
| 254 |
-
errors =
|
| 255 |
file_id = None
|
| 256 |
file_obj = None
|
| 257 |
-
for attr in
|
| 258 |
val = getattr(msg_obj, attr, None)
|
| 259 |
if val:
|
| 260 |
file_obj = val
|
|
@@ -307,7 +307,7 @@ async def helper_download_file(client, msg_obj):
|
|
| 307 |
GEMINI_KEYS_STR1 = os.environ.get("GEMINI_API_KEYS1", "")
|
| 308 |
GEMINI_KEYS_STR2 = os.environ.get("GEMINI_API_KEYS2", "")
|
| 309 |
|
| 310 |
-
_raw_keys =
|
| 311 |
if GEMINI_KEYS_STR1:
|
| 312 |
_raw_keys.extend(GEMINI_KEYS_STR1.split(","))
|
| 313 |
if GEMINI_KEYS_STR2:
|
|
@@ -332,10 +332,10 @@ def get_next_gemini_keys(count=100):
|
|
| 332 |
with gemini_key_lock:
|
| 333 |
total_keys = len(GEMINI_KEYS)
|
| 334 |
if total_keys == 0:
|
| 335 |
-
return
|
| 336 |
|
| 337 |
actual_count = min(count, total_keys)
|
| 338 |
-
selected_keys =
|
| 339 |
|
| 340 |
for _ in range(actual_count):
|
| 341 |
selected_keys.append(GEMINI_KEYS[current_gemini_key_index])
|
|
@@ -344,7 +344,7 @@ def get_next_gemini_keys(count=100):
|
|
| 344 |
return selected_keys
|
| 345 |
|
| 346 |
HF_TOKENS_STR = os.environ.get("HF_TOKENS", "")
|
| 347 |
-
HF_TOKENS =
|
| 348 |
|
| 349 |
bot_token = os.environ.get("RUBIKA_AUTH", "").strip()
|
| 350 |
|
|
@@ -352,7 +352,7 @@ bot_token = os.environ.get("RUBIKA_AUTH", "").strip()
|
|
| 352 |
# --- 🚨 تابع اختصاصی آپلود فایل به روبیکا 🚨 ---
|
| 353 |
async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""):
|
| 354 |
abs_path = os.path.abspath(file_name)
|
| 355 |
-
error_logs =
|
| 356 |
|
| 357 |
api_file_type = "Image" if file_type in ["photo", "Image", "image"] else "Voice" if file_type in ["voice", "Voice", "audio"] else "File"
|
| 358 |
|
|
@@ -413,7 +413,7 @@ async def helper_upload_file(client, chat_id, file_name, file_type="Image", capt
|
|
| 413 |
return "\n".join(error_logs)
|
| 414 |
|
| 415 |
|
| 416 |
-
WORKER_URLS =
|
| 417 |
"https://hamed744-ttspro.hf.space/generate",
|
| 418 |
"https://hamed744-ttspro2.hf.space/generate",
|
| 419 |
"https://hamed744-ttspro3.hf.space/generate",
|
|
@@ -454,7 +454,7 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
|
|
| 454 |
|
| 455 |
proc_msg = await send_with_keyboard(client, chat_id, "🧠 در حال پردازش...", False)
|
| 456 |
history = user_states[chat_id].get("history", [])
|
| 457 |
-
new_parts =
|
| 458 |
|
| 459 |
if prompt: new_parts.append({"text": prompt})
|
| 460 |
elif file_bytes: new_parts.append({"text": "لطفاً این فایل را به دقت بررسی کن."})
|
|
@@ -520,7 +520,7 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
|
|
| 520 |
|
| 521 |
try:
|
| 522 |
max_len = 1000
|
| 523 |
-
chunks =
|
| 524 |
temp_text = final_answer
|
| 525 |
while len(temp_text) > max_len:
|
| 526 |
split_idx = temp_text.rfind('\n', 0, max_len)
|
|
@@ -559,7 +559,7 @@ async def process_image(client, chat_id, prompt):
|
|
| 559 |
async with aiohttp.ClientSession() as session:
|
| 560 |
for key in keys_to_try_gemini:
|
| 561 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 562 |
-
payload = {"contents": [{"parts":
|
| 563 |
try:
|
| 564 |
async with session.post(url, json=payload, timeout=20) as response:
|
| 565 |
if response.status == 200:
|
|
@@ -572,7 +572,7 @@ async def process_image(client, chat_id, prompt):
|
|
| 572 |
if proc_msg:
|
| 573 |
msg_id = getattr(proc_msg, 'message_id', None)
|
| 574 |
if isinstance(proc_msg, dict): msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
|
| 575 |
-
if msg_id: await client.delete_messages(chat_id,
|
| 576 |
except Exception: pass
|
| 577 |
|
| 578 |
short_preview = enhanced_prompt[:150] + "..." if len(enhanced_prompt) > 150 else enhanced_prompt
|
|
@@ -621,7 +621,7 @@ async def translate_text_aloha(prompt_text):
|
|
| 621 |
session_hash = ''.join(random.choices(string.ascii_lowercase + string.digits, k=11))
|
| 622 |
join_url = "https://hamed744-translate-tts-aloha.hf.space/gradio_api/queue/join"
|
| 623 |
payload = {
|
| 624 |
-
"data":
|
| 625 |
"fn_index": 1,
|
| 626 |
"session_hash": session_hash
|
| 627 |
}
|
|
@@ -748,7 +748,7 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
|
|
| 748 |
if proc_msg:
|
| 749 |
msg_id = getattr(proc_msg, 'message_id', None)
|
| 750 |
if isinstance(proc_msg, dict): msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
|
| 751 |
-
if msg_id: await client.delete_messages(chat_id,
|
| 752 |
except Exception: pass
|
| 753 |
|
| 754 |
if audio_bytes:
|
|
@@ -775,7 +775,7 @@ async def process_podcast(client, chat_id, prompt):
|
|
| 775 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار ساخت پادکست شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
| 776 |
|
| 777 |
proc_msg = await send_with_keyboard(client, chat_id, "📻 در حال بررسی موضوع و نگارش سناریوی پادکست توسط هوش مصنوعی...\n(لطفاً صبور باشید)", False)
|
| 778 |
-
available_speakers =
|
| 779 |
for num_key, (spk_name, spk_id) in SPEAKERS.items():
|
| 780 |
gender = "male" if "مرد" in spk_name else "female"
|
| 781 |
available_speakers.append({"id": spk_id, "name": spk_name.split(' (')[0], "gender": gender})
|
|
@@ -799,7 +799,7 @@ async def process_podcast(client, chat_id, prompt):
|
|
| 799 |
if resp.status == 200:
|
| 800 |
status_data = await resp.json()
|
| 801 |
if status_data.get("status") == "completed":
|
| 802 |
-
script_data = status_data.get("data", {}).get("script",
|
| 803 |
break
|
| 804 |
elif status_data.get("status") == "failed":
|
| 805 |
return await send_with_keyboard(client, chat_id, "❌ متأسفانه هوش مصنوعی نتوانست برای این موضوع سناریو بنویسد.", True)
|
|
@@ -880,7 +880,7 @@ async def process_stt(client, chat_id, audio_bytes, file_name):
|
|
| 880 |
async with aiohttp.ClientSession() as session:
|
| 881 |
for key in keys_to_try:
|
| 882 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 883 |
-
payload = {"contents": [{"parts":
|
| 884 |
try:
|
| 885 |
async with session.post(url, json=payload, timeout=60) as response:
|
| 886 |
if response.status == 200:
|
|
@@ -927,7 +927,7 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
|
|
| 927 |
async with aiohttp.ClientSession() as session:
|
| 928 |
for key in keys_to_try:
|
| 929 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 930 |
-
payload = {"contents":
|
| 931 |
try:
|
| 932 |
async with session.post(url, json=payload, timeout=45) as response:
|
| 933 |
if response.status == 200:
|
|
@@ -963,6 +963,13 @@ else:
|
|
| 963 |
async def main_handler(client, update):
|
| 964 |
global BOT_GUID
|
| 965 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 966 |
try:
|
| 967 |
# 🛡 دریافت آیدی یکتای ربات برای جلوگیری از لوپ 🛡
|
| 968 |
if not BOT_GUID:
|
|
@@ -975,7 +982,7 @@ else:
|
|
| 975 |
|
| 976 |
msg_obj = getattr(update, "message", None) or getattr(update, "new_message", None)
|
| 977 |
|
| 978 |
-
# --- استخراج دقیق شناسه فرستنده
|
| 979 |
author_id = getattr(update, 'author_guid', None)
|
| 980 |
if not author_id and msg_obj:
|
| 981 |
author_id = msg_obj.get('author_object_guid') if isinstance(msg_obj, dict) else getattr(msg_obj, 'author_object_guid', None)
|
|
@@ -984,7 +991,8 @@ else:
|
|
| 984 |
if BOT_GUID and author_id == BOT_GUID:
|
| 985 |
return
|
| 986 |
|
| 987 |
-
#
|
|
|
|
| 988 |
msg_time = getattr(update, 'timestamp', None)
|
| 989 |
if not msg_time and msg_obj:
|
| 990 |
msg_time = msg_obj.get('timestamp') if isinstance(msg_obj, dict) else getattr(msg_obj, 'timestamp', None)
|
|
@@ -992,11 +1000,11 @@ else:
|
|
| 992 |
if msg_time:
|
| 993 |
try:
|
| 994 |
msg_time_int = int(msg_time)
|
| 995 |
-
if msg_time_int > 1e12: #
|
| 996 |
msg_time_int = msg_time_int / 1000.0
|
| 997 |
|
| 998 |
if msg_time_int < BOT_STARTUP_TIME:
|
| 999 |
-
# ⛔️ پیام م
|
| 1000 |
return
|
| 1001 |
except Exception:
|
| 1002 |
pass
|
|
@@ -1017,8 +1025,6 @@ else:
|
|
| 1017 |
processed_message_ids.add(unique_msg_key)
|
| 1018 |
if len(processed_message_ids) > 5000: processed_message_ids.clear()
|
| 1019 |
|
| 1020 |
-
current_time = time.time()
|
| 1021 |
-
|
| 1022 |
# 🛡 سیستم محدودکننده سرعت کاربر (Rate Limit) 🛡
|
| 1023 |
last_req_time = user_last_request_time.get(chat_id, 0)
|
| 1024 |
if current_time - last_req_time < 1.0:
|
|
@@ -1030,12 +1036,12 @@ else:
|
|
| 1030 |
user_text_str = str(user_text).strip() if user_text else ""
|
| 1031 |
user_text_lower = user_text_str.lower()
|
| 1032 |
|
| 1033 |
-
# ⛔️ لایه امنیتی
|
| 1034 |
if user_text_str and user_text_str.startswith(("⏳", "❌", "✅", "🧠", "🎨", "🪄", "🎙", "📻", "📝", "👁️", "💡", "📥")):
|
| 1035 |
return
|
| 1036 |
|
| 1037 |
if chat_id not in user_states:
|
| 1038 |
-
user_states[chat_id] = {"mode": None, "text": "", "history":
|
| 1039 |
|
| 1040 |
# 🛠 --- سیستم پنل مدیریت (بدون نیاز به لاگین) --- 🛠
|
| 1041 |
if user_text_lower.startswith(f"{ADMIN_CODE} pro=") or user_text_lower.startswith(f"{ADMIN_CODE}pro="):
|
|
@@ -1146,7 +1152,7 @@ else:
|
|
| 1146 |
file_name = f"unknown_file_{uuid.uuid4().hex[:6]}.jpg"
|
| 1147 |
|
| 1148 |
if msg_obj:
|
| 1149 |
-
for attr in
|
| 1150 |
file_attr = getattr(msg_obj, attr, None)
|
| 1151 |
if file_attr:
|
| 1152 |
is_file = True
|
|
@@ -1155,14 +1161,14 @@ else:
|
|
| 1155 |
|
| 1156 |
if not is_file and hasattr(msg_obj, 'to_dict'):
|
| 1157 |
msg_dict = msg_obj.to_dict()
|
| 1158 |
-
for attr in
|
| 1159 |
if attr in msg_dict:
|
| 1160 |
is_file = True
|
| 1161 |
file_attr = msg_dict.get(attr, {})
|
| 1162 |
file_name = file_attr.get('file_name', file_name) if isinstance(file_attr, dict) else file_name
|
| 1163 |
break
|
| 1164 |
|
| 1165 |
-
if user_text_str in
|
| 1166 |
user_states[chat_id]["mode"] = None
|
| 1167 |
user_states[chat_id]["file_bytes"] = None
|
| 1168 |
await send_with_keyboard(client, chat_id, "سلام! به ربات هوش مصنوعی آلفا خوش آمدید 🤖\n\nلطفاً برای شروع، از کیبورد پایین یکی از بخشها را انتخاب کنید:", True)
|
|
@@ -1252,7 +1258,7 @@ else:
|
|
| 1252 |
return
|
| 1253 |
|
| 1254 |
# --- دکمه انتقال اکانت ---
|
| 1255 |
-
if user_text_str in
|
| 1256 |
transfer_text = f"""🔄 **انتقال اکانت از برنامه به ربات**
|
| 1257 |
|
| 1258 |
کاربر گرامی، در صورتی که داخل برنامه «هوش مصنوعی آلفا» پیشتر اشتراک تهیه کردهاید، نیازی به خرید مجدد اشتراک داخل ربات نیست! 🎉
|
|
@@ -1268,7 +1274,7 @@ else:
|
|
| 1268 |
|
| 1269 |
if user_text_str in ["/chat", "💬 چت", "چت با هوش مصنوعی 🤖"]:
|
| 1270 |
user_states[chat_id]["mode"] = "chat"
|
| 1271 |
-
user_states[chat_id]["history"] =
|
| 1272 |
await send_with_keyboard(client, chat_id, "💬 شما وارد بخش **چت با هوش مصنوعی** شدید.\n\nهر سوالی دارید بفرستید تا جواب بدم:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1273 |
return
|
| 1274 |
|
|
@@ -1277,13 +1283,13 @@ else:
|
|
| 1277 |
await send_with_keyboard(client, chat_id, "🎨 شما وارد بخش **ساخت عکس پیشرفته** شدید.\n\nمتن خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1278 |
return
|
| 1279 |
|
| 1280 |
-
if user_text_str in
|
| 1281 |
user_states[chat_id]["mode"] = "image_edit_waiting_for_image"
|
| 1282 |
user_states[chat_id]["file_bytes"] = None
|
| 1283 |
await send_with_keyboard(client, chat_id, "🪄 به بخش **ویرایش عکس (Flux.2)** خوش آمدید.\n\nلطفاً ابتدا عکسی که میخواهید ویرایش کنید را بفرستید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1284 |
return
|
| 1285 |
|
| 1286 |
-
if user_text_str in
|
| 1287 |
user_states[chat_id]["mode"] = "tts_waiting_for_text"
|
| 1288 |
await send_with_keyboard(client, chat_id, "🎙️ شما وارد بخش **تبدیل متن به صدا** شدید.\n\nلطفاً متنی که میخواهید به صدا تبدیل شود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1289 |
return
|
|
@@ -1299,7 +1305,7 @@ else:
|
|
| 1299 |
await send_with_keyboard(client, chat_id, "📁 شما وارد بخش **تحلیل فایل اختصاصی** شدید.\n\nلطفاً فایل خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1300 |
return
|
| 1301 |
|
| 1302 |
-
if user_text_str in
|
| 1303 |
user_states[chat_id]["mode"] = "stt_waiting_for_audio"
|
| 1304 |
await send_with_keyboard(client, chat_id, "📝 شما وارد بخش **تبدیل صدا به متن** شدید.\n\nلطفاً فایل خود (ویس، آهنگ، ویدیو و...) را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1305 |
return
|
|
@@ -1418,5 +1424,5 @@ else:
|
|
| 1418 |
if __name__ == "__main__":
|
| 1419 |
threading.Thread(target=run_flask, daemon=True).start()
|
| 1420 |
if bot_token:
|
| 1421 |
-
print("ربات آلفا پرو با سیستم اشتراک نامحدود روشن شد...")
|
| 1422 |
-
bot.run()
|
|
|
|
| 23 |
# --- کد مدیریت برای ارتقای کاربران بدون نیاز به لاگین ---
|
| 24 |
ADMIN_CODE = "3011"
|
| 25 |
|
| 26 |
+
# --- ثبت زمان دقیق روشن شدن ربات ---
|
| 27 |
+
# (حذف ارفاق 10 ثانیهای قبلی برای جلوگیری کامل از پیامهای قدیمی)
|
| 28 |
+
BOT_STARTUP_TIME = time.time()
|
| 29 |
|
| 30 |
# متغیر سراسری برای ذخیره آیدی خود ربات (جلوگیری از جواب دادن ربات به خودش)
|
| 31 |
BOT_GUID = None
|
|
|
|
| 38 |
|
| 39 |
# --- الگوریتم تبدیل تاریخ میلادی به شمسی (بدون نیاز به نصب کتابخانه) ---
|
| 40 |
def gregorian_to_jalali(gy, gm, gd):
|
| 41 |
+
g_d_m =[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
|
| 42 |
gy2 = (gy + 1) if (gm > 2) else gy
|
| 43 |
days = 355666 + (365 * gy) + ((gy2 + 3) // 4) - ((gy2 + 99) // 100) + ((gy2 + 399) // 400) + gd + g_d_m[gm - 1]
|
| 44 |
jy = -1595 + (33 * (days // 12053))
|
|
|
|
| 185 |
|
| 186 |
# --- ساختار کیبورد آپدیت شده ---
|
| 187 |
MAIN_KEYPAD_DICT = {
|
| 188 |
+
"rows":[
|
| 189 |
{
|
| 190 |
+
"buttons":[
|
| 191 |
{"id": "chat_btn", "type": "Simple", "button_text": "چت با هوش مصنوعی 🤖"}
|
| 192 |
]
|
| 193 |
},
|
| 194 |
{
|
| 195 |
+
"buttons":[
|
| 196 |
{"id": "img_btn", "type": "Simple", "button_text": "ساخت تصاویر🎨"},
|
| 197 |
{"id": "edit_img_btn", "type": "Simple", "button_text": "ویرایش تصاویر 🪄"}
|
| 198 |
]
|
| 199 |
},
|
| 200 |
{
|
| 201 |
+
"buttons":[
|
| 202 |
{"id": "podcast_btn", "type": "Simple", "button_text": "ساخت پادکست 🎙️"},
|
| 203 |
{"id": "tts_btn", "type": "Simple", "button_text": "تبدیل متن به صدا🗣️"}
|
| 204 |
]
|
| 205 |
},
|
| 206 |
{
|
| 207 |
+
"buttons":[
|
| 208 |
{"id": "stt_btn", "type": "Simple", "button_text": "فایل صوتی به متن 📝"},
|
| 209 |
{"id": "file_btn", "type": "Simple", "button_text": "تحلیل فایل 📁"}
|
| 210 |
]
|
| 211 |
},
|
| 212 |
{
|
| 213 |
+
"buttons":[
|
| 214 |
{"id": "account_btn", "type": "Simple", "button_text": "حساب کاربری 👤"},
|
| 215 |
{"id": "buy_btn", "type": "Simple", "button_text": "خرید اشتراک 💎"}
|
| 216 |
]
|
| 217 |
},
|
| 218 |
{
|
| 219 |
+
"buttons":[
|
| 220 |
{"id": "transfer_btn", "type": "Simple", "button_text": "انتقال اکانت از برنامه به ربات"}
|
| 221 |
]
|
| 222 |
},
|
| 223 |
{
|
| 224 |
+
"buttons":[
|
| 225 |
{"id": "cancel_btn", "type": "Simple", "button_text": "برگشت♻️"}
|
| 226 |
]
|
| 227 |
}
|
|
|
|
| 251 |
|
| 252 |
# --- 🚨 تابع هوشمند دانلود فایل (با استفاده از UUID جهت جلوگیری از تداخل حریم خصوصی) 🚨 ---
|
| 253 |
async def helper_download_file(client, msg_obj):
|
| 254 |
+
errors =[]
|
| 255 |
file_id = None
|
| 256 |
file_obj = None
|
| 257 |
+
for attr in['file', 'file_inline', 'photo', 'voice', 'audio', 'document', 'video']:
|
| 258 |
val = getattr(msg_obj, attr, None)
|
| 259 |
if val:
|
| 260 |
file_obj = val
|
|
|
|
| 307 |
GEMINI_KEYS_STR1 = os.environ.get("GEMINI_API_KEYS1", "")
|
| 308 |
GEMINI_KEYS_STR2 = os.environ.get("GEMINI_API_KEYS2", "")
|
| 309 |
|
| 310 |
+
_raw_keys =[]
|
| 311 |
if GEMINI_KEYS_STR1:
|
| 312 |
_raw_keys.extend(GEMINI_KEYS_STR1.split(","))
|
| 313 |
if GEMINI_KEYS_STR2:
|
|
|
|
| 332 |
with gemini_key_lock:
|
| 333 |
total_keys = len(GEMINI_KEYS)
|
| 334 |
if total_keys == 0:
|
| 335 |
+
return[]
|
| 336 |
|
| 337 |
actual_count = min(count, total_keys)
|
| 338 |
+
selected_keys =[]
|
| 339 |
|
| 340 |
for _ in range(actual_count):
|
| 341 |
selected_keys.append(GEMINI_KEYS[current_gemini_key_index])
|
|
|
|
| 344 |
return selected_keys
|
| 345 |
|
| 346 |
HF_TOKENS_STR = os.environ.get("HF_TOKENS", "")
|
| 347 |
+
HF_TOKENS =[k.strip() for k in HF_TOKENS_STR.split(",") if k.strip()]
|
| 348 |
|
| 349 |
bot_token = os.environ.get("RUBIKA_AUTH", "").strip()
|
| 350 |
|
|
|
|
| 352 |
# --- 🚨 تابع اختصاصی آپلود فایل به روبیکا 🚨 ---
|
| 353 |
async def helper_upload_file(client, chat_id, file_name, file_type="Image", caption=""):
|
| 354 |
abs_path = os.path.abspath(file_name)
|
| 355 |
+
error_logs =[]
|
| 356 |
|
| 357 |
api_file_type = "Image" if file_type in ["photo", "Image", "image"] else "Voice" if file_type in ["voice", "Voice", "audio"] else "File"
|
| 358 |
|
|
|
|
| 413 |
return "\n".join(error_logs)
|
| 414 |
|
| 415 |
|
| 416 |
+
WORKER_URLS =[
|
| 417 |
"https://hamed744-ttspro.hf.space/generate",
|
| 418 |
"https://hamed744-ttspro2.hf.space/generate",
|
| 419 |
"https://hamed744-ttspro3.hf.space/generate",
|
|
|
|
| 454 |
|
| 455 |
proc_msg = await send_with_keyboard(client, chat_id, "🧠 در حال پردازش...", False)
|
| 456 |
history = user_states[chat_id].get("history", [])
|
| 457 |
+
new_parts =[]
|
| 458 |
|
| 459 |
if prompt: new_parts.append({"text": prompt})
|
| 460 |
elif file_bytes: new_parts.append({"text": "لطفاً این فایل را به دقت بررسی کن."})
|
|
|
|
| 520 |
|
| 521 |
try:
|
| 522 |
max_len = 1000
|
| 523 |
+
chunks =[]
|
| 524 |
temp_text = final_answer
|
| 525 |
while len(temp_text) > max_len:
|
| 526 |
split_idx = temp_text.rfind('\n', 0, max_len)
|
|
|
|
| 559 |
async with aiohttp.ClientSession() as session:
|
| 560 |
for key in keys_to_try_gemini:
|
| 561 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 562 |
+
payload = {"contents": [{"parts":[{"text": gemini_sys_prompt}]}], "generationConfig": {"temperature": 0.7}}
|
| 563 |
try:
|
| 564 |
async with session.post(url, json=payload, timeout=20) as response:
|
| 565 |
if response.status == 200:
|
|
|
|
| 572 |
if proc_msg:
|
| 573 |
msg_id = getattr(proc_msg, 'message_id', None)
|
| 574 |
if isinstance(proc_msg, dict): msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
|
| 575 |
+
if msg_id: await client.delete_messages(chat_id,[msg_id])
|
| 576 |
except Exception: pass
|
| 577 |
|
| 578 |
short_preview = enhanced_prompt[:150] + "..." if len(enhanced_prompt) > 150 else enhanced_prompt
|
|
|
|
| 621 |
session_hash = ''.join(random.choices(string.ascii_lowercase + string.digits, k=11))
|
| 622 |
join_url = "https://hamed744-translate-tts-aloha.hf.space/gradio_api/queue/join"
|
| 623 |
payload = {
|
| 624 |
+
"data":[prompt_text, "انگلیسی (آمریکا) - جنی (زن)", 0, 0, 0],
|
| 625 |
"fn_index": 1,
|
| 626 |
"session_hash": session_hash
|
| 627 |
}
|
|
|
|
| 748 |
if proc_msg:
|
| 749 |
msg_id = getattr(proc_msg, 'message_id', None)
|
| 750 |
if isinstance(proc_msg, dict): msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
|
| 751 |
+
if msg_id: await client.delete_messages(chat_id,[msg_id])
|
| 752 |
except Exception: pass
|
| 753 |
|
| 754 |
if audio_bytes:
|
|
|
|
| 775 |
return await send_with_keyboard(client, chat_id, "❌ اعتبار ساخت پادکست شما تمام شده است. لطفاً از منوی اصلی وارد بخش «خرید اشتراک 💎» شوید.", False)
|
| 776 |
|
| 777 |
proc_msg = await send_with_keyboard(client, chat_id, "📻 در حال بررسی موضوع و نگارش سناریوی پادکست توسط هوش مصنوعی...\n(لطفاً صبور باشید)", False)
|
| 778 |
+
available_speakers =[]
|
| 779 |
for num_key, (spk_name, spk_id) in SPEAKERS.items():
|
| 780 |
gender = "male" if "مرد" in spk_name else "female"
|
| 781 |
available_speakers.append({"id": spk_id, "name": spk_name.split(' (')[0], "gender": gender})
|
|
|
|
| 799 |
if resp.status == 200:
|
| 800 |
status_data = await resp.json()
|
| 801 |
if status_data.get("status") == "completed":
|
| 802 |
+
script_data = status_data.get("data", {}).get("script",[])
|
| 803 |
break
|
| 804 |
elif status_data.get("status") == "failed":
|
| 805 |
return await send_with_keyboard(client, chat_id, "❌ متأسفانه هوش مصنوعی نتوانست برای این موضوع سناریو بنویسد.", True)
|
|
|
|
| 880 |
async with aiohttp.ClientSession() as session:
|
| 881 |
for key in keys_to_try:
|
| 882 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 883 |
+
payload = {"contents": [{"parts":[{"text": prompt}, {"inlineData": {"mimeType": mime_type, "data": base64_data}}]}], "generationConfig": {"temperature": 0.2}}
|
| 884 |
try:
|
| 885 |
async with session.post(url, json=payload, timeout=60) as response:
|
| 886 |
if response.status == 200:
|
|
|
|
| 927 |
async with aiohttp.ClientSession() as session:
|
| 928 |
for key in keys_to_try:
|
| 929 |
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
|
| 930 |
+
payload = {"contents":[{"parts":[{"text": prompt}, {"inlineData": {"mimeType": mime_type, "data": base64_data}}]}], "generationConfig": {"temperature": 0.6}}
|
| 931 |
try:
|
| 932 |
async with session.post(url, json=payload, timeout=45) as response:
|
| 933 |
if response.status == 200:
|
|
|
|
| 963 |
async def main_handler(client, update):
|
| 964 |
global BOT_GUID
|
| 965 |
|
| 966 |
+
current_time = time.time()
|
| 967 |
+
|
| 968 |
+
# 🛡 سد دفاعی اول: فریز ۳۰ ثانیهای کامل 🛡
|
| 969 |
+
# در ۳۰ ثانیه اول راهاندازی، هیچ پیامی تحت هیچ شرایطی پردازش نمیشود
|
| 970 |
+
if current_time - BOT_STARTUP_TIME < 30:
|
| 971 |
+
return
|
| 972 |
+
|
| 973 |
try:
|
| 974 |
# 🛡 دریافت آیدی یکتای ربات برای جلوگیری از لوپ 🛡
|
| 975 |
if not BOT_GUID:
|
|
|
|
| 982 |
|
| 983 |
msg_obj = getattr(update, "message", None) or getattr(update, "new_message", None)
|
| 984 |
|
| 985 |
+
# --- استخراج دقیق شناسه فرستنده ---
|
| 986 |
author_id = getattr(update, 'author_guid', None)
|
| 987 |
if not author_id and msg_obj:
|
| 988 |
author_id = msg_obj.get('author_object_guid') if isinstance(msg_obj, dict) else getattr(msg_obj, 'author_object_guid', None)
|
|
|
|
| 991 |
if BOT_GUID and author_id == BOT_GUID:
|
| 992 |
return
|
| 993 |
|
| 994 |
+
# 🛡 سد دفاعی دوم: جلوگیری کامل از تلنبار شدن پیامهای قدیمی (Backlog) 🛡
|
| 995 |
+
# حتی اگر ۳۰ ثانیه گذشته باشد، اگر کاربر این پیام را در زمان خاموشی سرور داده باشد، درجا حذف میشود
|
| 996 |
msg_time = getattr(update, 'timestamp', None)
|
| 997 |
if not msg_time and msg_obj:
|
| 998 |
msg_time = msg_obj.get('timestamp') if isinstance(msg_obj, dict) else getattr(msg_obj, 'timestamp', None)
|
|
|
|
| 1000 |
if msg_time:
|
| 1001 |
try:
|
| 1002 |
msg_time_int = int(msg_time)
|
| 1003 |
+
if msg_time_int > 1e12: # تبدیل میلیثانیه به ثانیه اگر نیاز بود
|
| 1004 |
msg_time_int = msg_time_int / 1000.0
|
| 1005 |
|
| 1006 |
if msg_time_int < BOT_STARTUP_TIME:
|
| 1007 |
+
# ⛔️ پیام متعلق به گذشته است و برای همیشه دور ریخته میشود
|
| 1008 |
return
|
| 1009 |
except Exception:
|
| 1010 |
pass
|
|
|
|
| 1025 |
processed_message_ids.add(unique_msg_key)
|
| 1026 |
if len(processed_message_ids) > 5000: processed_message_ids.clear()
|
| 1027 |
|
|
|
|
|
|
|
| 1028 |
# 🛡 سیستم محدودکننده سرعت کاربر (Rate Limit) 🛡
|
| 1029 |
last_req_time = user_last_request_time.get(chat_id, 0)
|
| 1030 |
if current_time - last_req_time < 1.0:
|
|
|
|
| 1036 |
user_text_str = str(user_text).strip() if user_text else ""
|
| 1037 |
user_text_lower = user_text_str.lower()
|
| 1038 |
|
| 1039 |
+
# ⛔️ لایه امنیتی سوم برای جلوگیری از پاسخ دادن ربات به پیامهای سیستم خودش
|
| 1040 |
if user_text_str and user_text_str.startswith(("⏳", "❌", "✅", "🧠", "🎨", "🪄", "🎙", "📻", "📝", "👁️", "💡", "📥")):
|
| 1041 |
return
|
| 1042 |
|
| 1043 |
if chat_id not in user_states:
|
| 1044 |
+
user_states[chat_id] = {"mode": None, "text": "", "history":[], "file_bytes": None, "file_name": None}
|
| 1045 |
|
| 1046 |
# 🛠 --- سیستم پنل مدیریت (بدون نیاز به لاگین) --- 🛠
|
| 1047 |
if user_text_lower.startswith(f"{ADMIN_CODE} pro=") or user_text_lower.startswith(f"{ADMIN_CODE}pro="):
|
|
|
|
| 1152 |
file_name = f"unknown_file_{uuid.uuid4().hex[:6]}.jpg"
|
| 1153 |
|
| 1154 |
if msg_obj:
|
| 1155 |
+
for attr in['file', 'file_inline', 'photo', 'voice', 'audio', 'document', 'video']:
|
| 1156 |
file_attr = getattr(msg_obj, attr, None)
|
| 1157 |
if file_attr:
|
| 1158 |
is_file = True
|
|
|
|
| 1161 |
|
| 1162 |
if not is_file and hasattr(msg_obj, 'to_dict'):
|
| 1163 |
msg_dict = msg_obj.to_dict()
|
| 1164 |
+
for attr in['file', 'file_inline', 'photo', 'voice', 'audio', 'document', 'video']:
|
| 1165 |
if attr in msg_dict:
|
| 1166 |
is_file = True
|
| 1167 |
file_attr = msg_dict.get(attr, {})
|
| 1168 |
file_name = file_attr.get('file_name', file_name) if isinstance(file_attr, dict) else file_name
|
| 1169 |
break
|
| 1170 |
|
| 1171 |
+
if user_text_str in["/start", "سلام", "لغو", "/cancel", "❌ لغو", "برگشت♻️"]:
|
| 1172 |
user_states[chat_id]["mode"] = None
|
| 1173 |
user_states[chat_id]["file_bytes"] = None
|
| 1174 |
await send_with_keyboard(client, chat_id, "سلام! به ربات هوش مصنوعی آلفا خوش آمدید 🤖\n\nلطفاً برای شروع، از کیبورد پایین یکی از بخشها را انتخاب کنید:", True)
|
|
|
|
| 1258 |
return
|
| 1259 |
|
| 1260 |
# --- دکمه انتقال اکانت ---
|
| 1261 |
+
if user_text_str in["/transfer", "انتقال اکانت از برنامه به ربات"]:
|
| 1262 |
transfer_text = f"""🔄 **انتقال اکانت از برنامه به ربات**
|
| 1263 |
|
| 1264 |
کاربر گرامی، در صورتی که داخل برنامه «هوش مصنوعی آلفا» پیشتر اشتراک تهیه کردهاید، نیازی به خرید مجدد اشتراک داخل ربات نیست! 🎉
|
|
|
|
| 1274 |
|
| 1275 |
if user_text_str in ["/chat", "💬 چت", "چت با هوش مصنوعی 🤖"]:
|
| 1276 |
user_states[chat_id]["mode"] = "chat"
|
| 1277 |
+
user_states[chat_id]["history"] =[]
|
| 1278 |
await send_with_keyboard(client, chat_id, "💬 شما وارد بخش **چت با هوش مصنوعی** شدید.\n\nهر سوالی دارید بفرستید تا جواب بدم:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1279 |
return
|
| 1280 |
|
|
|
|
| 1283 |
await send_with_keyboard(client, chat_id, "🎨 شما وارد بخش **ساخت عکس پیشرفته** شدید.\n\nمتن خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1284 |
return
|
| 1285 |
|
| 1286 |
+
if user_text_str in["/edit_image", "ویرایش تصاویر 🪄"]:
|
| 1287 |
user_states[chat_id]["mode"] = "image_edit_waiting_for_image"
|
| 1288 |
user_states[chat_id]["file_bytes"] = None
|
| 1289 |
await send_with_keyboard(client, chat_id, "🪄 به بخش **ویرایش عکس (Flux.2)** خوش آمدید.\n\nلطفاً ابتدا عکسی که میخواهید ویرایش کنید را بفرستید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1290 |
return
|
| 1291 |
|
| 1292 |
+
if user_text_str in["/tts", "🎙️ صدا", "تبدیل متن به صدا🗣️"]:
|
| 1293 |
user_states[chat_id]["mode"] = "tts_waiting_for_text"
|
| 1294 |
await send_with_keyboard(client, chat_id, "🎙️ شما وارد بخش **تبدیل متن به صدا** شدید.\n\nلطفاً متنی که میخواهید به صدا تبدیل شود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1295 |
return
|
|
|
|
| 1305 |
await send_with_keyboard(client, chat_id, "📁 شما وارد بخش **تحلیل فایل اختصاصی** شدید.\n\nلطفاً فایل خود را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1306 |
return
|
| 1307 |
|
| 1308 |
+
if user_text_str in["/stt", "فایل صوتی به متن 📝"]:
|
| 1309 |
user_states[chat_id]["mode"] = "stt_waiting_for_audio"
|
| 1310 |
await send_with_keyboard(client, chat_id, "📝 شما وارد بخش **تبدیل صدا به متن** شدید.\n\nلطفاً فایل خود (ویس، آهنگ، ویدیو و...) را ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
|
| 1311 |
return
|
|
|
|
| 1424 |
if __name__ == "__main__":
|
| 1425 |
threading.Thread(target=run_flask, daemon=True).start()
|
| 1426 |
if bot_token:
|
| 1427 |
+
print("ربات آلفا پرو با سیستم اشتراک نامحدود و دیواره امنیتی ضد Backlog روشن شد...")
|
| 1428 |
+
bot.run()
|