Opera8 commited on
Commit
6885eb2
·
verified ·
1 Parent(s): d8191da

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +285 -123
main.py CHANGED
@@ -12,6 +12,7 @@ import json
12
  import datetime
13
  import string
14
  import uuid
 
15
  from flask import Flask
16
  from rubpy.bot import BotClient, filters
17
 
@@ -212,7 +213,28 @@ def home():
212
  return "ربات یکپارچه آلفا (نسخه پرو + مدیریت اشتراک نامحدود + دعوت دوستان + سیستم ضد باگ) روشن است! 🚀"
213
 
214
  def run_flask():
215
- app.run(host="0.0.0.0", port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
 
218
  # --- ساختار کیبورد آپدیت شده ---
@@ -368,7 +390,7 @@ async def helper_download_file(client, msg_obj):
368
  try:
369
  await client.download_file(msg_obj, temp_name)
370
  if os.path.exists(temp_name):
371
- with open(temp_name, 'rb') as f: data = f.read()
372
  os.remove(temp_name)
373
  return data
374
  except Exception as e: errors.append(f"تلاش ۱: {e}")
@@ -377,7 +399,7 @@ async def helper_download_file(client, msg_obj):
377
  try:
378
  await client.download_file(file_obj, temp_name)
379
  if os.path.exists(temp_name):
380
- with open(temp_name, 'rb') as f: data = f.read()
381
  os.remove(temp_name)
382
  return data
383
  except Exception as e: errors.append(f"تلاش ۲: {e}")
@@ -386,7 +408,7 @@ async def helper_download_file(client, msg_obj):
386
  try:
387
  await client.download_file(file_id, file_name=temp_name)
388
  if os.path.exists(temp_name):
389
- with open(temp_name, 'rb') as f: data = f.read()
390
  os.remove(temp_name)
391
  return data
392
  except Exception as e: errors.append(f"تلاش ۳: {e}")
@@ -394,7 +416,7 @@ async def helper_download_file(client, msg_obj):
394
  try:
395
  await client.download_file(file_id, save_as=temp_name)
396
  if os.path.exists(temp_name):
397
- with open(temp_name, 'rb') as f: data = f.read()
398
  os.remove(temp_name)
399
  return data
400
  except Exception as e: errors.append(f"تلاش ۴: {e}")
@@ -572,6 +594,9 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
572
  history = user_states[chat_id].get("history",[])
573
  new_parts =[]
574
 
 
 
 
575
  if prompt: new_parts.append({"text": prompt})
576
  elif file_bytes: new_parts.append({"text": "لطفاً این فایل را به دقت بررسی کن."})
577
 
@@ -587,6 +612,11 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
587
  elif file_name.endswith(('.ogg', '.oga')): mime_type = "audio/ogg"
588
  elif file_name.endswith('.wav'): mime_type = "audio/wav"
589
  else: mime_type = "image/jpeg"
 
 
 
 
 
590
  new_parts.append({"inlineData": {"mimeType": mime_type, "data": base64_data}})
591
 
592
  if history and history[-1]["role"] == "user": history[-1]["parts"].extend(new_parts)
@@ -613,43 +643,60 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
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:
619
- role = "assistant" if msg["role"] == "model" else "user"
620
- content_parts =[]
621
- for part in msg["parts"]:
622
- if "text" in part:
623
- content_parts.append({"type": "text", "text": part["text"]})
624
- elif "inlineData" in part:
625
- mime_t = part["inlineData"]["mimeType"]
626
- b64_d = part["inlineData"]["data"]
627
- content_parts.append({
628
- "type": "image_url",
629
- "image_url": {"url": f"data:{mime_t};base64,{b64_d}"}
630
- })
631
- hf_messages.append({"role": role, "content": content_parts})
632
-
633
- keys_to_try_hf = HF_TOKENS.copy()
634
- random.shuffle(keys_to_try_hf)
635
-
636
- async with aiohttp.ClientSession() as session:
637
- for hf_key in keys_to_try_hf:
638
- url = "https://router.huggingface.co/v1/chat/completions"
639
- headers = {"Authorization": f"Bearer {hf_key}", "Content-Type": "application/json"}
640
- payload = {
641
- "model": "google/gemma-4-31B-it:novita",
642
- "messages": hf_messages,
643
- "max_tokens": 4096
644
- }
645
- try:
646
- async with session.post(url, headers=headers, json=payload, timeout=60) as response:
647
- if response.status == 200:
648
- data = await response.json()
649
- final_answer = data["choices"][0]["message"]["content"]
650
- break
651
- except Exception:
652
- continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
653
 
654
  try:
655
  if proc_msg:
@@ -660,7 +707,7 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
660
 
661
  if not final_answer:
662
  if history and history[-1]["role"] == "user": history.pop()
663
- await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", False)
664
  return
665
 
666
  if not creds.get("is_premium"):
@@ -693,7 +740,7 @@ async def process_gemini(client, chat_id, prompt, file_bytes=None, file_name=Non
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)
699
  if creds["image"] <= 0:
@@ -747,8 +794,21 @@ async def process_image(client, chat_id, prompt):
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
751
- proc_msg = await send_with_keyboard(client, chat_id, f"🎨 در حال طراحی عکس...\n\n📝 پرامپت ساخته شده:\n`{short_preview}`\n\n(ممکن است چند ثانیه زمان ببرد)", False)
752
 
753
  keys_to_try = HF_TOKENS.copy()
754
  random.shuffle(keys_to_try)
@@ -758,7 +818,12 @@ async def process_image(client, chat_id, prompt):
758
  for token in keys_to_try:
759
  try:
760
  hf_client = AsyncInferenceClient(provider="fal-ai", api_key=token)
761
- generated_image = await hf_client.text_to_image(enhanced_prompt, model="Tongyi-MAI/Z-Image-Turbo")
 
 
 
 
 
762
  break
763
  except Exception as e:
764
  last_error_log = str(e)
@@ -778,10 +843,10 @@ async def process_image(client, chat_id, prompt):
778
 
779
  try:
780
  file_name = f"image_{uuid.uuid4().hex}.jpg"
781
- rgb_im = generated_image.convert('RGB')
782
- rgb_im.save(file_name, format="JPEG", quality=100)
783
  await asyncio.sleep(1)
784
- caption_text = f"🎨 تصویر شما با پرامپت هوشمند آماده شد!\n\n✨ ایده اولیه: {prompt}"
785
  upload_result = await helper_upload_file(client, chat_id, file_name, "Image", caption_text)
786
  if upload_result is not True: await send_with_keyboard(client, chat_id, f"❌ خطا در آپلود روبیکا:\n`{str(upload_result)[:800]}`", True)
787
  if os.path.exists(file_name): os.remove(file_name)
@@ -870,8 +935,8 @@ async def process_image_edit(client, chat_id, image_bytes, prompt):
870
 
871
  try:
872
  file_name = f"edited_flux_{uuid.uuid4().hex}.jpg"
873
- rgb_im = generated_image.convert('RGB')
874
- rgb_im.save(file_name, format="JPEG", quality=100)
875
  await asyncio.sleep(1)
876
  caption_text = f"🪄 ویرایش عکس با هوش مصنوعی Flux.2 انجام شد!\n\n✨ تغییرات خواسته شده: {prompt}\n🔤 متن ارسال شده به هوش: {translated_prompt}"
877
  upload_result = await helper_upload_file(client, chat_id, file_name, "Image", caption_text)
@@ -924,7 +989,8 @@ async def process_tts(client, chat_id, user_text, speaker_id, speaker_name):
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):")
@@ -1002,8 +1068,8 @@ async def process_podcast(client, chat_id, prompt):
1002
  if not chunk_audio_bytes: return await send_with_keyboard(client, chat_id, f"❌ خطا در تولید صدای بخش {index+1} از سرور. عملیات متوقف شد.", True)
