Spaces:
Runtime error
Runtime error
package chatgpt | |
import ( | |
"encoding/json" | |
"errors" | |
"fmt" | |
"io" | |
"strings" | |
"github.com/PuerkitoBio/goquery" | |
"github.com/linweiyuan/go-chatgpt-api/api" | |
http "github.com/bogdanfinn/fhttp" | |
) | |
//goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat | |
func (userLogin *UserLogin) GetAuthorizedUrl(csrfToken string) (string, int, error) { | |
params := fmt.Sprintf( | |
"callbackUrl=/&csrfToken=%s&json=true", | |
csrfToken, | |
) | |
req, err := http.NewRequest(http.MethodPost, promptLoginUrl, strings.NewReader(params)) | |
req.Header.Set("Content-Type", api.ContentType) | |
req.Header.Set("User-Agent", api.UserAgent) | |
resp, err := userLogin.client.Do(req) | |
if err != nil { | |
return "", http.StatusInternalServerError, err | |
} | |
defer resp.Body.Close() | |
if resp.StatusCode != http.StatusOK { | |
return "", resp.StatusCode, errors.New(api.GetAuthorizedUrlErrorMessage) | |
} | |
responseMap := make(map[string]string) | |
json.NewDecoder(resp.Body).Decode(&responseMap) | |
return responseMap["url"], http.StatusOK, nil | |
} | |
//goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat | |
func (userLogin *UserLogin) GetState(authorizedUrl string) (string, int, error) { | |
req, err := http.NewRequest(http.MethodGet, authorizedUrl, nil) | |
req.Header.Set("Content-Type", api.ContentType) | |
req.Header.Set("User-Agent", api.UserAgent) | |
resp, err := userLogin.client.Do(req) | |
if err != nil { | |
return "", http.StatusInternalServerError, err | |
} | |
defer resp.Body.Close() | |
if resp.StatusCode != http.StatusOK { | |
return "", resp.StatusCode, errors.New(api.GetStateErrorMessage) | |
} | |
doc, _ := goquery.NewDocumentFromReader(resp.Body) | |
state, _ := doc.Find("input[name=state]").Attr("value") | |
return state, http.StatusOK, nil | |
} | |
//goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat | |
func (userLogin *UserLogin) CheckUsername(state string, username string) (int, error) { | |
formParams := fmt.Sprintf( | |
"state=%s&username=%s&js-available=true&webauthn-available=true&is-brave=false&webauthn-platform-available=false&action=default", | |
state, | |
username, | |
) | |
req, _ := http.NewRequest(http.MethodPost, api.LoginUsernameUrl+state, strings.NewReader(formParams)) | |
req.Header.Set("Content-Type", api.ContentType) | |
req.Header.Set("User-Agent", api.UserAgent) | |
resp, err := userLogin.client.Do(req) | |
if err != nil { | |
return http.StatusInternalServerError, err | |
} | |
defer resp.Body.Close() | |
if resp.StatusCode != http.StatusOK { | |
return resp.StatusCode, errors.New(api.EmailInvalidErrorMessage) | |
} | |
return http.StatusOK, nil | |
} | |
//goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat | |
func (userLogin *UserLogin) CheckPassword(state string, username string, password string) (string, int, error) { | |
formParams := fmt.Sprintf( | |
"state=%s&username=%s&password=%s&action=default", | |
state, | |
username, | |
password, | |
) | |
req, err := http.NewRequest(http.MethodPost, api.LoginPasswordUrl+state, strings.NewReader(formParams)) | |
req.Header.Set("Content-Type", api.ContentType) | |
req.Header.Set("User-Agent", api.UserAgent) | |
userLogin.client.SetFollowRedirect(false) | |
resp, err := userLogin.client.Do(req) | |
if err != nil { | |
return "", http.StatusInternalServerError, err | |
} | |
defer resp.Body.Close() | |
if resp.StatusCode == http.StatusBadRequest { | |
doc, _ := goquery.NewDocumentFromReader(resp.Body) | |
alert := doc.Find("#prompt-alert").Text() | |
if alert != "" { | |
return "", resp.StatusCode, errors.New(strings.TrimSpace(alert)) | |
} | |
return "", resp.StatusCode, errors.New(api.EmailOrPasswordInvalidErrorMessage) | |
} | |
if resp.StatusCode == http.StatusFound { | |
req, _ := http.NewRequest(http.MethodGet, api.Auth0Url+resp.Header.Get("Location"), nil) | |
req.Header.Set("User-Agent", api.UserAgent) | |
resp, err := userLogin.client.Do(req) | |
if err != nil { | |
return "", http.StatusInternalServerError, err | |
} | |
defer resp.Body.Close() | |
if resp.StatusCode == http.StatusFound { | |
location := resp.Header.Get("Location") | |
if strings.HasPrefix(location, "/u/mfa-otp-challenge") { | |
return "", http.StatusBadRequest, errors.New("Login with two-factor authentication enabled is not supported currently.") | |
} | |
req, _ := http.NewRequest(http.MethodGet, location, nil) | |
req.Header.Set("User-Agent", api.UserAgent) | |
resp, err := userLogin.client.Do(req) | |
if err != nil { | |
return "", http.StatusInternalServerError, err | |
} | |
defer resp.Body.Close() | |
if resp.StatusCode == http.StatusFound { | |
return "", http.StatusOK, nil | |
} | |
if resp.StatusCode == http.StatusTemporaryRedirect { | |
errorDescription := req.URL.Query().Get("error_description") | |
if errorDescription != "" { | |
return "", resp.StatusCode, errors.New(errorDescription) | |
} | |
} | |
return "", resp.StatusCode, errors.New(api.GetAccessTokenErrorMessage) | |
} | |
return "", resp.StatusCode, errors.New(api.EmailOrPasswordInvalidErrorMessage) | |
} | |
return "", resp.StatusCode, nil | |
} | |
//goland:noinspection GoUnhandledErrorResult,GoErrorStringFormat,GoUnusedParameter | |
func (userLogin *UserLogin) GetAccessToken(code string) (string, int, error) { | |
req, err := http.NewRequest(http.MethodGet, authSessionUrl, nil) | |
req.Header.Set("User-Agent", api.UserAgent) | |
resp, err := userLogin.client.Do(req) | |
if err != nil { | |
return "", http.StatusInternalServerError, err | |
} | |
defer resp.Body.Close() | |
if resp.StatusCode != http.StatusOK { | |
if resp.StatusCode == http.StatusTooManyRequests { | |
responseMap := make(map[string]string) | |
json.NewDecoder(resp.Body).Decode(&responseMap) | |
return "", resp.StatusCode, errors.New(responseMap["detail"]) | |
} | |
return "", resp.StatusCode, errors.New(api.GetAccessTokenErrorMessage) | |
} | |
data, _ := io.ReadAll(resp.Body) | |
return string(data), http.StatusOK, nil | |
} | |