diff --git a/pkg/srun/api.go b/pkg/srun/api.go index 45c75d9..5077c07 100644 --- a/pkg/srun/api.go +++ b/pkg/srun/api.go @@ -2,18 +2,14 @@ package srun import ( "encoding/json" - "errors" "fmt" "github.com/Mmx233/tool" log "github.com/sirupsen/logrus" "io" "math/rand" "net/http" - "net/url" - "regexp" "strings" "time" - "unsafe" ) type Api struct { @@ -95,245 +91,6 @@ func (a *Api) GetUserInfo() (map[string]interface{}, error) { return a.request("cgi-bin/rad_user_info", nil) } -func (a *Api) _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 无效 - onResponse func(res *http.Response) (next *url.URL, err error) - // 获取到下一个请求地址时触发 - onNextAddr func(addr *url.URL) error -} - -func (a *Api) _FollowRedirect(addr *url.URL, conf _FollowRedirectConfig) (*url.URL, error) { - addrCopy := *addr - addr = &addrCopy - for { - log.Debugln("HTTP GET", addr) - req, err := http.NewRequest("GET", addr.String(), nil) - if err != nil { - return nil, err - } - for k, v := range a.CustomHeader { - req.Header.Set(k, fmt.Sprint(v)) - } - res, err := a.NoDirect.Do(req) - if err != nil { - return nil, err - } - if conf.onResponse != nil { - var nextAddr *url.URL - nextAddr, err = conf.onResponse(res) - if err != nil { - return nil, err - } else if nextAddr == nil { - break - } - addr = nextAddr - continue - } - _, _ = io.Copy(io.Discard, res.Body) - _ = res.Body.Close() - if res.StatusCode < 300 { - break - } else if res.StatusCode < 400 { - addr, err = a._JoinRedirectLocation(addr, res.Header.Get("location")) - if err != nil { - return nil, err - } - if conf.onNextAddr != nil { - if err = conf.onNextAddr(addr); err != nil { - return nil, err - } - } - } else { - return nil, fmt.Errorf("server return http status %d", res.StatusCode) - } - } - return addr, nil -} - -func (a *Api) _SearchAcid(query url.Values) (string, bool) { - addr := query.Get(`ac_id`) - return addr, addr != "" -} - -func (a *Api) DetectEnc() (string, error) { - log.Debugln("HTTP GET", a.BaseUrl) - res, err := a.Client.Get(a.BaseUrl) - if err != nil { - return "", err - } - defer res.Body.Close() - if res.StatusCode == 200 { - indexHtml, err := io.ReadAll(res.Body) - if err != nil { - return "", err - } - jsReg, err := regexp.Compile(`(?i)`) - if err != nil { - return - } - - result := reg.FindSubmatch(body) - if len(result) == 2 { - nextBytes := result[1] - nextAddr := unsafe.String(unsafe.SliceData(nextBytes), len(nextBytes)) - next, err = url.Parse(nextAddr) - } - } else if res.StatusCode < 400 { - next, err = a._JoinRedirectLocation(res.Request.URL, res.Header.Get("location")) - } - if getAcid && next != nil { - acid, _ = a._SearchAcid(next.Query()) - } - return - }, - }) - if err != nil { - if errors.Is(err, AlreadyOnline) { - online = true - err = nil - return - } - return - } - online = finalUrl.Host == startUrl.Host - return -} - type LoginRequest struct { Username string Password string diff --git a/pkg/srun/detect.go b/pkg/srun/detect.go new file mode 100644 index 0000000..781e580 --- /dev/null +++ b/pkg/srun/detect.go @@ -0,0 +1,264 @@ +package srun + +import ( + "errors" + "fmt" + log "github.com/sirupsen/logrus" + "io" + "net/http" + "net/url" + "regexp" + "strings" + "unsafe" +) + +func (a *Api) NewDetector() Detector { + return Detector{ + api: a, + } +} + +type Detector struct { + api *Api + + 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 无效 + onResponse func(res *http.Response) (next *url.URL, err error) + // 获取到下一个请求地址时触发 + onNextAddr func(addr *url.URL) error +} + +func (a *Detector) _FollowRedirect(addr *url.URL, conf _FollowRedirectConfig) (*url.URL, error) { + addrCopy := *addr + addr = &addrCopy + for { + log.Debugln("HTTP GET", addr) + req, err := http.NewRequest("GET", addr.String(), nil) + if err != nil { + return 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, err + } + if conf.onResponse != nil { + var nextAddr *url.URL + nextAddr, err = conf.onResponse(res) + if err != nil { + return nil, err + } else if nextAddr == nil { + break + } + addr = nextAddr + continue + } + _, _ = io.Copy(io.Discard, res.Body) + _ = res.Body.Close() + if res.StatusCode < 300 { + break + } else if res.StatusCode < 400 { + addr, err = a._JoinRedirectLocation(addr, res.Header.Get("location")) + if err != nil { + return nil, err + } + if conf.onNextAddr != nil { + if err = conf.onNextAddr(addr); err != nil { + return nil, err + } + } + } else { + return nil, fmt.Errorf("server return http status %d", res.StatusCode) + } + } + return addr, nil +} + +func (a *Detector) _SearchAcid(query url.Values) (string, bool) { + addr := query.Get(`ac_id`) + return addr, addr != "" +} + +func (a *Detector) DetectEnc() (string, error) { + 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 { + indexHtml, err := io.ReadAll(res.Body) + if err != nil { + return "", err + } + jsReg, err := regexp.Compile(`(?i)`) + if err != nil { + return + } + + result := reg.FindSubmatch(body) + if len(result) == 2 { + nextBytes := result[1] + nextAddr := unsafe.String(unsafe.SliceData(nextBytes), len(nextBytes)) + next, err = url.Parse(nextAddr) + } + } else if res.StatusCode < 400 { + next, err = a._JoinRedirectLocation(res.Request.URL, res.Header.Get("location")) + } + if getAcid && next != nil { + acid, _ = a._SearchAcid(next.Query()) + } + return + }, + }) + if err != nil { + if errors.Is(err, AlreadyOnline) { + online = true + err = nil + return + } + return + } + online = finalUrl.Host == startUrl.Host + return +}