149 lines
4.3 KiB
Go
149 lines
4.3 KiB
Go
package tf
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"stat/common/log"
|
|
"strings"
|
|
|
|
"github.com/PuerkitoBio/goquery"
|
|
)
|
|
|
|
type Result struct {
|
|
Valid bool
|
|
Desc string
|
|
AppName string
|
|
AppIcon string
|
|
}
|
|
|
|
// address: https://testflight.apple.com/join/whsnQnSb
|
|
// https://testflight.apple.com/join/M3cBOOzR
|
|
func CheckTFValid(address string) (*Result, error) {
|
|
var checkResult Result
|
|
req, err := http.NewRequest("GET", address, nil)
|
|
if err != nil {
|
|
log.Warn("CheckTFValid newRequest", log.Any("address", address), log.E(err))
|
|
checkResult.Desc = err.Error()
|
|
return nil, err
|
|
}
|
|
req.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
|
|
req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6")
|
|
req.Header.Add("Cache-Control", "no-cache")
|
|
req.Header.Add("Connection", "keep-alive")
|
|
req.Header.Add("Pragma", "no-cache")
|
|
req.Header.Add("Sec-Fetch-Dest", "document")
|
|
req.Header.Add("Sec-Fetch-Mode", "navigate")
|
|
req.Header.Add("Sec-Fetch-Site", "none")
|
|
req.Header.Add("Sec-Fetch-User", "?1")
|
|
req.Header.Add("Upgrade-Insecure-Requests", "1")
|
|
req.Header.Add("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1")
|
|
res, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
log.Warn("CheckTFValid Client Do", log.Any("address", address), log.E(err))
|
|
return nil, err
|
|
}
|
|
defer func() { _ = res.Body.Close() }()
|
|
//不为200 肯定出问题了
|
|
if res.StatusCode != http.StatusOK {
|
|
checkResult.Desc = fmt.Sprintf("HttpStatus:%d", res.StatusCode)
|
|
return &checkResult, nil
|
|
}
|
|
|
|
//状态为200,解析内容
|
|
doc, err := goquery.NewDocumentFromReader(res.Body)
|
|
if err != nil {
|
|
log.Warn("CheckTFValid NewDocumentFromReader err", log.Any("address", address), log.E(err))
|
|
return &checkResult, err
|
|
}
|
|
|
|
valid, desc := checkValid(doc)
|
|
if !valid {
|
|
checkResult.Desc = desc
|
|
return &checkResult, nil
|
|
}
|
|
appName := getAppName(doc)
|
|
appIcon := getAppIcon(doc)
|
|
checkResult.Valid = true
|
|
checkResult.AppName = appName
|
|
checkResult.AppIcon = appIcon
|
|
return &checkResult, nil
|
|
}
|
|
|
|
func checkValid(doc *goquery.Document) (bool, string) {
|
|
foundStartTesting := false
|
|
doc.Find("a").EachWithBreak(func(i int, s *goquery.Selection) bool {
|
|
text := strings.TrimSpace(s.Text())
|
|
if text == "Start Testing" || text == "开始测试" {
|
|
foundStartTesting = true
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
if foundStartTesting {
|
|
return true, "" //TF包有效
|
|
}
|
|
betaStatus := ""
|
|
doc.Find(".beta-status").EachWithBreak(func(i int, s *goquery.Selection) bool {
|
|
betaStatus = strings.TrimSpace(s.Text())
|
|
return false
|
|
})
|
|
if betaStatus == "" {
|
|
return true, ""
|
|
}
|
|
if strings.Contains(betaStatus, "install TestFlight") || strings.Contains(betaStatus, "安装 TestFlight") {
|
|
return true, ""
|
|
}
|
|
|
|
//TODO: 这里还需要测试,目前来看,出现betaStatus就是无效的
|
|
return false, betaStatus
|
|
}
|
|
|
|
func getAppName(doc *goquery.Document) string {
|
|
var appName string
|
|
doc.Find("title").EachWithBreak(func(i int, selection *goquery.Selection) bool {
|
|
//<title>加入 Beta 版“原创短视频” - TestFlight - Apple</title>
|
|
//<title>Join the READ-O beta - TestFlight - Apple</title>
|
|
v := strings.TrimSpace(selection.Text())
|
|
rawLen := len(v)
|
|
v = strings.TrimPrefix(v, "加入 Beta 版")
|
|
v = strings.TrimPrefix(v, "Join the")
|
|
v = strings.TrimSuffix(v, "beta - TestFlight - Apple")
|
|
v = strings.TrimSuffix(v, "- TestFlight - Apple")
|
|
v = strings.TrimSpace(v)
|
|
v = strings.TrimLeft(v, "“")
|
|
v = strings.TrimRight(v, "”")
|
|
currLen := len(v)
|
|
|
|
if rawLen == currLen {
|
|
return true
|
|
}
|
|
appName = v
|
|
return false
|
|
})
|
|
return appName
|
|
}
|
|
|
|
func getAppIcon(doc *goquery.Document) string {
|
|
var iconUrl string
|
|
doc.Find(".app-icon.callout.ios").EachWithBreak(func(i int, selection *goquery.Selection) bool {
|
|
nodes := selection.Nodes
|
|
if len(nodes) == 0 {
|
|
return true
|
|
}
|
|
attrs := selection.Nodes[0].Attr
|
|
for _, attr := range attrs {
|
|
if attr.Key == "style" {
|
|
href := attr.Val
|
|
href = strings.TrimPrefix(href, "background-image: url(")
|
|
href = strings.TrimSuffix(href, ");")
|
|
if len(href) != len(attr.Val) {
|
|
iconUrl = href
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
return iconUrl
|
|
}
|