package platform import ( "bufio" "bytes" "encoding/json" "fmt" "io" "strings" http "github.com/bogdanfinn/fhttp" "github.com/gin-gonic/gin" "github.com/linweiyuan/go-chatgpt-api/api" "github.com/linweiyuan/go-logger/logger" ) func CreateChatCompletions(c *gin.Context) { body, _ := io.ReadAll(c.Request.Body) var request struct { Stream bool `json:"stream"` } json.Unmarshal(body, &request) url := c.Request.URL.Path if strings.Contains(url, "/chat") { url = apiCreateChatCompletions } else { url = apiCreateCompletions } resp, err := handlePost(c, url, body, request.Stream) if err != nil { return } defer resp.Body.Close() if resp.StatusCode == http.StatusUnauthorized { logger.Error(fmt.Sprintf(api.AccountDeactivatedErrorMessage, c.GetString(api.EmailKey))) responseMap := make(map[string]interface{}) json.NewDecoder(resp.Body).Decode(&responseMap) c.AbortWithStatusJSON(resp.StatusCode, responseMap) return } if request.Stream { handleCompletionsResponse(c, resp) } else { io.Copy(c.Writer, resp.Body) } } func CreateCompletions(c *gin.Context) { CreateChatCompletions(c) } func handleCompletionsResponse(c *gin.Context, resp *http.Response) { c.Writer.Header().Set("Content-Type", "text/event-stream; charset=utf-8") reader := bufio.NewReader(resp.Body) for { if c.Request.Context().Err() != nil { break } line, err := reader.ReadString('\n') if err != nil { break } line = strings.TrimSpace(line) if strings.HasPrefix(line, "event") || strings.HasPrefix(line, "data: 20") || line == "" { continue } c.Writer.Write([]byte(line + "\n\n")) c.Writer.Flush() } } func handlePost(c *gin.Context, url string, data []byte, stream bool) (*http.Response, error) { req, _ := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(data)) req.Header.Set(api.AuthorizationHeader, api.GetAccessToken(c)) if stream { req.Header.Set("Accept", "text/event-stream") } req.Header.Set("Content-Type", "application/json") resp, err := api.Client.Do(req) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, api.ReturnMessage(err.Error())) return nil, err } return resp, nil }