1003
 
1004
  try:
1005
- audio_segment = AudioSegment.from_file(io.BytesIO(chunk_audio_bytes))
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"):
@@ -1011,7 +1077,8 @@ async def process_podcast(client, chat_id, prompt):
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
 
1016
  try:
1017
  if proc_msg:
@@ -1085,7 +1152,17 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
1085
  proc_msg = await send_with_keyboard(client, chat_id, "👁️ در حال تحلیل فایل...", False)
1086
  base64_data = base64.b64encode(file_bytes).decode('utf-8')
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
@@ -1102,6 +1179,43 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
1102
  break
1103
  except Exception: continue
1104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1105
  try:
1106
  if proc_msg:
1107
  msg_id = getattr(proc_msg, 'message_id', None)
@@ -1115,7 +1229,10 @@ async def process_file_analysis(client, chat_id, file_bytes, file_name, prompt):
1115
  save_db(user_credits_db)
1116
  await send_with_keyboard(client, chat_id, f"💡 **نتیجه تحلیل:**\n\n{final_answer}", True)
1117
  else:
1118
- await send_with_keyboard(client, chat_id, "❌ سرور شلوغ است فعلا بعدا امتحان کنید.", True)
 
 
 
1119
 
1120
 
1121
  async def process_create_file(client, chat_id, topic):
@@ -1136,7 +1253,7 @@ async def process_create_file(client, chat_id, topic):
1136
  async with aiohttp.ClientSession() as session:
1137
  for key in keys_to_try:
1138
  url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
1139
- payload = {"contents": [{"parts":[{"text": ai_prompt}]}], "generationConfig": {"temperature": 0.7, "maxOutputTokens": 8192}}
1140
  try:
1141
  async with session.post(url, json=payload, timeout=60) as response:
1142
  if response.status == 200:
@@ -1175,31 +1292,37 @@ async def process_create_file(client, chat_id, topic):
1175
  if msg_id: await client.delete_messages(chat_id,[msg_id])
1176
  except Exception: pass
1177
 
1178
- proc_msg = await send_with_keyboard(client, chat_id, "📄 مقاله با موفقیت نوشته شد! در حال ارتباط با سرور و تبدیل به فایل‌های PDF و Word...\n(لطفا صبور باشید)", False)
1179
-
1180
- pdf_bytes = None
1181
- docx_bytes = None
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)
1188
- form_data_pdf.add_field('format', 'pdf')
1189
- async with session.post(converter_url, data=form_data_pdf, timeout=60) as resp:
1190
- if resp.status == 200:
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)
1197
- form_data_docx.add_field('format', 'docx')
1198
- async with session.post(converter_url, data=form_data_docx, timeout=60) as resp:
1199
- if resp.status == 200:
1200
- docx_bytes = await resp.read()
1201
- except Exception as e: print("DOCX creation error:", e)
1202
-
 
 
 
 
 
 
1203
  try:
1204
  if proc_msg:
1205
  msg_id = getattr(proc_msg, 'message_id', None)
