Last active
May 30, 2016 11:36
-
-
Save christianchristensen/4409897 to your computer and use it in GitHub Desktop.
Check all 2 letter twitter usernames for availability
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | |
} | |
} |
Author
christianchristensen
commented
Jan 1, 2013
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