package srun
import (
"errors"
"fmt"
log "github.com/sirupsen/logrus"
"io"
"net/http"
"net/url"
"regexp"
"strings"
"unsafe"
)
func (a *Api) NewDetector() Detector {
redirectReg, err := regexp.Compile(
`|`,
)
if err != nil {
panic(err)
}
return Detector{
api: a,
redirectReg: redirectReg,
}
}
type Detector struct {
api *Api
redirectReg *regexp.Regexp
// 登录页 html data
page []byte
}
func (a *Detector) _JoinRedirectLocation(addr *url.URL, loc string) (*url.URL, error) {
if loc == "" {
return nil, errors.New("目标跳转地址缺失")
}
if strings.HasPrefix(loc, "/") {
addr.Path = strings.TrimPrefix(loc, "/")
return addr, nil
} else {
return url.Parse(loc)
}
}
type _FollowRedirectConfig struct {
// 获取到下一个请求地址时触发
onNextAddr func(addr *url.URL) error
}
func (a *Detector) _FollowRedirect(addr *url.URL, conf _FollowRedirectConfig) (*http.Response, []byte, error) {
addrCopy := *addr
addr = &addrCopy
var body []byte
var res *http.Response
for {
log.Debugln("HTTP GET", addr)
req, err := http.NewRequest("GET", addr.String(), nil)
if err != nil {
return nil, nil, err
}
for k, v := range a.api.CustomHeader {
req.Header.Set(k, fmt.Sprint(v))
}
res, err = a.api.NoDirect.Do(req)
if err != nil {
return nil, nil, err
}
if res.StatusCode < 300 {
body, err = io.ReadAll(res.Body)
_ = res.Body.Close()
if err != nil {
return nil, nil, err
}
locMatch := a.redirectReg.FindSubmatch(body)
if len(locMatch) > 2 {
locBytes := locMatch[1]
addr, err = a._JoinRedirectLocation(addr, unsafe.String(unsafe.SliceData(locBytes), len(locBytes)))
if err != nil {
return nil, nil, err
}
} else {
break
}
} else {
_, _ = io.Copy(io.Discard, res.Body)
_ = res.Body.Close()
if res.StatusCode < 400 {
addr, err = a._JoinRedirectLocation(addr, res.Header.Get("location"))
if err != nil {
return nil, nil, err
}
} else {
return nil, nil, fmt.Errorf("server return http status %d", res.StatusCode)
}
}
if conf.onNextAddr != nil {
if err = conf.onNextAddr(addr); err != nil {
return nil, nil, err
}
}
}
return res, body, nil
}
func (a *Detector) _SearchAcid(query url.Values) (string, bool) {
addr := query.Get(`ac_id`)
return addr, addr != ""
}
func (a *Detector) DetectEnc() (string, error) {
if a.page == nil {
log.Debugln("HTTP GET", a.api.BaseUrl)
res, err := a.api.Client.Get(a.api.BaseUrl)
if err != nil {
return "", err
}
defer res.Body.Close()
if res.StatusCode != 200 {
_, _ = io.Copy(io.Discard, res.Body)
return "", fmt.Errorf("server return http status: %d", res.StatusCode)
}
a.page, err = io.ReadAll(res.Body)
if err != nil {
return "", err
}
}
jsReg, err := regexp.Compile(`(?i)