@@ -1207,38 +1330,40 @@ async def process_create_file(client, chat_id, topic):
1207
  if msg_id: await client.delete_messages(chat_id, [msg_id])
1208
  except Exception: pass
1209
 
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)
1216
-
1217
- uid = uuid.uuid4().hex
1218
- pdf_filename = f"Article_{uid}.pdf"
1219
- docx_filename = f"Article_{uid}.docx"
1220
-
1221
- uploaded_any = False
1222
 
1223
  if pdf_bytes:
1224
- with open(pdf_filename, "wb") as f:
1225
- f.write(pdf_bytes)
1226
  res = await helper_upload_file(client, chat_id, pdf_filename, "File", f"📄 فایل PDF مقاله شما:\n\n💡 موضوع: {topic}")
1227
- if res is True: uploaded_any = True
1228
- if os.path.exists(pdf_filename): os.remove(pdf_filename)
1229
- await asyncio.sleep(1.5)
 
 
 
1230
 
1231
  if docx_bytes:
1232
- with open(docx_filename, "wb") as f:
1233
- f.write(docx_bytes)
1234
  res = await helper_upload_file(client, chat_id, docx_filename, "File", f"📝 فایل Word (DOCX) مقاله ��ما:\n\n💡 موضوع: {topic}")
1235
- if res is True: uploaded_any = True
1236
- if os.path.exists(docx_filename): os.remove(docx_filename)
 
 
1237
 
1238
- if uploaded_any:
1239
- await send_with_keyboard(client, chat_id, "✅ مقاله شما با موفقیت به صورت فایل تحویل داده شد!", True)
 
 
 
 
 
 
1240
  else:
1241
- await send_with_keyboard(client, chat_id, "❌ فایل‌ها ساخته شدند اما روبیکا در ارسال آن‌ها دچار مشکل شد.", True)
1242
 
1243
 
1244
  if not bot_token:
@@ -1382,7 +1507,7 @@ else:
1382
  expire_txt = f"{jy:04d}/{jm:02d}/{jd:02d}"
1383
  status_text = f"🌟 نسخه پرو (ویژه)\n📅 انقضا: {expire_txt}\n⏳ باقیمانده: {days_left} روز"
1384
  else:
1385
- status_text = "🥉 نسخه رایگان (آزمایشی)\n⏳ سهمیه روزانه"
1386
 
1387
  chat_rem = "نامحدود ∞" if is_prem else t_creds.get('chat', 0)
1388
  podcast_rem = "نامحدود ∞" if is_prem else t_creds.get('podcast', 0)
@@ -1392,23 +1517,27 @@ else:
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}
1403
- - تولید عکس: {image_rem}
1404
- - ویرایش عکس: {edit_image_rem}
1405
- - پادکست: {podcast_rem}
1406
- - متن به صدا: {tts_rem}
1407
- - تحلیل فایل: {file_rem}
1408
- - صدا به متن: {stt_rem}"""
1409
  await send_with_keyboard(client, chat_id, info_msg, False)
1410
  else:
1411
- await send_with_keyboard(client, chat_id, f"❌ کاربری با شناسه `{target_id}` در دیتابیس یافت نشد.", False)
1412
  return
1413
 
1414
  is_file = False
@@ -1594,7 +1723,7 @@ else:
1594
  🔑 **شناسه یکتای شما:** `{chat_id}`
1595
 
1596
  👨‍💻 **ارتباط با پشتیبانی:**
1597
- 🆔 @H_a_m_e_d100"""
1598
  await send_with_keyboard(client, chat_id, buy_text, True)
1599
  return
1600
 
@@ -1608,7 +1737,7 @@ else:
1608
  🔑 **شناسه یکتای ربات شما:** `{chat_id}`
1609
 
1610
  👨‍💻 **دقت کنید شناسه ربات رو به پشتیبانی داخل خود برنامه هوش مصنوعی آلفا ارسال کنید:**
