Opera8 commited on
Commit
30181ae
·
verified ·
1 Parent(s): c996b12

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -87
app.py CHANGED
@@ -10,7 +10,7 @@ app = FastAPI()
10
  UPLOAD_DIR = "temp_uploads"
11
  os.makedirs(UPLOAD_DIR, exist_ok=True)
12
 
13
- # لایه فرانت‌اند چت‌باکس فوتوریستی با استایل شیشه‌ای (Glassmorphism)
14
  HTML_CHAT_INTERFACE = """
15
  <!DOCTYPE html>
16
  <html lang="fa" dir="rtl">
@@ -425,94 +425,56 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
425
  )
426
 
427
  page = await context.new_page()
428
- await page.goto(url, wait_until="networkidle", timeout=45000)
429
- await page.wait_for_timeout(3000)
430
 
431
- # پروسه مالتی‌مدال و انتقال تصویر با ضریب ایمنی بالا و گام‌های مستقل خطا‌پذیر
 
 
 
 
 
 
432
  if saved_image_path and os.path.exists(saved_image_path):
433
  uploaded = False
434
-
435
- # استراتژی ۱: تلاش برای تزریق مستقیم به لایه بارگذاری فایل (بدون نیاز به کلیک و باز کردن منو)
436
  try:
437
  file_input = await page.query_selector("input[type='file']")
438
  if file_input:
439
  await file_input.set_input_files(saved_image_path)
440
- await page.wait_for_timeout(3000)
441
  uploaded = True
442
- print("Direct file input injection succeeded.")
443
  except Exception as e:
444
- print(f"Direct injection bypassed: {e}")
445
 
446
- # استراتژی ۲: اگر تزریق مستقیم عمل نکرد، کلیک روی آیکون پلاس با تایم‌اوت کوتاه و باز کردن منوی گالری
447
  if not uploaded:
448
  try:
449
- # فوکوس روی کادر چت با تایم‌اوت ۲ ثانیه‌ای برای باز شدن ابزارهای کناری
450
- chat_inputs = await page.query_selector_all("textarea, input[type='text'], [contenteditable='true']")
451
- for inp in chat_inputs:
452
- try:
453
- if await inp.is_visible():
454
- await inp.click(timeout=2000)
455
- await page.wait_for_timeout(500)
456
- break
457
- except:
458
- continue
459
-
460
- # پیدا کردن آیکون مثبت یا دوربین و فعال‌سازی شبیه‌ساز فایل چوزر
461
- elements = await page.query_selector_all("button, div[role='button'], svg, [aria-label]")
462
  for el in elements:
463
  try:
464
- if await el.is_visible():
465
- aria = (await el.get_attribute("aria-label") or "").lower()
466
- html = (await el.inner_html() or "").lower()
467
- text = (await el.inner_text() or "").lower()
468
- combined = aria + html + text
469
-
470
- if any(k in combined for k in ["+", "plus", "camera", "lens", "دوربین", "تصویر", "عکس"]):
471
- async with page.expect_file_chooser(timeout=3000) as fc_info:
472
- await el.click(timeout=2000) # تایم‌اوت امن ۲ ثانیه‌ای به جای ۳۰ ثانیه معطلی
473
- file_chooser = await fc_info.value
474
- await file_chooser.set_files(saved_image_path)
475
- await page.wait_for_timeout(3000)
476
- uploaded = True
477
- print("Uploaded via main UI icon trigger.")
478
- break
479
- except:
480
- continue
481
- except Exception as e:
482
- print(f"UI icon flow failed: {e}")
483
-
484
- # استراتژی ۳: کلیک مستقیم روی منوی پاپ‌آپ پایینی (گالری یا فایل‌ها) در صورت باز شدن لایه شیت گوگل
485
- if not uploaded:
486
- try:
487
- menu_items = await page.query_selector_all("div, span, button, p")
488
- for item in menu_items:
489
- try:
490
- item_text = (await item.inner_text() or "").strip()
491
- if item_text in ["گالری", "فایل‌ها", "Gallery", "Files"]:
492
- if await item.is_visible():
493
- async with page.expect_file_chooser(timeout=3000) as fc_info:
494
- await item.click(timeout=2000)
495
- file_chooser = await fc_info.value
496
- await file_chooser.set_files(saved_image_path)
497
- await page.wait_for_timeout(3000)
498
- uploaded = True
499
- print("Uploaded via bottom sheet item click.")
500
- break
501
  except:
502
  continue
503
  except Exception as e:
504
- print(f"Bottom sheet workflow failed: {e}")
505
 
506
- # یافتن کادر متنی گفتگو جهت وارد کردن متن پیام کاربر
507
  input_box = None
508
  candidates = await page.query_selector_all("textarea, input, [contenteditable='true']")
509
  for el in candidates:
510
  try:
511
- if await el.is_visible():
512
- placeholder = await el.get_attribute("placeholder") or ""
513
- if any(w in placeholder for w in ["بپرسید", "ask", "پیام", "چطور", "هرچه"]):
514
- input_box = el
515
- break
516
  except:
517
  continue
518
 
@@ -522,40 +484,56 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
522
  if input_box:
523
  await input_box.focus()
524
  await input_box.fill(message)
525
- await page.wait_for_timeout(500)
526
  await input_box.press("Enter")
527
-
528
- # کلیک بر روی آیکون ارسال فرم (فلش آبی بالا) با استفاده از زمان‌بندی محدود ۲ ثانیه‌ای
529
- try:
530
- send_buttons = await page.query_selector_all("button, [role='button']")
531
- for btn in send_buttons:
532
- if await btn.is_visible():
533
- aria = (await btn.get_attribute("aria-label") or "").lower()
534
- if any(w in aria for w in ["send", "ارسال", "arrow", "up"]):
535
- await btn.click(timeout=2000)
536
- break
537
- except:
538
- pass
539
 
540
- # انتظار تعمدی به مدت ۹ ثانیه جهت تایپ کامل جواب توسط هوش مصنوعی گوگل
541
- await page.wait_for_timeout(9000)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
 
543
  full_text = await page.evaluate("() => document.body.innerText")
544
  await browser.close()
545
 
546
- # فیلترسازی خطوط خروجی برای تمیز کردن تگ‌های اضافی سرچ گوگل
547
  lines = full_text.split('\n')
548
  cleaned_lines = []
549
- skip_headers = ["تصاویر", "ویدیوها", "اخبار", "نقشه‌ها", "خرید کردن", "کتاب‌ها", "مالی", "حالت موضوع‌محور", "ورود"]
 
 
 
 
 
550
 
551
  for line in lines:
552
  line_str = line.strip()
553
  if not line_str:
554
  continue
555
- if any(header in line_str for header in skip_headers):
 
 
556
  continue
557
- if "در پاسخ‌های" in line_str or "بیشتر بدانید" in line_str:
 
 
 
 
 
558
  continue
 
559
  cleaned_lines.append(line_str)
560
 
561
  ai_response = "\n".join(cleaned_lines)
@@ -567,7 +545,6 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
567
  await browser.close()
568
  raise HTTPException(status_code=500, detail=f"خطا در رندر سرور هوش مصنوعی: {str(e)}")
569
  finally:
570
- # پاکسازی حتمی فایل تصویر از روی سرور داکر
571
  if saved_image_path and os.path.exists(saved_image_path):
572
  try:
573
  os.remove(saved_image_path)
 
10
  UPLOAD_DIR = "temp_uploads"
11
  os.makedirs(UPLOAD_DIR, exist_ok=True)
12
 
13
+ # لایه فرانت‌اند چت‌باکس با استایل شیشه‌ای (Glassmorphism)
14
  HTML_CHAT_INTERFACE = """
