mirror of
https://github.com/oneclickvirt/backtrace.git
synced 2025-04-20 19:22:07 +08:00
149 lines
3.8 KiB
Go
149 lines
3.8 KiB
Go
package backtrace
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/imroc/req/v3"
|
||
"github.com/oneclickvirt/backtrace/model"
|
||
. "github.com/oneclickvirt/defaultset"
|
||
)
|
||
|
||
type Result struct {
|
||
i int
|
||
s string
|
||
}
|
||
|
||
// removeDuplicates 切片去重
|
||
func removeDuplicates(elements []string) []string {
|
||
if elements == nil {
|
||
return nil
|
||
}
|
||
seen := make(map[string]struct{})
|
||
var result []string
|
||
for _, v := range elements {
|
||
if _, ok := seen[v]; !ok {
|
||
seen[v] = struct{}{}
|
||
result = append(result, v)
|
||
}
|
||
}
|
||
return result
|
||
}
|
||
|
||
// getData 获取目标地址的文本内容
|
||
func getData(endpoint string) string {
|
||
client := req.C()
|
||
client.SetTimeout(6 * time.Second)
|
||
client.R().
|
||
SetRetryCount(2).
|
||
SetRetryBackoffInterval(1*time.Second, 5*time.Second).
|
||
SetRetryFixedInterval(2 * time.Second)
|
||
if model.EnableLoger {
|
||
InitLogger()
|
||
defer Logger.Sync()
|
||
}
|
||
for _, baseUrl := range model.CdnList {
|
||
url := baseUrl + endpoint
|
||
resp, err := client.R().Get(url)
|
||
if err == nil {
|
||
defer resp.Body.Close()
|
||
b, err := io.ReadAll(resp.Body)
|
||
if strings.Contains(string(b), "error") {
|
||
continue
|
||
}
|
||
if err == nil {
|
||
if model.EnableLoger {
|
||
Logger.Info(fmt.Sprintf("Received data length: %d", len(b)))
|
||
}
|
||
return string(b)
|
||
}
|
||
}
|
||
if model.EnableLoger {
|
||
Logger.Info(fmt.Sprintf("HTTP request failed: %v", err))
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// parseIcmpTargets 解析ICMP目标数据
|
||
func parseIcmpTargets(jsonData string) []model.IcmpTarget {
|
||
// 确保JSON数据格式正确,如果返回的是数组,需要添加[和]
|
||
if !strings.HasPrefix(jsonData, "[") {
|
||
jsonData = "[" + jsonData + "]"
|
||
}
|
||
// 如果JSON数据中的对象没有正确用逗号分隔,修复它
|
||
jsonData = strings.ReplaceAll(jsonData, "}{", "},{")
|
||
var targets []model.IcmpTarget
|
||
err := json.Unmarshal([]byte(jsonData), &targets)
|
||
if err != nil {
|
||
if model.EnableLoger {
|
||
Logger.Error(fmt.Sprintf("Failed to parse ICMP targets: %v", err))
|
||
}
|
||
return nil
|
||
}
|
||
return targets
|
||
}
|
||
|
||
// tryAlternativeIPs 从IcmpTargets获取备选IP地址
|
||
func tryAlternativeIPs(targetName string, ipVersion string) []string {
|
||
if model.ParsedIcmpTargets == nil || (model.ParsedIcmpTargets != nil && len(model.ParsedIcmpTargets) == 0) {
|
||
return nil
|
||
}
|
||
if model.EnableLoger {
|
||
Logger.Info(fmt.Sprintf("使用备选地址: %s %s", targetName, ipVersion))
|
||
}
|
||
// 从目标名称中提取省份和ISP信息
|
||
var targetProvince, targetISP string
|
||
if strings.Contains(targetName, "北京") {
|
||
targetProvince = "北京"
|
||
} else if strings.Contains(targetName, "上海") {
|
||
targetProvince = "上海"
|
||
} else if strings.Contains(targetName, "广州") {
|
||
targetProvince = "广东"
|
||
} else if strings.Contains(targetName, "成都") {
|
||
targetProvince = "四川"
|
||
}
|
||
if strings.Contains(targetName, "电信") {
|
||
targetISP = "电信"
|
||
} else if strings.Contains(targetName, "联通") {
|
||
targetISP = "联通"
|
||
} else if strings.Contains(targetName, "移动") {
|
||
targetISP = "移动"
|
||
}
|
||
// 如果没有提取到信息,返回空
|
||
if targetProvince == "" || targetISP == "" {
|
||
return nil
|
||
}
|
||
// 查找匹配条件的目标
|
||
var result []string
|
||
for _, target := range model.ParsedIcmpTargets {
|
||
// 检查省份是否匹配(可能带有"省"字或不带)
|
||
provinceMatch := (target.Province == targetProvince) || (target.Province == targetProvince+"省")
|
||
// 检查ISP和IP版本是否匹配
|
||
if provinceMatch && target.ISP == targetISP && target.IPVersion == ipVersion {
|
||
// 解析IP列表
|
||
if target.IPs != "" {
|
||
ips := strings.Split(target.IPs, ",")
|
||
// 最多返回3个IP地址
|
||
count := 0
|
||
for _, ip := range ips {
|
||
if ip != "" {
|
||
result = append(result, strings.TrimSpace(ip))
|
||
count++
|
||
if count >= 3 {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
if len(result) > 0 {
|
||
return result
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return nil
|
||
}
|