Improve login flow
support LoginAcid task
This commit is contained in:
parent
3bb78070b7
commit
e86c2fa4ce
5 changed files with 58 additions and 7 deletions
1
.github/workflows/go.yml
vendored
1
.github/workflows/go.yml
vendored
|
|
@ -25,4 +25,5 @@ jobs:
|
||||||
env:
|
env:
|
||||||
TWITTER_USERNAME: ${{ secrets.TWITTER_USERNAME }}
|
TWITTER_USERNAME: ${{ secrets.TWITTER_USERNAME }}
|
||||||
TWITTER_PASSWORD: ${{ secrets.TWITTER_PASSWORD }}
|
TWITTER_PASSWORD: ${{ secrets.TWITTER_PASSWORD }}
|
||||||
|
TWITTER_EMAIL: ${{ secrets.TWITTER_EMAIL }}
|
||||||
run: go test -v
|
run: go test -v
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,13 @@ It is also required to search.
|
||||||
err := scraper.Login("username", "password")
|
err := scraper.Login("username", "password")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use username to login, not email!
|
||||||
|
But if you have email confirmation, use email address in addition:
|
||||||
|
|
||||||
|
```golang
|
||||||
|
err := scraper.Login("username", "password", "email")
|
||||||
|
```
|
||||||
|
|
||||||
Status of login can be checked with:
|
Status of login can be checked with:
|
||||||
|
|
||||||
```golang
|
```golang
|
||||||
|
|
|
||||||
50
auth.go
50
auth.go
|
|
@ -22,6 +22,9 @@ type (
|
||||||
} `json:"errors"`
|
} `json:"errors"`
|
||||||
FlowToken string `json:"flow_token"`
|
FlowToken string `json:"flow_token"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
|
Subtasks []struct {
|
||||||
|
SubtaskID string `json:"subtask_id"`
|
||||||
|
} `json:"subtasks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyCredentials struct {
|
verifyCredentials struct {
|
||||||
|
|
@ -69,7 +72,15 @@ func (s *Scraper) getFlowToken(data map[string]interface{}) (string, error) {
|
||||||
return "", fmt.Errorf("auth error (%d): %v", info.Errors[0].Code, info.Errors[0].Message)
|
return "", fmt.Errorf("auth error (%d): %v", info.Errors[0].Code, info.Errors[0].Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return info.FlowToken, nil
|
if info.Subtasks != nil && len(info.Subtasks) > 0 {
|
||||||
|
if info.Subtasks[0].SubtaskID == "LoginEnterAlternateIdentifierSubtask" {
|
||||||
|
err = fmt.Errorf("auth error: %v", "LoginEnterAlternateIdentifierSubtask")
|
||||||
|
} else if info.Subtasks[0].SubtaskID == "LoginAcid" {
|
||||||
|
err = fmt.Errorf("auth error: %v", "LoginAcid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return info.FlowToken, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLoggedIn check if scraper logged in
|
// IsLoggedIn check if scraper logged in
|
||||||
|
|
@ -92,7 +103,21 @@ func (s *Scraper) IsLoggedIn() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login to Twitter
|
// Login to Twitter
|
||||||
func (s *Scraper) Login(username string, password string) error {
|
// Use Login(username, password) for ordinary login
|
||||||
|
// or Login(username, password, email) for login if you have email confirmation
|
||||||
|
func (s *Scraper) Login(credentials ...string) error {
|
||||||
|
var username, password, email string
|
||||||
|
if len(credentials) == 2 {
|
||||||
|
username = credentials[0]
|
||||||
|
password = credentials[1]
|
||||||
|
} else if len(credentials) == 3 {
|
||||||
|
username = credentials[0]
|
||||||
|
password = credentials[1]
|
||||||
|
email = credentials[2]
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("invalid credentials")
|
||||||
|
}
|
||||||
|
|
||||||
s.setBearerToken(bearerToken2)
|
s.setBearerToken(bearerToken2)
|
||||||
|
|
||||||
err := s.GetGuestToken()
|
err := s.GetGuestToken()
|
||||||
|
|
@ -178,9 +203,26 @@ func (s *Scraper) Login(username string, password string) error {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err = s.getFlowToken(data)
|
flowToken, err = s.getFlowToken(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
if strings.Contains(err.Error(), "LoginAcid") {
|
||||||
|
// flow acid
|
||||||
|
data = map[string]interface{}{
|
||||||
|
"flow_token": flowToken,
|
||||||
|
"subtask_inputs": []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"subtask_id": "LoginAcid",
|
||||||
|
"enter_text": map[string]interface{}{"text": email, "link": "next_link"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = s.getFlowToken(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.isLogged = true
|
s.isLogged = true
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,16 @@ import (
|
||||||
var (
|
var (
|
||||||
username = os.Getenv("TWITTER_USERNAME")
|
username = os.Getenv("TWITTER_USERNAME")
|
||||||
password = os.Getenv("TWITTER_PASSWORD")
|
password = os.Getenv("TWITTER_PASSWORD")
|
||||||
|
email = os.Getenv("TWITTER_EMAIL")
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAuth(t *testing.T) {
|
func TestAuth(t *testing.T) {
|
||||||
scraper := twitterscraper.New()
|
scraper := twitterscraper.New()
|
||||||
if err := scraper.Login(username, password); err != nil {
|
if err := scraper.Login(username, password, email); err != nil {
|
||||||
t.Fatalf("Login() error = %v", err)
|
t.Fatalf("Login() error = %v", err)
|
||||||
}
|
}
|
||||||
if !scraper.IsLoggedIn() {
|
if !scraper.IsLoggedIn() {
|
||||||
t.Error("Expected IsLoggedIn() = true")
|
t.Fatalf("Expected IsLoggedIn() = true")
|
||||||
}
|
}
|
||||||
cookies := scraper.GetCookies()
|
cookies := scraper.GetCookies()
|
||||||
scraper.Logout()
|
scraper.Logout()
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ func authSearchScraper() error {
|
||||||
if searchScraper.IsLoggedIn() {
|
if searchScraper.IsLoggedIn() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return searchScraper.Login(username, password)
|
return searchScraper.Login(username, password, email)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFetchSearchCursor(t *testing.T) {
|
func TestFetchSearchCursor(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue