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

Commit 5afd148

Browse files
author
Antonio Cheong
authored
Merge pull request #92 from xqdoo00o/master
Chinese doc, auto renew token, uniform proxy
2 parents 59cd92b + 2b22c04 commit 5afd148

File tree

8 files changed

+540
-323
lines changed

8 files changed

+540
-323
lines changed

README.md

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,63 +6,66 @@ Create a fake API using ChatGPT's website
66
77
**API endpoint: http://127.0.0.1:8080/v1/chat/completions.**
88

9-
[中文文档(Chinese Docs)](README_CN.md)
10-
11-
## Help needed
12-
- Documentation.
13-
9+
[中文文档(Chinese Docs)](https://github.com/xqdoo00o/ChatGPT-to-API/blob/master/README_ZH.md)
1410
## Setup
15-
16-
<details>
17-
<summary>
1811

1912
### Authentication
20-
</summary>
21-
22-
Access token retrieval has been automated:
23-
https://github.com/acheong08/ChatGPT-to-API/tree/master/tools/authenticator
2413

25-
Converting from a newline delimited list of access tokens to `access_tokens.json`
26-
```bash
27-
#!/bin/bash
14+
Access token retrieval has been automated by [OpenAIAuth](https://github.com/acheong08/OpenAIAuth/) with account email & password.
15+
16+
`accounts.txt` - A list of accounts separated by new line
2817

29-
START="["
30-
END="]"
18+
Format:
19+
```
20+
email:password
21+
...
22+
```
3123

32-
TOKENS=""
24+
All authenticated access tokens will store in `access_tokens.json`
3325

34-
while read -r line; do
35-
if [ -z "$TOKENS" ]; then
36-
TOKENS="\"$line\""
37-
else
38-
TOKENS+=",\"$line\""
39-
fi
40-
done < access_tokens.txt
26+
Auto renew access tokens after 14 days
4127

42-
echo "$START$TOKENS$END" > access_tokens.json
43-
```
28+
Caution! please use unblocked ip for authentication, first login to `https://chat.openai.com/` to check ip availability if you can.
29+
30+
### API Authentication (Optional)
4431

45-
</details>
32+
Custom API keys for this fake API, just like OpenAI api
33+
34+
`api_keys.txt` - A list of API keys separated by new line
35+
36+
Format:
37+
```
38+
sk-123456
39+
88888888
40+
...
41+
```
4642

4743
## Getting set up
48-
49-
`git clone https://github.com/acheong08/ChatGPT-to-API`
50-
`cd ChatGPT-to-API`
51-
`go build`
52-
`./freechatgpt`
44+
```
45+
git clone https://github.com/xqdoo00o/ChatGPT-to-API
46+
cd ChatGPT-to-API
47+
go build
48+
./freechatgpt
49+
```
5350

5451
### Environment variables
5552
- `PUID` - A cookie found on chat.openai.com for Plus users. This gets around Cloudflare rate limits
56-
- `http_proxy` - SOCKS5 or HTTP proxy. `socks5://HOST:PORT`
5753
- `SERVER_HOST` - Set to 127.0.0.1 by default
5854
- `SERVER_PORT` - Set to 8080 by default
5955
- `OPENAI_EMAIL` and `OPENAI_PASSWORD` - It will automatically refresh your PUID if set (requires Plus account)
56+
- `ENABLE_HISTORY` - Set to true by default
6057

6158
### Files (Optional)
62-
- `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))
63-
- `proxies.txt` - A list of proxies separated by new line (Format: `USERNAME:PASSWORD:HOST:PORT`)
64-
59+
- `proxies.txt` - A list of proxies separated by new line
6560

61+
```
62+
http://127.0.0.1:8888
63+
...
64+
```
65+
- `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))
66+
```
67+
["access_token1", "access_token2"...]
68+
```
6669
6770
## Admin API docs
6871
https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md

