Maint: hardcoded data in JSON embedded file
- Server information, versions and timestamps together in internal/constants/servers.json - breaking change: updater cli uses -enduser instead of -file - breaking change: updater cli uses -maintainer instead of -stdout - Fix: replace special last a character with 'a' from Bogota for PrivateVPN - Feat: do not write out servers and timestamp if no change was detected
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CyberghostServer struct {
|
||||
@@ -14,11 +11,6 @@ type CyberghostServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *CyberghostServer) String() string {
|
||||
return fmt.Sprintf("{Region: %q, Group: %q, Hostname: %q, IPs: %s}",
|
||||
s.Region, s.Group, s.Hostname, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type FastestvpnServer struct {
|
||||
Hostname string `json:"hostname"`
|
||||
TCP bool `json:"tcp"`
|
||||
@@ -27,11 +19,6 @@ type FastestvpnServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *FastestvpnServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, Hostname: %q, UDP: %t, TCP: %t, IPs: %s}",
|
||||
s.Country, s.Hostname, s.UDP, s.TCP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type HideMyAssServer struct {
|
||||
Country string `json:"country"`
|
||||
Region string `json:"region"`
|
||||
@@ -42,11 +29,6 @@ type HideMyAssServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *HideMyAssServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, Region: %q, City: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}",
|
||||
s.Country, s.Region, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type IpvanishServer struct {
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
@@ -56,11 +38,6 @@ type IpvanishServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *IpvanishServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, City: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}",
|
||||
s.Country, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type IvpnServer struct {
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
@@ -70,11 +47,6 @@ type IvpnServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *IvpnServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, City: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}",
|
||||
s.Country, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type MullvadServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
IPsV6 []net.IP `json:"ipsv6"`
|
||||
@@ -85,11 +57,6 @@ type MullvadServer struct {
|
||||
Owned bool `json:"owned"`
|
||||
}
|
||||
|
||||
func (s *MullvadServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, City: %q, Hostname: %q, ISP: %q, Owned: %t, IPs: %s, IPsV6: %s}",
|
||||
s.Country, s.City, s.Hostname, s.ISP, s.Owned, goStringifyIPs(s.IPs), goStringifyIPs(s.IPsV6))
|
||||
}
|
||||
|
||||
type NordvpnServer struct { //nolint:maligned
|
||||
Region string `json:"region"`
|
||||
Hostname string `json:"hostname"`
|
||||
@@ -100,11 +67,6 @@ type NordvpnServer struct { //nolint:maligned
|
||||
UDP bool `json:"udp"`
|
||||
}
|
||||
|
||||
func (s *NordvpnServer) String() string {
|
||||
return fmt.Sprintf("{Region: %q, Hostname: %q, Name: %q, Number: %d, TCP: %t, UDP: %t, IP: %s}",
|
||||
s.Region, s.Hostname, s.Name, s.Number, s.TCP, s.UDP, goStringifyIP(s.IP))
|
||||
}
|
||||
|
||||
type PrivadoServer struct {
|
||||
Country string `json:"country"`
|
||||
Region string `json:"region"`
|
||||
@@ -113,11 +75,6 @@ type PrivadoServer struct {
|
||||
IP net.IP `json:"ip"`
|
||||
}
|
||||
|
||||
func (s *PrivadoServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, Region: %q, City: %q, Hostname: %q, IP: %s}",
|
||||
s.Country, s.Region, s.City, s.Hostname, goStringifyIP(s.IP))
|
||||
}
|
||||
|
||||
type PIAServer struct {
|
||||
Region string `json:"region"`
|
||||
Hostname string `json:"hostname"`
|
||||
@@ -128,11 +85,6 @@ type PIAServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (p *PIAServer) String() string {
|
||||
return fmt.Sprintf("{Region: %q, Hostname: %q, ServerName: %q, TCP: %t, UDP: %t, PortForward: %t, IPs: %s}",
|
||||
p.Region, p.Hostname, p.ServerName, p.TCP, p.UDP, p.PortForward, goStringifyIPs(p.IPs))
|
||||
}
|
||||
|
||||
type PrivatevpnServer struct {
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
@@ -140,11 +92,6 @@ type PrivatevpnServer struct {
|
||||
IPs []net.IP `json:"ip"`
|
||||
}
|
||||
|
||||
func (s *PrivatevpnServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, City: %q, Hostname: %q, IPs: %s}",
|
||||
s.Country, s.City, s.Hostname, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type ProtonvpnServer struct {
|
||||
Country string `json:"country"`
|
||||
Region string `json:"region"`
|
||||
@@ -155,11 +102,6 @@ type ProtonvpnServer struct {
|
||||
ExitIP net.IP `json:"exit_ip"` // TODO verify it matches with public IP once connected
|
||||
}
|
||||
|
||||
func (s *ProtonvpnServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, Region: %q, City: %q, Name: %q, Hostname: %q, EntryIP: %s, ExitIP: %s}",
|
||||
s.Country, s.Region, s.City, s.Name, s.Hostname, goStringifyIP(s.EntryIP), goStringifyIP(s.ExitIP))
|
||||
}
|
||||
|
||||
type PurevpnServer struct {
|
||||
Country string `json:"country"`
|
||||
Region string `json:"region"`
|
||||
@@ -170,11 +112,6 @@ type PurevpnServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *PurevpnServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, Region: %q, City: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}",
|
||||
s.Country, s.Region, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type SurfsharkServer struct {
|
||||
Region string `json:"region"`
|
||||
Hostname string `json:"hostname"`
|
||||
@@ -183,11 +120,6 @@ type SurfsharkServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *SurfsharkServer) String() string {
|
||||
return fmt.Sprintf("{Region: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}",
|
||||
s.Region, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type TorguardServer struct {
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
@@ -197,11 +129,6 @@ type TorguardServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *TorguardServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, City: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}",
|
||||
s.Country, s.City, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type VPNUnlimitedServer struct {
|
||||
Country string `json:"country"`
|
||||
City string `json:"city"`
|
||||
@@ -213,11 +140,6 @@ type VPNUnlimitedServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *VPNUnlimitedServer) String() string {
|
||||
return fmt.Sprintf("{Country: %q, City: %q, Hostname: %q, Free: %t, Stream: %t, TCP: %t, UDP: %t, IPs: %s}",
|
||||
s.Country, s.City, s.Hostname, s.Free, s.Stream, s.TCP, s.UDP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type VyprvpnServer struct {
|
||||
Region string `json:"region"`
|
||||
Hostname string `json:"hostname"`
|
||||
@@ -226,65 +148,9 @@ type VyprvpnServer struct {
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *VyprvpnServer) String() string {
|
||||
return fmt.Sprintf("{Region: %q, Hostname: %q, TCP: %t, UDP: %t, IPs: %s}",
|
||||
s.Region, s.Hostname, s.TCP, s.UDP, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
type WindscribeServer struct {
|
||||
Region string `json:"region"`
|
||||
City string `json:"city"`
|
||||
Hostname string `json:"hostname"`
|
||||
IPs []net.IP `json:"ips"`
|
||||
}
|
||||
|
||||
func (s *WindscribeServer) String() string {
|
||||
return fmt.Sprintf("{Region: %q, City: %q, Hostname: %q, IPs: %s}",
|
||||
s.Region, s.City, s.Hostname, goStringifyIPs(s.IPs))
|
||||
}
|
||||
|
||||
func goStringifyIP(ip net.IP) string {
|
||||
s := fmt.Sprintf("%#v", ip)
|
||||
s = strings.TrimSuffix(strings.TrimPrefix(s, "net.IP{"), "}")
|
||||
fields := strings.Split(s, ", ")
|
||||
isIPv4 := ip.To4() != nil
|
||||
if isIPv4 {
|
||||
fields = fields[len(fields)-4:]
|
||||
}
|
||||
|
||||
// Count leading zeros
|
||||
leadingZeros := 0
|
||||
for i := range fields {
|
||||
if fields[i] == "0x0" {
|
||||
leadingZeros++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Remove leading zeros
|
||||
fields = fields[leadingZeros:]
|
||||
|
||||
for i := range fields {
|
||||
// IPv4 is better understood in integer notation, whereas IPv6 is written in hex notation
|
||||
if isIPv4 {
|
||||
hexString := strings.Replace(fields[i], "0x", "", 1)
|
||||
if len(hexString) == 1 {
|
||||
hexString = "0" + hexString
|
||||
}
|
||||
b, _ := hex.DecodeString(hexString)
|
||||
fields[i] = fmt.Sprintf("%d", b[0])
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("net.IP{%s}", strings.Join(fields, ", "))
|
||||
}
|
||||
|
||||
func goStringifyIPs(ips []net.IP) string {
|
||||
ipStrings := make([]string, len(ips))
|
||||
for i := range ips {
|
||||
ipStrings[i] = goStringifyIP(ips[i])
|
||||
ipStrings[i] = strings.TrimPrefix(ipStrings[i], "net.IP")
|
||||
}
|
||||
return "[]net.IP{" + strings.Join(ipStrings, ", ") + "}"
|
||||
}
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_MullvadServer_String(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := map[string]struct {
|
||||
server MullvadServer
|
||||
s string
|
||||
}{
|
||||
"example": {
|
||||
server: MullvadServer{
|
||||
IPs: []net.IP{{1, 1, 1, 1}},
|
||||
IPsV6: []net.IP{{0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1}},
|
||||
Country: "That Country",
|
||||
City: "That City",
|
||||
Hostname: "hostname",
|
||||
ISP: "not spying on you",
|
||||
Owned: true,
|
||||
},
|
||||
//nolint:lll
|
||||
s: `{Country: "That Country", City: "That City", Hostname: "hostname", ISP: "not spying on you", Owned: true, IPs: []net.IP{{1, 1, 1, 1}}, IPsV6: []net.IP{{0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1}}}`,
|
||||
},
|
||||
}
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := testCase.server.String()
|
||||
assert.Equal(t, testCase.s, s)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_goStringifyIP(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := map[string]struct {
|
||||
ip net.IP
|
||||
s string
|
||||
}{
|
||||
"nil ip": {
|
||||
s: "net.IP{net.IP(nil)}",
|
||||
},
|
||||
"empty ip": {
|
||||
ip: net.IP{},
|
||||
s: "net.IP{}",
|
||||
},
|
||||
"ipv4": {
|
||||
ip: net.IP{10, 16, 54, 25},
|
||||
s: "net.IP{10, 16, 54, 25}",
|
||||
},
|
||||
"ipv6": {
|
||||
ip: net.IP{0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1},
|
||||
s: "net.IP{0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1}",
|
||||
},
|
||||
"zeros ipv4": {
|
||||
ip: net.IP{0, 0, 0, 0},
|
||||
s: "net.IP{}",
|
||||
},
|
||||
"zeros ipv46": {
|
||||
ip: net.ParseIP("::"),
|
||||
s: "net.IP{}",
|
||||
},
|
||||
}
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := goStringifyIP(testCase.ip)
|
||||
assert.Equal(t, testCase.s, s)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_stringifyIPs(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := map[string]struct {
|
||||
ips []net.IP
|
||||
s string
|
||||
}{
|
||||
"nil ips": {
|
||||
s: "[]net.IP{}",
|
||||
},
|
||||
"empty ips": {
|
||||
ips: []net.IP{},
|
||||
s: "[]net.IP{}",
|
||||
},
|
||||
"single ipv4": {
|
||||
ips: []net.IP{{10, 16, 54, 25}},
|
||||
s: "[]net.IP{{10, 16, 54, 25}}",
|
||||
},
|
||||
"single ipv6": {
|
||||
ips: []net.IP{{0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1}},
|
||||
s: "[]net.IP{{0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1}}",
|
||||
},
|
||||
"mix of ips": {
|
||||
ips: []net.IP{
|
||||
{10, 16, 54, 25},
|
||||
{0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1},
|
||||
{0, 0, 0, 0},
|
||||
},
|
||||
//nolint:lll
|
||||
s: "[]net.IP{{10, 16, 54, 25}, {0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1}, {}}",
|
||||
},
|
||||
}
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
s := goStringifyIPs(testCase.ips)
|
||||
assert.Equal(t, testCase.s, s)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package models
|
||||
|
||||
type AllServers struct {
|
||||
Version uint16 `json:"version"`
|
||||
Version uint16 `json:"version"` // used for migration of the top level scheme
|
||||
Cyberghost CyberghostServers `json:"cyberghost"`
|
||||
Fastestvpn FastestvpnServers `json:"fastestvpn"`
|
||||
HideMyAss HideMyAssServers `json:"hidemyass"`
|
||||
|
||||
Reference in New Issue
Block a user