2023-04-05 10:07:07 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"encoding/json"
|
|
|
|
"freechatgpt/internal/chatgpt"
|
|
|
|
"freechatgpt/internal/tokens"
|
|
|
|
typings "freechatgpt/internal/typings"
|
|
|
|
"freechatgpt/internal/typings/responses"
|
|
|
|
"io"
|
2023-04-14 03:52:31 +00:00
|
|
|
"os"
|
2023-04-05 10:07:07 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
)
|
|
|
|
|
|
|
|
func passwordHandler(c *gin.Context) {
|
|
|
|
// 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
|
2023-04-14 03:52:31 +00:00
|
|
|
// Set environment variable
|
|
|
|
os.Setenv("ADMIN_PASSWORD", ADMIN_PASSWORD)
|
2023-04-05 10:07:07 +00:00
|
|
|
c.String(200, "password updated")
|
|
|
|
}
|
|
|
|
|
|
|
|
func tokensHandler(c *gin.Context) {
|
|
|
|
// 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.NewAccessToken(request_tokens)
|
|
|
|
c.String(200, "tokens updated")
|
|
|
|
}
|
|
|
|
func optionsHandler(c *gin.Context) {
|
|
|
|
// Set headers for CORS
|
|
|
|
c.Header("Access-Control-Allow-Origin", "*")
|
|
|
|
c.Header("Access-Control-Allow-Methods", "POST")
|
|
|
|
c.Header("Access-Control-Allow-Headers", "*")
|
|
|
|
c.JSON(200, gin.H{
|
|
|
|
"message": "pong",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
func nightmare(c *gin.Context) {
|
2023-04-08 12:01:00 +00:00
|
|
|
var original_request typings.APIRequest
|
|
|
|
err := c.BindJSON(&original_request)
|
2023-05-17 13:28:24 +00:00
|
|
|
if err != nil {
|
|
|
|
c.JSON(400, gin.H{"error": gin.H{
|
|
|
|
"message": "Request must be proper JSON",
|
|
|
|
"type": "invalid_request_error",
|
|
|
|
"param": nil,
|
|
|
|
"code": err.Error(),
|
|
|
|
}})
|
|
|
|
}
|
2023-04-05 10:07:07 +00:00
|
|
|
// Convert the chat request to a ChatGPT request
|
2023-04-08 12:01:00 +00:00
|
|
|
translated_request := chatgpt.ConvertAPIRequest(original_request)
|
2023-04-05 10:07:07 +00:00
|
|
|
// c.JSON(200, chatgpt_request)
|
2023-04-12 02:31:44 +00:00
|
|
|
|
2023-04-14 03:55:50 +00:00
|
|
|
// authHeader := c.GetHeader("Authorization")
|
2023-04-12 02:31:44 +00:00
|
|
|
token := ACCESS_TOKENS.GetToken()
|
2023-04-14 03:55:50 +00:00
|
|
|
// if authHeader != "" {
|
|
|
|
// customAccessToken := strings.Replace(authHeader, "Bearer ", "", 1)
|
|
|
|
// if customAccessToken != "" {
|
|
|
|
// token = customAccessToken
|
|
|
|
// println("customAccessToken set:" + customAccessToken)
|
|
|
|
// }
|
|
|
|
// }
|
2023-04-12 02:31:44 +00:00
|
|
|
|
2023-04-30 09:13:20 +00:00
|
|
|
response, err := chatgpt.SendRequest(translated_request, token)
|
2023-04-05 10:07:07 +00:00
|
|
|
if err != nil {
|
|
|
|
c.JSON(500, gin.H{
|
|
|
|
"error": "error sending request",
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != 200 {
|
2023-04-17 12:59:48 +00:00
|
|
|
// Try read response body as JSON
|
|
|
|
var error_response map[string]interface{}
|
|
|
|
err = json.NewDecoder(response.Body).Decode(&error_response)
|
|
|
|
if err != nil {
|
2023-05-17 13:21:31 +00:00
|
|
|
c.JSON(500, gin.H{"error": gin.H{
|
|
|
|
"message": "Unknown error",
|
|
|
|
"type": "internal_server_error",
|
|
|
|
"param": nil,
|
|
|
|
"code": "500",
|
|
|
|
}})
|
2023-04-17 12:59:48 +00:00
|
|
|
return
|
|
|
|
}
|
2023-05-17 13:21:31 +00:00
|
|
|
c.JSON(response.StatusCode, gin.H{"error": gin.H{
|
|
|
|
"message": error_response["detail"],
|
|
|
|
"type": response.Status,
|
|
|
|
"param": nil,
|
|
|
|
"code": "error",
|
|
|
|
}})
|
2023-04-05 10:07:07 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
// Create a bufio.Reader from the response body
|
|
|
|
reader := bufio.NewReader(response.Body)
|
|
|
|
|
|
|
|
var fulltext string
|
|
|
|
|
|
|
|
// Read the response byte by byte until a newline character is encountered
|
2023-04-08 12:01:00 +00:00
|
|
|
if original_request.Stream {
|
2023-04-06 02:00:42 +00:00
|
|
|
// Response content type is text/event-stream
|
|
|
|
c.Header("Content-Type", "text/event-stream")
|
|
|
|
} else {
|
|
|
|
// Response content type is application/json
|
|
|
|
c.Header("Content-Type", "application/json")
|
|
|
|
}
|
2023-04-05 10:07:07 +00:00
|
|
|
for {
|
|
|
|
line, err := reader.ReadString('\n')
|
|
|
|
if err != nil {
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if len(line) < 6 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// Remove "data: " from the beginning of the line
|
|
|
|
line = line[6:]
|
2023-04-11 05:08:38 +00:00
|
|
|
// Check if line starts with [DONE]
|
|
|
|
if !strings.HasPrefix(line, "[DONE]") {
|
|
|
|
// Parse the line as JSON
|
|
|
|
var original_response responses.Data
|
|
|
|
err = json.Unmarshal([]byte(line), &original_response)
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if original_response.Error != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if original_response.Message.Content.Parts[0] == "" || original_response.Message.Author.Role != "assistant" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if original_response.Message.Metadata.Timestamp == "absolute" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
tmp_fulltext := original_response.Message.Content.Parts[0]
|
|
|
|
original_response.Message.Content.Parts[0] = strings.ReplaceAll(original_response.Message.Content.Parts[0], fulltext, "")
|
2023-04-22 03:12:10 +00:00
|
|
|
translated_response := responses.NewChatCompletionChunk(original_response.Message.Content.Parts[0])
|
2023-04-05 10:07:07 +00:00
|
|
|
|
2023-04-11 05:08:38 +00:00
|
|
|
// Stream the response to the client
|
2023-05-10 05:01:01 +00:00
|
|
|
response_string := translated_response.String()
|
2023-04-11 05:08:38 +00:00
|
|
|
if original_request.Stream {
|
|
|
|
_, err = c.Writer.WriteString("data: " + string(response_string) + "\n\n")
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2023-04-05 10:07:07 +00:00
|
|
|
}
|
|
|
|
|
2023-04-11 05:08:38 +00:00
|
|
|
// Flush the response writer buffer to ensure that the client receives each line as it's written
|
|
|
|
c.Writer.Flush()
|
|
|
|
fulltext = tmp_fulltext
|
|
|
|
} else {
|
2023-04-08 12:01:00 +00:00
|
|
|
if !original_request.Stream {
|
2023-04-22 03:12:10 +00:00
|
|
|
full_response := responses.NewChatCompletion(fulltext)
|
2023-04-05 10:07:07 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
c.JSON(200, full_response)
|
|
|
|
return
|
|
|
|
}
|
2023-05-10 05:01:01 +00:00
|
|
|
final_line := responses.StopChunk()
|
|
|
|
c.Writer.WriteString("data: " + final_line.String() + "\n\n")
|
|
|
|
|
2023-05-10 07:42:24 +00:00
|
|
|
c.String(200, "data: [DONE]\n\n")
|
2023-05-10 07:43:11 +00:00
|
|
|
return
|
2023-04-11 05:08:38 +00:00
|
|
|
|
2023-04-05 10:07:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|