1
0
This commit is contained in:
Antonio Cheong 2023-04-03 00:37:16 +08:00
parent 955e530e35
commit bec2d3a9b5
4 changed files with 75 additions and 41 deletions

2
go.mod
View File

@ -3,6 +3,7 @@ module freechatgpt
go 1.20
require (
github.com/bogdanfinn/fhttp v0.5.19
github.com/bogdanfinn/tls-client v1.3.8
github.com/gin-gonic/gin v1.9.0
github.com/google/uuid v1.3.0
@ -11,7 +12,6 @@ require (
require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/bogdanfinn/fhttp v0.5.19 // indirect
github.com/bogdanfinn/utls v1.5.15 // indirect
github.com/bytedance/sonic v1.8.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect

View File

@ -1,7 +1,6 @@
package chatgpt
import (
"bufio"
"bytes"
"encoding/json"
@ -22,32 +21,31 @@ var (
client, _ = tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
)
func constructRequest(body typings.ChatGPTRequest, puid string) (*http.Request, error) {
func SendRequest(message typings.ChatGPTRequest, puid *string, access_token string) (*http.Response, error) {
// JSONify the body and add it to the request
body_json, err := json.Marshal(body)
if err != nil {
return &http.Request{}, err
}
request, err := http.NewRequest(http.MethodPost, "https://chat.openai.com/backend-api/conversation", bufio.NewReader(bytes.NewBuffer(body_json)))
request.Header.Set("Host", "chat.openai.com")
request.Header.Set("Origin", "https://chat.openai.com/chat")
request.Header.Set("Content-Type", "application/json")
request.Header.Set("Connection", "keep-alive")
request.Header.Set("Keep-Alive", "timeout=360")
request.Header.Set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36")
request.AddCookie(&http.Cookie{
Name: "_puid",
Value: puid,
})
return request, err
}
func SendRequest(message typings.ChatGPTRequest, puid string) (*http.Response, error) {
request, err := constructRequest(message, puid)
body_json, err := json.Marshal(message)
if err != nil {
return &http.Response{}, err
}
request, err := http.NewRequest(http.MethodPost, "https://chat.openai.com/backend-api/conversation", bytes.NewBuffer(body_json))
if err != nil {
return &http.Response{}, err
}
request.Header.Set("Content-Type", "application/json")
request.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36")
request.Header.Set("Accept", "*/*")
request.AddCookie(&http.Cookie{
Name: "_puid",
Value: *puid,
})
if access_token != "" {
request.Header.Set("Authorization", "Bearer "+access_token)
}
if err != nil {
return &http.Response{}, err
}
println(string(body_json))
response, err := client.Do(request)
return response, err
}

29
internal/tokens/tokens.go Normal file
View File

@ -0,0 +1,29 @@
package tokens
import (
"sync"
)
type AccessToken struct {
tokens []string
lock sync.Mutex
}
func NewAccessToken(tokens []string) AccessToken {
return AccessToken{
tokens: tokens,
}
}
func (a *AccessToken) GetToken() string {
a.lock.Lock()
defer a.lock.Unlock()
if len(a.tokens) == 0 {
return ""
}
token := a.tokens[0]
a.tokens = append(a.tokens[1:], token)
return token
}

41
main.go
View File

@ -2,6 +2,7 @@ package main
import (
"freechatgpt/internal/chatgpt"
"freechatgpt/internal/tokens"
typings "freechatgpt/internal/typings"
"io"
"os"
@ -13,7 +14,7 @@ import (
var HOST string
var PORT string
var PUID string
var ACCESS_TOKENS []string
var ACCESS_TOKENS tokens.AccessToken
func init() {
HOST = os.Getenv("SERVER_HOST")
@ -35,37 +36,42 @@ func main() {
/// Admin routes
router.PATCH("/admin/puid", admin_check, func(c *gin.Context) {
// Get the PUID from the request and update the PUID
puid := c.Query("puid")
if puid != "" {
PUID = puid
} else {
// Get the puid from the request (json) and update the puid
type puid_struct struct {
PUID string `json:"puid"`
}
var puid puid_struct
err := c.BindJSON(&puid)
if err != nil {
c.String(400, "puid not provided")
return
}
PUID = puid.PUID
c.String(200, "puid updated")
})
router.PATCH("/admin/password", admin_check, func(c *gin.Context) {
// Get the password from the request and update the password
password := c.Query("password")
if password != "" {
ADMIN_PASSWORD = password
} else {
// Get the password from the request (json) and update the password
type password_struct struct {
Password string `json:"password"`
}
var password password_struct
err := c.BindJSON(&password)
if err != nil {
c.String(400, "password not provided")
return
}
ADMIN_PASSWORD = password.Password
c.String(200, "password updated")
})
router.PATCH("/admin/tokens", admin_check, func(c *gin.Context) {
// Get the tokens from the request (json) and update the tokens
var tokens []string
err := c.BindJSON(&tokens)
// Get the request_tokens from the request (json) and update the request_tokens
var request_tokens []string
err := c.BindJSON(&request_tokens)
if err != nil {
c.String(400, "tokens not provided")
return
}
ACCESS_TOKENS = tokens
ACCESS_TOKENS = tokens.NewAccessToken(request_tokens)
c.String(200, "tokens updated")
})
/// Public routes
@ -79,12 +85,13 @@ func main() {
// Convert the chat request to a ChatGPT request
chatgpt_request := chatgpt.ConvertAPIRequest(chat_request)
// c.JSON(200, chatgpt_request)
response, err := chatgpt.SendRequest(chatgpt_request, PUID)
response, err := chatgpt.SendRequest(chatgpt_request, &PUID, ACCESS_TOKENS.GetToken())
if err != nil {
c.String(500, "error sending request")
return
}
defer response.Body.Close()
c.Status(response.StatusCode)
c.Stream(func(w io.Writer) bool {
// Write data to client
io.Copy(w, response.Body)