package strategy import ( "fmt" "net" "regexp" "strconv" "strings" "time" "github.com/eolinker/apinto/checker" "github.com/eolinker/eosc/log" ) type IPChecker struct { checker IChecker } func (i *IPChecker) Check(v string, has bool) bool { if !has { return false } return i.checker.Check(v) } func (i *IPChecker) Key() string { return i.checker.Key() } func (i *IPChecker) CheckType() checker.CheckType { return checker.CheckTypeIP } func (i *IPChecker) Value() string { return i.checker.Value() } func newIPChecker(pattern string) (*IPChecker, error) { if strings.Contains(pattern, "*") { checker, err := newIpV4RangeChecker(pattern) if err != nil { return nil, err } return &IPChecker{checker}, nil } if strings.Contains(pattern, "/") { checker, err := newIpCidrChecker(pattern) if err != nil { return nil, err } return &IPChecker{checker}, nil } return &IPChecker{newIpEqualChecker(pattern)}, nil } func newIpEqualChecker(ip string) *ipEqualChecker { return &ipEqualChecker{ip: ip} } type ipEqualChecker struct { ip string } func (i *ipEqualChecker) Key() string { return i.ip } func (i *ipEqualChecker) Value() string { return i.ip } func (i *ipEqualChecker) Check(v string) bool { return i.ip == v } type ipCidrChecker struct { cidr *net.IPNet org string } func (i *ipCidrChecker) Key() string { return i.org } func (i *ipCidrChecker) Value() string { return i.cidr.String() } func newIpCidrChecker(ip string) (*ipCidrChecker, error) { _, cidr, err := net.ParseCIDR(ip) if err != nil { return nil, err } return &ipCidrChecker{cidr: cidr, org: ip}, nil } func (i *ipCidrChecker) Check(ip string) bool { ipAddr := net.ParseIP(ip) if ipAddr == nil { log.Error("invalid ip: %s", ip) return false } return i.cidr.Contains(ipAddr) } func newIpV4RangeChecker(ip string) (*ipV4RangeChecker, error) { ipParts := strings.Split(ip, ".") patterns := make([]string, 0, 4) index := 0 for _, p := range ipParts { index++ v, err := strconv.Atoi(p) if err != nil || v < 1 || v > 255 { return nil, fmt.Errorf("invalid ip: %s", ip) } patterns = append(patterns, p) } for i := 4 - index; i > 0; i-- { patterns = append(patterns, "*") } return &ipV4RangeChecker{ipParts: patterns}, nil } type ipV4RangeChecker struct { ipParts []string org string } func (i *ipV4RangeChecker) Key() string { return i.org } func (i *ipV4RangeChecker) Value() string { return i.org } func (i *ipV4RangeChecker) Check(ip string) bool { ipParts := strings.Split(ip, ".") if len(ipParts) != 4 { return false } for index, p := range i.ipParts { if p == "*" { continue } if p != ipParts[index] { return false } } return true } type timestampChecker struct { org string startTime time.Time endTime time.Time } var ( timeRangeRegex = regexp.MustCompile(`^((?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d|24:00:00)$`) ) func newTimestampChecker(timeRange string) (*timestampChecker, error) { // 提取开始时间和结束时间 times := strings.Split(timeRange, "-") startTimeStr, endTimeStr := strings.TrimSpace(times[0]), strings.TrimSpace(times[1]) if !timeRangeRegex.MatchString(startTimeStr) { return nil, fmt.Errorf("invalid time format for start time: %s", startTimeStr) } if !timeRangeRegex.MatchString(endTimeStr) { return nil, fmt.Errorf("invalid time format for end time: %s", endTimeStr) } // 解析开始时间和结束时间(假设在当前日期) startTime, err := time.Parse("15:04:05", startTimeStr) if err != nil { return nil, fmt.Errorf("failed to parse start time: %v", err) } if endTimeStr == "24:00:00" { // 特殊处理 24:00:00,表示第二天的 00:00:00 endTimeStr = "23:59:59" } endTime, err := time.Parse("15:04:05", endTimeStr) if err != nil { return nil, fmt.Errorf("failed to parse end time: %v", err) } if startTime.After(endTime) { return nil, fmt.Errorf("start time %s cannot be after end time %s", startTimeStr, endTimeStr) } return ×tampChecker{startTime: startTime, endTime: endTime}, nil } func (t *timestampChecker) Check(v string, has bool) bool { if !has { return false } now, err := time.ParseInLocation("2006-01-02 15:04:05", v, time.Local) if err != nil { log.Error("invalid timestamp format: %s, error: %v", v, err) return false } startTime := time.Date(now.Year(), now.Month(), now.Day(), t.startTime.Hour(), t.startTime.Minute(), t.startTime.Second(), 0, time.Local) endTime := time.Date(now.Year(), now.Month(), now.Day(), t.endTime.Hour(), t.endTime.Minute(), t.endTime.Second(), 0, time.Local) if startTime.Before(now) && endTime.After(now) { return true } return false } func (t *timestampChecker) Key() string { return t.org } func (t *timestampChecker) CheckType() checker.CheckType { return checker.CheckTypeTimeRange } func (t *timestampChecker) Value() string { return t.org } type IChecker interface { Check(v string) bool Key() string Value() string }