- Use Windscribe API to fetch servers information - More data on servers about region, city and hostname - Add optional server filters with `REGION`, `CITY` and `HOSTNAME` csv environment variables
This commit is contained in:
@@ -2,14 +2,19 @@ package updater
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/qdm12/golibs/network"
|
||||
)
|
||||
|
||||
func (u *updater) updateWindscribe(ctx context.Context) (err error) {
|
||||
servers, err := findWindscribeServers(ctx, u.lookupIP)
|
||||
servers, err := findWindscribeServers(ctx, u.client)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update Windscribe servers: %w", err)
|
||||
}
|
||||
@@ -21,46 +26,53 @@ func (u *updater) updateWindscribe(ctx context.Context) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func findWindscribeServers(ctx context.Context, lookupIP lookupIPFunc) (servers []models.WindscribeServer, err error) {
|
||||
allCountryCodes := getCountryCodes()
|
||||
windscribeCountryCodes := getWindscribeSubdomainToRegion()
|
||||
possibleCountryCodes := mergeCountryCodes(windscribeCountryCodes, allCountryCodes)
|
||||
const domain = "windscribe.com"
|
||||
for countryCode, region := range possibleCountryCodes {
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
func findWindscribeServers(ctx context.Context, client network.Client) (servers []models.WindscribeServer, err error) {
|
||||
const baseURL = "https://assets.windscribe.com/serverlist/mob-v2/1/"
|
||||
cacheBreaker := time.Now().Unix()
|
||||
url := fmt.Sprintf("%s%d", baseURL, cacheBreaker)
|
||||
content, status, err := client.Get(ctx, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if status != http.StatusOK {
|
||||
return nil, fmt.Errorf(http.StatusText(status))
|
||||
}
|
||||
var jsonData struct {
|
||||
Data []struct {
|
||||
Region string `json:"name"`
|
||||
Groups []struct {
|
||||
City string `json:"city"`
|
||||
Nodes []struct {
|
||||
Hostname string `json:"hostname"`
|
||||
OpenvpnIP net.IP `json:"ip2"`
|
||||
} `json:"nodes"`
|
||||
} `json:"groups"`
|
||||
} `json:"data"`
|
||||
}
|
||||
if err := json.Unmarshal(content, &jsonData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, regionBlock := range jsonData.Data {
|
||||
region := regionBlock.Region
|
||||
for _, group := range regionBlock.Groups {
|
||||
city := group.City
|
||||
for _, node := range group.Nodes {
|
||||
server := models.WindscribeServer{
|
||||
Region: region,
|
||||
City: city,
|
||||
Hostname: node.Hostname,
|
||||
IP: node.OpenvpnIP,
|
||||
}
|
||||
servers = append(servers, server)
|
||||
}
|
||||
}
|
||||
host := countryCode + "." + domain
|
||||
const repetitions = 5
|
||||
ips, err := resolveRepeat(ctx, lookupIP, host, repetitions)
|
||||
if err != nil || len(ips) == 0 {
|
||||
continue
|
||||
}
|
||||
servers = append(servers, models.WindscribeServer{
|
||||
Region: region,
|
||||
IPs: ips,
|
||||
})
|
||||
}
|
||||
sort.Slice(servers, func(i, j int) bool {
|
||||
return servers[i].Region < servers[j].Region
|
||||
return servers[i].Region+servers[i].City+servers[i].Hostname <
|
||||
servers[j].Region+servers[j].City+servers[j].Hostname
|
||||
})
|
||||
return servers, nil
|
||||
}
|
||||
|
||||
func mergeCountryCodes(base, extend map[string]string) (merged map[string]string) {
|
||||
merged = make(map[string]string, len(base))
|
||||
for countryCode, region := range base {
|
||||
merged[countryCode] = region
|
||||
}
|
||||
for countryCode := range base {
|
||||
delete(extend, countryCode)
|
||||
}
|
||||
for countryCode, region := range extend {
|
||||
merged[countryCode] = region
|
||||
}
|
||||
return merged
|
||||
}
|
||||
|
||||
func stringifyWindscribeServers(servers []models.WindscribeServer) (s string) {
|
||||
s = "func WindscribeServers() []models.WindscribeServer {\n"
|
||||
s += " return []models.WindscribeServer{\n"
|
||||
@@ -71,77 +83,3 @@ func stringifyWindscribeServers(servers []models.WindscribeServer) (s string) {
|
||||
s += "}"
|
||||
return s
|
||||
}
|
||||
|
||||
func getWindscribeSubdomainToRegion() map[string]string {
|
||||
return map[string]string{
|
||||
"al": "Albania",
|
||||
"ar": "Argentina",
|
||||
"au": "Australia",
|
||||
"at": "Austria",
|
||||
"az": "Azerbaijan",
|
||||
"be": "Belgium",
|
||||
"ba": "Bosnia",
|
||||
"br": "Brazil",
|
||||
"bg": "Bulgaria",
|
||||
"ca": "Canada East",
|
||||
"ca-west": "Canada West",
|
||||
"co": "Colombia",
|
||||
"hr": "Croatia",
|
||||
"cy": "Cyprus",
|
||||
"cz": "Czech republic",
|
||||
"dk": "Denmark",
|
||||
"ee": "Estonia",
|
||||
"aq": "Fake antarctica",
|
||||
"fi": "Finland",
|
||||
"fr": "France",
|
||||
"ge": "Georgia",
|
||||
"de": "Germany",
|
||||
"gr": "Greece",
|
||||
"hk": "Hong kong",
|
||||
"hu": "Hungary",
|
||||
"is": "Iceland",
|
||||
"in": "India",
|
||||
"id": "Indonesia",
|
||||
"ie": "Ireland",
|
||||
"il": "Israel",
|
||||
"it": "Italy",
|
||||
"jp": "Japan",
|
||||
"lv": "Latvia",
|
||||
"lt": "Lithuania",
|
||||
"mk": "Macedonia",
|
||||
"my": "Malaysia",
|
||||
"mx": "Mexico",
|
||||
"md": "Moldova",
|
||||
"nl": "Netherlands",
|
||||
"nz": "New zealand",
|
||||
"no": "Norway",
|
||||
"ph": "Philippines",
|
||||
"pl": "Poland",
|
||||
"pt": "Portugal",
|
||||
"ro": "Romania",
|
||||
"ru": "Russia",
|
||||
"rs": "Serbia",
|
||||
"sg": "Singapore",
|
||||
"sk": "Slovakia",
|
||||
"si": "Slovenia",
|
||||
"za": "South Africa",
|
||||
"kr": "South Korea",
|
||||
"es": "Spain",
|
||||
"se": "Sweden",
|
||||
"ch": "Switzerland",
|
||||
"th": "Thailand",
|
||||
"tn": "Tunisia",
|
||||
"tr": "Turkey",
|
||||
"ua": "Ukraine",
|
||||
"ae": "United Arab Emirates",
|
||||
"uk": "United Kingdom",
|
||||
"us-central": "US Central",
|
||||
"us-east": "US East",
|
||||
"us-west": "US West",
|
||||
"vn": "Vietnam",
|
||||
"wf-ca": "Windflix CA",
|
||||
"wf-jp": "Windflix JP",
|
||||
"wf-uk": "Windflix UK",
|
||||
"wf-us": "Windflix US",
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user