1611
- 🆔 @H_a_m_e_d100"""
1612
  await send_with_keyboard(client, chat_id, transfer_text, True)
1613
  return
1614
 
@@ -1620,7 +1749,7 @@ else:
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", "ویرایش تصاویر 🪄"]:
@@ -1745,8 +1874,35 @@ else:
1745
  elif user_text_str: asyncio.create_task(process_gemini(client, chat_id, user_text_str))
1746
  return
1747
 
 
 
 
1748
  elif current_mode == "image_waiting_for_text":
1749
- if user_text_str: asyncio.create_task(process_image(client, chat_id, user_text_str))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1750
  return
1751
 
1752
  elif current_mode == "image_edit_waiting_for_image":
@@ -1824,7 +1980,7 @@ else:
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
 
@@ -1848,6 +2004,12 @@ else:
1848
 
1849
  if __name__ == "__main__":
1850
  threading.Thread(target=run_flask, daemon=True).start()
 
1851
  if bot_token:
1852
- print("ربات آلفا پرو با سیستم اشتراک نامحدود + کد هدیه یکتا + سپر امنیتی روشن شد...")
 
 
 
 
 
1853
  bot.run()
 
12
  import datetime
13
  import string
14
  import uuid
15
+ import concurrent.futures
16
  from flask import Flask
17
  from rubpy.bot import BotClient, filters
18
 
 
213
  return "ربات یکپارچه آلفا (نسخه پرو + مدیریت اشتراک نامحدود + دعوت دوستان + سیستم ضد باگ) روشن است! 🚀"
214
 
215
  def run_flask():
216
+ app.run(host="0.0.0.0", port=7860, threaded=True)
217
+
218
+
219
+ # --- توابع کمکی برای جلوگیری از بلاک شدن Event Loop ---
220
+ def sync_save_image(image, file_name):
221
+ rgb_im = image.convert('RGB')
222
+ rgb_im.save(file_name, format="JPEG", quality=100)
223
+
224
+ def sync_write_file(file_name, data):
225
+ with open(file_name, "wb") as f:
226
+ f.write(data)
227
+
228
+ def sync_read_file(file_name):
229
+ with open(file_name, 'rb') as f:
230
+ return f.read()
231
+
232
+ def sync_combine_audio(current_audio, new_bytes):
233
+ audio_segment = AudioSegment.from_file(io.BytesIO(new_bytes))
234
+ return current_audio + audio_segment
235
+
236
+ def sync_export_audio(audio_obj, file_name):
237
+ audio_obj.export(file_name, format="mp3")
238
 
239
 
240
  # --- ساختار کیبورد آپدیت شده ---
 
390
  try:
391
  await client.download_file(msg_obj, temp_name)
392
  if os.path.exists(temp_name):
393
+ data = await asyncio.to_thread(sync_read_file, temp_name)
394
  os.remove(temp_name)
395
  return data
396
  except Exception as e: errors.append(f"تلاش ۱: {e}")
 
399
  try:
400
  await client.download_file(file_obj, temp_name)
401
  if os.path.exists(temp_name):
402
+ data = await asyncio.to_thread(sync_read_file, temp_name)
403
  os.remove(temp_name)
404
  return data
405
  except Exception as e: errors.append(f"تلاش ۲: {e}")
 
408
  try:
409
  await client.download_file(file_id, file_name=temp_name)
410
  if os.path.exists(temp_name):
411
+ data = await asyncio.to_thread(sync_read_file, temp_name)
412
  os.remove(temp_name)
413
  return data
414
  except Exception as e: errors.append(f"تلاش ۳: {e}")
 
416
  try:
417
  await client.download_file(file_id, save_as=temp_name)
418
  if os.path.exists(temp_name):
419
+ data = await asyncio.to_thread(sync_read_file, temp_name)
420
  os.remove(temp_name)
421
  return data
422
  except Exception as e: errors.append(f"تلاش ۴: {e}")
 
594
  history = user_states[chat_id].get("history",[])
595
  new_parts =[]
596
 
597
+ is_image = True
598
+ has_non_image_file = False
599
+
600
  if prompt: new_parts.append({"text": prompt})
601
  elif file_bytes: new_parts.append({"text": "لطفاً این فایل را به دقت بررسی کن."})
602
 
 
612
  elif file_name.endswith(('.ogg', '.oga')): mime_type = "audio/ogg"
613
  elif file_name.endswith('.wav'): mime_type = "audio/wav"
614
  else: mime_type = "image/jpeg"
615
+
616
+ is_image = mime_type.startswith('image/')
617
+ if not is_image:
618
+ has_non_image_file = True
619
+
620
  new_parts.append({"inlineData": {"mimeType": mime_type, "data": base64_data}})
621
 
622
  if history and history[-1]["role"] == "user": history[-1]["parts"].extend(new_parts)
 
643
  except (KeyError, IndexError): continue
644
  except Exception: continue
645
 
646
+ # اگر جیمینای جواب نداد
647
+ if not final_answer:
648
+ # اگر فایل ارسال شده عکس نبود، خطای اختصاصی می‌دهیم
649
+ if has_non_image_file:
650
+ if history and history[-1]["role"] == "user": history.pop()
651
+ try:
652
+ if proc_msg:
653
+ msg_id = getattr(proc_msg, 'message_id', None)
654
+ if isinstance(proc_msg, dict): msg_id = proc_msg.get('message_update', {}).get('message_id') or proc_msg.get('message_id')
655
+ if msg_id: await client.delete_messages(chat_id,[msg_id])
656
+ except Exception: pass
657
+ await send_with_keyboard(client, chat_id, "❌ متأسفانه سرور اصلی در حال حاضر شلوغ است و در این شرایط **فعلاً تنها امکان تحلیل تصاویر** توسط سرور جایگزین در دسترس است.", False)
658
+ return
659
+
660
+ # اگر فایل عکس بود یا فقط متن بود، می‌رویم سراغ مدل جایگزین (هاگینگ فیس)
661
+ if HF_TOKENS:
662
+ hf_messages =[]
663
+ for msg in history:
664
+ role = "assistant" if msg["role"] == "model" else "user"
665
+ content_parts =[]
666
+ for part in msg["parts"]:
667
+ if "text" in part:
668
+ content_parts.append({"type": "text", "text": part["text"]})
669
+ elif "inlineData" in part:
670
+ mime_t = part["inlineData"]["mimeType"]
671
+ b64_d = part["inlineData"]["data"]
672
+ if mime_t.startswith('image/'):
673
+ content_parts.append({
674
+ "type": "image_url",
675
+ "image_url": {"url": f"data:{mime_t};base64,{b64_d}"}
676
+ })
677
+ if content_parts:
678
+ hf_messages.append({"role": role, "content": content_parts})
679
+
680
+ keys_to_try_hf = HF_TOKENS.copy()
681
+ random.shuffle(keys_to_try_hf)
682
+
683
+ async with aiohttp.ClientSession() as session:
684
+ for hf_key in keys_to_try_hf:
685
+ url = "https://router.huggingface.co/v1/chat/completions"
686
+ headers = {"Authorization": f"Bearer {hf_key}", "Content-Type": "application/json"}
687
+ payload = {
688
+ "model": "google/gemma-4-31B-it:novita",
689
+ "messages": hf_messages,
690
+ "max_tokens": 4096
691
+ }
692
+ try:
693
+ async with session.post(url, headers=headers, json=payload, timeout=60) as response:
694
+ if response.status == 200:
695
+ data = await response.json()
696
+ final_answer = data["choices"][0]["message"]["content"]
697
+ break
698
+ except Exception:
699
+ continue
700
 
701
  try:
702
  if proc_msg:
 
707
 
708
  if not final_answer:
709
  if history and history[-1]["role"] == "user": history.pop()
710
+ await send_with_keyboard(client, chat_id, "❌ تمامی سرورها شلوغ هستند. لطفاً بعداً امتحان کنید.", False)
711
  return
712
 
713
  if not creds.get("is_premium"):
 
740
  await send_with_keyboard(client, chat_id, "❌ خطایی در ارسال پیام رخ داد.", False)
741
 
742
 
743
+ async def process_image(client, chat_id, prompt, size_choice="1"):
744
  str_chat_id = str(chat_id).replace("`", "").replace("'", "").replace('"', "").strip()
745
  creds = get_user_credits(str_chat_id)
746
  if creds["image"] <= 0:
 
794
  if msg_id: await client.delete_messages(chat_id,[msg_id])
795
  except Exception: pass
796
 
797
+ # تنظیم ابعاد انتخابی کاربر
798
+ w, h = 1024, 1024
799
+ size_name = "مربع (1:1) ⬛"
800
+ if size_choice == "2":
801
+ w, h = 768, 1344
802
+ size_name = "عمودی (9:16) 📱"
803
+ elif size_choice == "3":
804
+ w, h = 1344, 768
805
+ size_name = "افقی (16:9) 🖥️"
806
+ elif size_choice == "4":
807
+ w, h = 1024, 768
808
+ size_name = "استاندارد (4:3) 📸"
809
+
810
  short_preview = enhanced_prompt[:150] + "..." if len(enhanced_prompt) > 150 else enhanced_prompt
811
+ proc_msg = await send_with_keyboard(client, chat_id, f"🎨 در حال طراحی عکس...\n\n📏 **ابعاد:** {size_name}\n📝 **پرامپت ساخته شده:**\n`{short_preview}`\n\n(ممکن است چند ثانیه زمان ببرد)", False)
812
 
813
  keys_to_try = HF_TOKENS.copy()
814
  random.shuffle(keys_to_try)
 
818
  for token in keys_to_try:
819
  try:
820
  hf_client = AsyncInferenceClient(provider="fal-ai", api_key=token)
821
+ generated_image = await hf_client.text_to_image(
822
+ enhanced_prompt,
823
+ model="Tongyi-MAI/Z-Image-Turbo",
824
+ width=w,
825
+ height=h
826
+ )
827
  break
828
  except Exception as e:
829
  last_error_log = str(e)
 
843
 
844
  try:
845
  file_name = f"image_{uuid.uuid4().hex}.jpg"
846
+ # استفاده از ترد برای جلوگیری از مسدود شدن برنامه حین کار با PIL
847
+ await asyncio.to_thread(sync_save_image, generated_image, file_name)
848
  await asyncio.sleep(1)
849
+ caption_text = f"🎨 تصویر شما با پرامپت هوشمند آماده شد!\n\n📏 ابعاد تصویر: {size_name}\n✨ ایده اولیه: {prompt}"
850
  upload_result = await helper_upload_file(client, chat_id, file_name, "Image", caption_text)
851
  if upload_result is not True: await send_with_keyboard(client, chat_id, f"❌ خطا در آپلود روبیکا:\n`{str(upload_result)[:800]}`", True)
852
  if os.path.exists(file_name): os.remove(file_name)
 
935
 
936
  try:
937
  file_name = f"edited_flux_{uuid.uuid4().hex}.jpg"
938
+ # استفاده از ترد برای ذخیره عکس
939
+ await asyncio.to_thread(sync_save_image, generated_image, file_name)
940
  await asyncio.sleep(1)
941
  caption_text = f"🪄 ویرایش عکس با هوش مصنوعی Flux.2 انجام شد!\n\n✨ تغییرات خواسته شده: {prompt}\n🔤 متن ارسال شده به هوش: {translated_prompt}"
942
  upload_result = await helper_upload_file(client, chat_id, file_name, "Image", caption_text)
 
989
 
990
  file_name_mp3 = f"audio_{uuid.uuid4().hex}.mp3"
991
 
992
+ # ذخیره فایل در ترد جداگانه
993
+ await asyncio.to_thread(sync_write_file, file_name_mp3, audio_bytes)
994
 
995
  await asyncio.sleep(1)
996
  upload_result_file = await helper_upload_file(client, chat_id, file_name_mp3, "File", "✅ صدای شما با موفقیت آماده شد (فایل MP3):")
 
1068
  if not chunk_audio_bytes: return await send_with_keyboard(client, chat_id, f"❌ خطا در تولید صدای بخش {index+1} از سرور. عملیات متوقف شد.", True)
1069
 
1070
  try:
1071
+ # جلوگیری از گیر کردن لوپ در هنگام ترکیب فایل‌های صوتی سنگین
1072
+ combined_audio = await asyncio.to_thread(sync_combine_audio, combined_audio, chunk_audio_bytes)
1073
  except Exception as e: return await send_with_keyboard(client, chat_id, f"❌ خطا در پردازش صدا (آیا pydub و ffmpeg نصب است؟):\n{str(e)}", True)
1074
 
1075
  if not creds.get("is_premium"):
 
1077
  save_db(user_credits_db)
1078
 
1079
  file_name_mp3 = f"final_podcast_{uuid.uuid4().hex}.mp3"
1080
+ # اکسپورت فایل صوتی در ترد جدا
1081
+ await asyncio.to_thread(sync_export_audio, combined_audio, file_name_mp3)
1082
 
1083
  try:
1084
  if proc_msg:
 
1152
  proc_msg = await send_with_keyboard(client, chat_id, "👁️ در حال تحلیل فایل...", False)
1153
  base64_data = base64.b64encode(file_bytes).decode('utf-8')
1154
  mime_type, _ = mimetypes.guess_type(file_name)
1155
+ if not mime_type:
1156
+ if file_name.endswith(('.jpg', '.jpeg')): mime_type = "image/jpeg"
1157
+ elif file_name.endswith('.png'): mime_type = "image/png"
1158
+ elif file_name.endswith('.pdf'): mime_type = "application/pdf"
1159
+ elif file_name.endswith('.mp4'): mime_type = "video/mp4"
1160
+ elif file_name.endswith('.mp3'): mime_type = "audio/mp3"
1161
+ elif file_name.endswith(('.ogg', '.oga')): mime_type = "audio/ogg"
1162
+ elif file_name.endswith('.wav'): mime_type = "audio/wav"
1163
+ else: mime_type = "image/jpeg"
1164
+
1165
+ is_image = mime_type.startswith('image/')
1166
 
1167
  keys_to_try = get_next_gemini_keys(100)
1168
  final_answer = None
 
1179
  break
1180
  except Exception: continue
1181
 
1182
+ # جایگزین تصویر اگر جیمینای جواب نداد
1183
+ if not final_answer:
1184
+ if is_image and HF_TOKENS:
1185
+ keys_to_try_hf = HF_TOKENS.copy()
1186
+ random.shuffle(keys_to_try_hf)
1187
+
1188
+ hf_messages =[
1189
+ {
1190
+ "role": "user",
1191
+ "content":[
1192
+ {"type": "text", "text": prompt},
1193
+ {
1194
+ "type": "image_url",
1195
+ "image_url": {"url": f"data:{mime_type};base64,{base64_data}"}
1196
+ }
1197
+ ]
1198
+ }
1199
+ ]
1200
+
1201
+ async with aiohttp.ClientSession() as session:
1202
+ for hf_key in keys_to_try_hf:
1203
+ url = "https://router.huggingface.co/v1/chat/completions"
1204
+ headers = {"Authorization": f"Bearer {hf_key}", "Content-Type": "application/json"}
1205
+ payload = {
1206
+ "model": "google/gemma-4-31B-it:novita",
1207
+ "messages": hf_messages,
1208
+ "max_tokens": 4096
1209
+ }
1210
+ try:
1211
+ async with session.post(url, headers=headers, json=payload, timeout=60) as response:
1212
+ if response.status == 200:
1213
+ data = await response.json()
1214
+ final_answer = data["choices"][0]["message"]["content"]
1215
+ break
1216
+ except Exception:
1217
+ continue
1218
+
1219
  try:
1220
  if proc_msg:
1221
  msg_id = getattr(proc_msg, 'message_id', None)
 
1229
  save_db(user_credits_db)
1230
  await send_with_keyboard(client, chat_id, f"💡 **نتیجه تحلیل:**\n\n{final_answer}", True)
1231
  else:
1232
+ if not is_image:
1233
+ await send_with_keyboard(client, chat_id, "❌ متأسفانه سرور اصلی در حال حاضر شلوغ است و در این شرایط **فعلاً تنها امکان تحلیل تصاویر** توسط سرور جایگزین در دسترس است.", True)
1234
+ else:
1235
+ await send_with_keyboard(client, chat_id, "❌ تمامی سرورها شلوغ هستند. لطفاً بعداً امتحان کنید.", True)
1236
 
1237
 
1238
  async def process_create_file(client, chat_id, topic):
 
1253
  async with aiohttp.ClientSession() as session:
1254
  for key in keys_to_try:
1255
  url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={key}"
1256
+ payload = {"contents":[{"parts":[{"text": ai_prompt}]}], "generationConfig": {"temperature": 0.7, "maxOutputTokens": 8192}}
1257
  try:
1258
  async with session.post(url, json=payload, timeout=60) as response:
1259
  if response.status == 200:
 
1292
  if msg_id: await client.delete_messages(chat_id,[msg_id])
1293
  except Exception: pass
1294
 
 
 
 
 
1295
  converter_url = "https://opera8-texttopdf.hf.space/"
1296
+ uid = uuid.uuid4().hex
1297
+
1298
+ # پیام اطلاع رسانی قبل از ساخت فایل‌ها
1299
+ proc_msg = await send_with_keyboard(client, chat_id, "📄 مقاله با موفقیت نوشته شد!\n\n⏳ در حال ارتباط همزمان با هوش مصنوعی برای دریافت فایل‌های PDF و Word...\n", False)
1300
 
1301
+ # تابع کمکی برای درخواست همزمان به سرور
1302
+ async def fetch_document(fmt):
1303
+ for attempt in range(3):
1304
+ try:
1305
+ async with aiohttp.ClientSession() as session:
1306
+ form_data = aiohttp.FormData()
1307
+ form_data.add_field('content', article_text)
1308
+ form_data.add_field('format', fmt)
1309
+ # تایم‌اوت 180 ثانیه برای فرصت کافی به Weasyprint
1310
+ async with session.post(converter_url, data=form_data, timeout=180) as resp:
1311
+ if resp.status == 200:
1312
+ data = await resp.read()
1313
+ if data and len(data) > 0:
1314
+ return data
1315
+ except Exception:
1316
+ pass
1317
+ await asyncio.sleep(2)
1318
+ return None
1319
+
1320
+ # اجرای همزمان هر دو درخواست برای سرعت بیشتر و جلوگیری از تایم‌اوت متوالی
1321
+ pdf_bytes, docx_bytes = await asyncio.gather(
1322
+ fetch_document('pdf'),
1323
+ fetch_document('docx')
1324
+ )
1325
+
1326
  try:
1327
  if proc_msg:
1328
  msg_id = getattr(proc_msg, 'message_id', None)
 
1330
  if msg_id: await client.delete_messages(chat_id, [msg_id])
1331
  except Exception: pass
1332
 
1333
+ # --- آپلود فایل‌ها در روبیکا ---
1334
+ uploaded_pdf = False
1335
+ uploaded_docx = False
 
 
 
 
 
 
 
 
 
1336
 
1337
  if pdf_bytes:
1338
+ pdf_filename = f"Article_{uid}.pdf"
1339
+ await asyncio.to_thread(sync_write_file, pdf_filename, pdf_bytes)
1340
  res = await helper_upload_file(client, chat_id, pdf_filename, "File", f"📄 فایل PDF مقاله شما:\n\n💡 موضوع: {topic}")
1341
+ if res is True:
1342
+ uploaded_pdf = True
1343
+ if os.path.exists(pdf_filename):
1344
+ os.remove(pdf_filename)
1345
+
1346
+ await asyncio.sleep(1.5)
1347
 
1348
  if docx_bytes:
1349
+ docx_filename = f"Article_{uid}.docx"
1350
+ await asyncio.to_thread(sync_write_file, docx_filename, docx_bytes)
1351
  res = await helper_upload_file(client, chat_id, docx_filename, "File", f"📝 فایل Word (DOCX) مقاله ��ما:\n\n💡 موضوع: {topic}")
1352
+ if res is True:
1353
+ uploaded_docx = True
1354
+ if os.path.exists(docx_filename):
1355
+ os.remove(docx_filename)
1356
 
1357
+ if not creds.get("is_premium"):
1358
+ user_credits_db[str_chat_id]["chat"] -= 1
1359
+ save_db(user_credits_db)
1360
+
1361
+ if uploaded_pdf and uploaded_docx:
1362
+ await send_with_keyboard(client, chat_id, "✅ هر دو فایل (PDF و Word) مقاله شما با موفقیت تحویل داده شد!", True)
1363
+ elif uploaded_pdf or uploaded_docx:
1364
+ await send_with_keyboard(client, chat_id, "⚠️ یکی از فایل‌ها با موفقیت ارسال شد، اما در ساخت یا ارسال فایل دیگر مشکلی از سمت سرور پیش آمد.", True)
1365
  else:
1366
+ await send_with_keyboard(client, chat_id, "❌ فایل‌ها ساخته شدند اما متأسفانه روبیکا در ارسال آن‌ها دچار مشکل شد.", True)
1367
 
1368
 
1369
  if not bot_token:
 
1507
  expire_txt = f"{jy:04d}/{jm:02d}/{jd:02d}"
1508
  status_text = f"🌟 نسخه پرو (ویژه)\n📅 انقضا: {expire_txt}\n⏳ باقیمانده: {days_left} روز"
1509
  else:
1510
+ status_text = "🥉 نسخه رایگان (آزمایشی)\n⏳ وضعیت: سهمیه روزانه محدود"
1511
 
1512
  chat_rem = "نامحدود ∞" if is_prem else t_creds.get('chat', 0)
1513
  podcast_rem = "نامحدود ∞" if is_prem else t_creds.get('podcast', 0)
 
1517
  image_rem = t_creds.get('image', 0)
1518
  edit_image_rem = t_creds.get('edit_image', 0)
1519
  invs = t_creds.get('invited_count', 0)
1520
+ joined_status = "بله ✅" if t_creds.get('has_joined') else "خیر ❌"
1521
 
1522
+ info_msg = f"""🔍 **اطلاعات اختصاصی کاربر:**
1523
+ 👤 شناسه: `{target_id}`
1524
+ عضو کانال: {joined_status}
1525
 
