Created
August 27, 2014 13:46
-
-
Save umayr/6d29a1500f10ee237caa to your computer and use it in GitHub Desktop.
This file contains 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 main | |
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(n int) { | |
var names []string | |
switch n { | |
case 1: | |
fmt.Printf("Invalid number provided") | |
return | |
case 2: | |
names = generate2letterUsernames() | |
case 3: | |
names = generate3letterUsernames() | |
default: | |
names = generate4letterUsernames() | |
} | |
// 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) | |
fmt.Printf("Username %s is %s\n", result.name, isAvailable(result.valid)) | |
} | |
} | |
} | |
func isAvailable(value bool) string { | |
if value { | |
return "Available" | |
} | |
return "Unavailable" | |
} | |
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 generate3letterUsernames() []string { | |
validchars := "0123456789abcdefghijklmnopqrstuvwxyz_" | |
var result []string | |
for _, firstchar := range validchars { | |
for _, secondchar := range validchars { | |
for _, thirdchar := range validchars { | |
result = append(result, string(firstchar)+string(secondchar)+string(thirdchar)) | |
} | |
} | |
} | |
return result | |
} | |
func generate4letterUsernames() []string { | |
validchars := "0123456789abcdefghijklmnopqrstuvwxyz_" | |
var result []string | |
for _, firstchar := range validchars { | |
for _, secondchar := range validchars { | |
for _, thirdchar := range validchars { | |
for _, fourthchar := range validchars { | |
result = append(result, string(firstchar)+string(secondchar)+string(thirdchar)+string(fourthchar)) | |
} | |
} | |
} | |
} | |
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 | |
} | |
func main() { | |
FindTwitterUsernames(4) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment