Skip to content

Instantly share code, notes, and snippets.

@broady
Created December 19, 2017 02:34
Show Gist options
  • Save broady/7a70fd9e81ecd2f4f9e5875feece0c93 to your computer and use it in GitHub Desktop.
Save broady/7a70fd9e81ecd2f4f9e5875feece0c93 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"time"
"github.com/kurrik/oauth1a"
"github.com/kurrik/twittergo"
)
type UsersResponse struct {
Users []*twittergo.User `json:"users"`
Next string `json:"next_cursor_str"`
}
func main() {
conf := &oauth1a.ClientConfig{
ConsumerKey: "Vldy5iHv2cUW4dZiF9LV9T3d0",
ConsumerSecret: "oxBcYaraLjAsld7B4mFiqWT364ic4lkILdZh9gtBIkvzdO5bJi",
CallbackURL: "oob",
}
oauthUser := &oauth1a.UserConfig{}
if b, err := ioutil.ReadFile("credentials"); err == nil {
if err := json.Unmarshal(b, oauthUser); err != nil {
oauthUser = &oauth1a.UserConfig{}
}
}
c := twittergo.NewClient(conf, oauthUser)
if err := authUser(c); err != nil {
log.Fatal(err)
}
screenName := c.User.AccessValues.Get("screen_name")
if screenName == "" {
log.Fatal("Expecting screen_name in the credentials")
}
type user [2]string // id, screen_name
var users []user
_ = users
cursor := "-1"
for {
vals := url.Values{
"cursor": []string{cursor},
"screen_name": []string{screenName},
"count": []string{"200"},
"skip_status": []string{"true"},
}
url := "/1.1/followers/list.json?" + vals.Encode()
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Fatal(err)
}
page := &UsersResponse{}
resp, err := c.SendRequest(req)
if err != nil {
log.Fatal(err)
}
if resp.HasRateLimit() {
log.Printf("Remaining: %d", resp.RateLimitRemaining())
if resp.RateLimitRemaining() == 0 {
log.Printf("Waiting until: %s", resp.RateLimitReset())
time.Sleep(resp.RateLimitReset().Sub(time.Now()) + time.Second)
continue // try again
}
}
if err := resp.Parse(page); err != nil {
log.Fatal("Parse: ", err)
}
log.Printf("Next page: %s", page.Next)
for _, u := range page.Users {
fmt.Printf("%s\t%s\n", u.IdStr(), u.ScreenName())
}
cursor = page.Next
log.Printf("Got %d followers", len(page.Users))
if len(page.Users) == 0 {
break
}
time.Sleep(400 * time.Millisecond)
}
log.Print("Done!")
}
func authUser(c *twittergo.Client) error {
// Check creds
if c.User.AccessTokenSecret != "" {
req, _ := http.NewRequest("GET", "/1.1/account/verify_credentials.json", nil)
if resp, err := c.SendRequest(req); err == nil {
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
return nil
}
log.Printf("Bad response from server: %#v", resp)
return errors.New("bad response")
}
}
if err := c.User.GetRequestToken(c.OAuth, http.DefaultClient); err != nil {
return err
}
url, err := c.User.GetAuthorizeURL(c.OAuth)
if err != nil {
return err
}
fmt.Println("Go here:", url)
fmt.Print("Enter the code shown: ")
var code string
if _, err := fmt.Scanf("%s\n", &code); err != nil {
return err
}
if err := c.User.GetAccessToken(c.User.RequestTokenKey, code, c.OAuth, http.DefaultClient); err != nil {
return err
}
b, err := json.Marshal(c.User)
if err != nil {
return err
}
return ioutil.WriteFile("credentials", b, 0600)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment