mirror of
https://github.com/oneclickvirt/backtrace.git
synced 2025-04-20 11:12:08 +08:00
143 lines
3.5 KiB
Go
143 lines
3.5 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 {
|
|
var targets []model.IcmpTarget
|
|
err := json.Unmarshal([]byte(jsonData), &targets)
|
|
if err != nil {
|
|
if model.EnableLoger {
|
|
Logger.Info(fmt.Sprintf("解析ICMP目标失败: %s", err.Error()))
|
|
}
|
|
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
|
|
}
|