Skip to content

Commit 1ca93bf

Browse files
committed
Update adapter, setup websockets
1 parent cbec917 commit 1ca93bf

11 files changed

+294
-64
lines changed

aternos_api.go

+17-16
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package aternos_api
22

33
import (
4+
tls "github.com/refraction-networking/utls"
5+
"github.com/sleeyax/aternos-api/internal/tlsadapter"
46
"github.com/sleeyax/gotcha"
5-
"github.com/sleeyax/gotcha/adapters/fhttp"
6-
httpx "github.com/useflyent/fhttp"
77
"net/http"
88
"net/http/cookiejar"
99
"net/url"
10+
"strings"
1011
)
1112

1213
type AternosApi struct {
@@ -22,29 +23,29 @@ type AternosApi struct {
2223
func New(options *Options) *AternosApi {
2324
jar, _ := cookiejar.New(&cookiejar.Options{})
2425

25-
var adapter gotcha.Adapter
26-
if options.Proxy != nil {
27-
adapter = &fhttp.Adapter{Transport: &httpx.Transport{
28-
Proxy: httpx.ProxyURL(options.Proxy),
29-
}}
30-
} else {
31-
adapter = fhttp.NewAdapter()
32-
}
26+
adapter := tlsadapter.New(&tls.Config{ServerName: "aternos.org", InsecureSkipVerify: options.InsecureSkipVerify})
3327

3428
client, _ := gotcha.NewClient(&gotcha.Options{
3529
Adapter: adapter,
3630
PrefixURL: "https://aternos.org/",
3731
Headers: http.Header{
38-
"user-agent": {"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"},
39-
"accept": {"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"},
40-
"accept-language": {"en-US,en;q=0.9"},
41-
"accept-encoding": {"gzip, deflate, br"},
42-
"cookie": nil,
43-
httpx.HeaderOrderKey: []string{"user-agent", "accept", "accept-language", "accept-encoding", "cookie"},
32+
"User-Agent": {"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"},
33+
"Accept": {"*/*"},
34+
"Accept-Language": {"en-US,en;q=0.9"},
4435
},
4536
CookieJar: jar,
4637
FollowRedirect: false,
4738
Retry: false,
39+
Hooks: gotcha.Hooks{
40+
AfterResponse: []gotcha.AfterResponseHook{
41+
func(response *gotcha.Response, retry gotcha.RetryFunc) (*gotcha.Response, error) {
42+
if location := response.Header.Get("location"); strings.Contains(location, "go") {
43+
return response, UnauthenticatedError
44+
}
45+
return response, nil
46+
},
47+
},
48+
},
4849
})
4950

5051
u, _ := url.Parse(client.Options.PrefixURL)

errors.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ package aternos_api
22

33
import "errors"
44

5-
var ServerAlreadyStartedError = errors.New("server already running")
5+
var ServerAlreadyStartedError = errors.New("server already started")
66
var ServerAlreadyStoppedError = errors.New("server already stopped")
7+
var UnauthenticatedError = errors.New("unauthenticated")

go.mod

+9-2
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,25 @@ go 1.17
55
require (
66
github.com/PuerkitoBio/goquery v1.8.0
77
github.com/dop251/goja v0.0.0-20211217115348-3f9136fa235d
8+
github.com/gorilla/websocket v1.4.3-0.20220104015952-9111bb834a68
9+
github.com/refraction-networking/utls v1.0.0
810
github.com/sleeyax/gotcha v0.0.2
911
github.com/sleeyax/gotcha/adapters/fhttp v0.0.0-20211225143732-1ae0bde30de1
1012
github.com/useflyent/fhttp v0.0.0-20210801005649-f160dd923789
1113
)
1214

1315
require (
1416
github.com/Sleeyax/urlValues v1.0.0 // indirect
15-
github.com/andybalholm/brotli v1.0.3 // indirect
17+
github.com/andybalholm/brotli v1.0.4 // indirect
1618
github.com/andybalholm/cascadia v1.3.1 // indirect
1719
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
1820
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
1921
github.com/imdario/mergo v0.3.12 // indirect
20-
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 // indirect
22+
github.com/klauspost/compress v1.13.6 // indirect
23+
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
24+
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
25+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
2126
golang.org/x/text v0.3.6 // indirect
2227
)
28+
29+
replace github.com/refraction-networking/utls => github.com/sleeyax/utls v1.1.1

go.sum

+17-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0g
22
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
33
github.com/Sleeyax/urlValues v1.0.0 h1:dtjjBUoygDTofrYiGupYG61+Dw87tpQJ9jkc+3o4fjU=
44
github.com/Sleeyax/urlValues v1.0.0/go.mod h1:IiljpGAUgWNsPFduJzF/fBnlfRwNvRPGG7evNThNaSw=
5-
github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM=
65
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
6+
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
7+
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
78
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
89
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
910
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -14,8 +15,12 @@ github.com/dop251/goja v0.0.0-20211217115348-3f9136fa235d/go.mod h1:R9ET47fwRVRP
1415
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
1516
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
1617
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
18+
github.com/gorilla/websocket v1.4.3-0.20220104015952-9111bb834a68 h1:m6V3+LXduRWqp1rg8FMHBagwmNsgXMVj5PHVLYnPeVQ=
19+
github.com/gorilla/websocket v1.4.3-0.20220104015952-9111bb834a68/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
1720
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
1821
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
22+
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
23+
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
1924
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
2025
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
2126
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -24,16 +29,26 @@ github.com/sleeyax/gotcha v0.0.2 h1:eiCFjEa4nwl/eZ7etBswDKPQ0bUp8YPbuicCHJtD68I=
2429
github.com/sleeyax/gotcha v0.0.2/go.mod h1:H2TKsKYJIXgmFGGUqs21FCr1HXVXjNWccX5/WexkLOM=
2530
github.com/sleeyax/gotcha/adapters/fhttp v0.0.0-20211225143732-1ae0bde30de1 h1:qlengZ6XaJeHZl4AgIOvcGMs4r75V6DFuP+7zjgQzo0=
2631
github.com/sleeyax/gotcha/adapters/fhttp v0.0.0-20211225143732-1ae0bde30de1/go.mod h1:LrrdDyEt7OnH6iI0XvXoJgh6hweTOSkNmDR0TOqG5b0=
32+
github.com/sleeyax/utls v1.1.1 h1:tVapK30m6pEJd4zq5Cmq/SwmkhPsbxfik1bBagMpKgw=
33+
github.com/sleeyax/utls v1.1.1/go.mod h1:+D89TUtA8+NKVFj1IXWr0p3tSdX1+SqUB7rL0QnGqyg=
2734
github.com/useflyent/fhttp v0.0.0-20210801005649-f160dd923789 h1:EnTm6BiUoGxi7fdeHMnSBnDyyKYT0AWq96V3cXouL4s=
2835
github.com/useflyent/fhttp v0.0.0-20210801005649-f160dd923789/go.mod h1:GTDLTqqiwTuUM1f9bCE/HoHOzBaCtT1Zjkd98vUEwrI=
36+
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
37+
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
38+
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
39+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
2940
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
30-
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 h1:/6y1LfuqNuQdHAm0jjtPtgRcxIxjVZgm5OTu8/QhZvk=
3141
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
42+
golang.org/x/net v0.0.0-20211111160137-58aab5ef257a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
43+
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
44+
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
3245
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
3346
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
47+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
3448
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3549
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
3650
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
51+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
3752
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
3853
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
3954
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

http.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,6 @@ func (api *AternosApi) GetServerInfo() (ServerInfo, error) {
106106
return info, err
107107
}
108108

109-
// TODO: start & stop server over websockets (wss://aternos.org/hermes/)
110-
111109
// StartServer starts your Minecraft server over HTTP.
112110
func (api *AternosApi) StartServer() error {
113111
info, err := api.GetServerInfo()
@@ -167,7 +165,7 @@ func (api *AternosApi) ConfirmServer(delay time.Duration) error {
167165
return nil
168166
}
169167

170-
// StopServer stops the minecraft server over HTTP.
168+
// StopServer stops the Minecraft server over HTTP.
171169
// This function doesn't wait until the server is fully stopped, it only requests a shutdown.
172170
func (api *AternosApi) StopServer() error {
173171
info, err := api.GetServerInfo()

internal/tlsadapter/clienthello.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package tlsadapter
2+
3+
import tls "github.com/refraction-networking/utls"
4+
5+
// CustomClientHelloSpec is a custom tls.ClientHelloSpec for the Chrome v96 browser (but with HTTP 2 disabled!)
6+
var CustomClientHelloSpec = &tls.ClientHelloSpec{
7+
CipherSuites: []uint16{
8+
tls.GREASE_PLACEHOLDER,
9+
tls.TLS_AES_128_GCM_SHA256,
10+
tls.TLS_AES_256_GCM_SHA384,
11+
tls.TLS_CHACHA20_POLY1305_SHA256,
12+
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
13+
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
14+
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
15+
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
16+
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
17+
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
18+
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
19+
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
20+
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
21+
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
22+
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
23+
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
24+
},
25+
CompressionMethods: []byte{
26+
0x00, // compressionNone
27+
},
28+
Extensions: []tls.TLSExtension{
29+
&tls.UtlsGREASEExtension{},
30+
&tls.SNIExtension{},
31+
&tls.UtlsExtendedMasterSecretExtension{},
32+
&tls.RenegotiationInfoExtension{Renegotiation: tls.RenegotiateOnceAsClient},
33+
&tls.SupportedCurvesExtension{[]tls.CurveID{
34+
tls.CurveID(tls.GREASE_PLACEHOLDER),
35+
tls.X25519,
36+
tls.CurveP256,
37+
tls.CurveP384,
38+
}},
39+
&tls.SupportedPointsExtension{SupportedPoints: []byte{
40+
0x00, // pointFormatUncompressed
41+
}},
42+
&tls.SessionTicketExtension{},
43+
// NOTE: HTTP 2 is disabled for now because the websockets server only supports http 1.
44+
// TODO: control HTTP version from parent code instead.
45+
// &tls.ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
46+
&tls.ALPNExtension{AlpnProtocols: []string{"http/1.1"}},
47+
&tls.StatusRequestExtension{},
48+
&tls.SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []tls.SignatureScheme{
49+
tls.ECDSAWithP256AndSHA256,
50+
tls.PSSWithSHA256,
51+
tls.PKCS1WithSHA256,
52+
tls.ECDSAWithP384AndSHA384,
53+
tls.PSSWithSHA384,
54+
tls.PKCS1WithSHA384,
55+
tls.PSSWithSHA512,
56+
tls.PKCS1WithSHA512,
57+
}},
58+
&tls.SCTExtension{},
59+
&tls.KeyShareExtension{[]tls.KeyShare{
60+
{Group: tls.CurveID(tls.GREASE_PLACEHOLDER), Data: []byte{0}},
61+
{Group: tls.X25519},
62+
}},
63+
&tls.PSKKeyExchangeModesExtension{[]uint8{
64+
tls.PskModeDHE,
65+
}},
66+
&tls.SupportedVersionsExtension{[]uint16{
67+
tls.GREASE_PLACEHOLDER,
68+
tls.VersionTLS13,
69+
tls.VersionTLS12,
70+
tls.VersionTLS11,
71+
tls.VersionTLS10,
72+
}},
73+
&tls.UtlsCompressCertExtension{[]tls.CertCompressionAlgo{
74+
tls.CertCompressionBrotli,
75+
}},
76+
&tls.GenericExtension{Id: 0x4469}, // WARNING: UNKNOWN EXTENSION, USE AT YOUR OWN RISK
77+
&tls.UtlsGREASEExtension{},
78+
&tls.UtlsPaddingExtension{GetPaddingLen: tls.BoringPaddingStyle},
79+
},
80+
}

internal/tlsadapter/tls_adapter.go

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package tlsadapter
2+
3+
import (
4+
"context"
5+
tls "github.com/refraction-networking/utls"
6+
"github.com/sleeyax/gotcha"
7+
fhttpadapter "github.com/sleeyax/gotcha/adapters/fhttp"
8+
fhttp "github.com/useflyent/fhttp"
9+
"net"
10+
"net/url"
11+
)
12+
13+
// TLSAdapter implements a custom gotcha.Adapter with advanced TLS options.
14+
type TLSAdapter struct {
15+
// TLS fingerprint to use.
16+
// Defaults to tls.HelloCustom.
17+
Fingerprint tls.ClientHelloID
18+
19+
// Optional custom client hello specification to use.
20+
// When specified, Fingerprint should be set to tls.HelloCustom.
21+
// Defaults to a custom Chrome 96 spec.
22+
ClientHelloSpec *tls.ClientHelloSpec
23+
24+
// Optional TLS configuration to use.
25+
Config *tls.Config
26+
}
27+
28+
// New creates a new gotcha adapter configured with a Chrome 96 browser TLS fingerprint.
29+
func New(config *tls.Config) *TLSAdapter {
30+
return &TLSAdapter{Fingerprint: tls.HelloCustom, ClientHelloSpec: CustomClientHelloSpec, Config: config}
31+
}
32+
33+
// DoRequest executes a HTTP 1 request and returns its response.
34+
func (ua *TLSAdapter) DoRequest(options *gotcha.Options) (*gotcha.Response, error) {
35+
transport := &fhttp.Transport{
36+
Proxy: func(*fhttp.Request) (*url.URL, error) {
37+
return options.Proxy, nil
38+
},
39+
// TODO: fix
40+
//DialTLSContext: ua.DialTLSContext,
41+
MaxConnsPerHost: 1,
42+
MaxIdleConns: 1,
43+
MaxIdleConnsPerHost: 1,
44+
}
45+
46+
adapter := fhttpadapter.Adapter{Transport: transport}
47+
48+
return adapter.DoRequest(options)
49+
}
50+
51+
func (ua *TLSAdapter) DialTLSContext(_ context.Context, network string, addr string) (net.Conn, error) {
52+
conn, err := net.Dial(network, addr)
53+
if err != nil {
54+
return nil, err
55+
}
56+
57+
uconn := tls.UClient(conn, ua.Config, ua.Fingerprint)
58+
59+
if ua.Fingerprint == tls.HelloCustom {
60+
if err = uconn.ApplyPreset(ua.ClientHelloSpec); err != nil {
61+
return nil, err
62+
}
63+
}
64+
65+
if err = uconn.Handshake(); err != nil {
66+
return nil, err
67+
}
68+
69+
return uconn, err
70+
}

options.go

+4
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,8 @@ type Options struct {
1515

1616
// Optional HTTP proxy to use.
1717
Proxy *url.URL
18+
19+
// Disables server SSL certificate checks.
20+
// It's recommended to enable this only for debugging purposes, such as debugging traffic with a web debugging/HTTP/MITM proxy.
21+
InsecureSkipVerify bool
1822
}

server_info.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ type ServerInfo struct {
7575
// E.g vanilla, papermc.
7676
SoftwareType string `json:"type"`
7777

78-
// Current minecraft version.
78+
// Current Minecraft version.
7979
Version string `json:"version"`
8080

8181
IsDeprecated bool `json:"deprecated"`

utils.go

-39
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,9 @@ package aternos_api
22

33
import (
44
"encoding/base64"
5-
"github.com/PuerkitoBio/goquery"
65
"math/rand"
7-
"strings"
86
)
97

10-
// findList finds and extracts a list of items from a HTML document.
11-
//
12-
// Example:
13-
//
14-
// <ul>
15-
// <li>foo</li>
16-
// <li>bar</li>
17-
// </ul>
18-
//
19-
// findList(document, "li") -> ["foo", "bar"]
20-
func findList(document *goquery.Document, selector string) []string {
21-
items := make([]string, 0)
22-
23-
document.Find(selector).Each(func(i int, selection *goquery.Selection) {
24-
items = append(items, strings.TrimSpace(selection.Text()))
25-
})
26-
27-
return items
28-
}
29-
308
// randomString generates a random lowercase string.
319
// E.g. mdlc2c9chx9, mbywjir33mm
3210
func randomString(length int) string {
@@ -41,23 +19,6 @@ func randomString(length int) string {
4119
return string(s)
4220
}
4321

44-
// GetStringInBetween finds a string between two substrings and returns an empty string if no string has been found.
45-
func getStringInBetween(str string, left string, right string) string {
46-
s := strings.Index(str, left)
47-
if s == -1 {
48-
return ""
49-
}
50-
51-
s += len(left)
52-
53-
e := strings.Index(str, right)
54-
if e == -1 {
55-
return ""
56-
}
57-
58-
return str[s:e]
59-
}
60-
6122
func atob(encoded string) (string, error) {
6223
decoded, err := base64.StdEncoding.DecodeString(encoded)
6324
if err != nil {

0 commit comments

Comments
 (0)