mihomo/rules/common/schedule.go
2025-11-29 17:20:50 -08:00

118 lines
3.3 KiB
Go

package common
import (
"fmt"
"strconv"
"strings"
"time"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
"golang.org/x/net/idna"
)
// make sure the system has install related zoneinfo for local time zone!
func init() {
log.Infoln("current system time is %s", time.Now().Format("2006-01-02 15:04:05"))
}
type Schedule struct {
*Base
weekDayArr [7]bool
startHour int
startMinute int
endHour int
endMinute int
schedule string
adapter string
}
func (d *Schedule) RuleType() C.RuleType {
return C.Schedule
}
func (d *Schedule) Match(metadata *C.Metadata) (bool, string) {
now := time.Now()
//log.Infoln("system time is %", now.Format("2006-01-02 15:04:05.000 Mon Jan"))
if d.weekDayArr[now.Weekday()] {
startTime := time.Date(now.Year(), now.Month(), now.Day(), d.startHour, d.startMinute, 0, 0, now.Location())
endTime := time.Date(now.Year(), now.Month(), now.Day(), d.endHour, d.endMinute, 59, 999999999, now.Location())
if now.After(startTime) && now.Before(endTime) {
//log.Infoln("src ip %s in the time %d:%d~%d:%d. adapter is %s.", metadata.SrcIP.String(), d.startHour, d.startMinute, d.endHour, d.endMinute, d.adapter)
return true, d.adapter
}
}
return false, d.adapter
}
func (d *Schedule) Adapter() string {
return d.adapter
}
func (d *Schedule) Payload() string {
return d.schedule
}
func NewSchedule(schedule string, adapter string) (*Schedule, error) {
punycode, _ := idna.ToASCII(strings.ToUpper(schedule))
weekDayArr := [7]bool{false, false, false, false, false, false, false}
if len(punycode) != 19 {
return nil, fmt.Errorf("could you initial Schedule rule %s, the rule format is not correct!", punycode)
}
if punycode[0] == 'S' {
weekDayArr[0] = true
}
if punycode[1] == 'M' {
weekDayArr[1] = true
}
if punycode[2] == 'T' {
weekDayArr[2] = true
}
if punycode[3] == 'W' {
weekDayArr[3] = true
}
if punycode[4] == 'T' {
weekDayArr[4] = true
}
if punycode[5] == 'F' {
weekDayArr[5] = true
}
if punycode[6] == 'S' {
weekDayArr[6] = true
}
startHour, err := strconv.Atoi(punycode[8:10])
if err != nil {
return nil, fmt.Errorf("could you initial Schedule rule %s, the time format is not correct!", punycode)
}
startMinute, err := strconv.Atoi(punycode[11:13])
if err != nil {
return nil, fmt.Errorf("could you initial Schedule rule %s, the time format is not correct!", punycode)
}
endHour, err := strconv.Atoi(punycode[14:16])
if err != nil {
return nil, fmt.Errorf("could you initial Schedule rule %s, the time format is not correct!", punycode)
}
endMinute, err := strconv.Atoi(punycode[17:19])
if err != nil {
return nil, fmt.Errorf("could you initial Schedule rule %s, the time format is not correct!", punycode)
}
if startHour > endHour {
return nil, fmt.Errorf("could you initial Schedule rule %s, the end time should not be earlier than start time!", punycode)
}
if startHour == endHour && startMinute > endMinute {
return nil, fmt.Errorf("could you initial Schedule rule %s, the end time should not be earlier than start time!", punycode)
}
return &Schedule{
Base: &Base{},
weekDayArr: weekDayArr,
startHour: startHour,
startMinute: startMinute,
endHour: endHour,
endMinute: endMinute,
schedule: punycode,
adapter: adapter,
}, nil
}
//var _ C.Rule = (*Schedule)(nil)