59 lines
1.7 KiB
Go
59 lines
1.7 KiB
Go
package proxy
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"gpt-plus/config"
|
|
)
|
|
|
|
// b2proxyResponse represents the JSON response from the B2Proxy API.
|
|
type b2proxyResponse struct {
|
|
Code int `json:"code"`
|
|
Data []struct {
|
|
IP string `json:"ip"`
|
|
Port int `json:"port"`
|
|
} `json:"data"`
|
|
}
|
|
|
|
// FetchB2Proxy calls the B2Proxy API to get a proxy IP for the given country.
|
|
// Returns a proxy URL like "socks5://1.2.3.4:10000" or "http://1.2.3.4:10000".
|
|
// Uses a direct HTTP client (no proxy) with a 10-second timeout.
|
|
func FetchB2Proxy(cfg config.B2ProxyConfig, countryCode string) (string, error) {
|
|
// Build the API URL
|
|
url := fmt.Sprintf("%s/gen?zone=%s&ptype=%d&count=1&proto=%s&stype=json&sessType=sticky&sessTime=%d&sessAuto=1®ion=%s",
|
|
cfg.APIBase, cfg.Zone, cfg.PType, cfg.Proto, cfg.SessTime, countryCode)
|
|
|
|
// Use a direct HTTP client (must not go through proxy to fetch proxy)
|
|
directClient := &http.Client{Timeout: 10 * time.Second}
|
|
|
|
resp, err := directClient.Get(url)
|
|
if err != nil {
|
|
return "", fmt.Errorf("b2proxy API request failed: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return "", fmt.Errorf("b2proxy API returned status %d", resp.StatusCode)
|
|
}
|
|
|
|
var result b2proxyResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
return "", fmt.Errorf("b2proxy API decode failed: %w", err)
|
|
}
|
|
|
|
if result.Code != 200 {
|
|
return "", fmt.Errorf("b2proxy API error code: %d", result.Code)
|
|
}
|
|
|
|
if len(result.Data) == 0 {
|
|
return "", fmt.Errorf("b2proxy API returned no proxy for region %s", countryCode)
|
|
}
|
|
|
|
entry := result.Data[0]
|
|
proxyURL := fmt.Sprintf("%s://%s:%d", cfg.Proto, entry.IP, entry.Port)
|
|
return proxyURL, nil
|
|
}
|