Update app.py
Browse files
app.py
CHANGED
|
@@ -17,7 +17,7 @@ HTML_CHAT_INTERFACE = """
|
|
| 17 |
<head>
|
| 18 |
<meta charset="UTF-8">
|
| 19 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 20 |
-
<title>Google AI Free Chatbot +
|
| 21 |
<style>
|
| 22 |
:root {
|
| 23 |
--bg-gradient: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
|
@@ -153,7 +153,7 @@ HTML_CHAT_INTERFACE = """
|
|
| 153 |
try {
|
| 154 |
const response = await fetch('/api/chat', { method: 'POST', body: formData });
|
| 155 |
if (!response.ok) {
|
| 156 |
-
aiMessageDiv.innerText = "خطا در ارتباط با گوگل یا مسدود شدن آیپ
|
| 157 |
setLoading(false);
|
| 158 |
return;
|
| 159 |
}
|
|
@@ -210,37 +210,40 @@ HTML_CHAT_INTERFACE = """
|
|
| 210 |
</html>
|
| 211 |
"""
|
| 212 |
|
| 213 |
-
# الگوریتم فی
|
| 214 |
def clean_text(full_text: str, message: str) -> str:
|
| 215 |
if "ترافیک غیر عادی" in full_text or "Our systems have detected unusual traffic" in full_text:
|
| 216 |
return "🚨 سیستم امنیتی گوگل فعال شد و آیپی سرور هاگینگفیس را مسدود کرد (کپچا رخ داد)."
|
| 217 |
|
| 218 |
lines = full_text.split('\n')
|
| 219 |
|
| 220 |
-
# کلمات کلیدی
|
| 221 |
junk_keywords = [
|
| 222 |
"حالت هوشواره", "هوژواره", "ایمیل کنید", "تصاویر", "ویدیو", "ویدئو", "اخبار",
|
| 223 |
"نقشه", "خرید", "کتاب", "مالی", "موضوعمحور", "ورود", "ارسال", "همه",
|
| 224 |
-
"آماده است", "items removed", "بیشتر بدانید", "محتمل است", "هویشواره", "هرچه میخواهید"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
]
|
| 226 |
|
| 227 |
-
# فاز
|
| 228 |
filtered_lines = []
|
| 229 |
for line in lines:
|
| 230 |
line_str = line.strip()
|
| 231 |
if not line_str:
|
| 232 |
continue
|
| 233 |
-
if "هوشواره ممکن است اشتباه" in line_str or "در پاسخهای" in line_str or "بیشتر بدانید" in line_str:
|
| 234 |
break
|
| 235 |
if any(junk in line_str for junk in junk_keywords):
|
| 236 |
continue
|
| 237 |
filtered_lines.append(line_str)
|
| 238 |
|
| 239 |
-
# فاز
|
| 240 |
final_lines = []
|
| 241 |
found_query_anchor = False
|
| 242 |
for line in filtered_lines:
|
| 243 |
-
# اگر خط جاری شامل یا بخشی از پیام کاربر بود، کل دیتای فیلتر شده قبلی (هدرها) را پاک کن
|
| 244 |
if not found_query_anchor and (message.lower() in line.lower() or line.lower() in message.lower()):
|
| 245 |
found_query_anchor = True
|
| 246 |
final_lines = []
|
|
@@ -267,7 +270,6 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
|
|
| 267 |
except Exception as e:
|
| 268 |
return StreamingResponse(iter([f"خطا در ذخیره تصویر روی داکر: {str(e)}"]), media_type="text/plain")
|
| 269 |
|
| 270 |
-
# امضای استریم کلمه به کلمه زنده کلاینت
|
| 271 |
async def response_generator():
|
| 272 |
async with async_playwright() as p:
|
| 273 |
browser = await p.chromium.launch(
|
|
@@ -294,44 +296,44 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
|
|
| 294 |
page = await context.new_page()
|
| 295 |
|
| 296 |
try:
|
| 297 |
-
#
|
| 298 |
if saved_image_path and os.path.exists(saved_image_path):
|
| 299 |
-
# اگر تصویر وجود دارد: ابتدا لود کردن
|
| 300 |
-
print("🖼 روند آپلود و تحلیل تصویر مالتیمدال فعال شد.")
|
| 301 |
await page.goto("https://www.google.com/search?q=سلام&udm=50", wait_until="domcontentloaded", timeout=30000)
|
| 302 |
await page.wait_for_timeout(1000)
|
| 303 |
|
| 304 |
-
#
|
| 305 |
init_input = await page.query_selector("textarea, input[type='text'], [contenteditable='true']")
|
| 306 |
if init_input:
|
| 307 |
-
await init_input.click()
|
| 308 |
await page.wait_for_timeout(500)
|
| 309 |
-
|
| 310 |
-
#
|
| 311 |
file_input = await page.query_selector("input[type='file']")
|
| 312 |
if file_input:
|
| 313 |
await file_input.set_input_files(saved_image_path)
|
| 314 |
-
|
|
|
|
|
|
|
| 315 |
|
| 316 |
-
# نوشتن
|
| 317 |
input_box = await page.query_selector("textarea, input[type='text'], [contenteditable='true']")
|
| 318 |
if input_box:
|
| 319 |
await input_box.focus()
|
| 320 |
await input_box.fill(message)
|
| 321 |
-
await page.wait_for_timeout(
|
| 322 |
await input_box.press("Enter")
|
| 323 |
else:
|
| 324 |
-
# اگر فقط متن است: لود
|
| 325 |
-
print("📝 روند لود مستقیم کوئری متنی فعال شد.")
|
| 326 |
url = f"https://www.google.com/search?q={message}&udm=50"
|
| 327 |
await page.goto(url, wait_until="domcontentloaded", timeout=30000)
|
| 328 |
|
| 329 |
-
# ⚡
|
| 330 |
last_sent_text = ""
|
| 331 |
no_change_count = 0
|
| 332 |
|
| 333 |
for _ in range(50):
|
| 334 |
-
await page.wait_for_timeout(300)
|
| 335 |
full_text = await page.evaluate("() => document.body.innerText")
|
| 336 |
current_clean_text = clean_text(full_text, message)
|
| 337 |
|
|
@@ -339,7 +341,7 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
|
|
| 339 |
yield current_clean_text
|
| 340 |
break
|
| 341 |
|
| 342 |
-
#
|
| 343 |
if len(current_clean_text) > len(last_sent_text):
|
| 344 |
new_chunk = current_clean_text[len(last_sent_text):]
|
| 345 |
yield new_chunk
|
|
@@ -349,7 +351,6 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
|
|
| 349 |
if len(current_clean_text) > 0:
|
| 350 |
no_change_count += 1
|
| 351 |
|
| 352 |
-
# اگر تایپ هوش مصنوعی تمام شد، استریم را خاتمه بده
|
| 353 |
if "هوشواره ممکن است اشتباه" in full_text or "بیشتر بدانید" in full_text or "پاسخهای مربوط به افراد" in full_text:
|
| 354 |
full_text = await page.evaluate("() => document.body.innerText")
|
| 355 |
current_clean_text = clean_text(full_text, message)
|
|
@@ -361,7 +362,7 @@ async def chat_endpoint(message: str = Form(...), image: UploadFile = File(None)
|
|
| 361 |
break
|
| 362 |
|
| 363 |
except Exception as e:
|
| 364 |
-
yield f"خطای پردازش
|
| 365 |
finally:
|
| 366 |
await context.close()
|
| 367 |
await browser.close()
|
|
|
|
| 17 |
<head>
|
| 18 |
<meta charset="UTF-8">
|
| 19 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 20 |
+
<title>Google AI Free Chatbot + Stealth Streaming</title>
|
| 21 |
<style>
|
| 22 |
:root {
|
| 23 |
--bg-gradient: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
|
|
|
| 153 |
try {
|
| 154 |
const response = await fetch('/api/chat', { method: 'POST', body: formData });
|
| 155 |
if (!response.ok) {
|
| 156 |
+
aiMessageDiv.innerText = "خطا در ارتباط با گوگل یا مسدود شدن آیپی سرور.";
|
| 157 |
setLoading(false);
|
| 158 |
return;
|
| 159 |
}
|
|
|
|
| 210 |
</html>
|
| 211 |
"""
|
| 212 |
|
| 213 |
+
# الگوریتم تصفیه رادیکال پاسخ هوش مصنوعی
|
| 214 |
def clean_text(full_text: str, message: str) -> str:
|
| 215 |
if "ترافیک غیر عادی" in full_text or "Our systems have detected unusual traffic" in full_text:
|
| 216 |
return "🚨 سیستم امنیتی گوگل فعال شد و آیپی سرور هاگینگفیس را مسدود کرد (کپچا رخ داد)."
|
| 217 |
|
| 218 |
lines = full_text.split('\n')
|
| 219 |
|
| 220 |
+
# کلمات کلیدی و جملات خوشآمدگویی پیشفرض گوگل که کلاً باید فیلتر شوند
|
| 221 |
junk_keywords = [
|
| 222 |
"حالت هوشواره", "هوژواره", "ایمیل کنید", "تصاویر", "ویدیو", "ویدئو", "اخبار",
|
| 223 |
"نقشه", "خرید", "کتاب", "مالی", "موضوعمحور", "ورود", "ارسال", "همه",
|
| 224 |
+
"آماده است", "items removed", "بیشتر بدانید", "محتمل است", "هویشواره", "هرچه میخواهید",
|
| 225 |
+
"پاسخ به سوالات علمی", "نگارش، ویرایش یا ترجمه", "برنامهنویسی و حل مسائل",
|
| 226 |
+
"ایدهپردازی و کارهای خلاقانه", "لطفاً موضوع مورد نظرتون", "روزتون بخیر. من دستیار هوش مصنوعی",
|
| 227 |
+
"امروز چطور میتونم کمکتون کنم", "نیاز به راهنمایی دارید", "در چه زمینهای نیاز",
|
| 228 |
+
"شما تصویر، متن یا فایلی ارسال نکردید", "متوجه منظور دقیق شما نشدم"
|
| 229 |
]
|
| 230 |
|
| 231 |
+
# فاز ۱: فیلتر کلمات هدر و متوقف شدن حلقه در ابتدای بدنه فوتر سلب مسئولیت
|
| 232 |
filtered_lines = []
|
| 233 |
for line in lines:
|
| 234 |
line_str = line.strip()
|
| 235 |
if not line_str:
|
| 236 |
continue
|
| 237 |
+
if "هوشواره ممکن است اشتباه" in line_str or "در پاسخهای" in line_str or "بیشتر بدانید" in line_str or "پاسخ «حالت" in line_str:
|
| 238 |
break
|
| 239 |
if any(junk in line_str for junk in junk_keywords):
|
| 240 |
continue
|
| 241 |
filtered_lines.append(line_str)
|
| 242 |
|
| 243 |
+
# فاز ۲: برش قطعی لایههای بالای متن پاسخ بر اساس تطابق لنگر پیام کاربر
|
| 244 |
final_lines = []
|
| 245 |
found_query_anchor = False
|
| 246 |
for line in filtered_lines:
|
|
|
|
| 247 |
if not found_query_anchor and (message.lower() in line.lower() or line.lower() in message.lower()):
|
| 248 |
found_query_anchor = True
|
| 249 |
final_lines = []
|
|
|
|
| 270 |
except Exception as e:
|
| 271 |
return StreamingResponse(iter([f"خطا در ذخیره تصویر روی داکر: {str(e)}"]), media_type="text/plain")
|
| 272 |
|
|
|
|
| 273 |
async def response_generator():
|
| 274 |
async with async_playwright() as p:
|
| 275 |
browser = await p.chromium.launch(
|
|
|
|
| 296 |
page = await context.new_page()
|
| 297 |
|
| 298 |
try:
|
| 299 |
+
# مانیتورینگ مسیر ترکیبی بر اساس وجود فایل مالتیمدال
|
| 300 |
if saved_image_path and os.path.exists(saved_image_path):
|
| 301 |
+
# اگر تصویر وجود دارد: ابتدا لود کردن کادر چت اصلی گوگل هوشواره
|
|
|
|
| 302 |
await page.goto("https://www.google.com/search?q=سلام&udm=50", wait_until="domcontentloaded", timeout=30000)
|
| 303 |
await page.wait_for_timeout(1000)
|
| 304 |
|
| 305 |
+
# فعالسازی کادر چت با کلیک اجباری (بدون ارور تایماوت)
|
| 306 |
init_input = await page.query_selector("textarea, input[type='text'], [contenteditable='true']")
|
| 307 |
if init_input:
|
| 308 |
+
await init_input.click(force=True, timeout=2000)
|
| 309 |
await page.wait_for_timeout(500)
|
| 310 |
+
|
| 311 |
+
# تزریق مستقیم فایل به لایه آپلودر بومی
|
| 312 |
file_input = await page.query_selector("input[type='file']")
|
| 313 |
if file_input:
|
| 314 |
await file_input.set_input_files(saved_image_path)
|
| 315 |
+
# شلیک دستی رویداد change به کامپوننت لنز گوگل تا فورا متوجه حضور عکس بشود
|
| 316 |
+
await page.evaluate("el => el.dispatchEvent(new Event('change', { bubbles: true }))", file_input)
|
| 317 |
+
await page.wait_for_timeout(2000)
|
| 318 |
|
| 319 |
+
# نوشتن پیام متنی کاربر
|
| 320 |
input_box = await page.query_selector("textarea, input[type='text'], [contenteditable='true']")
|
| 321 |
if input_box:
|
| 322 |
await input_box.focus()
|
| 323 |
await input_box.fill(message)
|
| 324 |
+
await page.wait_for_timeout(300)
|
| 325 |
await input_box.press("Enter")
|
| 326 |
else:
|
| 327 |
+
# اگر فقط متن است: لود سریع و مستقیم از طریق URL کوئری (سرعت زیر ۲ ثانیه)
|
|
|
|
| 328 |
url = f"https://www.google.com/search?q={message}&udm=50"
|
| 329 |
await page.goto(url, wait_until="domcontentloaded", timeout=30000)
|
| 330 |
|
| 331 |
+
# ⚡ حلقه شنود استریم فوق سریع
|
| 332 |
last_sent_text = ""
|
| 333 |
no_change_count = 0
|
| 334 |
|
| 335 |
for _ in range(50):
|
| 336 |
+
await page.wait_for_timeout(300)
|
| 337 |
full_text = await page.evaluate("() => document.body.innerText")
|
| 338 |
current_clean_text = clean_text(full_text, message)
|
| 339 |
|
|
|
|
| 341 |
yield current_clean_text
|
| 342 |
break
|
| 343 |
|
| 344 |
+
# تزریق آنلاین کلمات جدید به صورت کلمه به کلمه به صفحه چت کاربر
|
| 345 |
if len(current_clean_text) > len(last_sent_text):
|
| 346 |
new_chunk = current_clean_text[len(last_sent_text):]
|
| 347 |
yield new_chunk
|
|
|
|
| 351 |
if len(current_clean_text) > 0:
|
| 352 |
no_change_count += 1
|
| 353 |
|
|
|
|
| 354 |
if "هوشواره ممکن است اشتباه" in full_text or "بیشتر بدانید" in full_text or "پاسخهای مربوط به افراد" in full_text:
|
| 355 |
full_text = await page.evaluate("() => document.body.innerText")
|
| 356 |
current_clean_text = clean_text(full_text, message)
|
|
|
|
| 362 |
break
|
| 363 |
|
| 364 |
except Exception as e:
|
| 365 |
+
yield f"خطای پردازش مرورگر: {str(e)}"
|
| 366 |
finally:
|
| 367 |
await context.close()
|
| 368 |
await browser.close()
|