1526
+ 🔹 **وضعیت اشتراک:**
1527
+ {status_text}
1528
  🎁 **تعداد افراد دعوت شده:** {invs} نفر
1529
 
1530
+ 📊 **سهمیه باقی‌مانده فعلی:**
1531
+ 💬 چت: {chat_rem}
1532
+ 🎨 تولید عکس: {image_rem}
1533
+ 🪄 ویرایش عکس: {edit_image_rem}
1534
+ 🎙 پادکست: {podcast_rem}
1535
+ 🗣 متن به صدا: {tts_rem}
1536
+ 📁 تحلیل فایل: {file_rem}
1537
+ 📝 صدا به متن: {stt_rem}"""
1538
  await send_with_keyboard(client, chat_id, info_msg, False)
1539
  else:
1540
+ await send_with_keyboard(client, chat_id, f"❌ کاربری با شناسه `{target_id}` در دیتابیس ربات یافت نشد.", False)
1541
  return
1542
 
1543
  is_file = False
 
1723
  🔑 **شناسه یکتای شما:** `{chat_id}`
1724
 
1725
  👨‍💻 **ارتباط با پشتیبانی:**
1726
+ 🆔 @aialpha_admin"""
1727
  await send_with_keyboard(client, chat_id, buy_text, True)
1728
  return
