XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Fix headless mode detection and enhance button click handling in Google AI Mode

cff1e04c
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

2 个文件 +42 -18
Modified g4f/api/__init__.py +1 -1
@@ -1392,7 +1392,7 @@ class Api:
1392 1392 try:
1393 1393 async with lock:
1394 1394 from g4f.requests.cdp import CDPSession
1395 session = CDPSession(headless="&headless=false" not in url)
1395 session = CDPSession(headless="headless=false" not in url)
1396 1396 await session.start()
1397 1397 try:
1398 1398 screenshot_path = await session.capture_screenshot(url, 1 if "q=" in url else 3)
Modified g4f/requests/cdp.py +41 -17
@@ -693,7 +693,8 @@ const targetTexts = [
693 693 'Accept All Cookies', 'Accept all cookies',
694 694 'Einwilligen', 'Alle akzeptieren',
695 695 'Zustimmen und weiter', 'Zustimmen',
696 'Run'
696 'Run',
697 ...params.getAll('click')
697 698 ];
698 699 const acceptBtns = (() => {
699 700 function searchDocument(doc, offsetX = 0, offsetY = 0) {
@@ -702,7 +703,7 @@ const acceptBtns = (() => {
702 703 if (!doc) return [];
703 704
704 705 // 1. Search buttons in the current document
705 const buttons = doc.querySelectorAll('button, input[type="submit"], [role="button"], a');
706 const buttons = doc.querySelectorAll('button, input[type="submit"], [role="button"], a, h2');
706 707 for (let button of buttons) {
707 708 const text = (button.innerText || button.value || button.textContent || '').trim();
708 709 if (targetTexts.includes(text)) {
@@ -749,23 +750,31 @@ if (acceptBtns && acceptBtns.length > 0) {
749 750 }
750 751
751 752 // 4. Enable Google AI Mode if the URL has the ai-mode parameter
753 let googleAiModeButton = null;
752 754 function enableGoogleAiMode() {
753 755 // Enable Google AI Mode if the URL has the ai-mode parameter
754 756 const aiMode = params.has('ai-mode');
755 757 if (aiMode) {
756 const b = Array.from(document.querySelectorAll("a, button")).filter(a => {
758 googleAiModeButton = Array.from(document.querySelectorAll("a, button")).filter(a => {
757 759 return a.textContent.endsWith("KI‑Modus") || a.textContent.endsWith("AI Mode");
758 760 }).pop();
759 b ? b.click() : null;
761 googleAiModeButton ? googleAiModeButton.click() : null;
760 762 setTimeout(() => {
761 b ? b.click() : null;
763 googleAiModeButton ? googleAiModeButton.click() : null;
762 764 }, 1000);
765 return !!googleAiModeButton;
763 766 }
767 return false;
764 768 }
765 769 enableGoogleAiMode();
766 770
767 771 // 5. Find the textarea
768 const textarea = document.querySelector('textarea[name="prompt"], [class^="MessageInput__TextArea--"], [placeholder="Type a message..."]');
772 const fieldSelectors = [
773 'textarea[name="prompt"]',
774 '[class^="MessageInput__TextArea--"]',
775 '[placeholder="Type a message..."]',
776 ];
777 const textarea = document.querySelector(fieldSelectors.join(', '));
769 778
770 779 // 6. Only proceed if we found a query and the textarea exists
771 780 if (searchQuery && textarea) {
@@ -825,7 +834,7 @@ if (searchQuery && textarea) {
825 834 })();
826 835
827 836
828 // 8. Click the send button if it exists
837 // 8. Click the send / submit button if it exists
829 838 const sendButtonSelectors = [
830 839 '[data-send-label="Send message"]',
831 840 '[aria-label="Send message"]',
@@ -833,27 +842,40 @@ const sendButtonSelectors = [
833 842 '.send-button-container',
834 843 '.send-button',
835 844 '#send-message-button', // z.ai
845 '[data-testid="chat-submit"]', // grok.com
836 846 ];
837 document.querySelector(sendButtonSelectors.join(', '))?.click();
847 const sendButton = document.querySelector(sendButtonSelectors.join(', '));
848 if (sendButton) {
849 sendButton.click();
850 }
838 851
839 852 // 8. Click the send button on gemini.google.com
840 const trigger = (el, etype) => {
841 el?.dispatchEvent( new Event( etype, { bubbles: true } ) );
842 };
843 setTimeout(() =>
844 trigger(document.querySelector(`.send-button`), `click`),
845 1000);
853 const geminiSendButton = document.querySelector(`.send-button`);
854 if (geminiSendButton) {
855 setTimeout(() => {
856 geminiSendButton.dispatchEvent(new Event('click', {bubbles: true}));
857 }, 1000);
858 }
846 859
847 860 // 8. Click the send button on chat.deepseek.com
848 document.querySelector('[style="width: fit-content;"] [role="button"]')?.click();
861 const deepseekSendButton = document.querySelector('[style="width: fit-content;"] [role="button"]');
862 if (deepseekSendButton) {
863 deepseekSendButton.click();
864 }
865
866 // 9. Return the text content of the first found send button for logging/debugging
867 (
868 sendButton || geminiSendButton || deepseekSendButton || (acceptBtns && acceptBtns[0]) || googleAiModeButton
869 )?.textContent.trim();
849 870 """
850 871 try:
851 872 rect = await self.evaluate_js(js_code)
852 if rect:
853 debug.log(f"Accept button rect: {rect}")
854 873 if rect and isinstance(rect, list) and len(rect) == 2:
855 874 await self.click(int(rect[0]), int(rect[1]))
856 875 return True
876 elif rect and isinstance(rect, str):
877 debug.log(f"Clicked button with text: {rect}")
878 return True
857 879 except Exception as e:
858 880 debug.log(f"Failed to click accept button: {e}")
859 881 return False
@@ -909,6 +931,8 @@ document.querySelector('[style="width: fit-content;"] [role="button"]')?.click()
909 931 if await self.evaluate_js('!document.doctype'):
910 932 raise RuntimeError(f"Failed to load page {url} for screenshot, document.doctype={await self.evaluate_js('String(document.doctype)')}")
911 933
934 await self.bypass_turnstile()
935
912 936 result = None
913 937 for i in range(n):
914 938 await asyncio.sleep(1)