Spaces:
Runtime error
Runtime error
| package common | |
| import ( | |
| "WarpGPT/pkg/env" | |
| "WarpGPT/pkg/logger" | |
| "WarpGPT/pkg/plugins/service/proxypool" | |
| "encoding/json" | |
| browser "github.com/EDDYCJY/fake-useragent" | |
| http "github.com/bogdanfinn/fhttp" | |
| tls_client "github.com/bogdanfinn/tls-client" | |
| "github.com/bogdanfinn/tls-client/profiles" | |
| "github.com/gin-gonic/gin" | |
| "io" | |
| "fmt" | |
| "math/rand" | |
| "sync" | |
| ) | |
| type Context struct { | |
| GinContext *gin.Context | |
| RequestUrl string | |
| RequestClient tls_client.HttpClient | |
| RequestBody io.ReadCloser | |
| RequestParam string | |
| RequestMethod string | |
| RequestHeaders http.Header | |
| } | |
| type APIError struct { | |
| AccessToken string | |
| StatusCode int | |
| } | |
| func (e *APIError) Error() string { | |
| return fmt.Sprintf("HTTP status %d, AccessToken: %s", e.StatusCode, e.AccessToken) | |
| } | |
| var tu sync.Mutex | |
| type RequestUrl interface { | |
| Generate(path string, rawquery string) string | |
| } | |
| func GetContextPack[T RequestUrl](ctx *gin.Context, reqUrl T) Context { | |
| conversation := Context{} | |
| conversation.GinContext = ctx | |
| conversation.RequestUrl = reqUrl.Generate(ctx.Param("path"), ctx.Request.URL.RawQuery) | |
| conversation.RequestMethod = ctx.Request.Method | |
| conversation.RequestBody = ctx.Request.Body | |
| conversation.RequestParam = ctx.Param("path") | |
| conversation.RequestClient = GetHttpClient() | |
| conversation.RequestHeaders = http.Header(ctx.Request.Header) | |
| return conversation | |
| } | |
| func getUserAgent() string { | |
| tu.Lock() | |
| defer tu.Unlock() | |
| return browser.Safari() | |
| } | |
| func GetHttpClient() tls_client.HttpClient { | |
| jar := tls_client.NewCookieJar() | |
| userAgent := map[int]profiles.ClientProfile{ | |
| 1: profiles.Safari_15_6_1, | |
| 2: profiles.Safari_16_0, | |
| 3: profiles.Safari_IOS_15_5, | |
| 4: profiles.Safari_IOS_15_6, | |
| 5: profiles.Safari_IOS_16_0, | |
| } | |
| options := []tls_client.HttpClientOption{ | |
| tls_client.WithTimeoutSeconds(120), | |
| tls_client.WithClientProfile(userAgent[rand.Intn(5)+1]), | |
| tls_client.WithNotFollowRedirects(), | |
| tls_client.WithCookieJar(jar), | |
| tls_client.WithRandomTLSExtensionOrder(), | |
| } | |
| if env.E.ProxyPoolUrl != "" { | |
| ip, err := proxypool.ProxyPoolInstance.GetIpInRedis() | |
| if err != nil { | |
| logger.Log.Warning(err.Error()) | |
| return nil | |
| } | |
| options = append(options, tls_client.WithProxyUrl(ip)) | |
| } else { | |
| options = append(options, tls_client.WithProxyUrl(env.E.Proxy)) | |
| } | |
| client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...) | |
| if err != nil { | |
| logger.Log.Error("Error creating http client:", err) | |
| return nil | |
| } | |
| return client | |
| } | |
| func RequestOpenAI[T any](path string, body io.Reader, accessToken string, requestMethod string) (*T, error) { | |
| url := "https://" + env.E.OpenaiHost + path | |
| req, err := http.NewRequest(requestMethod, url, body) | |
| if err != nil { | |
| logger.Log.Error("Error creating request:", err) | |
| return nil, err | |
| } | |
| userAgentStr := getUserAgent() | |
| headers := map[string]string{ | |
| "Host": env.E.OpenaiHost, | |
| "Origin": "https://" + env.E.OpenaiHost, | |
| "Authorization": accessToken, | |
| "Connection": "keep-alive", | |
| "User-Agent": userAgentStr, | |
| "Referer": "https://" + env.E.OpenaiHost, | |
| "Content-Type": "application/json", | |
| "Accept": "*/*", | |
| "sec-fetch-dest": "empty", | |
| "sec-fetch-site": "same-origin", | |
| } | |
| for key, value := range headers { | |
| req.Header.Set(key, value) | |
| } | |
| resp, err := GetHttpClient().Do(req) | |
| if err != nil { | |
| logger.Log.Error("Error sending request:", err) | |
| return nil, err | |
| } | |
| defer resp.Body.Close() | |
| if resp.StatusCode != http.StatusOK { | |
| apiError := &APIError{ | |
| AccessToken: accessToken, | |
| StatusCode: resp.StatusCode, | |
| } | |
| return nil, apiError | |
| } | |
| var data T | |
| readAll, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| logger.Log.Error("Read error:", err) | |
| return nil, err | |
| } | |
| if readAll == nil { | |
| return nil, nil | |
| } | |
| err = json.Unmarshal(readAll, &data) | |
| if err != nil { | |
| logger.Log.Error("Unmarshal error:", err) | |
| return nil, err | |
| } | |
| return &data, nil | |
| } | |