Merge pull request #1302 from hlohaus/go

Add get_session_from_browser as cloudflare bypass
pull/1320/head
Tekky 7 months ago committed by GitHub
commit 045d4073ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -6,7 +6,7 @@ import random
from ..typing import CreateResult, Messages from ..typing import CreateResult, Messages
from .base_provider import BaseProvider from .base_provider import BaseProvider
from .helper import format_prompt, get_random_string from .helper import format_prompt, get_random_string
from .webdriver import WebDriver, WebDriverSession from ..webdriver import WebDriver, WebDriverSession
from .. import debug from .. import debug
class AItianhuSpace(BaseProvider): class AItianhuSpace(BaseProvider):

@ -1,9 +1,8 @@
from __future__ import annotations from __future__ import annotations
from ..requests import StreamSession from ..requests import Session, get_session_from_browser
from ..typing import Messages from ..typing import Messages
from .base_provider import AsyncProvider from .base_provider import AsyncProvider
from .helper import get_cookies
class GptChatly(AsyncProvider): class GptChatly(AsyncProvider):
@ -18,40 +17,20 @@ class GptChatly(AsyncProvider):
cls, cls,
model: str, model: str,
messages: Messages, messages: Messages,
proxy: str = None, cookies: dict = None, **kwargs) -> str: proxy: str = None,
timeout: int = 120,
cookies = get_cookies('gptchatly.com') if not cookies else cookies session: Session = None,
if not cookies: **kwargs
raise RuntimeError( ) -> str:
"g4f.provider.GptChatly requires cookies, [refresh https://gptchatly.com on chrome]" if not session:
) session = get_session_from_browser(cls.url, proxy=proxy, timeout=timeout)
if model.startswith("gpt-4"): if model.startswith("gpt-4"):
chat_url = f"{cls.url}/fetch-gpt4-response" chat_url = f"{cls.url}/fetch-gpt4-response"
else: else:
chat_url = f"{cls.url}/fetch-response" chat_url = f"{cls.url}/felch-response"
data = {
headers = { "past_conversations": messages
'authority': 'gptchatly.com',
'accept': '*/*',
'accept-language': 'en,fr-FR;q=0.9,fr;q=0.8,es-ES;q=0.7,es;q=0.6,en-US;q=0.5,am;q=0.4,de;q=0.3',
'content-type': 'application/json',
'origin': 'https://gptchatly.com',
'referer': 'https://gptchatly.com/',
'sec-ch-ua': '"Chromium";v="118", "Google Chrome";v="118", "Not=A?Brand";v="99"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"macOS"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
} }
response = session.post(chat_url, json=data)
async with StreamSession(headers=headers, response.raise_for_status()
proxies={"https": proxy}, cookies=cookies, impersonate='chrome110') as session: return response.json()["chatGPTResponse"]
data = {
"past_conversations": messages
}
async with session.post(chat_url, json=data) as response:
response.raise_for_status()
return (await response.json())["chatGPTResponse"]

@ -5,7 +5,7 @@ import time, json
from ..typing import CreateResult, Messages from ..typing import CreateResult, Messages
from .base_provider import BaseProvider from .base_provider import BaseProvider
from .helper import format_prompt from .helper import format_prompt
from .webdriver import WebDriver, WebDriverSession from ..webdriver import WebDriver, WebDriverSession
class MyShell(BaseProvider): class MyShell(BaseProvider):
url = "https://app.myshell.ai/chat" url = "https://app.myshell.ai/chat"

@ -5,7 +5,7 @@ import time
from ..typing import CreateResult, Messages from ..typing import CreateResult, Messages
from .base_provider import BaseProvider from .base_provider import BaseProvider
from .helper import format_prompt from .helper import format_prompt
from .webdriver import WebDriver, WebDriverSession from ..webdriver import WebDriver, WebDriverSession
class PerplexityAi(BaseProvider): class PerplexityAi(BaseProvider):
url = "https://www.perplexity.ai" url = "https://www.perplexity.ai"

@ -4,10 +4,10 @@ from ..typing import CreateResult, Messages
from .base_provider import BaseProvider, format_prompt from .base_provider import BaseProvider, format_prompt
import json import json
from cloudscraper import CloudScraper, session, create_scraper from ..requests import Session, get_session_from_browser
class Pi(BaseProvider): class Pi(BaseProvider):
url = "https://chat-gpt.com" url = "https://pi.ai/talk"
working = True working = True
supports_stream = True supports_stream = True
@ -17,75 +17,52 @@ class Pi(BaseProvider):
model: str, model: str,
messages: Messages, messages: Messages,
stream: bool, stream: bool,
session: Session = None,
proxy: str = None, proxy: str = None,
scraper: CloudScraper = None, timeout: int = 180,
conversation: dict = None, conversation_id: str = None,
**kwargs **kwargs
) -> CreateResult: ) -> CreateResult:
if not scraper: if not session:
scraper = cls.get_scraper(proxy) session = get_session_from_browser(url=cls.url, proxy=proxy, timeout=timeout)
if not conversation: if not conversation_id:
conversation = cls.start_conversation(scraper) conversation_id = cls.start_conversation(session)
answer = cls.ask(scraper, messages, conversation) answer = cls.ask(session, messages, conversation_id)
for line in answer: for line in answer:
if "text" in line: if "text" in line:
yield line["text"] yield line["text"]
def get_scraper(proxy: str): @classmethod
return create_scraper( def start_conversation(cls, session: Session) -> str:
browser={ response = session.post('https://pi.ai/api/chat/start', data="{}", headers={
'browser': 'chrome',
'platform': 'windows',
'desktop': True
},
headers={
'Accept': '*/*',
'Accept-Encoding': 'deflate,gzip,br',
},
proxies={
"https": proxy
}
)
def start_conversation(scraper: CloudScraper):
response = scraper.post('https://pi.ai/api/chat/start', data="{}", headers={
'accept': 'application/json', 'accept': 'application/json',
'x-api-version': '3' 'x-api-version': '3'
}) })
if 'Just a moment' in response.text: if 'Just a moment' in response.text:
raise RuntimeError('Error: Cloudflare detected') raise RuntimeError('Error: Cloudflare detected')
return Conversation( return response.json()['conversations'][0]['sid']
response.json()['conversations'][0]['sid'],
response.cookies
)
def get_chat_history(scraper: CloudScraper, conversation: Conversation): def get_chat_history(session: Session, conversation_id: str):
params = { params = {
'conversation': conversation.sid, 'conversation': conversation_id,
} }
response = scraper.get('https://pi.ai/api/chat/history', params=params, cookies=conversation.cookies) response = session.get('https://pi.ai/api/chat/history', params=params)
if 'Just a moment' in response.text: if 'Just a moment' in response.text:
raise RuntimeError('Error: Cloudflare detected') raise RuntimeError('Error: Cloudflare detected')
return response.json() return response.json()
def ask(scraper: CloudScraper, messages: Messages, conversation: Conversation): def ask(session: Session, messages: Messages, conversation_id: str):
json_data = { json_data = {
'text': format_prompt(messages), 'text': format_prompt(messages),
'conversation': conversation.sid, 'conversation': conversation_id,
'mode': 'BASE', 'mode': 'BASE',
} }
response = scraper.post('https://pi.ai/api/chat', json=json_data, cookies=conversation.cookies, stream=True) response = session.post('https://pi.ai/api/chat', json=json_data, stream=True)
for line in response.iter_lines():
for line in response.iter_lines(chunk_size=1024, decode_unicode=True): if b'Just a moment' in line:
if 'Just a moment' in line:
raise RuntimeError('Error: Cloudflare detected') raise RuntimeError('Error: Cloudflare detected')
if line.startswith('data: {"text":'): if line.startswith(b'data: {"text":'):
yield json.loads(line.split('data: ')[1]) yield json.loads(line.split(b'data: ')[1])
if line.startswith('data: {"title":'): elif line.startswith(b'data: {"title":'):
yield json.loads(line.split('data: ')[1]) yield json.loads(line.split(b'data: ')[1])
class Conversation():
def __init__(self, sid: str, cookies):
self.sid = sid
self.cookies = cookies

@ -4,7 +4,7 @@ import time, json, time
from ..typing import CreateResult, Messages from ..typing import CreateResult, Messages
from .base_provider import BaseProvider from .base_provider import BaseProvider
from .webdriver import WebDriver, WebDriverSession from ..webdriver import WebDriver, WebDriverSession
class TalkAi(BaseProvider): class TalkAi(BaseProvider):
url = "https://talkai.info" url = "https://talkai.info"

@ -5,7 +5,7 @@ import time
from ...typing import CreateResult, Messages from ...typing import CreateResult, Messages
from ..base_provider import BaseProvider from ..base_provider import BaseProvider
from ..helper import format_prompt from ..helper import format_prompt
from ..webdriver import WebDriver, WebDriverSession from ...webdriver import WebDriver, WebDriverSession
class Bard(BaseProvider): class Bard(BaseProvider):
url = "https://bard.google.com" url = "https://bard.google.com"

@ -7,7 +7,7 @@ from async_property import async_cached_property
from ..base_provider import AsyncGeneratorProvider from ..base_provider import AsyncGeneratorProvider
from ..helper import get_event_loop from ..helper import get_event_loop
from ..webdriver import get_browser from ...webdriver import get_browser
from ...typing import AsyncResult, Messages from ...typing import AsyncResult, Messages
from ...requests import StreamSession from ...requests import StreamSession

