chore(updater): common GetServers signature
- Log warnings when running outside of CLI mode - Remove updater CLI bool setting - Warnings are logged in updating functions
This commit is contained in:
@@ -36,10 +36,8 @@ type UpdaterLogger interface {
|
|||||||
Error(s string)
|
Error(s string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func boolPtr(b bool) *bool { return &b }
|
|
||||||
|
|
||||||
func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) error {
|
func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) error {
|
||||||
options := settings.Updater{CLI: boolPtr(true)}
|
options := settings.Updater{}
|
||||||
var endUserMode, maintainerMode, updateAll bool
|
var endUserMode, maintainerMode, updateAll bool
|
||||||
var dnsAddress, csvProviders string
|
var dnsAddress, csvProviders string
|
||||||
flagSet := flag.NewFlagSet("update", flag.ExitOnError)
|
flagSet := flag.NewFlagSet("update", flag.ExitOnError)
|
||||||
|
|||||||
@@ -26,11 +26,6 @@ type Updater struct {
|
|||||||
// Providers is the list of VPN service providers
|
// Providers is the list of VPN service providers
|
||||||
// to update server information for.
|
// to update server information for.
|
||||||
Providers []string
|
Providers []string
|
||||||
// CLI is to precise the updater is running in CLI
|
|
||||||
// mode. This is set automatically and cannot be set
|
|
||||||
// by settings sources. It cannot be nil in the
|
|
||||||
// internal state.
|
|
||||||
CLI *bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u Updater) Validate() (err error) {
|
func (u Updater) Validate() (err error) {
|
||||||
@@ -62,7 +57,6 @@ func (u *Updater) copy() (copied Updater) {
|
|||||||
Period: helpers.CopyDurationPtr(u.Period),
|
Period: helpers.CopyDurationPtr(u.Period),
|
||||||
DNSAddress: helpers.CopyIP(u.DNSAddress),
|
DNSAddress: helpers.CopyIP(u.DNSAddress),
|
||||||
Providers: helpers.CopyStringSlice(u.Providers),
|
Providers: helpers.CopyStringSlice(u.Providers),
|
||||||
CLI: u.CLI,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +66,6 @@ func (u *Updater) mergeWith(other Updater) {
|
|||||||
u.Period = helpers.MergeWithDuration(u.Period, other.Period)
|
u.Period = helpers.MergeWithDuration(u.Period, other.Period)
|
||||||
u.DNSAddress = helpers.MergeWithIP(u.DNSAddress, other.DNSAddress)
|
u.DNSAddress = helpers.MergeWithIP(u.DNSAddress, other.DNSAddress)
|
||||||
u.Providers = helpers.MergeStringSlices(u.Providers, other.Providers)
|
u.Providers = helpers.MergeStringSlices(u.Providers, other.Providers)
|
||||||
u.CLI = helpers.MergeWithBool(u.CLI, other.CLI)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// overrideWith overrides fields of the receiver
|
// overrideWith overrides fields of the receiver
|
||||||
@@ -82,13 +75,11 @@ func (u *Updater) overrideWith(other Updater) {
|
|||||||
u.Period = helpers.OverrideWithDuration(u.Period, other.Period)
|
u.Period = helpers.OverrideWithDuration(u.Period, other.Period)
|
||||||
u.DNSAddress = helpers.OverrideWithIP(u.DNSAddress, other.DNSAddress)
|
u.DNSAddress = helpers.OverrideWithIP(u.DNSAddress, other.DNSAddress)
|
||||||
u.Providers = helpers.OverrideWithStringSlice(u.Providers, other.Providers)
|
u.Providers = helpers.OverrideWithStringSlice(u.Providers, other.Providers)
|
||||||
u.CLI = helpers.MergeWithBool(u.CLI, other.CLI)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Updater) SetDefaults(vpnProvider string) {
|
func (u *Updater) SetDefaults(vpnProvider string) {
|
||||||
u.Period = helpers.DefaultDuration(u.Period, 0)
|
u.Period = helpers.DefaultDuration(u.Period, 0)
|
||||||
u.DNSAddress = helpers.DefaultIP(u.DNSAddress, net.IPv4(1, 1, 1, 1))
|
u.DNSAddress = helpers.DefaultIP(u.DNSAddress, net.IPv4(1, 1, 1, 1))
|
||||||
u.CLI = helpers.DefaultBool(u.CLI, false)
|
|
||||||
if len(u.Providers) == 0 && vpnProvider != providers.Custom {
|
if len(u.Providers) == 0 && vpnProvider != providers.Custom {
|
||||||
u.Providers = []string{vpnProvider}
|
u.Providers = []string{vpnProvider}
|
||||||
}
|
}
|
||||||
@@ -108,9 +99,5 @@ func (u Updater) toLinesNode() (node *gotree.Node) {
|
|||||||
node.Appendf("DNS address: %s", u.DNSAddress)
|
node.Appendf("DNS address: %s", u.DNSAddress)
|
||||||
node.Appendf("Providers to update: %s", strings.Join(u.Providers, ", "))
|
node.Appendf("Providers to update: %s", strings.Join(u.Providers, ", "))
|
||||||
|
|
||||||
if *u.CLI {
|
|
||||||
node.Appendf("CLI mode: enabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetServers(ctx context.Context, presolver resolver.Parallel,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
minServers int) (servers []models.Server, err error) {
|
servers []models.Server, err error) {
|
||||||
possibleServers := getPossibleServers()
|
possibleServers := getPossibleServers()
|
||||||
|
|
||||||
possibleHosts := possibleServers.hostsSlice()
|
possibleHosts := possibleServers.hostsSlice()
|
||||||
hostToIPs, err := resolveHosts(ctx, presolver, possibleHosts, minServers)
|
hostToIPs, err := resolveHosts(ctx, u.presolver, possibleHosts, minServers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
13
internal/provider/cyberghost/updater/updater.go
Normal file
13
internal/provider/cyberghost/updater/updater.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package cyberghost
|
||||||
|
|
||||||
|
import "github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
presolver resolver.Parallel
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(presolver resolver.Parallel) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
presolver: presolver,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,15 +9,12 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"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")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
servers = hardcodedServers()
|
servers = hardcodedServers()
|
||||||
|
|
||||||
hosts := make([]string, len(servers))
|
hosts := make([]string, len(servers))
|
||||||
@@ -25,10 +22,12 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
hosts[i] = servers[i].Hostname
|
hosts[i] = servers[i].Hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
@@ -46,11 +45,11 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
servers = servers[:i]
|
servers = servers[:i]
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
25
internal/provider/expressvpn/updater/updater.go
Normal file
25
internal/provider/expressvpn/updater/updater.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package expressvpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(unzipper unzip.Unzipper, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,21 +10,18 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
const url = "https://support.fastestvpn.com/download/openvpn-tcp-udp-config-files"
|
const url = "https://support.fastestvpn.com/download/openvpn-tcp-udp-config-files"
|
||||||
contents, err := unzipper.FetchAndExtract(ctx, url)
|
contents, err := u.unzipper.FetchAndExtract(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
} else if len(contents) < minServers {
|
} else if len(contents) < minServers {
|
||||||
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(contents), minServers)
|
ErrNotEnoughServers, len(contents), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,18 +34,17 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
|
|
||||||
country, tcp, udp, err := parseFilename(fileName)
|
country, tcp, udp, err := parseFilename(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
warnings = append(warnings, err.Error())
|
u.warner.Warn(err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
host, warning, err := openvpn.ExtractHost(content)
|
host, warning, err := openvpn.ExtractHost(content)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,15 +52,17 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(hts) < minServers {
|
if len(hts) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(hts), minServers)
|
ErrNotEnoughServers, len(hts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
@@ -72,11 +70,11 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
25
internal/provider/fastestvpn/updater/updater.go
Normal file
25
internal/provider/fastestvpn/updater/updater.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package fastestvpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(unzipper unzip.Unzipper, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,33 +6,33 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, client *http.Client,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
tcpHostToURL, udpHostToURL, err := getAllHostToURL(ctx, u.client)
|
||||||
tcpHostToURL, udpHostToURL, err := getAllHostToURL(ctx, client)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := getUniqueHosts(tcpHostToURL, udpHostToURL)
|
hosts := getUniqueHosts(tcpHostToURL, udpHostToURL)
|
||||||
|
|
||||||
if len(hosts) < minServers {
|
if len(hosts) < minServers {
|
||||||
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(hosts), minServers)
|
ErrNotEnoughServers, len(hosts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hostToIPs, warnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
servers = make([]models.Server, 0, len(hostToIPs))
|
servers = make([]models.Server, 0, len(hostToIPs))
|
||||||
@@ -66,5 +66,5 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
26
internal/provider/hidemyass/updater/updater.go
Normal file
26
internal/provider/hidemyass/updater/updater.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package hidemyass
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package ipvanish
|
||||||
|
|
||||||
|
//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . Warner
|
||||||
46
internal/provider/ipvanish/updater/mocks_test.go
Normal file
46
internal/provider/ipvanish/updater/mocks_test.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/qdm12/gluetun/internal/provider/ipvanish/updater (interfaces: Warner)
|
||||||
|
|
||||||
|
// Package ipvanish is a generated GoMock package.
|
||||||
|
package ipvanish
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockWarner is a mock of Warner interface.
|
||||||
|
type MockWarner struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockWarnerMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockWarnerMockRecorder is the mock recorder for MockWarner.
|
||||||
|
type MockWarnerMockRecorder struct {
|
||||||
|
mock *MockWarner
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockWarner creates a new mock instance.
|
||||||
|
func NewMockWarner(ctrl *gomock.Controller) *MockWarner {
|
||||||
|
mock := &MockWarner{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockWarnerMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockWarner) EXPECT() *MockWarnerMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn mocks base method.
|
||||||
|
func (m *MockWarner) Warn(arg0 string) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "Warn", arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn indicates an expected call of Warn.
|
||||||
|
func (mr *MockWarnerMockRecorder) Warn(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warn", reflect.TypeOf((*MockWarner)(nil).Warn), arg0)
|
||||||
|
}
|
||||||
@@ -10,23 +10,20 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
"golang.org/x/text/cases"
|
"golang.org/x/text/cases"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
const url = "https://www.ipvanish.com/software/configs/configs.zip"
|
const url = "https://www.ipvanish.com/software/configs/configs.zip"
|
||||||
contents, err := unzipper.FetchAndExtract(ctx, url)
|
contents, err := u.unzipper.FetchAndExtract(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
} else if len(contents) < minServers {
|
} else if len(contents) < minServers {
|
||||||
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(contents), minServers)
|
ErrNotEnoughServers, len(contents), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,27 +38,24 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
tcp, udp, err := openvpn.ExtractProto(content)
|
tcp, udp, err := openvpn.ExtractProto(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + ": in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
hostname, warning, err := openvpn.ExtractHost(content)
|
hostname, warning, err := openvpn.ExtractHost(content)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
country, city, err := parseFilename(fileName, hostname, titleCaser)
|
country, city, err := parseFilename(fileName, hostname, titleCaser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,15 +63,17 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(hts) < minServers {
|
if len(hts) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(hts), minServers)
|
ErrNotEnoughServers, len(hts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
@@ -85,11 +81,11 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,15 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_GetServers(t *testing.T) {
|
func Test_Updater_GetServers(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
// Inputs
|
// Inputs
|
||||||
minServers int
|
minServers int
|
||||||
|
|
||||||
|
// Mocks
|
||||||
|
warnerBuilder func(ctrl *gomock.Controller) Warner
|
||||||
|
|
||||||
// Unzip
|
// Unzip
|
||||||
unzipContents map[string][]byte
|
unzipContents map[string][]byte
|
||||||
unzipErr error
|
unzipErr error
|
||||||
@@ -35,48 +38,67 @@ func Test_GetServers(t *testing.T) {
|
|||||||
resolveErr error
|
resolveErr error
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
servers []models.Server
|
servers []models.Server
|
||||||
warnings []string
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
"unzipper error": {
|
"unzipper error": {
|
||||||
unzipErr: errors.New("dummy"),
|
warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil },
|
||||||
err: errors.New("dummy"),
|
unzipErr: errors.New("dummy"),
|
||||||
|
err: errors.New("dummy"),
|
||||||
},
|
},
|
||||||
"not enough unzip contents": {
|
"not enough unzip contents": {
|
||||||
minServers: 1,
|
minServers: 1,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil },
|
||||||
unzipContents: map[string][]byte{},
|
unzipContents: map[string][]byte{},
|
||||||
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
||||||
},
|
},
|
||||||
"no openvpn file": {
|
"no openvpn file": {
|
||||||
minServers: 1,
|
minServers: 1,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil },
|
||||||
unzipContents: map[string][]byte{"somefile.txt": {}},
|
unzipContents: map[string][]byte{"somefile.txt": {}},
|
||||||
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
||||||
},
|
},
|
||||||
"invalid proto": {
|
"invalid proto": {
|
||||||
minServers: 1,
|
minServers: 1,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner {
|
||||||
|
warner := NewMockWarner(ctrl)
|
||||||
|
warner.EXPECT().Warn("unknown protocol: invalid in badproto.ovpn")
|
||||||
|
return warner
|
||||||
|
},
|
||||||
unzipContents: map[string][]byte{"badproto.ovpn": []byte(`proto invalid`)},
|
unzipContents: map[string][]byte{"badproto.ovpn": []byte(`proto invalid`)},
|
||||||
warnings: []string{"unknown protocol: invalid: in badproto.ovpn"},
|
|
||||||
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
||||||
},
|
},
|
||||||
"no host": {
|
"no host": {
|
||||||
minServers: 1,
|
minServers: 1,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner {
|
||||||
|
warner := NewMockWarner(ctrl)
|
||||||
|
warner.EXPECT().Warn("remote host not found in nohost.ovpn")
|
||||||
|
return warner
|
||||||
|
},
|
||||||
unzipContents: map[string][]byte{"nohost.ovpn": []byte(``)},
|
unzipContents: map[string][]byte{"nohost.ovpn": []byte(``)},
|
||||||
warnings: []string{"remote host not found in nohost.ovpn"},
|
|
||||||
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
||||||
},
|
},
|
||||||
"multiple hosts": {
|
"multiple hosts": {
|
||||||
minServers: 1,
|
minServers: 1,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner {
|
||||||
|
warner := NewMockWarner(ctrl)
|
||||||
|
warner.EXPECT().Warn("only using the first host \"hosta\" and discarding 1 other hosts")
|
||||||
|
return warner
|
||||||
|
},
|
||||||
unzipContents: map[string][]byte{
|
unzipContents: map[string][]byte{
|
||||||
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta\nremote hostb"),
|
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta\nremote hostb"),
|
||||||
},
|
},
|
||||||
expectResolve: true,
|
expectResolve: true,
|
||||||
hostsToResolve: []string{"hosta"},
|
hostsToResolve: []string{"hosta"},
|
||||||
resolveSettings: getResolveSettings(1),
|
resolveSettings: getResolveSettings(1),
|
||||||
warnings: []string{"only using the first host \"hosta\" and discarding 1 other hosts"},
|
|
||||||
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
||||||
},
|
},
|
||||||
"resolve error": {
|
"resolve error": {
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner {
|
||||||
|
warner := NewMockWarner(ctrl)
|
||||||
|
warner.EXPECT().Warn("resolve warning")
|
||||||
|
return warner
|
||||||
|
},
|
||||||
unzipContents: map[string][]byte{
|
unzipContents: map[string][]byte{
|
||||||
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta"),
|
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta"),
|
||||||
},
|
},
|
||||||
@@ -85,19 +107,27 @@ func Test_GetServers(t *testing.T) {
|
|||||||
resolveSettings: getResolveSettings(0),
|
resolveSettings: getResolveSettings(0),
|
||||||
resolveWarnings: []string{"resolve warning"},
|
resolveWarnings: []string{"resolve warning"},
|
||||||
resolveErr: errors.New("dummy"),
|
resolveErr: errors.New("dummy"),
|
||||||
warnings: []string{"resolve warning"},
|
|
||||||
err: errors.New("dummy"),
|
err: errors.New("dummy"),
|
||||||
},
|
},
|
||||||
"filename parsing error": {
|
"filename parsing error": {
|
||||||
minServers: 1,
|
minServers: 1,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner {
|
||||||
|
warner := NewMockWarner(ctrl)
|
||||||
|
warner.EXPECT().Warn("country code is unknown: unknown in ipvanish-unknown-City-A-hosta.ovpn")
|
||||||
|
return warner
|
||||||
|
},
|
||||||
unzipContents: map[string][]byte{
|
unzipContents: map[string][]byte{
|
||||||
"ipvanish-unknown-City-A-hosta.ovpn": []byte("remote hosta"),
|
"ipvanish-unknown-City-A-hosta.ovpn": []byte("remote hosta"),
|
||||||
},
|
},
|
||||||
warnings: []string{"country code is unknown: unknown in ipvanish-unknown-City-A-hosta.ovpn"},
|
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
||||||
err: errors.New("not enough servers found: 0 and expected at least 1"),
|
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
minServers: 1,
|
minServers: 1,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner {
|
||||||
|
warner := NewMockWarner(ctrl)
|
||||||
|
warner.EXPECT().Warn("resolve warning")
|
||||||
|
return warner
|
||||||
|
},
|
||||||
unzipContents: map[string][]byte{
|
unzipContents: map[string][]byte{
|
||||||
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta"),
|
"ipvanish-CA-City-A-hosta.ovpn": []byte("remote hosta"),
|
||||||
"ipvanish-LU-City-B-hostb.ovpn": []byte("remote hostb"),
|
"ipvanish-LU-City-B-hostb.ovpn": []byte("remote hostb"),
|
||||||
@@ -128,7 +158,6 @@ func Test_GetServers(t *testing.T) {
|
|||||||
IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}},
|
IPs: []net.IP{{3, 3, 3, 3}, {4, 4, 4, 4}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
warnings: []string{"resolve warning"},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
@@ -150,10 +179,13 @@ func Test_GetServers(t *testing.T) {
|
|||||||
Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr)
|
Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
servers, warnings, err := GetServers(ctx, unzipper, presolver, testCase.minServers)
|
warner := testCase.warnerBuilder(ctrl)
|
||||||
|
|
||||||
|
updater := New(unzipper, presolver, warner)
|
||||||
|
|
||||||
|
servers, err := updater.GetServers(ctx, testCase.minServers)
|
||||||
|
|
||||||
assert.Equal(t, testCase.servers, servers)
|
assert.Equal(t, testCase.servers, servers)
|
||||||
assert.Equal(t, testCase.warnings, warnings)
|
|
||||||
if testCase.err != nil {
|
if testCase.err != nil {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, testCase.err.Error(), err.Error())
|
assert.Equal(t, testCase.err.Error(), err.Error())
|
||||||
|
|||||||
25
internal/provider/ipvanish/updater/updater.go
Normal file
25
internal/provider/ipvanish/updater/updater.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package ipvanish
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(unzipper unzip.Unzipper, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
3
internal/provider/ivpn/updater/mocks_generate_test.go
Normal file
3
internal/provider/ivpn/updater/mocks_generate_test.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package ivpn
|
||||||
|
|
||||||
|
//go:generate mockgen -destination=mocks_test.go -package $GOPACKAGE . Warner
|
||||||
46
internal/provider/ivpn/updater/mocks_test.go
Normal file
46
internal/provider/ivpn/updater/mocks_test.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/qdm12/gluetun/internal/provider/ivpn/updater (interfaces: Warner)
|
||||||
|
|
||||||
|
// Package ivpn is a generated GoMock package.
|
||||||
|
package ivpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockWarner is a mock of Warner interface.
|
||||||
|
type MockWarner struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockWarnerMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockWarnerMockRecorder is the mock recorder for MockWarner.
|
||||||
|
type MockWarnerMockRecorder struct {
|
||||||
|
mock *MockWarner
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockWarner creates a new mock instance.
|
||||||
|
func NewMockWarner(ctrl *gomock.Controller) *MockWarner {
|
||||||
|
mock := &MockWarner{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockWarnerMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockWarner) EXPECT() *MockWarnerMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn mocks base method.
|
||||||
|
func (m *MockWarner) Warn(arg0 string) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
m.ctrl.Call(m, "Warn", arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn indicates an expected call of Warn.
|
||||||
|
func (mr *MockWarnerMockRecorder) Warn(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warn", reflect.TypeOf((*MockWarner)(nil).Warn), arg0)
|
||||||
|
}
|
||||||
@@ -6,23 +6,20 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotEnoughServers = errors.New("not enough servers found")
|
ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetServers(ctx context.Context, client *http.Client,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
data, err := fetchAPI(ctx, u.client)
|
||||||
data, err := fetchAPI(ctx, client)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed fetching API: %w", err)
|
return nil, fmt.Errorf("failed fetching API: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := make([]string, 0, len(data.Servers))
|
hosts := make([]string, 0, len(data.Servers))
|
||||||
@@ -40,13 +37,16 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(hosts) < minServers {
|
if len(hosts) < minServers {
|
||||||
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(hosts), minServers)
|
ErrNotEnoughServers, len(hosts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hostToIPs, warnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
servers = make([]models.Server, 0, len(hosts))
|
servers = make([]models.Server, 0, len(hosts))
|
||||||
@@ -78,5 +78,5 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,13 +18,16 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_GetServers(t *testing.T) {
|
func Test_Updater_GetServers(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
testCases := map[string]struct {
|
testCases := map[string]struct {
|
||||||
// Inputs
|
// Inputs
|
||||||
minServers int
|
minServers int
|
||||||
|
|
||||||
|
// Mocks
|
||||||
|
warnerBuilder func(ctrl *gomock.Controller) Warner
|
||||||
|
|
||||||
// From API
|
// From API
|
||||||
responseBody string
|
responseBody string
|
||||||
responseStatus int
|
responseStatus int
|
||||||
@@ -38,15 +41,20 @@ func Test_GetServers(t *testing.T) {
|
|||||||
resolveErr error
|
resolveErr error
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
servers []models.Server
|
servers []models.Server
|
||||||
warnings []string
|
err error
|
||||||
err error
|
|
||||||
}{
|
}{
|
||||||
"http response error": {
|
"http response error": {
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil },
|
||||||
responseStatus: http.StatusNoContent,
|
responseStatus: http.StatusNoContent,
|
||||||
err: errors.New("failed fetching API: HTTP status code not OK: 204 No Content"),
|
err: errors.New("failed fetching API: HTTP status code not OK: 204 No Content"),
|
||||||
},
|
},
|
||||||
"resolve error": {
|
"resolve error": {
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner {
|
||||||
|
warner := NewMockWarner(ctrl)
|
||||||
|
warner.EXPECT().Warn("resolve warning")
|
||||||
|
return warner
|
||||||
|
},
|
||||||
responseBody: `{"servers":[
|
responseBody: `{"servers":[
|
||||||
{"hostnames":{"openvpn":"hosta"}}
|
{"hostnames":{"openvpn":"hosta"}}
|
||||||
]}`,
|
]}`,
|
||||||
@@ -56,11 +64,11 @@ func Test_GetServers(t *testing.T) {
|
|||||||
resolveSettings: getResolveSettings(0),
|
resolveSettings: getResolveSettings(0),
|
||||||
resolveWarnings: []string{"resolve warning"},
|
resolveWarnings: []string{"resolve warning"},
|
||||||
resolveErr: errors.New("dummy"),
|
resolveErr: errors.New("dummy"),
|
||||||
warnings: []string{"resolve warning"},
|
|
||||||
err: errors.New("dummy"),
|
err: errors.New("dummy"),
|
||||||
},
|
},
|
||||||
"not enough servers": {
|
"not enough servers": {
|
||||||
minServers: 2,
|
minServers: 2,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner { return nil },
|
||||||
responseBody: `{"servers":[
|
responseBody: `{"servers":[
|
||||||
{"hostnames":{"openvpn":"hosta"}}
|
{"hostnames":{"openvpn":"hosta"}}
|
||||||
]}`,
|
]}`,
|
||||||
@@ -69,6 +77,11 @@ func Test_GetServers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
minServers: 1,
|
minServers: 1,
|
||||||
|
warnerBuilder: func(ctrl *gomock.Controller) Warner {
|
||||||
|
warner := NewMockWarner(ctrl)
|
||||||
|
warner.EXPECT().Warn("resolve warning")
|
||||||
|
return warner
|
||||||
|
},
|
||||||
responseBody: `{"servers":[
|
responseBody: `{"servers":[
|
||||||
{"country":"Country1","city":"City A","hostnames":{"openvpn":"hosta"}},
|
{"country":"Country1","city":"City A","hostnames":{"openvpn":"hosta"}},
|
||||||
{"country":"Country2","city":"City B","hostnames":{"openvpn":"hostb"},"wg_public_key":"xyz"},
|
{"country":"Country2","city":"City B","hostnames":{"openvpn":"hostb"},"wg_public_key":"xyz"},
|
||||||
@@ -97,7 +110,6 @@ func Test_GetServers(t *testing.T) {
|
|||||||
WgPubKey: "xyz",
|
WgPubKey: "xyz",
|
||||||
IPs: []net.IP{{5, 5, 5, 5}, {6, 6, 6, 6}}},
|
IPs: []net.IP{{5, 5, 5, 5}, {6, 6, 6, 6}}},
|
||||||
},
|
},
|
||||||
warnings: []string{"resolve warning"},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for name, testCase := range testCases {
|
for name, testCase := range testCases {
|
||||||
@@ -126,10 +138,13 @@ func Test_GetServers(t *testing.T) {
|
|||||||
Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr)
|
Return(testCase.hostToIPs, testCase.resolveWarnings, testCase.resolveErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
servers, warnings, err := GetServers(ctx, client, presolver, testCase.minServers)
|
warner := testCase.warnerBuilder(ctrl)
|
||||||
|
|
||||||
|
updater := New(client, presolver, warner)
|
||||||
|
|
||||||
|
servers, err := updater.GetServers(ctx, testCase.minServers)
|
||||||
|
|
||||||
assert.Equal(t, testCase.servers, servers)
|
assert.Equal(t, testCase.servers, servers)
|
||||||
assert.Equal(t, testCase.warnings, warnings)
|
|
||||||
if testCase.err != nil {
|
if testCase.err != nil {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, testCase.err.Error(), err.Error())
|
assert.Equal(t, testCase.err.Error(), err.Error())
|
||||||
|
|||||||
26
internal/provider/ivpn/updater/updater.go
Normal file
26
internal/provider/ivpn/updater/updater.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package ivpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,16 +6,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, err error) {
|
servers []models.Server, err error) {
|
||||||
data, err := fetchAPI(ctx, client)
|
data, err := fetchAPI(ctx, u.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
15
internal/provider/mullvad/updater/updater.go
Normal file
15
internal/provider/mullvad/updater/updater.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package mullvad
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -19,30 +18,29 @@ var (
|
|||||||
ErrNotEnoughServers = errors.New("not enough servers found")
|
ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, warnings []string, err error) {
|
servers []models.Server, err error) {
|
||||||
data, err := fetchAPI(ctx, client)
|
data, err := fetchAPI(ctx, u.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
servers = make([]models.Server, 0, len(data))
|
servers = make([]models.Server, 0, len(data))
|
||||||
|
|
||||||
for _, jsonServer := range data {
|
for _, jsonServer := range data {
|
||||||
if !jsonServer.Features.TCP && !jsonServer.Features.UDP {
|
if !jsonServer.Features.TCP && !jsonServer.Features.UDP {
|
||||||
warning := "server does not support TCP and UDP for openvpn: " + jsonServer.Name
|
u.warner.Warn("server does not support TCP and UDP for openvpn: " + jsonServer.Name)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
ip, err := parseIPv4(jsonServer.IPAddress)
|
ip, err := parseIPv4(jsonServer.IPAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("%w for server %s", err, jsonServer.Name)
|
return nil, fmt.Errorf("%w for server %s", err, jsonServer.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
number, err := parseServerName(jsonServer.Name)
|
number, err := parseServerName(jsonServer.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
server := models.Server{
|
server := models.Server{
|
||||||
@@ -58,11 +56,11 @@ func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
21
internal/provider/nordvpn/updater/updater.go
Normal file
21
internal/provider/nordvpn/updater/updater.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package nordvpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(message string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,13 +9,12 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper, minServers int) (
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, warnings []string, err error) {
|
servers []models.Server, err error) {
|
||||||
zipURL := url.URL{
|
zipURL := url.URL{
|
||||||
Scheme: "https",
|
Scheme: "https",
|
||||||
Host: "www.perfect-privacy.com",
|
Host: "www.perfect-privacy.com",
|
||||||
@@ -28,9 +27,9 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper, minServers int) (
|
|||||||
values.Set("protocol", "udp") // all support both TCP and UDP
|
values.Set("protocol", "udp") // all support both TCP and UDP
|
||||||
zipURL.RawQuery = values.Encode()
|
zipURL.RawQuery = values.Encode()
|
||||||
|
|
||||||
contents, err := unzipper.FetchAndExtract(ctx, zipURL.String())
|
contents, err := u.unzipper.FetchAndExtract(ctx, zipURL.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cts := make(cityToServer)
|
cts := make(cityToServer)
|
||||||
@@ -38,12 +37,12 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper, minServers int) (
|
|||||||
for fileName, content := range contents {
|
for fileName, content := range contents {
|
||||||
err := addServerFromOvpn(cts, fileName, content)
|
err := addServerFromOvpn(cts, fileName, content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
warnings = append(warnings, fileName+": "+err.Error())
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(cts) < minServers {
|
if len(cts) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(cts), minServers)
|
ErrNotEnoughServers, len(cts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +50,7 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper, minServers int) (
|
|||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addServerFromOvpn(cts cityToServer,
|
func addServerFromOvpn(cts cityToServer,
|
||||||
|
|||||||
19
internal/provider/perfectprivacy/updater/updater.go
Normal file
19
internal/provider/perfectprivacy/updater/updater.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package perfectprivacy
|
||||||
|
|
||||||
|
import "github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(unzipper unzip.Unzipper, warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
unzipper: unzipper,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,26 +6,22 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
client *http.Client, presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
const url = "https://privado.io/apps/ovpn_configs.zip"
|
const url = "https://privado.io/apps/ovpn_configs.zip"
|
||||||
contents, err := unzipper.FetchAndExtract(ctx, url)
|
contents, err := u.unzipper.FetchAndExtract(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
} else if len(contents) < minServers {
|
} else if len(contents) < minServers {
|
||||||
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(contents), minServers)
|
ErrNotEnoughServers, len(contents), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,12 +34,11 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
|
|
||||||
host, warning, err := openvpn.ExtractHost(content)
|
host, warning, err := openvpn.ExtractHost(content)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,26 +46,28 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(hts) < minServers {
|
if len(hts) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(hts), minServers)
|
ErrNotEnoughServers, len(hts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
|
|
||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
if err := setLocationInfo(ctx, client, servers); err != nil {
|
if err := setLocationInfo(ctx, u.client, servers); err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
29
internal/provider/privado/updater/updater.go
Normal file
29
internal/provider/privado/updater/updater.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package privado
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, unzipper unzip.Unzipper,
|
||||||
|
presolver resolver.Parallel, warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -14,7 +13,7 @@ import (
|
|||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, err error) {
|
servers []models.Server, err error) {
|
||||||
nts := make(nameToServer)
|
nts := make(nameToServer)
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
|||||||
maxTimer := time.NewTimer(maxDuration)
|
maxTimer := time.NewTimer(maxDuration)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
data, err := fetchAPI(ctx, client)
|
data, err := fetchAPI(ctx, u.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
19
internal/provider/privateinternetaccess/updater/updater.go
Normal file
19
internal/provider/privateinternetaccess/updater/updater.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package privateinternetaccess
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,21 +11,18 @@ import (
|
|||||||
"github.com/qdm12/gluetun/internal/constants"
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
const url = "https://privatevpn.com/client/PrivateVPN-TUN.zip"
|
const url = "https://privatevpn.com/client/PrivateVPN-TUN.zip"
|
||||||
contents, err := unzipper.FetchAndExtract(ctx, url)
|
contents, err := u.unzipper.FetchAndExtract(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
} else if len(contents) < minServers {
|
} else if len(contents) < minServers {
|
||||||
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(contents), minServers)
|
ErrNotEnoughServers, len(contents), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,18 +38,19 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
|
|
||||||
countryCode, city, err := parseFilename(fileName)
|
countryCode, city, err := parseFilename(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
warnings = append(warnings, err.Error())
|
// treat error as warning and go to next file
|
||||||
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
country, warning := codeToCountry(countryCode, countryCodes)
|
country, warning := codeToCountry(countryCode, countryCodes)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
|
|
||||||
host, warning, err := openvpn.ExtractHost(content)
|
host, warning, err := openvpn.ExtractHost(content)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
if err == nil { // found host
|
if err == nil { // found host
|
||||||
hts.add(host, country, city)
|
hts.add(host, country, city)
|
||||||
@@ -61,12 +59,11 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
|
|
||||||
ips, extractIPErr := openvpn.ExtractIPs(content)
|
ips, extractIPErr := openvpn.ExtractIPs(content)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
if extractIPErr != nil {
|
if extractIPErr != nil {
|
||||||
// treat extract host error as warning and go to next file
|
// treat extract host error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(extractIPErr.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
server := models.Server{
|
server := models.Server{
|
||||||
@@ -80,16 +77,18 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(noHostnameServers)+len(hts) < minServers {
|
if len(noHostnameServers)+len(hts) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers)+len(hts), minServers)
|
ErrNotEnoughServers, len(servers)+len(hts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
|
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
@@ -99,5 +98,5 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
25
internal/provider/privatevpn/updater/updater.go
Normal file
25
internal/provider/privatevpn/updater/updater.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package privatevpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(unzipper unzip.Unzipper, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants"
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -14,11 +13,11 @@ import (
|
|||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, warnings []string, err error) {
|
servers []models.Server, err error) {
|
||||||
data, err := fetchAPI(ctx, client)
|
data, err := fetchAPI(ctx, u.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
countryCodes := constants.CountryCodes()
|
countryCodes := constants.CountryCodes()
|
||||||
@@ -29,7 +28,7 @@ func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if count < minServers {
|
if count < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, count, minServers)
|
ErrNotEnoughServers, count, minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +39,7 @@ func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
|||||||
name := logicalServer.Name
|
name := logicalServer.Name
|
||||||
for _, physicalServer := range logicalServer.Servers {
|
for _, physicalServer := range logicalServer.Servers {
|
||||||
if physicalServer.Status == 0 { // disabled so skip server
|
if physicalServer.Status == 0 { // disabled so skip server
|
||||||
warnings = append(warnings,
|
u.warner.Warn("ignoring server " + physicalServer.Domain + " with status 0")
|
||||||
"ignoring server "+physicalServer.Domain+" with status 0")
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +51,7 @@ func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
|||||||
countryCode := logicalServer.ExitCountry
|
countryCode := logicalServer.ExitCountry
|
||||||
country, warning := codeToCountry(countryCode, countryCodes)
|
country, warning := codeToCountry(countryCode, countryCodes)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
|
|
||||||
ipToServer.add(country, region, city, name, hostname, entryIP)
|
ipToServer.add(country, region, city, name, hostname, entryIP)
|
||||||
@@ -61,7 +59,7 @@ func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(ipToServer) < minServers {
|
if len(ipToServer) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(ipToServer), minServers)
|
ErrNotEnoughServers, len(ipToServer), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +67,7 @@ func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
|||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStringValue(ptr *string) string {
|
func getStringValue(ptr *string) string {
|
||||||
|
|||||||
21
internal/provider/protonvpn/updater/updater.go
Normal file
21
internal/provider/protonvpn/updater/updater.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package protonvpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,27 +7,23 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/publicip"
|
"github.com/qdm12/gluetun/internal/publicip"
|
||||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, client *http.Client,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
unzipper unzip.Unzipper, presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
const url = "https://d32d3g1fvkpl8y.cloudfront.net/heartbleed/windows/New+OVPN+Files.zip"
|
const url = "https://d32d3g1fvkpl8y.cloudfront.net/heartbleed/windows/New+OVPN+Files.zip"
|
||||||
contents, err := unzipper.FetchAndExtract(ctx, url)
|
contents, err := u.unzipper.FetchAndExtract(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
} else if len(contents) < minServers {
|
} else if len(contents) < minServers {
|
||||||
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(contents), minServers)
|
ErrNotEnoughServers, len(contents), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,20 +37,18 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
tcp, udp, err := openvpn.ExtractProto(content)
|
tcp, udp, err := openvpn.ExtractProto(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
host, warning, err := openvpn.ExtractHost(content)
|
host, warning, err := openvpn.ExtractHost(content)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,15 +56,17 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(hts) < minServers {
|
if len(hts) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(hts), minServers)
|
ErrNotEnoughServers, len(hts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
@@ -78,7 +74,7 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,9 +83,9 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
for i := range servers {
|
for i := range servers {
|
||||||
ipsToGetInfo[i] = servers[i].IPs[0]
|
ipsToGetInfo[i] = servers[i].IPs[0]
|
||||||
}
|
}
|
||||||
ipsInfo, err := publicip.MultiInfo(ctx, client, ipsToGetInfo)
|
ipsInfo, err := publicip.MultiInfo(ctx, u.client, ipsToGetInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for i := range servers {
|
for i := range servers {
|
||||||
servers[i].Country = ipsInfo[i].Country
|
servers[i].Country = ipsInfo[i].Country
|
||||||
@@ -99,5 +95,5 @@ func GetServers(ctx context.Context, client *http.Client,
|
|||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
29
internal/provider/purevpn/updater/updater.go
Normal file
29
internal/provider/purevpn/updater/updater.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package purevpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, unzipper unzip.Unzipper,
|
||||||
|
presolver resolver.Parallel, warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,39 +6,40 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotEnoughServers = errors.New("not enough servers found")
|
ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
client *http.Client, presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
hts := make(hostToServer)
|
hts := make(hostToServer)
|
||||||
|
|
||||||
err = addServersFromAPI(ctx, client, hts)
|
err = addServersFromAPI(ctx, u.client, hts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("cannot fetch server information from API: %w", err)
|
return nil, fmt.Errorf("cannot fetch server information from API: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
warnings, err = addOpenVPNServersFromZip(ctx, unzipper, hts)
|
warnings, err := addOpenVPNServersFromZip(ctx, u.unzipper, hts)
|
||||||
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("cannot get OpenVPN ZIP file: %w", err)
|
return nil, fmt.Errorf("cannot get OpenVPN ZIP file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
getRemainingServers(hts)
|
getRemainingServers(hts)
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
@@ -46,11 +47,11 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
29
internal/provider/surfshark/updater/updater.go
Normal file
29
internal/provider/surfshark/updater/updater.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package surfshark
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, unzipper unzip.Unzipper,
|
||||||
|
presolver resolver.Parallel, warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,27 +10,24 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
"golang.org/x/text/cases"
|
"golang.org/x/text/cases"
|
||||||
"golang.org/x/text/language"
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
const tcpURL = "https://torguard.net/downloads/OpenVPN-TCP-Linux.zip"
|
const tcpURL = "https://torguard.net/downloads/OpenVPN-TCP-Linux.zip"
|
||||||
tcpContents, err := unzipper.FetchAndExtract(ctx, tcpURL)
|
tcpContents, err := u.unzipper.FetchAndExtract(ctx, tcpURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const udpURL = "https://torguard.net/downloads/OpenVPN-UDP-Linux.zip"
|
const udpURL = "https://torguard.net/downloads/OpenVPN-UDP-Linux.zip"
|
||||||
udpContents, err := unzipper.FetchAndExtract(ctx, udpURL)
|
udpContents, err := u.unzipper.FetchAndExtract(ctx, udpURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts := make(hostToServer)
|
hts := make(hostToServer)
|
||||||
@@ -38,26 +35,26 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
|
|
||||||
for fileName, content := range tcpContents {
|
for fileName, content := range tcpContents {
|
||||||
const tcp, udp = true, false
|
const tcp, udp = true, false
|
||||||
newWarnings := addServerFromOvpn(fileName, content, hts, tcp, udp, titleCaser)
|
warnings := addServerFromOvpn(fileName, content, hts, tcp, udp, titleCaser)
|
||||||
warnings = append(warnings, newWarnings...)
|
u.warnWarnings(warnings)
|
||||||
}
|
}
|
||||||
|
|
||||||
for fileName, content := range udpContents {
|
for fileName, content := range udpContents {
|
||||||
const tcp, udp = false, true
|
const tcp, udp = false, true
|
||||||
newWarnings := addServerFromOvpn(fileName, content, hts, tcp, udp, titleCaser)
|
warnings := addServerFromOvpn(fileName, content, hts, tcp, udp, titleCaser)
|
||||||
warnings = append(warnings, newWarnings...)
|
u.warnWarnings(warnings)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(hts) < minServers {
|
if len(hts) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(hts), minServers)
|
ErrNotEnoughServers, len(hts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
u.warnWarnings(warnings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
@@ -65,13 +62,13 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addServerFromOvpn(fileName string, content []byte,
|
func addServerFromOvpn(fileName string, content []byte,
|
||||||
@@ -104,3 +101,9 @@ func addServerFromOvpn(fileName string, content []byte,
|
|||||||
hts.add(host, country, city, tcp, udp, ips)
|
hts.add(host, country, city, tcp, udp, ips)
|
||||||
return warnings
|
return warnings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *Updater) warnWarnings(warnings []string) {
|
||||||
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
25
internal/provider/torguard/updater/updater.go
Normal file
25
internal/provider/torguard/updater/updater.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package torguard
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(unzipper unzip.Unzipper, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,23 +8,25 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"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")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
// Hardcoded data from a user provided ZIP file since it's behind a login wall
|
// Hardcoded data from a user provided ZIP file since it's behind a login wall
|
||||||
hts, warnings := getHostToServer()
|
hts, warnings := getHostToServer()
|
||||||
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
@@ -32,11 +34,11 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
25
internal/provider/vpnunlimited/updater/updater.go
Normal file
25
internal/provider/vpnunlimited/updater/updater.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package vpnunlimited
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(unzipper unzip.Unzipper, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,21 +10,18 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
"github.com/qdm12/gluetun/internal/updater/openvpn"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater/unzip"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotEnoughServers = errors.New("not enough servers found")
|
var ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
|
|
||||||
func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
presolver resolver.Parallel, minServers int) (
|
servers []models.Server, err error) {
|
||||||
servers []models.Server, warnings []string, err error) {
|
|
||||||
const url = "https://support.vyprvpn.com/hc/article_attachments/360052617332/Vypr_OpenVPN_20200320.zip"
|
const url = "https://support.vyprvpn.com/hc/article_attachments/360052617332/Vypr_OpenVPN_20200320.zip"
|
||||||
contents, err := unzipper.FetchAndExtract(ctx, url)
|
contents, err := u.unzipper.FetchAndExtract(ctx, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, err
|
||||||
} else if len(contents) < minServers {
|
} else if len(contents) < minServers {
|
||||||
return nil, nil, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(contents), minServers)
|
ErrNotEnoughServers, len(contents), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,26 +34,25 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
|
|
||||||
host, warning, err := openvpn.ExtractHost(content)
|
host, warning, err := openvpn.ExtractHost(content)
|
||||||
if warning != "" {
|
if warning != "" {
|
||||||
warnings = append(warnings, warning)
|
u.warner.Warn(warning)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp, udp, err := openvpn.ExtractProto(content)
|
tcp, udp, err := openvpn.ExtractProto(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// treat error as warning and go to next file
|
// treat error as warning and go to next file
|
||||||
warning := err.Error() + " in " + fileName
|
u.warner.Warn(err.Error() + " in " + fileName)
|
||||||
warnings = append(warnings, warning)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
region, err := parseFilename(fileName)
|
region, err := parseFilename(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
warnings = append(warnings, err.Error())
|
// treat error as warning and go to next file
|
||||||
|
u.warner.Warn(err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,15 +60,17 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(hts) < minServers {
|
if len(hts) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(hts), minServers)
|
ErrNotEnoughServers, len(hts), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := hts.toHostsSlice()
|
hosts := hts.toHostsSlice()
|
||||||
hostToIPs, newWarnings, err := resolveHosts(ctx, presolver, hosts, minServers)
|
hostToIPs, warnings, err := resolveHosts(ctx, u.presolver, hosts, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hts.adaptWithIPs(hostToIPs)
|
hts.adaptWithIPs(hostToIPs)
|
||||||
@@ -80,11 +78,11 @@ func GetServers(ctx context.Context, unzipper unzip.Unzipper,
|
|||||||
servers = hts.toServersSlice()
|
servers = hts.toServersSlice()
|
||||||
|
|
||||||
if len(servers) < minServers {
|
if len(servers) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
25
internal/provider/vyprvpn/updater/updater.go
Normal file
25
internal/provider/vyprvpn/updater/updater.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package vyprvpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/unzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
unzipper unzip.Unzipper
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(unzipper unzip.Unzipper, presolver resolver.Parallel,
|
||||||
|
warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
unzipper: unzipper,
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
"github.com/qdm12/gluetun/internal/updater/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -18,8 +17,8 @@ var (
|
|||||||
ErrNotEnoughServers = errors.New("not enough servers found")
|
ErrNotEnoughServers = errors.New("not enough servers found")
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetServers(ctx context.Context, presolver resolver.Parallel, minServers int) (
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, warnings []string, err error) {
|
servers []models.Server, err error) {
|
||||||
cities := getAvailableCities()
|
cities := getAvailableCities()
|
||||||
servers = make([]models.Server, 0, len(cities))
|
servers = make([]models.Server, 0, len(cities))
|
||||||
hostnames := make([]string, len(cities))
|
hostnames := make([]string, len(cities))
|
||||||
@@ -31,14 +30,16 @@ func GetServers(ctx context.Context, presolver resolver.Parallel, minServers int
|
|||||||
hostnameToCity[hostname] = city
|
hostnameToCity[hostname] = city
|
||||||
}
|
}
|
||||||
|
|
||||||
hostnameToIPs, newWarnings, err := resolveHosts(ctx, presolver, hostnames, minServers)
|
hostnameToIPs, warnings, err := resolveHosts(ctx, u.presolver, hostnames, minServers)
|
||||||
warnings = append(warnings, newWarnings...)
|
for _, warning := range warnings {
|
||||||
|
u.warner.Warn(warning)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, warnings, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(hostnameToIPs) < minServers {
|
if len(hostnameToIPs) < minServers {
|
||||||
return nil, warnings, fmt.Errorf("%w: %d and expected at least %d",
|
return nil, fmt.Errorf("%w: %d and expected at least %d",
|
||||||
ErrNotEnoughServers, len(servers), minServers)
|
ErrNotEnoughServers, len(servers), minServers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,5 +57,5 @@ func GetServers(ctx context.Context, presolver resolver.Parallel, minServers int
|
|||||||
|
|
||||||
sortServers(servers)
|
sortServers(servers)
|
||||||
|
|
||||||
return servers, warnings, nil
|
return servers, nil
|
||||||
}
|
}
|
||||||
|
|||||||
21
internal/provider/wevpn/updater/updater.go
Normal file
21
internal/provider/wevpn/updater/updater.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package wevpn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/qdm12/gluetun/internal/updater/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
presolver resolver.Parallel
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(presolver resolver.Parallel, warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
presolver: presolver,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants/vpn"
|
"github.com/qdm12/gluetun/internal/constants/vpn"
|
||||||
"github.com/qdm12/gluetun/internal/models"
|
"github.com/qdm12/gluetun/internal/models"
|
||||||
@@ -18,9 +17,9 @@ var (
|
|||||||
ErrNoWireguardKey = errors.New("no wireguard public key found")
|
ErrNoWireguardKey = errors.New("no wireguard public key found")
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetServers(ctx context.Context, client *http.Client, minServers int) (
|
func (u *Updater) GetServers(ctx context.Context, minServers int) (
|
||||||
servers []models.Server, err error) {
|
servers []models.Server, err error) {
|
||||||
data, err := fetchAPI(ctx, client)
|
data, err := fetchAPI(ctx, u.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
21
internal/provider/windscribe/updater/updater.go
Normal file
21
internal/provider/windscribe/updater/updater.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package windscribe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Updater struct {
|
||||||
|
client *http.Client
|
||||||
|
warner Warner
|
||||||
|
}
|
||||||
|
|
||||||
|
type Warner interface {
|
||||||
|
Warn(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, warner Warner) *Updater {
|
||||||
|
return &Updater{
|
||||||
|
client: client,
|
||||||
|
warner: warner,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,75 +30,76 @@ import (
|
|||||||
windscribe "github.com/qdm12/gluetun/internal/provider/windscribe/updater"
|
windscribe "github.com/qdm12/gluetun/internal/provider/windscribe/updater"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (u *Updater) updateProvider(ctx context.Context, provider string) (
|
func (u *Updater) updateProvider(ctx context.Context, provider string) (err error) {
|
||||||
warnings []string, err error) {
|
|
||||||
existingServers := u.getProviderServers(provider)
|
existingServers := u.getProviderServers(provider)
|
||||||
minServers := getMinServers(existingServers)
|
minServers := getMinServers(existingServers)
|
||||||
servers, warnings, err := u.getServers(ctx, provider, minServers)
|
servers, err := u.getServers(ctx, provider, minServers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return warnings, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.DeepEqual(existingServers, servers) {
|
if reflect.DeepEqual(existingServers, servers) {
|
||||||
return warnings, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
u.patchProvider(provider, servers)
|
u.patchProvider(provider, servers)
|
||||||
return warnings, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Updater) getServers(ctx context.Context, provider string,
|
func (u *Updater) getServers(ctx context.Context, provider string,
|
||||||
minServers int) (servers []models.Server, warnings []string, err error) {
|
minServers int) (servers []models.Server, err error) {
|
||||||
|
var providerUpdater interface {
|
||||||
|
GetServers(ctx context.Context, minServers int) (servers []models.Server, err error)
|
||||||
|
}
|
||||||
switch provider {
|
switch provider {
|
||||||
case providers.Custom:
|
case providers.Custom:
|
||||||
panic("cannot update custom provider")
|
panic("cannot update custom provider")
|
||||||
case providers.Cyberghost:
|
case providers.Cyberghost:
|
||||||
servers, err = cyberghost.GetServers(ctx, u.presolver, minServers)
|
providerUpdater = cyberghost.New(u.presolver)
|
||||||
return servers, nil, err
|
|
||||||
case providers.Expressvpn:
|
case providers.Expressvpn:
|
||||||
return expressvpn.GetServers(ctx, u.unzipper, u.presolver, minServers)
|
providerUpdater = expressvpn.New(u.unzipper, u.presolver, u.logger)
|
||||||
case providers.Fastestvpn:
|
case providers.Fastestvpn:
|
||||||
return fastestvpn.GetServers(ctx, u.unzipper, u.presolver, minServers)
|
providerUpdater = fastestvpn.New(u.unzipper, u.presolver, u.logger)
|
||||||
case providers.HideMyAss:
|
case providers.HideMyAss:
|
||||||
return hidemyass.GetServers(ctx, u.client, u.presolver, minServers)
|
providerUpdater = hidemyass.New(u.client, u.presolver, u.logger)
|
||||||
case providers.Ipvanish:
|
case providers.Ipvanish:
|
||||||
return ipvanish.GetServers(ctx, u.unzipper, u.presolver, minServers)
|
providerUpdater = ipvanish.New(u.unzipper, u.presolver, u.logger)
|
||||||
case providers.Ivpn:
|
case providers.Ivpn:
|
||||||
return ivpn.GetServers(ctx, u.client, u.presolver, minServers)
|
providerUpdater = ivpn.New(u.client, u.presolver, u.logger)
|
||||||
case providers.Mullvad:
|
case providers.Mullvad:
|
||||||
servers, err = mullvad.GetServers(ctx, u.client, minServers)
|
providerUpdater = mullvad.New(u.client)
|
||||||
return servers, nil, err
|
|
||||||
case providers.Nordvpn:
|
case providers.Nordvpn:
|
||||||
return nordvpn.GetServers(ctx, u.client, minServers)
|
providerUpdater = nordvpn.New(u.client, u.logger)
|
||||||
case providers.Perfectprivacy:
|
case providers.Perfectprivacy:
|
||||||
return perfectprivacy.GetServers(ctx, u.unzipper, minServers)
|
providerUpdater = perfectprivacy.New(u.unzipper, u.logger)
|
||||||
case providers.Privado:
|
case providers.Privado:
|
||||||
return privado.GetServers(ctx, u.unzipper, u.client, u.presolver, minServers)
|
providerUpdater = privado.New(u.client, u.unzipper, u.presolver, u.logger)
|
||||||
case providers.PrivateInternetAccess:
|
case providers.PrivateInternetAccess:
|
||||||
servers, err = privateinternetaccess.GetServers(ctx, u.client, minServers)
|
providerUpdater = privateinternetaccess.New(u.client)
|
||||||
return servers, nil, err
|
|
||||||
case providers.Privatevpn:
|
case providers.Privatevpn:
|
||||||
return privatevpn.GetServers(ctx, u.unzipper, u.presolver, minServers)
|
providerUpdater = privatevpn.New(u.unzipper, u.presolver, u.logger)
|
||||||
case providers.Protonvpn:
|
case providers.Protonvpn:
|
||||||
return protonvpn.GetServers(ctx, u.client, minServers)
|
providerUpdater = protonvpn.New(u.client, u.logger)
|
||||||
case providers.Purevpn:
|
case providers.Purevpn:
|
||||||
return purevpn.GetServers(ctx, u.client, u.unzipper, u.presolver, minServers)
|
providerUpdater = purevpn.New(u.client, u.unzipper, u.presolver, u.logger)
|
||||||
case providers.Surfshark:
|
case providers.Surfshark:
|
||||||
return surfshark.GetServers(ctx, u.unzipper, u.client, u.presolver, minServers)
|
providerUpdater = surfshark.New(u.client, u.unzipper, u.presolver, u.logger)
|
||||||
case providers.Torguard:
|
case providers.Torguard:
|
||||||
return torguard.GetServers(ctx, u.unzipper, u.presolver, minServers)
|
providerUpdater = torguard.New(u.unzipper, u.presolver, u.logger)
|
||||||
case providers.VPNUnlimited:
|
case providers.VPNUnlimited:
|
||||||
return vpnunlimited.GetServers(ctx, u.unzipper, u.presolver, minServers)
|
providerUpdater = vpnunlimited.New(u.unzipper, u.presolver, u.logger)
|
||||||
case providers.Vyprvpn:
|
case providers.Vyprvpn:
|
||||||
return vyprvpn.GetServers(ctx, u.unzipper, u.presolver, minServers)
|
providerUpdater = vyprvpn.New(u.unzipper, u.presolver, u.logger)
|
||||||
case providers.Wevpn:
|
case providers.Wevpn:
|
||||||
return wevpn.GetServers(ctx, u.presolver, minServers)
|
providerUpdater = wevpn.New(u.presolver, u.logger)
|
||||||
case providers.Windscribe:
|
case providers.Windscribe:
|
||||||
servers, err = windscribe.GetServers(ctx, u.client, minServers)
|
providerUpdater = windscribe.New(u.client, u.logger)
|
||||||
return servers, nil, err
|
|
||||||
default:
|
default:
|
||||||
panic("provider " + provider + " is unknown")
|
panic("provider " + provider + " is unknown")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
servers, err = providerUpdater.GetServers(ctx, minServers)
|
||||||
|
return servers, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *Updater) getProviderServers(provider string) (servers []models.Server) {
|
func (u *Updater) getProviderServers(provider string) (servers []models.Server) {
|
||||||
|
|||||||
@@ -56,12 +56,7 @@ func (u *Updater) UpdateServers(ctx context.Context) (allServers models.AllServe
|
|||||||
u.logger.Info("updating " + caser.String(provider) + " servers...")
|
u.logger.Info("updating " + caser.String(provider) + " servers...")
|
||||||
// TODO support servers offering only TCP or only UDP
|
// TODO support servers offering only TCP or only UDP
|
||||||
// for NordVPN and PureVPN
|
// for NordVPN and PureVPN
|
||||||
warnings, err := u.updateProvider(ctx, provider)
|
err := u.updateProvider(ctx, provider)
|
||||||
if *u.options.CLI {
|
|
||||||
for _, warning := range warnings {
|
|
||||||
u.logger.Warn(provider + ": " + warning)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if ctxErr := ctx.Err(); ctxErr != nil {
|
if ctxErr := ctx.Err(); ctxErr != nil {
|
||||||
return allServers, ctxErr
|
return allServers, ctxErr
|
||||||
|
|||||||
Reference in New Issue
Block a user