VPN Unlimited support (#499)
- Fixes #420 - Revert to docker/build-push-action@v2.4.0
This commit is contained in:
160
internal/updater/providers/vpnunlimited/constants.go
Normal file
160
internal/updater/providers/vpnunlimited/constants.go
Normal file
@@ -0,0 +1,160 @@
|
||||
package vpnunlimited
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/constants"
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
)
|
||||
|
||||
func getHostToServer() (hts hostToServer, warnings []string) {
|
||||
shortHTS := map[string]models.VPNUnlimitedServer{
|
||||
"ae": {},
|
||||
"ar": {},
|
||||
"at": {},
|
||||
"au-syd": {
|
||||
City: "Sydney",
|
||||
},
|
||||
"ba": {},
|
||||
"be": {},
|
||||
"bg": {},
|
||||
"br": {},
|
||||
"by": {},
|
||||
"ca-tr": {
|
||||
City: "Toronto",
|
||||
},
|
||||
"ca-vn": {
|
||||
City: "Vancouver",
|
||||
},
|
||||
"ca": {},
|
||||
"ch": {},
|
||||
"cr": {},
|
||||
"cy": {},
|
||||
"cz": {},
|
||||
"de-dus": {
|
||||
City: "Düsseldorf",
|
||||
},
|
||||
"de": {},
|
||||
"dk": {},
|
||||
"ee": {},
|
||||
"es": {},
|
||||
"fi": {},
|
||||
"fr-rbx": {
|
||||
City: "Roubaix",
|
||||
},
|
||||
"fr": {},
|
||||
"gr": {},
|
||||
"hr": {},
|
||||
"hu": {},
|
||||
"ie-dub": {
|
||||
City: "Dublin",
|
||||
},
|
||||
"il": {},
|
||||
"im": {},
|
||||
"in-ka": {
|
||||
City: "Karnataka",
|
||||
},
|
||||
"in": {},
|
||||
"is": {},
|
||||
"it-mil": {
|
||||
City: "Milan",
|
||||
},
|
||||
"jp": {},
|
||||
"kr": {},
|
||||
"lt": {},
|
||||
"lu": {},
|
||||
"lv": {},
|
||||
"ly": {},
|
||||
"md": {},
|
||||
"mx": {},
|
||||
"mys": {},
|
||||
"nl": {},
|
||||
"no": {},
|
||||
"nz": {},
|
||||
"om": {},
|
||||
"pl": {},
|
||||
"pt": {},
|
||||
"ro": {},
|
||||
"rs": {},
|
||||
"se": {},
|
||||
"sg-free": {
|
||||
Free: true,
|
||||
},
|
||||
"sg": {},
|
||||
"si": {},
|
||||
"sk": {},
|
||||
"th": {},
|
||||
"tr": {},
|
||||
"uk-cv": {
|
||||
City: "London",
|
||||
},
|
||||
"uk-lon": {
|
||||
City: "London",
|
||||
},
|
||||
"uk": {},
|
||||
"us-chi": {
|
||||
City: "Chicago",
|
||||
},
|
||||
"us-dal": {
|
||||
City: "Dallas",
|
||||
},
|
||||
"us-den": {
|
||||
City: "Denver",
|
||||
},
|
||||
"us-hou": {
|
||||
City: "Houston",
|
||||
},
|
||||
"us-la": {
|
||||
City: "Los Angeles",
|
||||
},
|
||||
"us-lv": {
|
||||
City: "Las Vegas",
|
||||
},
|
||||
"us-mia": {
|
||||
City: "Miami",
|
||||
},
|
||||
"us-ny-free": {
|
||||
City: "New York",
|
||||
Free: true,
|
||||
},
|
||||
"us-ny": {
|
||||
City: "New York",
|
||||
},
|
||||
"us-sea": {
|
||||
City: "Seattle",
|
||||
},
|
||||
"us-sf": {
|
||||
City: "San Francisco",
|
||||
},
|
||||
"us-sl": {
|
||||
City: "Saint Louis",
|
||||
},
|
||||
"us-slc": {
|
||||
City: "Salt Lake City",
|
||||
},
|
||||
"us-stream": {
|
||||
Stream: true,
|
||||
},
|
||||
"us": {},
|
||||
"vn": {},
|
||||
"za": {},
|
||||
}
|
||||
|
||||
hts = make(hostToServer, len(shortHTS))
|
||||
|
||||
countryCodesMap := constants.CountryCodes()
|
||||
for shortHost, server := range shortHTS {
|
||||
server.UDP = true
|
||||
server.Hostname = shortHost + ".vpnunlimitedapp.com"
|
||||
countryCode := strings.Split(shortHost, "-")[0]
|
||||
country, ok := countryCodesMap[countryCode]
|
||||
if !ok {
|
||||
warnings = append(warnings, "country code not found: "+countryCode)
|
||||
continue
|
||||
}
|
||||
server.Country = country
|
||||
hts[server.Hostname] = server
|
||||
}
|
||||
|
||||
return hts, warnings
|
||||
}
|
||||
38
internal/updater/providers/vpnunlimited/hosttoserver.go
Normal file
38
internal/updater/providers/vpnunlimited/hosttoserver.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package vpnunlimited
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
)
|
||||
|
||||
type hostToServer map[string]models.VPNUnlimitedServer
|
||||
|
||||
func (hts hostToServer) toHostsSlice() (hosts []string) {
|
||||
hosts = make([]string, 0, len(hts))
|
||||
for host := range hts {
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
return hosts
|
||||
}
|
||||
|
||||
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]net.IP) {
|
||||
for host, IPs := range hostToIPs {
|
||||
server := hts[host]
|
||||
server.IPs = IPs
|
||||
hts[host] = server
|
||||
}
|
||||
for host, server := range hts {
|
||||
if len(server.IPs) == 0 {
|
||||
delete(hts, host)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (hts hostToServer) toServersSlice() (servers []models.VPNUnlimitedServer) {
|
||||
servers = make([]models.VPNUnlimitedServer, 0, len(hts))
|
||||
for _, server := range hts {
|
||||
servers = append(servers, server)
|
||||
}
|
||||
return servers
|
||||
}
|
||||
32
internal/updater/providers/vpnunlimited/resolve.go
Normal file
32
internal/updater/providers/vpnunlimited/resolve.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package vpnunlimited
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||
)
|
||||
|
||||
func resolveHosts(ctx context.Context, presolver resolver.Parallel,
|
||||
hosts []string, minServers int) (hostToIPs map[string][]net.IP,
|
||||
warnings []string, err error) {
|
||||
const (
|
||||
maxFailRatio = 0.1
|
||||
maxDuration = 20 * time.Second
|
||||
betweenDuration = time.Second
|
||||
maxNoNew = 2
|
||||
maxFails = 2
|
||||
)
|
||||
settings := resolver.ParallelSettings{
|
||||
MaxFailRatio: maxFailRatio,
|
||||
MinFound: minServers,
|
||||
Repeat: resolver.RepeatSettings{
|
||||
MaxDuration: maxDuration,
|
||||
BetweenDuration: betweenDuration,
|
||||
MaxNoNew: maxNoNew,
|
||||
MaxFails: maxFails,
|
||||
},
|
||||
}
|
||||
return presolver.Resolve(ctx, hosts, settings)
|
||||
}
|
||||
42
internal/updater/providers/vpnunlimited/servers.go
Normal file
42
internal/updater/providers/vpnunlimited/servers.go
Normal file
@@ -0,0 +1,42 @@
|
||||
// Package vpnunlimited contains code to obtain the server information
|
||||
// for the VPNUnlimited provider.
|
||||
package vpnunlimited
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||
)
|
||||
|
||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||
|
||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
||||
presolver resolver.Parallel, minServers int) (
|
||||
servers []models.VPNUnlimitedServer, warnings []string, err error) {
|
||||
// Hardcoded data from a user provided ZIP file since it's behind a login wall
|
||||
hts, warnings := getHostToServer()
|
||||
|
||||
hosts := hts.toHostsSlice()
|
||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
||||
warnings = append(warnings, newWarnings...)
|
||||
if err != nil {
|
||||
return nil, warnings, err
|
||||
}
|
||||
|
||||
hts.adaptWithIPs(hostToIPs)
|
||||
|
||||
servers = hts.toServersSlice()
|
||||
|
||||
if len(servers) < minServers {
|
||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
||||
ErrNotEnoughServers, len(servers), minServers)
|
||||
}
|
||||
|
||||
sortServers(servers)
|
||||
|
||||
return servers, warnings, nil
|
||||
}
|
||||
19
internal/updater/providers/vpnunlimited/sort.go
Normal file
19
internal/updater/providers/vpnunlimited/sort.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package vpnunlimited
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
)
|
||||
|
||||
func sortServers(servers []models.VPNUnlimitedServer) {
|
||||
sort.Slice(servers, func(i, j int) bool {
|
||||
if servers[i].Country == servers[j].Country {
|
||||
if servers[i].City == servers[j].City {
|
||||
return servers[i].Hostname < servers[j].Hostname
|
||||
}
|
||||
return servers[i].City < servers[j].City
|
||||
}
|
||||
return servers[i].Country < servers[j].Country
|
||||
})
|
||||
}
|
||||
14
internal/updater/providers/vpnunlimited/string.go
Normal file
14
internal/updater/providers/vpnunlimited/string.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package vpnunlimited
|
||||
|
||||
import "github.com/qdm12/gluetun/internal/models"
|
||||
|
||||
func Stringify(servers []models.VPNUnlimitedServer) (s string) {
|
||||
s = "func VPNUnlimitedServers() []models.VPNUnlimitedServer {\n"
|
||||
s += " return []models.VPNUnlimitedServer{\n"
|
||||
for _, server := range servers {
|
||||
s += " " + server.String() + ",\n"
|
||||
}
|
||||
s += " }\n"
|
||||
s += "}"
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user