authenticator
This commit is contained in:
parent
8b1f4115f7
commit
967b08eb0c
391
tools/authenticator/auth/auth.go
Normal file
391
tools/authenticator/auth/auth.go
Normal file
@ -0,0 +1,391 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"crypto/rand"
|
||||
|
||||
http "github.com/bogdanfinn/fhttp"
|
||||
tls_client "github.com/bogdanfinn/tls-client"
|
||||
pkce "github.com/nirasan/go-oauth-pkce-code-verifier"
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
Location string
|
||||
StatusCode int
|
||||
Details string
|
||||
Error error
|
||||
}
|
||||
|
||||
func NewError(location string, statusCode int, details string, err error) *Error {
|
||||
return &Error{
|
||||
Location: location,
|
||||
StatusCode: statusCode,
|
||||
Details: details,
|
||||
Error: err,
|
||||
}
|
||||
}
|
||||
|
||||
type Authenticator struct {
|
||||
EmailAddress string
|
||||
Password string
|
||||
Proxy string
|
||||
Session tls_client.HttpClient
|
||||
AccessToken string
|
||||
UserAgent string
|
||||
State string
|
||||
URL string
|
||||
Verifier_code string
|
||||
Verifier_challenge string
|
||||
AuthDetails AuthDetails
|
||||
}
|
||||
|
||||
type AuthDetails struct {
|
||||
ClientID string `json:"client_id"`
|
||||
Scope string `json:"scope"`
|
||||
ResponseType string `json:"response_type"`
|
||||
RedirectURL string `json:"redirect_url"`
|
||||
Audience string `json:"audience"`
|
||||
Prompt string `json:"prompt"`
|
||||
State string `json:"state"`
|
||||
CodeChallenge string `json:"code_challenge"`
|
||||
CodeChallengeMethod string `json:"code_challenge_method"`
|
||||
}
|
||||
|
||||
func NewAuthDetails(challenge string) AuthDetails {
|
||||
// Generate state (secrets.token_urlsafe(32))
|
||||
b := make([]byte, 32)
|
||||
rand.Read(b)
|
||||
state := base64.URLEncoding.EncodeToString(b)
|
||||
return AuthDetails{
|
||||
ClientID: "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh",
|
||||
Scope: "openid email profile offline_access model.request model.read organization.read",
|
||||
ResponseType: "code",
|
||||
RedirectURL: "com.openai.chat://auth0.openai.com/ios/com.openai.chat/callback",
|
||||
Audience: "https://api.openai.com/v1",
|
||||
Prompt: "login",
|
||||
State: state,
|
||||
CodeChallenge: challenge,
|
||||
CodeChallengeMethod: "S256",
|
||||
}
|
||||
}
|
||||
|
||||
func NewAuthenticator(emailAddress, password, proxy string) *Authenticator {
|
||||
auth := &Authenticator{
|
||||
EmailAddress: emailAddress,
|
||||
Password: password,
|
||||
Proxy: proxy,
|
||||
UserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
|
||||
}
|
||||
jar := tls_client.NewCookieJar()
|
||||
options := []tls_client.HttpClientOption{
|
||||
tls_client.WithTimeoutSeconds(20),
|
||||
tls_client.WithClientProfile(tls_client.Firefox_102),
|
||||
tls_client.WithNotFollowRedirects(),
|
||||
tls_client.WithCookieJar(jar), // create cookieJar instance and pass it as argument
|
||||
// Proxy
|
||||
tls_client.WithProxyUrl(proxy),
|
||||
}
|
||||
auth.Session, _ = tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
|
||||
|
||||
// PKCE
|
||||
verifier, _ := pkce.CreateCodeVerifier()
|
||||
auth.Verifier_code = verifier.String()
|
||||
auth.Verifier_challenge = verifier.CodeChallengeS256()
|
||||
|
||||
auth.AuthDetails = NewAuthDetails(auth.Verifier_challenge)
|
||||
|
||||
return auth
|
||||
}
|
||||
|
||||
func (auth *Authenticator) URLEncode(str string) string {
|
||||
return url.QueryEscape(str)
|
||||
}
|
||||
|
||||
func (auth *Authenticator) Begin() Error {
|
||||
// Just realized that the client id is hardcoded in the JS file
|
||||
|
||||
return auth.partOne()
|
||||
}
|
||||
func (auth *Authenticator) partOne() Error {
|
||||
|
||||
auth_url := "https://auth0.openai.com/authorize"
|
||||
headers := map[string]string{
|
||||
"User-Agent": auth.UserAgent,
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Accept": "*/*",
|
||||
"Sec-Gpc": "1",
|
||||
"Accept-Language": "en-US,en;q=0.8",
|
||||
"Origin": "https://chat.openai.com",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Referer": "https://chat.openai.com/auth/login",
|
||||
"Accept-Encoding": "gzip, deflate",
|
||||
}
|
||||
// Construct payload
|
||||
payload := url.Values{
|
||||
"client_id": {auth.AuthDetails.ClientID},
|
||||
"scope": {auth.AuthDetails.Scope},
|
||||
"response_type": {auth.AuthDetails.ResponseType},
|
||||
"redirect_uri": {auth.AuthDetails.RedirectURL},
|
||||
"audience": {auth.AuthDetails.Audience},
|
||||
"prompt": {auth.AuthDetails.Prompt},
|
||||
"state": {auth.AuthDetails.State},
|
||||
"code_challenge": {auth.AuthDetails.CodeChallenge},
|
||||
"code_challenge_method": {auth.AuthDetails.CodeChallengeMethod},
|
||||
}
|
||||
auth_url = auth_url + "?" + payload.Encode()
|
||||
req, err := http.NewRequest("GET", auth_url, nil)
|
||||
if err != nil {
|
||||
return *NewError("part_one", 0, "", err)
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := auth.Session.Do(req)
|
||||
if err != nil {
|
||||
return *NewError("part_one", 0, "", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return *NewError("part_one", 0, "", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode == 302 {
|
||||
return auth.partTwo("https://auth0.openai.com" + resp.Header.Get("Location"))
|
||||
} else {
|
||||
err := NewError("part_one", resp.StatusCode, string(body), fmt.Errorf("error: Check details"))
|
||||
return *err
|
||||
}
|
||||
}
|
||||
|
||||
func (auth *Authenticator) partTwo(url string) Error {
|
||||
|
||||
headers := map[string]string{
|
||||
"Host": "auth0.openai.com",
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"Connection": "keep-alive",
|
||||
"User-Agent": auth.UserAgent,
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
"Referer": "https://ios.chat.openai.com/",
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return *NewError("part_two", 0, "", err)
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := auth.Session.Do(req)
|
||||
if err != nil {
|
||||
return *NewError("part_two", 0, "", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return *NewError("part_two", 0, "", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode == 302 || resp.StatusCode == 200 {
|
||||
|
||||
stateRegex := regexp.MustCompile(`state=(.*)`)
|
||||
stateMatch := stateRegex.FindStringSubmatch(string(body))
|
||||
if len(stateMatch) < 2 {
|
||||
return *NewError("part_two", 0, "Could not find state in response", fmt.Errorf("error: Check details"))
|
||||
}
|
||||
|
||||
state := strings.Split(stateMatch[1], `"`)[0]
|
||||
return auth.partThree(state)
|
||||
} else {
|
||||
err := NewError("__part_two", resp.StatusCode, string(body), fmt.Errorf("error: Check details"))
|
||||
return *err
|
||||
}
|
||||
}
|
||||
func (auth *Authenticator) partThree(state string) Error {
|
||||
|
||||
url := fmt.Sprintf("https://auth0.openai.com/u/login/identifier?state=%s", state)
|
||||
emailURLEncoded := auth.URLEncode(auth.EmailAddress)
|
||||
|
||||
payload := fmt.Sprintf(
|
||||
"state=%s&username=%s&js-available=false&webauthn-available=true&is-brave=false&webauthn-platform-available=true&action=default",
|
||||
state, emailURLEncoded,
|
||||
)
|
||||
|
||||
headers := map[string]string{
|
||||
"Host": "auth0.openai.com",
|
||||
"Origin": "https://auth0.openai.com",
|
||||
"Connection": "keep-alive",
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"User-Agent": auth.UserAgent,
|
||||
"Referer": fmt.Sprintf("https://auth0.openai.com/u/login/identifier?state=%s", state),
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, strings.NewReader(payload))
|
||||
if err != nil {
|
||||
return *NewError("part_four", 0, "", err)
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := auth.Session.Do(req)
|
||||
if err != nil {
|
||||
return *NewError("part_four", 0, "", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 302 || resp.StatusCode == 200 {
|
||||
return auth.partFive(state)
|
||||
} else {
|
||||
err := NewError("__part_four", resp.StatusCode, "Your email address is invalid.", fmt.Errorf("error: Check details"))
|
||||
return *err
|
||||
}
|
||||
|
||||
}
|
||||
func (auth *Authenticator) partFive(state string) Error {
|
||||
|
||||
url := fmt.Sprintf("https://auth0.openai.com/u/login/password?state=%s", state)
|
||||
emailURLEncoded := auth.URLEncode(auth.EmailAddress)
|
||||
passwordURLEncoded := auth.URLEncode(auth.Password)
|
||||
payload := fmt.Sprintf("state=%s&username=%s&password=%s&action=default", state, emailURLEncoded, passwordURLEncoded)
|
||||
|
||||
headers := map[string]string{
|
||||
"Host": "auth0.openai.com",
|
||||
"Origin": "https://auth0.openai.com",
|
||||
"Connection": "keep-alive",
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"User-Agent": auth.UserAgent,
|
||||
"Referer": fmt.Sprintf("https://auth0.openai.com/u/login/password?state=%s", state),
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, strings.NewReader(payload))
|
||||
if err != nil {
|
||||
return *NewError("part_five", 0, "", err)
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := auth.Session.Do(req)
|
||||
if err != nil {
|
||||
return *NewError("part_five", 0, "", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 302 {
|
||||
redirectURL := resp.Header.Get("Location")
|
||||
return auth.partSix(state, redirectURL)
|
||||
} else {
|
||||
body := bytes.NewBuffer(nil)
|
||||
_, err1 := body.ReadFrom(resp.Body)
|
||||
if err1 != nil {
|
||||
return *NewError("part_five", 0, "", err1)
|
||||
}
|
||||
err := NewError("__part_five", resp.StatusCode, body.String(), fmt.Errorf("error: Check details"))
|
||||
return *err
|
||||
}
|
||||
|
||||
}
|
||||
func (auth *Authenticator) partSix(oldState string, redirectURL string) Error {
|
||||
|
||||
url := "https://auth0.openai.com" + redirectURL
|
||||
|
||||
headers := map[string]string{
|
||||
"Host": "auth0.openai.com",
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"Connection": "keep-alive",
|
||||
"User-Agent": auth.UserAgent,
|
||||
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
|
||||
"Referer": fmt.Sprintf("https://auth0.openai.com/u/login/password?state=%s", oldState),
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return *NewError("part_six", 0, "", err)
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := auth.Session.Do(req)
|
||||
if err != nil {
|
||||
return *NewError("part_six", 0, "", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 302 {
|
||||
auth.URL = resp.Header.Get("Location")
|
||||
|
||||
return Error{}
|
||||
} else {
|
||||
err := NewError("__part_six", resp.StatusCode, resp.Status, fmt.Errorf("error: Check details"))
|
||||
return *err
|
||||
}
|
||||
|
||||
}
|
||||
func (auth *Authenticator) GetAccessToken() (string, Error) {
|
||||
code := regexp.MustCompile(`code=(.*)&`).FindStringSubmatch(auth.URL)
|
||||
if len(code) == 0 {
|
||||
err := NewError("__get_access_token", 0, auth.URL, fmt.Errorf("error: Check details"))
|
||||
return "", *err
|
||||
}
|
||||
payload, _ := json.Marshal(map[string]string{
|
||||
"redirect_uri": "com.openai.chat://auth0.openai.com/ios/com.openai.chat/callback",
|
||||
"grant_type": "authorization_code",
|
||||
"client_id": "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh",
|
||||
"code": code[1],
|
||||
"code_verifier": auth.Verifier_code,
|
||||
"state": auth.State,
|
||||
})
|
||||
|
||||
req, _ := http.NewRequest("POST", "https://auth0.openai.com/oauth/token", strings.NewReader(string(payload)))
|
||||
for k, v := range map[string]string{
|
||||
"User-Agent": auth.UserAgent,
|
||||
"content-type": "application/json",
|
||||
} {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
resp, err := auth.Session.Do(req)
|
||||
if err != nil {
|
||||
return "", *NewError("get_access_token", 0, "", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// Parse response
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
// Parse as JSON
|
||||
var data map[string]interface{}
|
||||
|
||||
err = json.Unmarshal(body, &data)
|
||||
|
||||
if err != nil {
|
||||
return "", *NewError("get_access_token", 0, "", err)
|
||||
}
|
||||
|
||||
// Check if access token in data
|
||||
if _, ok := data["access_token"]; !ok {
|
||||
return "", *NewError("get_access_token", 0, "Missing access token", fmt.Errorf("error: Check details"))
|
||||
}
|
||||
|
||||
return data["access_token"].(string), Error{}
|
||||
}
|
@ -2,17 +2,19 @@ module authenticator
|
||||
|
||||
go 1.20
|
||||
|
||||
require github.com/acheong08/OpenAIAuth v0.0.0-20230429052354-04da1ae7b97d
|
||||
require (
|
||||
github.com/bogdanfinn/fhttp v0.5.22
|
||||
github.com/bogdanfinn/tls-client v1.3.12
|
||||
github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/bogdanfinn/fhttp v0.5.22 // indirect
|
||||
github.com/bogdanfinn/tls-client v1.3.11 // indirect
|
||||
github.com/bogdanfinn/utls v1.5.16 // indirect
|
||||
github.com/klauspost/compress v1.16.5 // indirect
|
||||
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 // indirect
|
||||
golang.org/x/crypto v0.8.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.9.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
)
|
||||
|
@ -1,22 +1,22 @@
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230429052354-04da1ae7b97d h1:FzHwikMWrKMRWNEg3ovAC0aF256+hC3ATK5EtTWsiMU=
|
||||
github.com/acheong08/OpenAIAuth v0.0.0-20230429052354-04da1ae7b97d/go.mod h1:QAJ15BSNp3HNgPWPn2CK1zsZnCeBR60v2u798OTBif8=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/bogdanfinn/fhttp v0.5.22 h1:U1jhZRtuaOanWWcm1WdMFnwMvSxUQgvO6berqAVTc5o=
|
||||
github.com/bogdanfinn/fhttp v0.5.22/go.mod h1:brqi5woc5eSCVHdKYBV8aZLbO7HGqpwyDLeXW+fT18I=
|
||||
github.com/bogdanfinn/tls-client v1.3.11 h1:3rI+ysCEtnLdmDYlL7cPq2kF3Sj+bSvhgaHPmjLbjOE=
|
||||
github.com/bogdanfinn/tls-client v1.3.11/go.mod h1:+TLNqnOtUQmYu/qrd/qMuLleoHoTRCcZazkmvNYuiVc=
|
||||
github.com/bogdanfinn/tls-client v1.3.12 h1:jpNj7owMY/oULUQyAhAv6tRFkliFGLyr8Qx1ZZY/gp8=
|
||||
github.com/bogdanfinn/tls-client v1.3.12/go.mod h1:Q46nwIm0wPCweDM3XZcupxEIsTOWo3HVYSSsDj02/Qo=
|
||||
github.com/bogdanfinn/utls v1.5.16 h1:NhhWkegEcYETBMj9nvgO4lwvc6NcLH+znrXzO3gnw4M=
|
||||
github.com/bogdanfinn/utls v1.5.16/go.mod h1:mHeRCi69cUiEyVBkKONB1cAbLjRcZnlJbGzttmiuK4o=
|
||||
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
|
||||
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c h1:4RYnE0ISVwRxm9Dfo7utw1dh0kdRDEmVYq2MFVLy5zI=
|
||||
github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20220510032225-4f9f17eaec4c/go.mod h1:DvuJJ/w1Y59rG8UTDxsMk5U+UJXJwuvUgbiJSm9yhX8=
|
||||
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 h1:YqAladjX7xpA6BM04leXMWAEjS0mTZ5kUU9KRBriQJc=
|
||||
github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5/go.mod h1:2JjD2zLQYH5HO74y5+aE3remJQvl6q4Sn6aWA2wD1Ng=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/acheong08/OpenAIAuth/auth"
|
||||
"authenticator/auth"
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
@ -61,7 +61,7 @@ func readProxies() []Proxy {
|
||||
// Read proxies.txt and create a list of proxies
|
||||
file, err := os.Open("proxies.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return []Proxy{}
|
||||
}
|
||||
defer file.Close()
|
||||
// Loop through each line in the file
|
||||
@ -109,13 +109,15 @@ func main() {
|
||||
println(account.Password)
|
||||
var proxy_url string
|
||||
if len(proxies) == 0 {
|
||||
proxy_url = ""
|
||||
if os.Getenv("http_proxy") != "" {
|
||||
proxy_url = os.Getenv("http_proxy")
|
||||
}
|
||||
} else {
|
||||
proxy_url = proxies[0].Socks5URL()
|
||||
// Push used proxy to the back of the list
|
||||
proxies = append(proxies[1:], proxies[0])
|
||||
println(proxies[0].Socks5URL())
|
||||
}
|
||||
println(proxy_url)
|
||||
authenticator := auth.NewAuthenticator(account.Email, account.Password, proxy_url)
|
||||
err := authenticator.Begin()
|
||||
if err.Error != nil {
|
||||
@ -131,6 +133,7 @@ func main() {
|
||||
// println("Error: " + err.Details)
|
||||
println("Location: " + err.Location)
|
||||
println("Status code: " + fmt.Sprint(err.StatusCode))
|
||||
println("Details: " + err.Details)
|
||||
println("Embedded error: " + err.Error.Error())
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user