Check all 2 letter twitter usernames for availability
package twitterfindname | |
import ( | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"net/http" | |
"strings" | |
) | |
type HttpResponse struct { | |
url string | |
name string | |
nameresp UsernameLookup | |
valid bool | |
response *http.Response | |
err error | |
} | |
type UsernameLookup struct { | |
// Reason: for twitter username: available, taken | |
Reason string `json:"reason"` | |
// Message: Message about selected username | |
Message string `json:"msg"` | |
// Valid: Is this a valid username? | |
Valid bool `json:"valid"` | |
// Description: More info about the chosen username | |
Description string `json:"desc"` | |
} | |
// Given a JSON string return if the serialized data says is Available | |
func TwitterNameAvailable(s string) (bool, UsernameLookup, error) { | |
// See docs: http://golang.org/pkg/encoding/json/#example_Decoder | |
dec := json.NewDecoder(strings.NewReader(s)) | |
var m UsernameLookup | |
if err := dec.Decode(&m); err != nil { | |
return false, UsernameLookup{}, err | |
} | |
return m.Valid, m, nil | |
} | |
func FindTwitterUsernames() { | |
names := generate2letterUsernames() | |
// Split the number of concurrent dispatches into chunks | |
// This was necessary on my local machine b/c dispatching all resulted in: | |
// panic: runtime error: invalid memory address or nil pointer dereference | |
// [signal 0xb code=0x1 addr=0x38 pc=0x26399] | |
// goroutine 257 [running]:... | |
// Note: ^ interesting that it's ~256-ish... | |
splitby := 200 | |
splitnames := names | |
for i := 0; i*splitby < len(names); i++ { | |
if (i+1)*splitby > len(names) { | |
splitnames = names[(i * splitby):len(names)] | |
} else { | |
splitnames = names[(i * splitby):((i + 1) * splitby)] | |
} | |
results := asyncHttpGetsValidate(splitnames) | |
for _ = range splitnames { | |
result := <-results | |
fmt.Printf("%t: %s - %s\n", result.valid, result.name, result.nameresp) | |
} | |
} | |
} | |
func generate2letterUsernames() []string { | |
validchars := "0123456789abcdefghijklmnopqrstuvwxyz_" | |
var result []string | |
for _, firstchar := range validchars { | |
for _, secondchar := range validchars { | |
result = append(result, string(firstchar)+string(secondchar)) | |
} | |
} | |
return result | |
} | |
func asyncHttpGetsValidate(names []string) <-chan *HttpResponse { | |
// Originally from: https://gist.github.com/4013851 | |
ch := make(chan *HttpResponse, len(names)) // buffered | |
for _, name := range names { | |
go func(name string) { | |
// Lookup if the twitter username is available | |
url := "https://twitter.com/users/username_available?username=" + name | |
fmt.Printf("Fetching username: %s \n", name) | |
resp, err := http.Get(url) | |
body, err := ioutil.ReadAll(resp.Body) | |
valid, usernamejson, err := TwitterNameAvailable(string(body)) | |
resp.Body.Close() | |
ch <- &HttpResponse{url, name, usernamejson, valid, resp, err} | |
}(name) | |
} | |
return ch | |
} |
package twitterfindname | |
import "testing" | |
func TestTwitterNameAvailable(t *testing.T) { | |
var tests = []struct { | |
valid bool | |
name, response string | |
}{ | |
{false, "☃", `{"reason":"improper_format","msg":"Only use letters, numbers and '_'","valid":false,"desc":"Your username can only contain letters, numbers and '_'"}`}, | |
{true, "thisnameisnottaken", `{"reason":"available","msg":"Available!","valid":true,"desc":"Available!"}`}, | |
{false, "a", `{"reason":"taken","msg":"Username has already been taken","valid":false,"desc":"That username has been taken. Please choose another."}`}, | |
} | |
for _, c := range tests { | |
valid, _, _ := TwitterNameAvailable(c.response) | |
if valid != c.valid { | |
t.Errorf("TwitterNameAvailable(%q) should be %t", c.name, c.valid) | |
} | |
} | |
} | |
func TestFindTwitterUsername(t *testing.T) { | |
if len(generate2letterUsernames()) != 1369 { | |
t.Errorf("generate2letterUsernames") | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
Interesting analysis of taken twitter usernames: http://cresspahl.blogspot.com/2012/03/list-of-three-letter-twitter-names.html |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.