Skip to content

Instantly share code, notes, and snippets.

@umayr
Created August 27, 2014 13:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save umayr/6d29a1500f10ee237caa to your computer and use it in GitHub Desktop.
Save umayr/6d29a1500f10ee237caa to your computer and use it in GitHub Desktop.
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