monra's picture
Initial commit
aae4949
raw
history blame
5.17 kB
import os, re, json
try:
from tls_client import Session
except ImportError:
os.system("pip install tls_client --no-cache-dir")
from uuid import uuid4
from pydantic import BaseModel
from fake_useragent import UserAgent
from typing import Optional, List, Dict, Any
class Completion:
"""A class that provides methods for creating completion requests."""
@staticmethod
def create(
prompt: str,
page: int = 1,
count: int = 10,
safe_search: str = "Moderate",
on_shopping_page: bool = False,
mkt: str = "",
response_filter: str = "WebPages,Translations,TimeZone,Computation,RelatedSearches",
domain: str = "youchat",
query_trace_id: str = None,
chat: List[str] = None,
include_links: bool = False,
detailed: bool = False,
proxy: Optional[str] = None,
) -> dict:
"""
Creates a completion request.
Args:
prompt (str): The prompt text for the completion.
page (int, optional): The page number for pagination. Defaults to 1.
count (int, optional): The number of results per page. Defaults to 10.
safe_search (str, optional): The safe search level. Defaults to 'Moderate'.
on_shopping_page (bool, optional): Indicates if the completion is on a shopping page. Defaults to False.
mkt (str, optional): The market for the completion. Defaults to ''.
response_filter (str, optional): The filter for the response. Defaults to 'WebPages,Translations,TimeZone,Computation,RelatedSearches'.
domain (str, optional): The domain for the completion. Defaults to 'youchat'.
query_trace_id (str, optional): The trace ID for the query. Defaults to None.
chat (list, optional): A list of chat messages. Defaults to None.
include_links (bool, optional): Indicates if links should be included in the response. Defaults to False.
detailed (bool, optional): Indicates if detailed results should be included in the response. Defaults to False.
proxy (str, optional): The proxy server to use. Defaults to None.
Returns:
dict: The completion response as a dictionary.
Raises:
Exception: If unable to get the response.
"""
if chat is None:
chat = []
proxies = (
{"http": "http://" + proxy, "https": "http://" + proxy} if proxy else {}
)
client = Session(client_identifier="chrome_108")
client.headers = Completion.__get_headers()
client.proxies = proxies
response = client.get(
f"https://you.com/api/streamingSearch",
params={
"q": prompt,
"page": page,
"count": count,
"safeSearch": safe_search,
"onShoppingPage": on_shopping_page,
"mkt": mkt,
"responseFilter": response_filter,
"domain": domain,
"queryTraceId": str(uuid4())
if query_trace_id is None
else query_trace_id,
"chat": str(chat),
},
)
if "youChatToken" not in response.text:
raise Exception("Unable to fetch the response.")
you_chat_serp_results = re.search(
r"(?<=event: youChatSerpResults\ndata:)(.*\n)*?(?=event: )", response.text
).group()
third_party_search_results = re.search(
r"(?<=event: thirdPartySearchResults\ndata:)(.*\n)*?(?=event: )",
response.text,
).group()
text = "".join(re.findall(r'{"youChatToken": "(.*?)"}', response.text))
extra = {
"youChatSerpResults": json.loads(you_chat_serp_results),
}
result = {
"text": text.replace("\\n", "\n").replace("\\\\", "\\").replace('\\"', '"')
}
if include_links:
result["links"] = json.loads(third_party_search_results)["search"][
"third_party_search_results"
]
if detailed:
result["extra"] = extra
return result
@staticmethod
def __get_headers() -> dict:
"""
Returns the headers for the completion request.
Returns:
dict: The headers as a dictionary.
"""
return {
"authority": "you.com",
"accept": "text/event-stream",
"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",
"cache-control": "no-cache",
"referer": "https://you.com/search?q=who+are+you&tbm=youchat",
"sec-ch-ua": '"Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"cookie": f"safesearch_guest=Moderate; uuid_guest={str(uuid4())}",
"user-agent": UserAgent().random,
}