Go/Github 用户名可用性并发检测

一个简单的脚本, 用来并发检测 Github 用户名是否可被注册.

package main

import (
    "bytes"
    "log"
    "net/http"
    "os"
    "strings"
    "sync"
)

func nameUsableOnce(name string) (int, error) {
    body := strings.Replace("------WebKitFormBoundaryF15rNsGN08qoXN2Z\r\nContent-Disposition: form-data; name=\"authenticity_token\"\r\n\r\n5aXlNWinJebbx/yVkzgwb2l8Bwwhkg0fgsveQm4+u9Wc1spycql8131Jr243x9Z3EY+Kfi4vP+dVjjXfgtxF5g==\r\n------WebKitFormBoundaryF15rNsGN08qoXN2Z\r\nContent-Disposition: form-data; name=\"value\"\r\n\r\njack\r\n------WebKitFormBoundaryF15rNsGN08qoXN2Z--\r\n", "jack", name, 1)
    requ, err := http.NewRequest(http.MethodPost, "https://github.com/signup_check/username", bytes.NewReader([]byte(body)))
    if err != nil {
        return 0, err
    }
    requ.Header.Set("accept", "*/*")
    requ.Header.Set("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,zh-TW;q=0.5")
    requ.Header.Set("content-type", "multipart/form-data; boundary=----WebKitFormBoundaryJ387fEq3mIJpLAfG")
    requ.Header.Set("sec-ch-ua", "\"Not A(Brand\";v=\"99\", \"Microsoft Edge\";v=\"121\", \"Chromium\";v=\"121\"")
    requ.Header.Set("sec-ch-ua-mobile", "?0")
    requ.Header.Set("sec-ch-ua-platform", "\"Windows\"")
    requ.Header.Set("sec-fetch-dest", "empty")
    requ.Header.Set("sec-fetch-mode", "cors")
    requ.Header.Set("sec-fetch-site", "same-origin")
    requ.Header.Set("cookie", "_octo=GH1.1.867648387.1708765773; logged_in=no; preferred_color_mode=light; tz=Asia%2FShanghai; _gh_sess=zjDsVXWemwKElzIr0bYNgR%2FRUZ34KY03HmmfUPjONO3%2B92DMW8%2F24p5kupdy5D0rUE4OtyBeOpDOKIC8PUcv5tIY5oz7W14bch5Jf72bOJeMbHbONnNyK69CjA%2BGRWI7BB%2FlC4L%2FnQtcfjUS69n3h2AEiPmMPumEwHxN%2FlLa8kyKVt4m%2FAzqqyvzXhSOQfCPTnhh%2BW8ciVwxWqJkPQute23j%2BMYg6MrrZb4fDpQbbsHi2duqWtjTK26diGqA%2BirURVF12T8EbCXhL90fuFsOFEvnCeCK%2BDOSiJlSQKPZy6y5VoRa--DavafQZCTdYzzivi--4JLPykEtSgSAkUNIJ32ANw%3D%3D")
    requ.Header.Set("Referer", "https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F&source=header-home")
    requ.Header.Set("Referrer-Policy", "strict-origin-when-cross-origin")
    resp, err := http.DefaultClient.Do(requ)
    if err != nil {
        return 0, err
    }
    if resp.StatusCode == 200 {
        return 1, nil
    } else {
        return 0, nil
    }
}

func nameUsableReno(name string) (int, error) {
    for {
        r, err := nameUsableOnce(name)
        if err != nil {
            log.Println(err)
            continue
        }
        return r, nil
    }
}

func nameStable(name string) {
    w, err := os.OpenFile("/tmp/github", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
    if err != nil {
        panic(err)
    }
    defer w.Close()
    w.Write([]byte(name))
    w.Write([]byte("\n"))
}

func main() {
    source := make(chan string, 8)
    result := make(chan string, 8)

    w0 := sync.WaitGroup{}
    w1 := sync.WaitGroup{}

    go func() {
        source <- "ada"
        source <- "bob"
        close(source)
    }()

    go func() {
        for name := range result {
            nameStable(name)
            w1.Done()
        }
    }()

    for i := 0; i < 4; i++ {
        w0.Add(1)
        go func() {
            for name := range source {
                b, _ := nameUsableReno(name)
                log.Println(name, b)
                if b != 0 {
                    w1.Add(1)
                    result <- name
                }
            }
            w0.Done()
        }()
    }
    w0.Wait()
    close(result)
    w1.Wait()
}

以上的示例代码会检测 "ada" 和 "bob" 两个用户名是否用. 可用的用户名将以文本形式写入 "/tmp/github" 文件内.