1729
 
 
1737
  🔑 **شناسه یکتای ربات شما:** `{chat_id}`
1738
 
1739
  👨‍💻 **دقت کنید شناسه ربات رو به پشتیبانی داخل خود برنامه هوش مصنوعی آلفا ارسال کنید:**
1740
+ 🤖"""
1741
  await send_with_keyboard(client, chat_id, transfer_text, True)
1742
  return
1743
 
 
1749
 
1750
  if user_text_str in["/image", "🎨 عکس", "ساخت تصاویر🎨"]:
1751
  user_states[str_chat_id]["mode"] = "image_waiting_for_text"
1752
+ await send_with_keyboard(client, chat_id, "🎨 شما وارد بخش **ساخت عکس پیشرفته** شدید.\n\nمتن (ایده) خود را به صورت کامل ارسال کنید:\n(برای خروج دکمه «برگشت♻️» را بزنید)", True)
1753
  return
1754
 
1755
  if user_text_str in["/edit_image", "ویرایش تصاویر 🪄"]:
 
1874
  elif user_text_str: asyncio.create_task(process_gemini(client, chat_id, user_text_str))
1875
  return
1876
 
1877
+ # ===============================================
1878
+ # آپدیت جدید: دریافت سایز قبل از ساخت عکس
1879
+ # ===============================================
1880
  elif current_mode == "image_waiting_for_text":
1881
+ if user_text_str:
1882
+ user_states[str_chat_id]["text"] = user_text_str
1883
+ user_states[str_chat_id]["mode"] = "image_waiting_for_size"
1884
+
1885
+ size_menu = """🖼 **لطفاً ابعاد تصویر خود را انتخاب کنید:**
1886
+
1887
+ 1️⃣ `1:1` (مربع) - مناسب پروفایل ⬛
1888
+ 2️⃣ `9:16` (عمودی) - مناسب استوری و پس‌زمینه گوشی 📱
1889
+ 3️⃣ `16:9` (افقی) - مناسب دسکتاپ و ویدیو 🖥️
1890
+ 4️⃣ `4:3` (استاندارد) - مناسب چاپ و پست 📸
1891
+
1892
+ (لطفاً فقط عدد 1 تا 4 را بفرستید)"""
1893
+ await send_with_keyboard(client, chat_id, size_menu, False)
1894
+ else:
1895
+ await send_with_keyboard(client, chat_id, "⚠️ لطفاً ایده عکس خود را به صورت متنی بفرستید.", False)
1896
+ return
1897
+
1898
+ elif current_mode == "image_waiting_for_size":
1899
+ normalized_choice = to_english_digits(user_text_str).strip()
1900
+ if normalized_choice in["1", "2", "3", "4"]:
1901
+ saved_text = user_states[str_chat_id].get("text", "")
1902
+ user_states[str_chat_id]["mode"] = None
1903
+ asyncio.create_task(process_image(client, chat_id, saved_text, normalized_choice))
1904
+ else:
1905
+ await send_with_keyboard(client, chat_id, "❌ عدد وارد شده نامعتبر است! لطفاً فقط یکی از اعداد 1 تا 4 را بفرستید.", False)
1906
  return
1907
 
1908
  elif current_mode == "image_edit_waiting_for_image":
 
1980
  user_states[str_chat_id]["file_bytes"] = file_bytes
1981
  user_states[str_chat_id]["file_name"] = file_name
1982
  user_states[str_chat_id]["mode"] = "file_waiting_for_prompt"
1983
+ await send_with_keyboard(client, chat_id, "✅ فایل با موفقیت دریافت شد.\n\nحالا لطفاً متنی بگویید **چگونه تحلیل شود؟**\n(می‌توانید سوال خاصی بپرسید یا فقط بخواهید فایل را توضیح دهد)", False)
1984
  except Exception as dl_err: await send_with_keyboard(client, chat_id, f"❌ خطا در دریافت فایل!\n{str(dl_err)}", False)
1985
  return
1986
 
 
2004
 
2005
  if __name__ == "__main__":
2006
  threading.Thread(target=run_flask, daemon=True).start()
2007
+
2008
  if bot_token:
2009
+ # افزایش ظرفیت کارگرهای (Workers) پس‌زمینه در Asyncio برای افزایش شدید سرعت پاسخگویی
2010
+ loop = asyncio.get_event_loop()
2011
+ # تنظیم ترد پول روی 16 کارگر به جای 1 پیش‌فرض که باعث کندی میشد
2012
+ loop.set_default_executor(concurrent.futures.ThreadPoolExecutor(max_workers=16))
2013
+
2014
+ print("ربات آلفا پرو با سیستم اشتراک نامحدود + سپر امنیتی + 16 Worker پس‌زمینه روشن شد...")
2015
  bot.run()