15
  <!DOCTYPE html>
16
  <html lang="fa" dir="rtl">
 
425
  )
426
 
427
  page = await context.new_page()
428
+ # لود اولیه سبک domcontentloaded به جای networkidle جهت افزایش سرعت
429
+ await page.goto(url, wait_until="domcontentloaded", timeout=30000)
430
 
431
+ # پیدا کردن کادر متن فرم برای آمادگی تزریق
432
+ try:
433
+ await page.wait_for_selector("textarea, input[type='text']", timeout=4000)
434
+ except:
435
+ pass
436
+
437
+ # پروسه مالتی‌مدال خطا‌پذیر بدون قفل شدن مرورگر
438
  if saved_image_path and os.path.exists(saved_image_path):
439
  uploaded = False
 
 
440
  try:
441
  file_input = await page.query_selector("input[type='file']")
442
  if file_input:
443
  await file_input.set_input_files(saved_image_path)
444
+ await page.wait_for_timeout(1500) # زمان کوتاه فقط برای متصل شدن فایل به فرم گوگل
445
  uploaded = True
 
446
  except Exception as e:
447
+ print(f"Direct injection warning: {e}")
448
 
 
449
  if not uploaded:
450
  try:
451
+ elements = await page.query_selector_all("button, div[role='button'], svg")
 
 
 
 
 
 
 
 
 
 
 
 
452
  for el in elements:
