Update app.py
Browse files
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">
|
|
@@ -428,35 +428,93 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
|
|
| 428 |
await page.goto(url, wait_until="networkidle", timeout=45000)
|
| 429 |
await page.wait_for_timeout(3000)
|
| 430 |
|
| 431 |
-
#
|
| 432 |
-
initial_input = await page.query_selector("textarea, input[type='text'], [contenteditable='true']")
|
| 433 |
-
if initial_input:
|
| 434 |
-
await initial_input.click()
|
| 435 |
-
await page.wait_for_timeout(1000)
|
| 436 |
-
|
| 437 |
-
# عملیات تزریق مستقیم فایل به تگ مخفی اینپوت بدون وابستگی به کلیک روی منوها
|
| 438 |
if saved_image_path and os.path.exists(saved_image_path):
|
|
|
|
|
|
|
|
|
|
| 439 |
try:
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 453 |
input_box = None
|
| 454 |
candidates = await page.query_selector_all("textarea, input, [contenteditable='true']")
|
| 455 |
for el in candidates:
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 460 |
|
| 461 |
if not input_box:
|
| 462 |
input_box = await page.query_selector("textarea") or await page.query_selector("input[type='text']")
|
|
@@ -464,28 +522,28 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
|
|
| 464 |
if input_box:
|
| 465 |
await input_box.focus()
|
| 466 |
await input_box.fill(message)
|
| 467 |
-
await page.wait_for_timeout(
|
| 468 |
await input_box.press("Enter")
|
| 469 |
|
| 470 |
-
#
|
| 471 |
try:
|
| 472 |
send_buttons = await page.query_selector_all("button, [role='button']")
|
| 473 |
for btn in send_buttons:
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
if
|
| 477 |
-
await btn.click(timeout=
|
| 478 |
break
|
| 479 |
except:
|
| 480 |
pass
|
| 481 |
|
| 482 |
-
# انتظار
|
| 483 |
await page.wait_for_timeout(9000)
|
| 484 |
|
| 485 |
full_text = await page.evaluate("() => document.body.innerText")
|
| 486 |
await browser.close()
|
| 487 |
|
| 488 |
-
# فیلترسازی و تمیز کردن
|
| 489 |
lines = full_text.split('\n')
|
| 490 |
cleaned_lines = []
|
| 491 |
skip_headers = ["تصاویر", "ویدیوها", "اخبار", "نقشهها", "خرید کردن", "کتابها", "مالی", "حالت موضوعمحور", "ورود"]
|
|
@@ -509,6 +567,7 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
|
|
| 509 |
await browser.close()
|
| 510 |
raise HTTPException(status_code=500, detail=f"خطا در رندر سرور هوش مصنوعی: {str(e)}")
|
| 511 |
finally:
|
|
|
|
| 512 |
if saved_image_path and os.path.exists(saved_image_path):
|
| 513 |
try:
|
| 514 |
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">
|
|
|
|
| 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 |
|
| 519 |
if not input_box:
|
| 520 |
input_box = await page.query_selector("textarea") or await page.query_selector("input[type='text']")
|
|
|
|
| 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 = ["تصاویر", "ویدیوها", "اخبار", "نقشهها", "خرید کردن", "کتابها", "مالی", "حالت موضوعمحور", "ورود"]
|
|
|
|
| 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)
|