README_ZH.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# ChatGPT-to-API
2+
从ChatGPT网站模拟使用API
3+
4+
**模拟API地址: http://127.0.0.1:8080/v1/chat/completions.**
5+
6+
## 使用
7+
8+
### 设置
9+
10+
配置账户邮箱和密码,自动生成和更新Access tokens(使用[OpenAIAuth](https://github.com/acheong08/OpenAIAuth/)
11+
12+
`accounts.txt` - 存放OpenAI账号邮箱和密码的文件
13+
14+
格式:
15+
```
16+
邮箱:密码
17+
邮箱:密码
18+
...
19+
```
20+
21+
所有登录后的Access tokens会存放在`access_tokens.json`
22+
23+
每14天自动更新Access tokens
24+
25+
注意! 请使用未封锁的ip登录账号,请先打开浏览器登录`https://chat.openai.com/`以检查ip是否可用
26+
27+
### API 密钥(可选)
28+
29+
如OpenAI的官方API一样,可给模拟的API添加API密钥认证
30+
31+
`api_keys.txt` - 存放API密钥的文件
32+
33+
格式:
34+
```
35+
sk-123456
36+
88888888
37+
...
38+
```
39+
40+
## 开始
41+
```
42+
git clone https://github.com/xqdoo00o/ChatGPT-to-API
43+
cd ChatGPT-to-API
44+
go build
45+
./freechatgpt
46+
```
47+
48+
### 环境变量
49+
- `PUID` - Plus账户可在`chat.openai.com`的cookies里找到,用于绕过cf的频率限制
50+
- `SERVER_HOST` - 默认127.0.0.1
51+
- `SERVER_PORT` - 默认8080
52+
- `ENABLE_HISTORY` - 默认true,允许网页端历史记录
53+
### 可选文件配置
54+
- `proxies.txt` - 存放代理地址的文件
55+
56+
```
57+
http://127.0.0.1:8888
58+
socks5://127.0.0.1:9999
59+
...
60+
```
61+
- `access_tokens.json` - 一个存放Access tokens JSON数组的文件 (可使用 PATCH请求更新Access tokens [correct endpoint](https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md))
62+
```
63+
["access_token1", "access_token2"...]
64+
```
65+
66+
## 用户管理文档
67+
https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md
68+
69+
## API使用说明
70+
https://platform.openai.com/docs/api-reference/chat

auth.go

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"encoding/json"
6+
"fmt"
7+
"os"
8+
"os/exec"
9+
"strings"
10+
"time"
11+
12+
"freechatgpt/internal/tokens"
13+
14+
"github.com/acheong08/OpenAIAuth/auth"
15+
)
16+
17+
var accounts []Account
18+
19+
type Account struct {
20+
Email string `json:"username"`
21+
Password string `json:"password"`
22+
}
23+
24+
// Read accounts.txt and create a list of accounts
25+
func readAccounts() {
26+
accounts = []Account{}
27+
// Read accounts.txt and create a list of accounts
28+
if _, err := os.Stat("accounts.txt"); err == nil {
29+
// Each line is a proxy, put in proxies array
30+
file, _ := os.Open("accounts.txt")
31+
defer file.Close()
32+
scanner := bufio.NewScanner(file)
33+
for scanner.Scan() {
34+
// Split by :
35+
line := strings.Split(scanner.Text(), ":")
36+
// Create an account
37+
account := Account{
38+
Email: line[0],
39+
Password: line[1],
40+
}
41+
// Append to accounts
42+
accounts = append(accounts, account)
43+
}
44+
}
45+
}
46+
func scheduleToken() {
47+
// Check if access_tokens.json exists
48+
if stat, err := os.Stat("access_tokens.json"); os.IsNotExist(err) {
49+
// Create the file
50+
file, err := os.Create("access_tokens.json")
51+
if err != nil {
52+
panic(err)
53+
}
54+
defer file.Close()
55+
updateToken()
56+
} else {
57+
nowTime := time.Now()
58+
usedTime := nowTime.Sub(stat.ModTime())
59+
// update access token 14 days after last modify token file
60+
toExpire := 1.2096e15 - usedTime
61+
if toExpire > 0 {
62+
file, err := os.Open("access_tokens.json")
63+
if err != nil {
64+
panic(err)
65+
}
66+
defer file.Close()
67+
decoder := json.NewDecoder(file)
68+
var token_list []string
69+
err = decoder.Decode(&token_list)
70+
if err != nil {
71+
updateToken()
72+
return
73+
}
74+
if len(token_list) == 0 {
75+
updateToken()
76+
} else {
77+
ACCESS_TOKENS = tokens.NewAccessToken(token_list, false)
78+
time.AfterFunc(toExpire, updateToken)
79+
}
80+
} else {
81+
updateToken()
82+
}
83+
}
84+
}
85+
86+
func updateToken() {
87+
token_list := []string{}
88+
// Loop through each account
89+
for _, account := range accounts {
90+
if os.Getenv("CF_PROXY") != "" {
91+
// exec warp-cli disconnect and connect
92+
exec.Command("warp-cli", "disconnect").Run()
93+
exec.Command("warp-cli", "connect").Run()
94+
time.Sleep(5 * time.Second)
95+
}
96+
println("Updating access token for " + account.Email)
97+
var proxy_url string
98+
if len(proxies) == 0 {
99+
proxy_url = ""
100+
} else {
101+
proxy_url = proxies[0]
102+
// Push used proxy to the back of the list
103+
proxies = append(proxies[1:], proxies[0])
104+
}
105+
authenticator := auth.NewAuthenticator(account.Email, account.Password, proxy_url)
106+
err := authenticator.Begin()
107+
if err != nil {
108+
// println("Error: " + err.Details)
109+
println("Location: " + err.Location)
110+
println("Status code: " + fmt.Sprint(err.StatusCode))
111+
println("Details: " + err.Details)
112+
println("Embedded error: " + err.Error.Error())
113+
return
114+
}
115+
access_token := authenticator.GetAccessToken()
116+
token_list = append(token_list, access_token)
117+
println("Success!")
118+
// Write authenticated account to authenticated_accounts.txt
119+
f, go_err := os.OpenFile("authenticated_accounts.txt", os.O_APPEND|os.O_WRONLY, 0600)
120+
if go_err != nil {
121+
continue
122+
}
123+
defer f.Close()
124+
if _, go_err = f.WriteString(account.Email + ":" + account.Password + "\n"); go_err != nil {
125+
continue
126+
}
127+
// Remove accounts.txt
128+
os.Remove("accounts.txt")
129+
// Create accounts.txt
130+
f, go_err = os.Create("accounts.txt")
131+
if go_err != nil {
132+
continue
133+
}
134+
defer f.Close()
135+
// Remove account from accounts
136+
accounts = accounts[1:]
137+
// Write unauthenticated accounts to accounts.txt
138+
for _, acc := range accounts {
139+
// Check if account is authenticated
140+
if acc.Email == account.Email {
141+
continue
142+
}
143+
if _, go_err = f.WriteString(acc.Email + ":" + acc.Password + "\n"); go_err != nil {
144+
continue
145+
}
146+
}
147+
}
148+
// Append access token to access_tokens.json
149+
ACCESS_TOKENS = tokens.NewAccessToken(token_list, true)
150+
time.AfterFunc(1.2096e15, updateToken)
151+
}

conversion/requests/chatgpt/convert.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ func ConvertAPIRequest(api_request official_types.APIRequest) chatgpt_types.Chat
2222
fmt.Println("Error getting Arkose token: ", err)
2323
}
2424
chatgpt_request.Model = api_request.Model
25+
// Cover some models like gpt-4-32k
26+
if len(api_request.Model) >= 7 && api_request.Model[6] >= 48 && api_request.Model[6] <= 57 {
27+
chatgpt_request.Model = "gpt-4"
28+
}
2529
}
2630
if api_request.PluginIDs != nil {
2731
chatgpt_request.PluginIDs = api_request.PluginIDs
2832
chatgpt_request.Model = "gpt-4-plugins"
2933
}
30-
3134
for _, api_message := range api_request.Messages {
3235
if api_message.Role == "system" {
3336
api_message.Role = "critic"

0 commit comments

Comments
 (0)