453
  try:
454
+ aria = (await el.get_attribute("aria-label") or "").lower()
455
+ html = (await el.inner_html() or "").lower()
456
+ combined = aria + html
457
+ if any(k in combined for k in ["+", "plus", "camera", "lens", "دوربین", "تصویر"]):
458
+ async with page.expect_file_chooser(timeout=2000) as fc_info:
459
+ await el.click(timeout=1500)
460
+ file_chooser = await fc_info.value
461
+ await file_chooser.set_files(saved_image_path)
462
+ await page.wait_for_timeout(1500)
463
+ break
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
464
  except:
465
  continue
466
  except Exception as e:
467
+ print(f"UI upload sequence warning: {e}")
468
 
469
+ # درج و ارسال نهایی پیام کاربر
470
  input_box = None
471
  candidates = await page.query_selector_all("textarea, input, [contenteditable='true']")
472
  for el in candidates:
473
  try:
474
+ placeholder = await el.get_attribute("placeholder") or ""
475
+ if any(w in placeholder for w in ["بپرسید", "ask", "پیام", "چطور", "هرچه"]):
476
+ input_box = el
477
+ break
 
478
  except:
479
  continue
480
 
 
484
  if input_box:
485
  await input_box.focus()
486
  await input_box.fill(message)
487
+ await page.wait_for_timeout(300)
488
  await input_box.press("Enter")
 
 
 
 
 
 
 
 
 
 
 
 
489
 
490
+ # 🚀 الگوریتم پایش داینامیک قد کشیدن متن (حذف ۹ ثانیه خواب اجباری)
491
+ await page.wait_for_timeout(2500) # مهلت اولیه برای استارت خوردن استریم جواب توسط گوگل
492
+
493
+ last_len = 0
494
+ stable_count = 0
495
+ for _ in range(20): # حداکثر ۱۰ ثانیه تلاش مجدد در گام‌های ۵۰۰ میلی‌ثانیه‌ای
496
+ current_text = await page.evaluate("() => document.body.innerText")
497
+ current_len = len(current_text or "")
498
+
499
+ if current_len == last_len and current_len > 0:
500
+ stable_count += 1
501
+ if stable_count >= 2: # اگر طول متن در ۲ دوره متوالی ثابت ماند، استریم به پایان رسیده است
502
+ break
503
+ else:
504
+ stable_count = 0
505
+ last_len = current_len
506
+ await page.wait_for_timeout(500)
507
 
508
  full_text = await page.evaluate("() => document.body.innerText")
509
  await browser.close()
510
 
511
+ # 🎯 الگوریتم پاکسازی کدهای اضافی و جداسازی پاسخ خالص هوش مصنوعی
512
  lines = full_text.split('\n')
513
  cleaned_lines = []
514
+
515
+ exclude_keywords = [
516
+ "حالت هوشواره‌ای", "ویدئوها", "نقشه‌ها", "اخبار", "تصاویر", "خرید کردن", "کتاب‌ها", "مالی",
517
+ "All items removed from input context", "ارسال", "هرچه می‌خواهید بپرسید", "بیشتر بدانید",
518
+ "اگر امکان دارد آن را به فارسی ایمیل کنید", "پاسخ «حالت هوشواره‌ای» آماده است", "همه"
519
+ ]
520
 
521
  for line in lines:
522
  line_str = line.strip()
523
  if not line_str:
524
  continue
525
+
526
+ # حذف خط اکو شده‌ی خود کلمه سرچ شده کاربر در ابتدای بدنه
527
+ if line_str == message.strip():
528
  continue
529
+
530
+ # نقطه قطع سابمیت: رسیدن به دکمه‌های لایک/دیس‌لایک یا کادر کپی‌رایت انتهای چت گوگل
531
+ if any(stop_word in line_str for stop_word in ["در پاسخ‌های هوشواره", "هوشواره ممکن است اشتباه", "پاسخ‌های مربوط به افراد"]):
532
+ break
533
+
534
+ if any(ex in line_str for ex in exclude_keywords):
535
  continue
536
+
537
  cleaned_lines.append(line_str)
538
 
539
  ai_response = "\n".join(cleaned_lines)
 
545
  await browser.close()
546
  raise HTTPException(status_code=500, detail=f"خطا در رندر سرور هوش مصنوعی: {str(e)}")
547
  finally:
 
548
  if saved_image_path and os.path.exists(saved_image_path):
549
  try:
550
  os.remove(saved_image_path)