@ -5,7 +5,7 @@ import time
from ...typing import CreateResult, Messages from ...typing import CreateResult, Messages
from ..base_provider import BaseProvider from ..base_provider import BaseProvider
from ..helper import format_prompt from ..helper import format_prompt
from ..webdriver import WebDriver, WebDriverSession from ...webdriver import WebDriver, WebDriverSession
models = { models = {
"meta-llama/Llama-2-7b-chat-hf": {"name": "Llama-2-7b"}, "meta-llama/Llama-2-7b-chat-hf": {"name": "Llama-2-7b"},

@ -5,7 +5,7 @@ import time
from ...typing import CreateResult, Messages from ...typing import CreateResult, Messages
from ..base_provider import BaseProvider from ..base_provider import BaseProvider
from ..helper import format_prompt from ..helper import format_prompt
from ..webdriver import WebDriver, WebDriverSession from ...webdriver import WebDriver, WebDriverSession
models = { models = {
"theb-ai": "TheB.AI", "theb-ai": "TheB.AI",

@ -6,7 +6,7 @@ from urllib.parse import quote
from ...typing import CreateResult, Messages from ...typing import CreateResult, Messages
from ..base_provider import BaseProvider from ..base_provider import BaseProvider
from ..helper import format_prompt from ..helper import format_prompt
from ..webdriver import WebDriver, WebDriverSession from ...webdriver import WebDriver, WebDriverSession
class Phind(BaseProvider): class Phind(BaseProvider):
url = "https://www.phind.com" url = "https://www.phind.com"
@ -26,7 +26,6 @@ class Phind(BaseProvider):
creative_mode: bool = None, creative_mode: bool = None,
**kwargs **kwargs
) -> CreateResult: ) -> CreateResult:
driver.start_session
with WebDriverSession(webdriver, "", proxy=proxy) as driver: with WebDriverSession(webdriver, "", proxy=proxy) as driver:
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait

@ -4,8 +4,12 @@ import json
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from functools import partialmethod from functools import partialmethod
from typing import AsyncGenerator from typing import AsyncGenerator
from urllib.parse import urlparse
from curl_cffi.requests import AsyncSession, Response from curl_cffi.requests import AsyncSession, Session, Response
from .webdriver import WebDriver, WebDriverSession
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class StreamResponse: class StreamResponse:
def __init__(self, inner: Response) -> None: def __init__(self, inner: Response) -> None:
@ -50,4 +54,50 @@ class StreamSession(AsyncSession):
post = partialmethod(request, "POST") post = partialmethod(request, "POST")
put = partialmethod(request, "PUT") put = partialmethod(request, "PUT")
patch = partialmethod(request, "PATCH") patch = partialmethod(request, "PATCH")
delete = partialmethod(request, "DELETE") delete = partialmethod(request, "DELETE")
def get_session_from_browser(url: str, webdriver: WebDriver = None, proxy: str = None, timeout: int = 120):
with WebDriverSession(webdriver, "", proxy=proxy, virtual_display=True) as driver:
driver.get(url)
# Is cloudflare protection
if driver.find_element(By.TAG_NAME, "body").get_attribute("class") == "no-js":
try:
# Click button in iframe
WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#turnstile-wrapper iframe"))
)
driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR, "#turnstile-wrapper iframe"))
WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "#challenge-stage input"))
)
driver.find_element(By.CSS_SELECTOR, "#challenge-stage input").click()
except:
pass
finally:
driver.switch_to.default_content()
# No cloudflare protection
WebDriverWait(driver, timeout).until(
EC.presence_of_element_located((By.CSS_SELECTOR, "body:not(.no-js)"))
)
cookies = dict([(cookie["name"], cookie["value"]) for cookie in driver.get_cookies()])
user_agent = driver.execute_script("return navigator.userAgent")
parse = urlparse(url)
return Session(
cookies=cookies,
headers={
'accept': '*/*',
'authority': parse.netloc,
'origin': f'{parse.scheme}://{parse.netloc}',
'referer': url,
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'user-agent': user_agent
},
proxies={"https": proxy, "http": proxy},
timeout=timeout,
impersonate="chrome110"
)

@ -2,20 +2,9 @@ from __future__ import annotations
import time import time
from platformdirs import user_config_dir from platformdirs import user_config_dir
try: from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webdriver import WebDriver from undetected_chromedriver import Chrome, ChromeOptions
except ImportError:
class WebDriver():
pass
try:
from undetected_chromedriver import Chrome, ChromeOptions
except ImportError:
class Chrome():
def __init__():
raise RuntimeError('Please install the "undetected_chromedriver" package')
class ChromeOptions():
def add_argument():
pass
try: try:
from pyvirtualdisplay import Display from pyvirtualdisplay import Display
has_pyvirtualdisplay = True has_pyvirtualdisplay = True
@ -27,12 +16,13 @@ def get_browser(
headless: bool = False, headless: bool = False,
proxy: str = None, proxy: str = None,
options: ChromeOptions = None options: ChromeOptions = None
) -> Chrome: ) -> WebDriver:
if user_data_dir == None: if user_data_dir == None:
user_data_dir = user_config_dir("g4f") user_data_dir = user_config_dir("g4f")
if not options:
options = ChromeOptions()
options.add_argument("window-size=1920,1080");
if proxy: if proxy:
if not options:
options = ChromeOptions()
options.add_argument(f'--proxy-server={proxy}') options.add_argument(f'--proxy-server={proxy}')
return Chrome(options=options, user_data_dir=user_data_dir, headless=headless) return Chrome(options=options, user_data_dir=user_data_dir, headless=headless)

@ -25,5 +25,4 @@ asyncstdlib
async-property async-property
undetected-chromedriver undetected-chromedriver
asyncstdlib asyncstdlib
async_property async_property
cloudscraper
Loading…
Cancel
Save