windport/pkg/windscribe/csrf.go

95 lines
1.6 KiB
Go
Raw Normal View History

2023-08-13 16:19:23 -04:00
package windscribe
import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"regexp"
"strconv"
"strings"
2023-08-13 23:22:48 -04:00
"time"
2023-08-13 16:19:23 -04:00
)
2023-08-13 23:22:48 -04:00
const (
csrfExpire time.Duration = time.Second * 4
)
type CSRF struct {
2023-08-13 16:19:23 -04:00
Token string `json:"csrf_token"`
2023-08-13 23:22:48 -04:00
Time int `json:"csrf_time"`
2023-08-13 16:19:23 -04:00
}
2023-08-13 23:22:48 -04:00
func (c *client) CSRF(ctx context.Context) *CSRF {
if c.csrf == nil || time.Now().Sub(time.Unix(int64(c.csrf.Time), 0)) > csrfExpire {
var err error
c.csrf, err = c.getCSRF(ctx)
if err != nil {
panic(err)
}
}
return c.csrf
}
func (c *client) getCSRF(ctx context.Context) (*CSRF, error) {
2023-08-13 16:19:23 -04:00
req, err := http.NewRequestWithContext(ctx, "POST", "https://res.windscribe.com/res/logintoken", strings.NewReader(""))
if err != nil {
return nil, err
}
fillReq(req)
resp, err := c.hc.Do(req)
if err != nil {
return nil, err
}
2023-08-13 23:22:48 -04:00
var csrf CSRF
2023-08-13 16:19:23 -04:00
decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(&csrf)
if err != nil {
return nil, err
}
cleanupBody(resp.Body)
return &csrf, nil
}
var csrfRE = regexp.MustCompile(`^\s*csrf_(time|token) = '?([0-9a-f]+)'?;\s*$`)
2023-08-13 23:22:48 -04:00
func (c *client) getCSRFfromBody(ctx context.Context, body io.Reader) (*CSRF, error) {
csrf := CSRF{}
2023-08-13 16:19:23 -04:00
scan := bufio.NewScanner(body)
for scan.Scan() {
ln := scan.Text()
m := csrfRE.FindStringSubmatch(ln)
if len(m) == 3 {
var err error
switch m[1] {
case "time":
csrf.Time, err = strconv.Atoi(m[2])
if err != nil {
return nil, err
}
case "token":
csrf.Token = m[2]
}
}
}
if err := scan.Err(); err != nil {
return nil, err
}
if csrf.Token == "" || csrf.Time == 0 {
return nil, fmt.Errorf("getCSRFfromBody: csrf is %+v", csrf)
}
return &csrf, nil
}