Skip to content
This repository was archived by the owner on Jan 25, 2023. It is now read-only.

Commit 0c53ffb

Browse files
committed
Improvements and chat stream
1 parent a46707a commit 0c53ffb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+21743
-300
lines changed

.github/workflows/deploy.yml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: Deploy to GitHub pages
2+
on:
3+
push:
4+
branches: [master]
5+
env:
6+
BUILD_FOLDER: ./docs
7+
jobs:
8+
build:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Deploy
12+
uses: JamesIves/github-pages-deploy-action@v4
13+
with:
14+
folder: ${{env.BUILD_FOLDER}}

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# Custom
22
.dccache
33
config.json
4+
config*
45
.vscode
6+
.chatgpt
57
cli.py
68
main.py
9+
_docs/
710

811
# Byte-compiled / optimized / DLL files
912
__pycache__/

README.md

+37-7
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,33 @@ pip install -U chatgpt
2121
> :warning:   Please, update the library. Note the change in the config file.
2222
2323
Create the file `config.json` in your working directory:
24+
```json
25+
{
26+
"email": "[email protected]",
27+
"password": "xxx",
28+
}
29+
```
2430

31+
### With proxy
2532
```json
2633
{
2734
"email": "[email protected]",
28-
"password": "xxx"
35+
"password": "xxx",
36+
"proxy": "socks5://user:pass@host:port"
37+
}
38+
```
39+
40+
### With other parameters
41+
```json
42+
{
43+
"email": "[email protected]",
44+
"password": "xxx",
45+
46+
//Timeout for requests made.
47+
"timeout":300,
48+
49+
//Cache for saving the cookies and the state of the session.
50+
"cache_file_path":"./path_and_filename"
2951
}
3052
```
3153

@@ -48,18 +70,26 @@ These are the available commands:
4870

4971
### SDK
5072
```python
73+
#!/usr/bin/env python
74+
# -*- coding: utf-8 -*-
75+
import sys
5176
from chatgpt import Conversation
5277

5378
conversation = Conversation()
54-
print(
55-
conversation.chat(
56-
"We are going to start a conversation. "
57-
"I will speak English and you will speak Portuguese."
58-
)
59-
)
79+
80+
# Python generator to stream the message in chunks.
81+
# the chunk give you a new part of the final message.
82+
for chunk in conversation.stream("We are going to start a conversation. I will speak English and you will speak Portuguese."):
83+
# print chunk without line break
84+
print(chunk, end="")
85+
# flush terminal output
86+
sys.stdout.flush()
87+
88+
# this conversation chat instead is going to wait until the response is completely received.
6089
print(conversation.chat("What's the color of the sky?"))
6190

6291
# The AI will forget it was speaking Portuguese
6392
conversation.reset()
6493
print(conversation.chat("What's the color of the sun?"))
94+
6595
```

chatgpt/__main__.py

-30
This file was deleted.

