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
+}