This repository has been archived by the owner on Aug 10, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 379
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #92 from xqdoo00o/master
Chinese doc, auto renew token, uniform proxy
- Loading branch information
Showing
8 changed files
with
540 additions
and
323 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# ChatGPT-to-API | ||
从ChatGPT网站模拟使用API | ||
|
||
**模拟API地址: http://127.0.0.1:8080/v1/chat/completions.** | ||
|
||
## 使用 | ||
|
||
### 设置 | ||
|
||
配置账户邮箱和密码,自动生成和更新Access tokens(使用[OpenAIAuth](https://github.com/acheong08/OpenAIAuth/)) | ||
|
||
`accounts.txt` - 存放OpenAI账号邮箱和密码的文件 | ||
|
||
格式: | ||
``` | ||
邮箱:密码 | ||
邮箱:密码 | ||
... | ||
``` | ||
|
||
所有登录后的Access tokens会存放在`access_tokens.json` | ||
|
||
每14天自动更新Access tokens | ||
|
||
注意! 请使用未封锁的ip登录账号,请先打开浏览器登录`https://chat.openai.com/`以检查ip是否可用 | ||
|
||
### API 密钥(可选) | ||
|
||
如OpenAI的官方API一样,可给模拟的API添加API密钥认证 | ||
|
||
`api_keys.txt` - 存放API密钥的文件 | ||
|
||
格式: | ||
``` | ||
sk-123456 | ||
88888888 | ||
... | ||
``` | ||
|
||
## 开始 | ||
``` | ||
git clone https://github.com/xqdoo00o/ChatGPT-to-API | ||
cd ChatGPT-to-API | ||
go build | ||
./freechatgpt | ||
``` | ||
|
||
### 环境变量 | ||
- `PUID` - Plus账户可在`chat.openai.com`的cookies里找到,用于绕过cf的频率限制 | ||
- `SERVER_HOST` - 默认127.0.0.1 | ||
- `SERVER_PORT` - 默认8080 | ||
- `ENABLE_HISTORY` - 默认true,允许网页端历史记录 | ||
### 可选文件配置 | ||
- `proxies.txt` - 存放代理地址的文件 | ||
|
||
``` | ||
http://127.0.0.1:8888 | ||
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_token1", "access_token2"...] | ||
``` | ||
## 用户管理文档 | ||
https://github.com/acheong08/ChatGPT-to-API/blob/master/docs/admin.md | ||
## API使用说明 | ||
https://platform.openai.com/docs/api-reference/chat |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
"time" | ||
|
||
"freechatgpt/internal/tokens" | ||
|
||
"github.com/acheong08/OpenAIAuth/auth" | ||
) | ||
|
||
var accounts []Account | ||
|
||
type Account struct { | ||
Email string `json:"username"` | ||
Password string `json:"password"` | ||
} | ||
|
||
// Read accounts.txt and create a list of accounts | ||
func readAccounts() { | ||
accounts = []Account{} | ||
// Read accounts.txt and create a list of accounts | ||
if _, err := os.Stat("accounts.txt"); err == nil { | ||
// Each line is a proxy, put in proxies array | ||
file, _ := os.Open("accounts.txt") | ||
defer file.Close() | ||
scanner := bufio.NewScanner(file) | ||
for scanner.Scan() { | ||
// Split by : | ||
line := strings.Split(scanner.Text(), ":") | ||
// Create an account | ||
account := Account{ | ||
Email: line[0], | ||
Password: line[1], | ||
} | ||
// Append to accounts | ||
accounts = append(accounts, account) | ||
} | ||
} | ||
} | ||
func scheduleToken() { | ||
// Check if access_tokens.json exists | ||
if stat, err := os.Stat("access_tokens.json"); os.IsNotExist(err) { | ||
// Create the file | ||
file, err := os.Create("access_tokens.json") | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer file.Close() | ||
updateToken() | ||
} else { | ||
nowTime := time.Now() | ||
usedTime := nowTime.Sub(stat.ModTime()) | ||
// update access token 14 days after last modify token file | ||
toExpire := 1.2096e15 - usedTime | ||
if toExpire > 0 { | ||
file, err := os.Open("access_tokens.json") | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer file.Close() | ||
decoder := json.NewDecoder(file) | ||
var token_list []string | ||
err = decoder.Decode(&token_list) | ||
if err != nil { | ||
updateToken() | ||
return | ||
} | ||
if len(token_list) == 0 { | ||
updateToken() | ||
} else { | ||
ACCESS_TOKENS = tokens.NewAccessToken(token_list, false) | ||
time.AfterFunc(toExpire, updateToken) | ||
} | ||
} else { | ||
updateToken() | ||
} | ||
} | ||
} | ||
|
||
func updateToken() { | ||
token_list := []string{} | ||
// Loop through each account | ||
for _, account := range accounts { | ||
if os.Getenv("CF_PROXY") != "" { | ||
// exec warp-cli disconnect and connect | ||
exec.Command("warp-cli", "disconnect").Run() | ||
exec.Command("warp-cli", "connect").Run() | ||
time.Sleep(5 * time.Second) | ||
} | ||
println("Updating access token for " + account.Email) | ||
var proxy_url string | ||
if len(proxies) == 0 { | ||
proxy_url = "" | ||
} else { | ||
proxy_url = proxies[0] | ||
// Push used proxy to the back of the list | ||
proxies = append(proxies[1:], proxies[0]) | ||
} | ||
authenticator := auth.NewAuthenticator(account.Email, account.Password, proxy_url) | ||
err := authenticator.Begin() | ||
if err != nil { | ||
// println("Error: " + err.Details) | ||
println("Location: " + err.Location) | ||
println("Status code: " + fmt.Sprint(err.StatusCode)) | ||
println("Details: " + err.Details) | ||
println("Embedded error: " + err.Error.Error()) | ||
return | ||
} | ||
access_token := authenticator.GetAccessToken() | ||
token_list = append(token_list, access_token) | ||
println("Success!") | ||
// Write authenticated account to authenticated_accounts.txt | ||
f, go_err := os.OpenFile("authenticated_accounts.txt", os.O_APPEND|os.O_WRONLY, 0600) | ||
if go_err != nil { | ||
continue | ||
} | ||
defer f.Close() | ||
if _, go_err = f.WriteString(account.Email + ":" + account.Password + "\n"); go_err != nil { | ||
continue | ||
} | ||
// Remove accounts.txt | ||
os.Remove("accounts.txt") | ||
// Create accounts.txt | ||
f, go_err = os.Create("accounts.txt") | ||
if go_err != nil { | ||
continue | ||
} | ||
defer f.Close() | ||
// Remove account from accounts | ||
accounts = accounts[1:] | ||
// Write unauthenticated accounts to accounts.txt | ||
for _, acc := range accounts { | ||
// Check if account is authenticated | ||
if acc.Email == account.Email { | ||
continue | ||
} | ||
if _, go_err = f.WriteString(acc.Email + ":" + acc.Password + "\n"); go_err != nil { | ||
continue | ||
} | ||
} | ||
} | ||
// Append access token to access_tokens.json | ||
ACCESS_TOKENS = tokens.NewAccessToken(token_list, true) | ||
time.AfterFunc(1.2096e15, updateToken) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.