chatgpt/authentication.py

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import urllib
2+
3+
from urllib.error import HTTPError as HTTPTLSError
4+
from chatgpt.sessions import HTTPTLSSession
5+
from chatgpt.utils import random_sleep_time
6+
from .errors import ChatgptError, ChatgptErrorCodes
7+
8+
class OpenAIAuthentication:
9+
10+
def __init__(self, session: HTTPTLSSession):
11+
self.session = session
12+
13+
14+
def _request_login(self):
15+
response = self.session.request(
16+
"GET", "https://chat.openai.com/auth/login")
17+
18+
return response
19+
20+
def _request_providers(self):
21+
response = self.session.request(
22+
"GET", "https://chat.openai.com/api/auth/providers")
23+
return response.json()
24+
25+
def _request_csrf(self):
26+
response = self.session.request(
27+
"GET", "https://chat.openai.com/api/auth/csrf",)
28+
return response.json()
29+
30+
def _request_signin(self, url, csrfToken: dict):
31+
payload = "callbackUrl=%2F&csrfToken={}&json=true".format(csrfToken)
32+
response = self.session.request("POST", "{}?prompt=login".format(url),
33+
headers={
34+
"Content-Type": "application/x-www-form-urlencoded",
35+
"Accept": "*/*"
36+
},
37+
data=payload)
38+
return response.json()
39+
40+
def _request_authorize(self, url: str):
41+
try:
42+
43+
self.session._headers = {
44+
"Upgrade-Insecure-Requests": "1"
45+
}
46+
response = self.session.request("GET", url)
47+
except HTTPTLSError as e:
48+
if e.code == 302:
49+
if "state" in str(e):
50+
return str(e).split("state=")[1].split("\">")[0]
51+
raise e
52+
raise HTTPTLSError(url, 200, "Bad authorize request",
53+
response.headers, None)
54+
55+
56+
def _request_login_identifier(self, state: str):
57+
url = "https://auth0.openai.com/u/login/identifier?state={}".format(
58+
state)
59+
response = self.session.request("GET", url)
60+
if "alt=\"captcha\"" in response.text:
61+
raise HTTPTLSError(
62+
url, 400, "Captcha needed", response.headers, None)
63+
return state
64+
65+
def _request_login_identifier_post(self, state, email):
66+
try:
67+
url = "https://auth0.openai.com/u/login/identifier?state={}".format(
68+
state)
69+
70+
email = urllib.parse.quote_plus(email)
71+
payload = "action=default&is-brave=false&js-available=false&state={}&username={}&webauthn-available=false&webauthn-platform-available=false".format(
72+
state, email)
73+
response = self.session.request("POST", url, data=payload, headers={
74+
"Content-Type": "application/x-www-form-urlencoded",
75+
})
76+
77+
except HTTPTLSError as e:
78+
if e.code == 302:
79+
return state
80+
else:
81+
raise e
82+
raise HTTPTLSError(url, 200, "Bad authorize request",
83+
response.headers, None)
84+
85+
def _request_login_password(self, state):
86+
url = "https://auth0.openai.com/u/login/password?state={}".format(
87+
state)
88+
self.session.request("GET", url)
89+
return state
90+
91+
def _request_login_password_post(self, state, email: str, password: str):
92+
url = "https://auth0.openai.com/u/login/password?state={}".format(
93+
state)
94+
email = urllib.parse.quote_plus(email)
95+
password = urllib.parse.quote_plus(password)
96+
payload = "action=default&password={}&state={}&username={}".format(
97+
password, state, email)
98+
try:
99+
response = self.session.request("POST", url, data=payload, headers={
100+
"Content-Type": "application/x-www-form-urlencoded",
101+
"Accept": "*/*"
102+
})
103+
except HTTPTLSError as e:
104+
if e.code == 302:
105+
return str(e).split("state=")[1].split("\">")[0]
106+
else:
107+
raise e
108+
raise HTTPTLSError(url, 200, "Bad authorize request",
109+
response.headers, None)
110+
111+
def _request_authorize_access_token(self, state):
112+
response = self.session.request("GET", "https://auth0.openai.com/authorize/resume?state={}".format(
113+
state), allow_redirects=True)
114+
return response.cookies.get("__Secure-next-auth.session-token")
115+
116+
def get_session(self):
117+
"""Get the actual gpt session.
118+
"""
119+
try:
120+
response = self.session.request(
121+
"GET", "https://chat.openai.com/api/auth/session")
122+
return response.json()
123+
except HTTPTLSError as e:
124+
raise ChatgptError(
125+
"Error getting the session. You may have a wrong access token; try to login again or insert an access_token yourself.",
126+
ChatgptErrorCodes.LOGIN_ERROR) from e
127+
128+
def login(self, username, password):
129+
"""Get the access token for chatgpt
130+
131+
Args:
132+
username (str): Email for chatgpt
133+
password (str): Password for chatgpt
134+
"""
135+
try:
136+
self._request_login()
137+
try:
138+
chatgpt_session = self.get_session()
139+
if chatgpt_session:
140+
return chatgpt_session
141+
except Exception:
142+
pass
143+
providers = self._request_providers()
144+
csrf = self._request_csrf()
145+
sigin = self._request_signin(
146+
providers["auth0"]["signinUrl"], csrf["csrfToken"])
147+
state = self._request_authorize(sigin["url"])
148+
state = self._request_login_identifier(state)
149+
state = self._request_login_identifier_post(state, username)
150+
state = self._request_login_password(state)
151+
state = self._request_login_password_post(state, username, password)
152+
self._request_authorize_access_token(state)
153+
random_sleep_time(1, 2)
154+
return self.get_session()
155+
except HTTPTLSError as err:
156+
raise ChatgptError("Login error. Try again or use interceptor.js as explained in the documentation.",
157+
ChatgptErrorCodes.LOGIN_ERROR) from err

0 commit comments

Comments
 (0)