fix GPT-4 model, structural change of access_tokens.json, add har file tutorial to readme
This commit is contained in:
parent
0431ff8703
commit
ce3c265994
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@ freechatgpt
|
||||
chatgpttoapi
|
||||
tools/authenticator/.proxies.txt.swp
|
||||
.env
|
||||
*.har
|
17
README.md
17
README.md
@ -11,7 +11,7 @@ Create a fake API using ChatGPT's website
|
||||
|
||||
### Authentication
|
||||
|
||||
Access token retrieval has been automated by [OpenAIAuth](https://github.com/acheong08/OpenAIAuth/) with account email & password.
|
||||
Access token and PUID(only for PLUS account) retrieval has been automated by [OpenAIAuth](https://github.com/acheong08/OpenAIAuth/) with account email & password.
|
||||
|
||||
`accounts.txt` - A list of accounts separated by new line
|
||||
|
||||
@ -21,12 +21,20 @@ email:password
|
||||
...
|
||||
```
|
||||
|
||||
All authenticated access tokens will store in `access_tokens.json`
|
||||
All authenticated access tokens and PUID will store in `access_tokens.json`
|
||||
|
||||
Auto renew access tokens after 14 days
|
||||
Auto renew access tokens and PUID after 7 days
|
||||
|
||||
Caution! please use unblocked ip for authentication, first login to `https://chat.openai.com/` to check ip availability if you can.
|
||||
|
||||
### GPT-4 Model (Optional)
|
||||
|
||||
If you configured a PLUS account and use the GPT-4 model, a HAR file (`chat.openai.com.har`) is required to complete CAPTCHA verification
|
||||
|
||||
1. Use a chromium-based browser (Chrome, Edge) or Safari to login to `https://chat.openai.com/`, then open the browser developer tools (F12), and switch to the Network tab.
|
||||
|
||||
2. Create a new chat and select the GPT-4 model, ask a question at will, click the Export HAR button under the Network tab, export the file `chat.openai.com.har`
|
||||
|
||||
### API Authentication (Optional)
|
||||
|
||||
Custom API keys for this fake API, just like OpenAI api
|
||||
@ -52,7 +60,6 @@ go build
|
||||
- `PUID` - A cookie found on chat.openai.com for Plus users. This gets around Cloudflare rate limits
|
||||
- `SERVER_HOST` - Set to 127.0.0.1 by default
|
||||
- `SERVER_PORT` - Set to 8080 by default
|
||||
- `OPENAI_EMAIL` and `OPENAI_PASSWORD` - It will automatically refresh your PUID if set (requires Plus account)
|
||||
- `ENABLE_HISTORY` - Set to true by default
|
||||
|
||||
### Files (Optional)
|
||||
@ -64,7 +71,7 @@ go build
|
||||
```
|
||||
- `access_tokens.json` - A JSON array of access tokens for cycling (Alternatively, send a PATCH request to the [correct endpoint](https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md))
|
||||
```
|
||||
["access_token1", "access_token2"...]
|
||||
[{token:"access_token1", puid:"puid1"}, {token:"access_token2", puid:"puid2"}...]
|
||||
```
|
||||
|
||||
## Admin API docs
|
||||
|
@ -24,7 +24,7 @@ email:password
|
||||
|
||||
すべての認証されたアクセストークンは `access_tokens.json` に保存されます
|
||||
|
||||
アクセストークンは 14 日後に自動更新されます
|
||||
アクセストークンは 7 日後に自動更新されます
|
||||
|
||||
注意!認証にはブロックされていない ip を使用してください。可能であれば、まず `https://chat.openai.com/` にログインして ip の可用性を確認してください。
|
||||
|
||||
|
19
README_ZH.md
19
README_ZH.md
@ -7,7 +7,7 @@
|
||||
|
||||
### 设置
|
||||
|
||||
配置账户邮箱和密码,自动生成和更新Access tokens(使用[OpenAIAuth](https://github.com/acheong08/OpenAIAuth/))
|
||||
配置账户邮箱和密码,自动生成和更新Access tokens 和 PUID(仅PLUS账户)(使用[OpenAIAuth](https://github.com/acheong08/OpenAIAuth/))
|
||||
|
||||
`accounts.txt` - 存放OpenAI账号邮箱和密码的文件
|
||||
|
||||
@ -18,12 +18,20 @@
|
||||
...
|
||||
```
|
||||
|
||||
所有登录后的Access tokens会存放在`access_tokens.json`
|
||||
所有登录后的Access tokens和PUID会存放在`access_tokens.json`
|
||||
|
||||
每14天自动更新Access tokens
|
||||
每7天自动更新Access tokens和PUID
|
||||
|
||||
注意! 请使用未封锁的ip登录账号,请先打开浏览器登录`https://chat.openai.com/`以检查ip是否可用
|
||||
|
||||
### GPT-4 设置(可选)
|
||||
|
||||
如果配置PLUS账户并使用GPT-4模型,则需要HAR文件(`chat.openai.com.har`)以完成captcha验证
|
||||
|
||||
1. 使用基于chromium的浏览器(Chrome,Edge)或Safari浏览器 登录`https://chat.openai.com/`,然后打开浏览器开发者工具(F12),并切换到网络标签页。
|
||||
|
||||
2. 新建聊天并选择GPT-4模型,随意问一个问题,点击网络标签页下的导出HAR按钮,导出文件`chat.openai.com.har`
|
||||
|
||||
### API 密钥(可选)
|
||||
|
||||
如OpenAI的官方API一样,可给模拟的API添加API密钥认证
|
||||
@ -50,6 +58,7 @@ go build
|
||||
- `SERVER_HOST` - 默认127.0.0.1
|
||||
- `SERVER_PORT` - 默认8080
|
||||
- `ENABLE_HISTORY` - 默认true,允许网页端历史记录
|
||||
|
||||
### 可选文件配置
|
||||
- `proxies.txt` - 存放代理地址的文件
|
||||
|
||||
@ -58,9 +67,9 @@ go build
|
||||
socks5://127.0.0.1:9999
|
||||
...
|
||||
```
|
||||
- `access_tokens.json` - 一个存放Access tokens JSON数组的文件 (可使用 PATCH请求更新Access tokens [correct endpoint](https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md))
|
||||
- `access_tokens.json` - 一个存放Access tokens 和PUID JSON数组的文件 (可使用 PATCH请求更新Access tokens [correct endpoint](https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md))
|
||||
```
|
||||
["access_token1", "access_token2"...]
|
||||
[{token:"access_token1", puid:"puid1"}, {token:"access_token2", puid:"puid2"}...]
|
||||
```
|
||||
|
||||
## 用户管理文档
|
||||
|
15
auth.go
15
auth.go
@ -43,7 +43,7 @@ func readAccounts() {
|
||||
}
|
||||
}
|
||||
}
|
||||
func scheduleToken() {
|
||||
func scheduleTokenPUID() {
|
||||
// Check if access_tokens.json exists
|
||||
if stat, err := os.Stat("access_tokens.json"); os.IsNotExist(err) {
|
||||
// Create the file
|
||||
@ -56,8 +56,8 @@ func scheduleToken() {
|
||||
} else {
|
||||
nowTime := time.Now()
|
||||
usedTime := nowTime.Sub(stat.ModTime())
|
||||
// update access token 14 days after last modify token file
|
||||
toExpire := 1.2096e15 - usedTime
|
||||
// update access token 7 days after last modify token file
|
||||
toExpire := 6.048e14 - usedTime
|
||||
if toExpire > 0 {
|
||||
file, err := os.Open("access_tokens.json")
|
||||
if err != nil {
|
||||
@ -65,7 +65,7 @@ func scheduleToken() {
|
||||
}
|
||||
defer file.Close()
|
||||
decoder := json.NewDecoder(file)
|
||||
var token_list []string
|
||||
var token_list []tokens.Secret
|
||||
err = decoder.Decode(&token_list)
|
||||
if err != nil {
|
||||
updateToken()
|
||||
@ -84,7 +84,7 @@ func scheduleToken() {
|
||||
}
|
||||
|
||||
func updateToken() {
|
||||
token_list := []string{}
|
||||
token_list := []tokens.Secret{}
|
||||
// Loop through each account
|
||||
for _, account := range accounts {
|
||||
if os.Getenv("CF_PROXY") != "" {
|
||||
@ -113,7 +113,8 @@ func updateToken() {
|
||||
return
|
||||
}
|
||||
access_token := authenticator.GetAccessToken()
|
||||
token_list = append(token_list, access_token)
|
||||
puid, _ := authenticator.GetPUID()
|
||||
token_list = append(token_list, tokens.Secret{access_token, puid})
|
||||
println("Success!")
|
||||
// Write authenticated account to authenticated_accounts.txt
|
||||
f, go_err := os.OpenFile("authenticated_accounts.txt", os.O_APPEND|os.O_WRONLY, 0600)
|
||||
@ -147,5 +148,5 @@ func updateToken() {
|
||||
}
|
||||
// Append access token to access_tokens.json
|
||||
ACCESS_TOKENS = tokens.NewAccessToken(token_list, true)
|
||||
time.AfterFunc(1.2096e15, updateToken)
|
||||
time.AfterFunc(6.048e14, updateToken)
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ import (
|
||||
arkose "github.com/acheong08/funcaptcha"
|
||||
)
|
||||
|
||||
func ConvertAPIRequest(api_request official_types.APIRequest) chatgpt_types.ChatGPTRequest {
|
||||
func ConvertAPIRequest(api_request official_types.APIRequest, puid string, proxy string) chatgpt_types.ChatGPTRequest {
|
||||
chatgpt_request := chatgpt_types.NewChatGPTRequest()
|
||||
if strings.HasPrefix(api_request.Model, "gpt-3.5") {
|
||||
chatgpt_request.Model = "text-davinci-002-render-sha"
|
||||
}
|
||||
if strings.HasPrefix(api_request.Model, "gpt-4") {
|
||||
token, _, err := arkose.GetOpenAIToken()
|
||||
token, _, err := arkose.GetOpenAIToken(puid, proxy)
|
||||
if err == nil {
|
||||
chatgpt_request.ArkoseToken = token
|
||||
} else {
|
||||
|
2
go.mod
2
go.mod
@ -5,7 +5,7 @@ go 1.20
|
||||
require (
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230719092354-c8cd4e19491b
|
||||
github.com/acheong08/endless v0.0.0-20230615162514-90545c7793fd
|
||||
github.com/acheong08/funcaptcha v1.2.2-0.20230702093045-02d1fbf1b0e8
|
||||
github.com/acheong08/funcaptcha v1.9.3-0.20230803133445-f4d081d60ac7
|
||||
github.com/bogdanfinn/fhttp v0.5.23
|
||||
github.com/bogdanfinn/tls-client v1.4.0
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
|
14
go.sum
14
go.sum
@ -1,19 +1,9 @@
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230609193408-55a0f33f1057 h1:AmqKpClFTUHREYekSfSy3Yn7MR/oc6WTfKtEyzB/J7o=
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230609193408-55a0f33f1057/go.mod h1:ES3Dh9hnbR2mDPlNTagj5e3b4nXECd4tbAjVgxggXEE=
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230716134840-dbf5ba4f9507 h1:1kZEmE1DeQEeIMHhQUqn+NqOdApF9BIv835ox09E2k8=
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230716134840-dbf5ba4f9507/go.mod h1:bkiXtklBFVpWHyWTys6Zhqb521i/gtT8cIUKWVx2m/M=
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230719092354-c8cd4e19491b h1:Jg+UV8bO5dXaisG/loeYFewewqmUJjjHGSxB9XZVqoc=
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230719092354-c8cd4e19491b/go.mod h1:bkiXtklBFVpWHyWTys6Zhqb521i/gtT8cIUKWVx2m/M=
|
||||
github.com/acheong08/endless v0.0.0-20230615162514-90545c7793fd h1:oIpfrRhD7Jus41dotbK+SQjWSFRnf1cLZUYCZpF/o/4=
|
||||
github.com/acheong08/endless v0.0.0-20230615162514-90545c7793fd/go.mod h1:0yO7neMeJLvKk/B/fq5votDY8rByrOPDubpvU+6saKo=
|
||||
github.com/acheong08/funcaptcha v0.2.1-0.20230628085018-57a8c9b81bc8 h1:COt2vPM8gz+PiUjeWH1enYPfMM3FiM/HFELqU6nO2PQ=
|
||||
github.com/acheong08/funcaptcha v0.2.1-0.20230628085018-57a8c9b81bc8/go.mod h1:VupbjtVAODvgyAB3Zo86fOA53G+UAmaV/Rk9jUCGuTU=
|
||||
github.com/acheong08/funcaptcha v0.2.1-0.20230628154248-28b05efd8e52 h1:cZ9RUUz+A5HUXQjIf9KJzF+K90EEcVdSJyWJc8S7qds=
|
||||
github.com/acheong08/funcaptcha v0.2.1-0.20230628154248-28b05efd8e52/go.mod h1:VupbjtVAODvgyAB3Zo86fOA53G+UAmaV/Rk9jUCGuTU=
|
||||
github.com/acheong08/funcaptcha v0.2.1-0.20230629044031-084e7dfaffef h1:B5fq4j+Qiu/6vay/70BG9mBuBgF28CnA4MTx1+J2V+o=
|
||||
github.com/acheong08/funcaptcha v0.2.1-0.20230629044031-084e7dfaffef/go.mod h1:VupbjtVAODvgyAB3Zo86fOA53G+UAmaV/Rk9jUCGuTU=
|
||||
github.com/acheong08/funcaptcha v1.2.2-0.20230702093045-02d1fbf1b0e8 h1:6VDA9GYZeDBc5xB6mmG9M/U2scvKCxd8izGxk6qHWmY=
|
||||
github.com/acheong08/funcaptcha v1.2.2-0.20230702093045-02d1fbf1b0e8/go.mod h1:azmXv2Mfbw5eBOnMw5e1yTMNVyku17klWhGtkHwm7PY=
|
||||
github.com/acheong08/funcaptcha v1.9.3-0.20230803133445-f4d081d60ac7 h1:lnvGKeyLfHKZOeYhUFRZE/GJjCAV1k3jW50e1UsZcVk=
|
||||
github.com/acheong08/funcaptcha v1.9.3-0.20230803133445-f4d081d60ac7/go.mod h1:azmXv2Mfbw5eBOnMw5e1yTMNVyku17klWhGtkHwm7PY=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/bogdanfinn/fhttp v0.5.23 h1:4Xb5OjYArB8GpnUw4A4r5jmt8UW0/Cvey3R9nS2dC9U=
|
||||
|
10
handlers.go
10
handlers.go
@ -70,7 +70,7 @@ func puidHandler(c *gin.Context) {
|
||||
|
||||
func tokensHandler(c *gin.Context) {
|
||||
// Get the request_tokens from the request (json) and update the request_tokens
|
||||
var request_tokens []string
|
||||
var request_tokens []tokens.Secret
|
||||
err := c.BindJSON(&request_tokens)
|
||||
if err != nil {
|
||||
c.String(400, "tokens not provided")
|
||||
@ -102,7 +102,7 @@ func nightmare(c *gin.Context) {
|
||||
}
|
||||
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
token := ACCESS_TOKENS.GetToken()
|
||||
token, puid := ACCESS_TOKENS.GetSecret()
|
||||
if authHeader != "" {
|
||||
customAccessToken := strings.Replace(authHeader, "Bearer ", "", 1)
|
||||
// Check if customAccessToken starts with sk-
|
||||
@ -120,9 +120,9 @@ func nightmare(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Convert the chat request to a ChatGPT request
|
||||
translated_request := chatgpt_request_converter.ConvertAPIRequest(original_request)
|
||||
translated_request := chatgpt_request_converter.ConvertAPIRequest(original_request, puid, proxy_url)
|
||||
|
||||
response, err := chatgpt.POSTconversation(translated_request, token, proxy_url)
|
||||
response, err := chatgpt.POSTconversation(translated_request, token, puid, proxy_url)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{
|
||||
"error": "error sending request",
|
||||
@ -147,7 +147,7 @@ func nightmare(c *gin.Context) {
|
||||
translated_request.Action = "continue"
|
||||
translated_request.ConversationID = continue_info.ConversationID
|
||||
translated_request.ParentMessageID = continue_info.ParentID
|
||||
response, err = chatgpt.POSTconversation(translated_request, token, proxy_url)
|
||||
response, err = chatgpt.POSTconversation(translated_request, token, puid, proxy_url)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{
|
||||
"error": "error sending request",
|
||||
|
@ -40,7 +40,7 @@ func init() {
|
||||
arkose.SetTLSClient(&client)
|
||||
}
|
||||
|
||||
func POSTconversation(message chatgpt_types.ChatGPTRequest, access_token string, proxy string) (*http.Response, error) {
|
||||
func POSTconversation(message chatgpt_types.ChatGPTRequest, access_token string, puid string, proxy string) (*http.Response, error) {
|
||||
if proxy != "" {
|
||||
client.SetProxy(proxy)
|
||||
}
|
||||
@ -61,8 +61,8 @@ func POSTconversation(message chatgpt_types.ChatGPTRequest, access_token string,
|
||||
return &http.Response{}, err
|
||||
}
|
||||
// Clear cookies
|
||||
if os.Getenv("PUID") != "" {
|
||||
request.Header.Set("Cookie", "_puid="+os.Getenv("PUID")+";")
|
||||
if puid != "" {
|
||||
request.Header.Set("Cookie", "_puid="+puid+";")
|
||||
}
|
||||
request.Header.Set("Content-Type", "application/json")
|
||||
request.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36")
|
||||
|
@ -6,12 +6,16 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Secret struct {
|
||||
Token string `json:"token"`
|
||||
PUID string `json:"puid"`
|
||||
}
|
||||
type AccessToken struct {
|
||||
tokens []string
|
||||
tokens []Secret
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func NewAccessToken(tokens []string, save bool) AccessToken {
|
||||
func NewAccessToken(tokens []Secret, save bool) AccessToken {
|
||||
// Save the tokens to a file
|
||||
if _, err := os.Stat("access_tokens.json"); os.IsNotExist(err) {
|
||||
// Create the file
|
||||
@ -32,7 +36,7 @@ func NewAccessToken(tokens []string, save bool) AccessToken {
|
||||
}
|
||||
}
|
||||
|
||||
func Save(tokens []string) bool {
|
||||
func Save(tokens []Secret) bool {
|
||||
file, err := os.OpenFile("access_tokens.json", os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return false
|
||||
@ -46,15 +50,15 @@ func Save(tokens []string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *AccessToken) GetToken() string {
|
||||
func (a *AccessToken) GetSecret() (string, string) {
|
||||
a.lock.Lock()
|
||||
defer a.lock.Unlock()
|
||||
|
||||
if len(a.tokens) == 0 {
|
||||
return ""
|
||||
return "", ""
|
||||
}
|
||||
|
||||
token := a.tokens[0]
|
||||
a.tokens = append(a.tokens[1:], token)
|
||||
return token
|
||||
secret := a.tokens[0]
|
||||
a.tokens = append(a.tokens[1:], secret)
|
||||
return secret.Token, secret.PUID
|
||||
}
|
||||
|
26
main.go
26
main.go
@ -3,12 +3,9 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"freechatgpt/internal/tokens"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/acheong08/OpenAIAuth/auth"
|
||||
"github.com/acheong08/endless"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/joho/godotenv"
|
||||
@ -49,27 +46,6 @@ func checkProxy() {
|
||||
|
||||
func init() {
|
||||
_ = godotenv.Load(".env")
|
||||
go func() {
|
||||
for {
|
||||
if os.Getenv("OPENAI_EMAIL") == "" || os.Getenv("OPENAI_PASSWORD") == "" {
|
||||
time.Sleep(24 * time.Hour * 7)
|
||||
continue
|
||||
}
|
||||
authenticator := auth.NewAuthenticator(os.Getenv("OPENAI_EMAIL"), os.Getenv("OPENAI_PASSWORD"), os.Getenv("http_proxy"))
|
||||
err := authenticator.Begin()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
break
|
||||
}
|
||||
puid, err := authenticator.GetPUID()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
os.Setenv("PUID", puid)
|
||||
println(puid)
|
||||
time.Sleep(24 * time.Hour * 7)
|
||||
}
|
||||
}()
|
||||
|
||||
HOST = os.Getenv("SERVER_HOST")
|
||||
PORT = os.Getenv("SERVER_PORT")
|
||||
@ -84,7 +60,7 @@ func init() {
|
||||
}
|
||||
checkProxy()
|
||||
readAccounts()
|
||||
scheduleToken()
|
||||
scheduleTokenPUID()
|
||||
}
|
||||
func main() {
|
||||
router := gin.Default()
|
||||
|
Reference in New Issue
Block a user