package main import ( "bufio" "encoding/json" "freechatgpt/internal/chatgpt" "freechatgpt/internal/tokens" typings "freechatgpt/internal/typings" "freechatgpt/internal/typings/responses" "io" "os" "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 // Set environment variable os.Setenv("ADMIN_PASSWORD", ADMIN_PASSWORD) c.String(200, "password updated") } func puidHandler(c *gin.Context) { // Get the password from the request (json) and update the password 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 } // Set environment variable os.Setenv("PUID", puid.PUID) c.String(200, "puid 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) { var original_request typings.APIRequest err := c.BindJSON(&original_request) 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(), }}) } // Convert the chat request to a ChatGPT request translated_request := chatgpt.ConvertAPIRequest(original_request) // c.JSON(200, chatgpt_request) // authHeader := c.GetHeader("Authorization") token := ACCESS_TOKENS.GetToken() // if authHeader != "" { // customAccessToken := strings.Replace(authHeader, "Bearer ", "", 1) // if customAccessToken != "" { // token = customAccessToken // println("customAccessToken set:" + customAccessToken) // } // } response, err := chatgpt.SendRequest(translated_request, token) if err != nil { c.JSON(response.StatusCode, gin.H{ "error": "error sending request", "message": response.Status, }) return } defer response.Body.Close() if response.StatusCode != 200 { // Try read response body as JSON var error_response map[string]interface{} err = json.NewDecoder(response.Body).Decode(&error_response) if err != nil { // Read response body body, _ := io.ReadAll(response.Body) c.JSON(500, gin.H{"error": gin.H{ "message": "Unknown error", "type": "internal_server_error", "param": nil, "code": "500", "details": string(body), }}) return } c.JSON(response.StatusCode, gin.H{"error": gin.H{ "message": error_response["detail"], "type": response.Status, "param": nil, "code": "error", }}) 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 if original_request.Stream { // 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") } 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:] // 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 == nil { continue } 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, "") translated_response := responses.NewChatCompletionChunk(original_response.Message.Content.Parts[0]) // Stream the response to the client response_string := translated_response.String() if original_request.Stream { _, err = c.Writer.WriteString("data: " + string(response_string) + "\n\n") if err != nil { return } } // Flush the response writer buffer to ensure that the client receives each line as it's written c.Writer.Flush() fulltext = tmp_fulltext } else { if !original_request.Stream { full_response := responses.NewChatCompletion(fulltext) if err != nil { return } c.JSON(200, full_response) return } final_line := responses.StopChunk() c.Writer.WriteString("data: " + final_line.String() + "\n\n") c.String(200, "data: [DONE]\n\n") return } } }