ZookChatBot / OpenAIAuth /OpenAIAuth.py
JeffJing's picture
Upload 4 files
3360b74
# Credits to github.com/rawandahmad698/PyChatGPT
import re
import urllib
import tls_client
class Debugger:
def __init__(self, debug: bool = False):
if debug:
print("Debugger enabled on OpenAIAuth")
self.debug = debug
def set_debug(self, debug: bool):
self.debug = debug
def log(self, message: str, end: str = "\n"):
if self.debug:
print(message, end=end)
class OpenAIAuth:
def __init__(
self,
email_address: str,
password: str,
proxy: str = None,
debug: bool = False,
):
self.session_token = None
self.email_address = email_address
self.password = password
self.proxy = proxy
self.session = tls_client.Session(
client_identifier="chrome_109",
)
self.access_token: str = None
self.debugger = Debugger(debug)
self.user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
@staticmethod
def url_encode(string: str) -> str:
"""
URL encode a string
:param string:
:return:
"""
return urllib.parse.quote(string)
def begin(self) -> None:
"""
Begin the auth process
"""
self.debugger.log("Beginning auth process")
if not self.email_address or not self.password:
return
if self.proxy:
proxies = {
"http": self.proxy,
"https": self.proxy,
}
self.session.proxies = proxies
# First, make a request to https://explorer.api.openai.com/auth/login
url = "https://explorer.api.openai.com/"
headers = {
"Host": "ask.openai.com",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"User-Agent": self.user_agent,
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
}
response = self.session.get(
url=url,
headers=headers,
)
if response.status_code == 200:
self.__part_two()
else:
self.debugger.log("Error in part one")
self.debugger.log("Response: ", end="")
self.debugger.log(response.text)
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
raise Exception("API error")
def __part_two(self) -> None:
"""
In part two, We make a request to https://explorer.api.openai.com/api/auth/csrf and grab a fresh csrf token
"""
self.debugger.log("Beginning part two")
url = "https://explorer.api.openai.com/api/auth/csrf"
headers = {
"Host": "ask.openai.com",
"Accept": "*/*",
"Connection": "keep-alive",
"User-Agent": self.user_agent,
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
"Referer": "https://explorer.api.openai.com/auth/login",
"Accept-Encoding": "gzip, deflate, br",
}
response = self.session.get(
url=url,
headers=headers,
)
if response.status_code == 200 and "json" in response.headers["Content-Type"]:
csrf_token = response.json()["csrfToken"]
self.__part_three(token=csrf_token)
else:
self.debugger.log("Error in part two")
self.debugger.log("Response: ", end="")
self.debugger.log(response.text)
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
raise Exception("Error logging in")
def __part_three(self, token: str) -> None:
"""
We reuse the token from part to make a request to /api/auth/signin/auth0?prompt=login
"""
self.debugger.log("Beginning part three")
url = "https://explorer.api.openai.com/api/auth/signin/auth0?prompt=login"
payload = f"callbackUrl=%2F&csrfToken={token}&json=true"
headers = {
"Host": "explorer.api.openai.com",
"User-Agent": self.user_agent,
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "*/*",
"Sec-Gpc": "1",
"Accept-Language": "en-US,en;q=0.8",
"Origin": "https://explorer.api.openai.com",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Dest": "empty",
"Referer": "https://explorer.api.openai.com/auth/login",
"Accept-Encoding": "gzip, deflate",
}
self.debugger.log("Payload: " + payload)
self.debugger.log("Payload length: " + str(len(payload)))
response = self.session.post(url=url, headers=headers, data=payload)
if response.status_code == 200 and "json" in response.headers["Content-Type"]:
url = response.json()["url"]
if (
url
== "https://explorer.api.openai.com/api/auth/error?error=OAuthSignin"
or "error" in url
):
self.debugger.log("You have been rate limited")
raise Exception("You have been rate limited.")
self.__part_four(url=url)
else:
self.debugger.log("Error in part three")
self.debugger.log("Response: ", end="")
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
self.debugger.log(response.headers)
self.debugger.log(self.session.cookies.get_dict())
raise Exception("Unknown error")
def __part_four(self, url: str) -> None:
"""
We make a GET request to url
:param url:
:return:
"""
self.debugger.log("Beginning part four")
headers = {
"Host": "auth0.openai.com",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Connection": "keep-alive",
"User-Agent": self.user_agent,
"Accept-Language": "en-US,en;q=0.9",
"Referer": "https://explorer.api.openai.com/",
}
response = self.session.get(
url=url,
headers=headers,
)
if response.status_code == 302:
try:
state = re.findall(r"state=(.*)", response.text)[0]
state = state.split('"')[0]
self.__part_five(state=state)
except IndexError as exc:
self.debugger.log("Error in part four")
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
self.debugger.log("Rate limit hit")
self.debugger.log("Response: " + str(response.text))
raise Exception("Rate limit hit") from exc
else:
self.debugger.log("Error in part four")
self.debugger.log("Response: ", end="")
self.debugger.log(response.text)
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
self.debugger.log("Wrong response code")
raise Exception("Unknown error")
def __part_five(self, state: str) -> None:
"""
We use the state to get the login page & check for a captcha
"""
self.debugger.log("Beginning part five")
url = f"https://auth0.openai.com/u/login/identifier?state={state}"
headers = {
"Host": "auth0.openai.com",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Connection": "keep-alive",
"User-Agent": self.user_agent,
"Accept-Language": "en-US,en;q=0.9",
"Referer": "https://explorer.api.openai.com/",
}
response = self.session.get(url, headers=headers)
if response.status_code == 200:
self.__part_six(state=state)
else:
self.debugger.log("Error in part five")
self.debugger.log("Response: ", end="")
self.debugger.log(response.text)
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
raise ValueError("Invalid response code")
def __part_six(self, state: str) -> None:
"""
We make a POST request to the login page with the captcha, email
:param state:
:return:
"""
self.debugger.log("Beginning part six")
url = f"https://auth0.openai.com/u/login/identifier?state={state}"
email_url_encoded = self.url_encode(self.email_address)
payload = (
f"state={state}&username={email_url_encoded}&js-available=false&webauthn-available=true&is"
f"-brave=false&webauthn-platform-available=true&action=default "
)
headers = {
"Host": "auth0.openai.com",
"Origin": "https://auth0.openai.com",
"Connection": "keep-alive",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"User-Agent": self.user_agent,
"Referer": f"https://auth0.openai.com/u/login/identifier?state={state}",
"Accept-Language": "en-US,en;q=0.9",
"Content-Type": "application/x-www-form-urlencoded",
}
response = self.session.post(
url,
headers=headers,
data=payload,
)
if response.status_code == 302:
self.__part_seven(state=state)
else:
self.debugger.log("Error in part six")
self.debugger.log("Response: ", end="")
self.debugger.log(response.text)
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
raise Exception("Unknown error")
def __part_seven(self, state: str) -> None:
"""
We enter the password
:param state:
:return:
"""
url = f"https://auth0.openai.com/u/login/password?state={state}"
self.debugger.log("Beginning part seven")
email_url_encoded = self.url_encode(self.email_address)
password_url_encoded = self.url_encode(self.password)
payload = f"state={state}&username={email_url_encoded}&password={password_url_encoded}&action=default"
headers = {
"Host": "auth0.openai.com",
"Origin": "https://auth0.openai.com",
"Connection": "keep-alive",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"User-Agent": self.user_agent,
"Referer": f"https://auth0.openai.com/u/login/password?state={state}",
"Accept-Language": "en-US,en;q=0.9",
"Content-Type": "application/x-www-form-urlencoded",
}
try:
response = self.session.post(
url,
headers=headers,
data=payload,
)
self.debugger.log("Request went through")
except Exception as exc:
self.debugger.log("Error in part seven")
self.debugger.log("Exception: ", end="")
self.debugger.log(exc)
raise Exception("Could not get response") from exc
if response.status_code == 302:
self.debugger.log("Response code is 302")
try:
new_state = re.findall(r"state=(.*)", response.text)[0]
new_state = new_state.split('"')[0]
self.debugger.log("New state found")
self.__part_eight(old_state=state, new_state=new_state)
except Exception as exc:
raise Exception("Could not find new state") from exc
else:
self.debugger.log("Error in part seven")
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
raise Exception("Wrong status code")
def __part_eight(self, old_state: str, new_state) -> None:
self.debugger.log("Beginning part eight")
url = f"https://auth0.openai.com/authorize/resume?state={new_state}"
headers = {
"Host": "auth0.openai.com",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Connection": "keep-alive",
"User-Agent": self.user_agent,
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
"Referer": f"https://auth0.openai.com/u/login/password?state={old_state}",
}
response = self.session.get(
url,
headers=headers,
allow_redirects=True,
)
if response.status_code == 200:
self.session_token = response.cookies.get_dict()[
"__Secure-next-auth.session-token"
]
self.get_access_token()
def get_access_token(self):
"""
Gets access token
"""
self.session.cookies.set(
"__Secure-next-auth.session-token",
self.session_token,
)
response = self.session.get(
"https://explorer.api.openai.com/api/auth/session",
)
if response.status_code == 200:
self.access_token = response.json()["accessToken"]
self.debugger.log("Access token found")
return self.access_token
else:
self.debugger.log("Error in part nine")
self.debugger.log("Status code: ", end="")
self.debugger.log(response.status_code)
raise Exception("Wrong status code")