From f5e2b3b76f3b6dfed52bcfda9169270d959b9af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E8=B6=85?= <7546302+red_q@user.noreply.gitee.com> Date: Thu, 27 Feb 2025 00:12:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=AE=89=E5=85=A8=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6xlsx=E8=A1=A8=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- attack_event/fw.go | 52 ++- attack_event/job.go | 196 ++++---- go.mod | 1 - go.sum | 2 - main.go | 27 +- method/hw_fw1.go | 3 +- modified_example.xlsx | Bin 0 -> 4590 bytes .../unioffice/spreadsheet/workbook.go | 11 +- vendor/github.com/robfig/cron/v3/.gitignore | 22 - vendor/github.com/robfig/cron/v3/.travis.yml | 1 - vendor/github.com/robfig/cron/v3/LICENSE | 21 - vendor/github.com/robfig/cron/v3/README.md | 125 ----- vendor/github.com/robfig/cron/v3/chain.go | 92 ---- .../robfig/cron/v3/constantdelay.go | 27 -- vendor/github.com/robfig/cron/v3/cron.go | 355 -------------- vendor/github.com/robfig/cron/v3/doc.go | 231 ---------- vendor/github.com/robfig/cron/v3/logger.go | 86 ---- vendor/github.com/robfig/cron/v3/option.go | 45 -- vendor/github.com/robfig/cron/v3/parser.go | 434 ------------------ vendor/github.com/robfig/cron/v3/spec.go | 188 -------- vendor/modules.txt | 3 - 21 files changed, 167 insertions(+), 1755 deletions(-) create mode 100644 modified_example.xlsx delete mode 100644 vendor/github.com/robfig/cron/v3/.gitignore delete mode 100644 vendor/github.com/robfig/cron/v3/.travis.yml delete mode 100644 vendor/github.com/robfig/cron/v3/LICENSE delete mode 100644 vendor/github.com/robfig/cron/v3/README.md delete mode 100644 vendor/github.com/robfig/cron/v3/chain.go delete mode 100644 vendor/github.com/robfig/cron/v3/constantdelay.go delete mode 100644 vendor/github.com/robfig/cron/v3/cron.go delete mode 100644 vendor/github.com/robfig/cron/v3/doc.go delete mode 100644 vendor/github.com/robfig/cron/v3/logger.go delete mode 100644 vendor/github.com/robfig/cron/v3/option.go delete mode 100644 vendor/github.com/robfig/cron/v3/parser.go delete mode 100644 vendor/github.com/robfig/cron/v3/spec.go diff --git a/attack_event/fw.go b/attack_event/fw.go index 25c95f7..b3082d6 100644 --- a/attack_event/fw.go +++ b/attack_event/fw.go @@ -8,12 +8,41 @@ import ( "fmt" "log" "net/url" + "strconv" "time" + + "github.com/Esword618/unioffice/schema/soo/sml" + "github.com/Esword618/unioffice/spreadsheet" ) -// var cookieStr string +var cookieStr string + +// 传入cookie +func Fw_event(cookieStr string) { + ss := spreadsheet.New() + sheet := ss.AddSheet() + // sheet.SetFrozen(true, false) + v := sheet.InitialView() + v.SetState(sml.ST_PaneStateFrozen) + v.SetXSplit(0) //冻结列 + v.SetYSplit(1) //冻结行 + // v.SetTopLeft("B2") + // // 获取第一个工作表 + // sheet, err := ss.GetSheet("Sheet2") + // if err != nil { + // log.Println(err) + // } + sheet.Cell("A1").SetString("序号") + sheet.Cell("B1").SetString("攻击时间") + sheet.Cell("C1").SetString("源安全域") + sheet.Cell("D1").SetString("目的安全域") + sheet.Cell("E1").SetString("源IP") + sheet.Cell("F1").SetString("目的IP") + sheet.Cell("G1").SetString("目的端口") + sheet.Cell("H1").SetString("攻击类型") + sheet.Cell("I1").SetString("应用协议") + sheet.Cell("J1").SetString("域名(host)") -func Fw_event() { //当前时间 EndTime := time.Unix(tool.Timestamp("second"), 0).Format("2006-01-02T15:04:05") //今天0点 @@ -35,6 +64,23 @@ func Fw_event() { log.Fatalf("Failed to unmarshal JSON: %v", err) } fmt.Println(v, a) - // fmt.Printf("序号:%d,攻击时间:[%s],安全域:%s-%s##攻击源IP:%s#目的源IP:%s:%s,攻击类型:%s,应用协议:%s,请求域名:%s\n", v, a["Time"], a["SrcZoneName"], a["DestZoneName"], a["SrcIPAddr"], a["DestIPAddr"], strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64), a["ThreatName"], a["Application"], a["HttpHost"]) + fmt.Printf("序号:%d,攻击时间:[%s],安全域:%s-%s##攻击源IP:%s#目的源IP:%s:%s,攻击类型:%s,应用协议:%s,请求域名:%s\n", v, a["Time"], a["SrcZoneName"], a["DestZoneName"], a["SrcIPAddr"], a["DestIPAddr"], strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64), a["ThreatName"], a["Application"], a["HttpHost"]) + sheet.Cell("A" + strconv.Itoa(v+1)).SetString(strconv.Itoa(v)) // 第一列 (A1) + sheet.Cell("B" + strconv.Itoa(v+1)).SetString(a["Time"].(string)) + sheet.Cell("C" + strconv.Itoa(v+1)).SetString(a["SrcZoneName"].(string)) + sheet.Cell("D" + strconv.Itoa(v+1)).SetString(a["DestZoneName"].(string)) + sheet.Cell("E" + strconv.Itoa(v+1)).SetString(a["SrcIPAddr"].(string)) + sheet.Cell("F" + strconv.Itoa(v+1)).SetString(a["DestIPAddr"].(string)) + sheet.Cell("G" + strconv.Itoa(v+1)).SetString(strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64)) + sheet.Cell("H" + strconv.Itoa(v+1)).SetString(a["ThreatName"].(string)) + sheet.Cell("I" + strconv.Itoa(v+1)).SetString(a["Application"].(string)) + sheet.Cell("J" + strconv.Itoa(v+1)).SetString(a["HttpHost"].(string)) + } + // 保存修改后的 Excel 文件 + if err := ss.Validate(); err != nil { + log.Fatalf("验证文件时出错: %s", err) + } + if err := ss.SaveToFile("防火墙安全事件.xlsx"); err != nil { + log.Fatalf("保存文件时出错: %s", err) } } diff --git a/attack_event/job.go b/attack_event/job.go index 18c2efb..d50bb47 100644 --- a/attack_event/job.go +++ b/attack_event/job.go @@ -1,109 +1,109 @@ package attackevent -import ( - "dt_automate/conn" - "dt_automate/tool" - "fmt" - "log" - "time" +// import ( +// "dt_automate/conn" +// "dt_automate/tool" +// "fmt" +// "log" +// "time" - "github.com/robfig/cron/v3" -) +// "github.com/robfig/cron/v3" +// ) -var cookieStr = "vindex==39=16=0AB00=0R; supportLang=cn%2Cen; lang=cn; sessionid=200001dc6ccf3da4c61484899a31aaf741de; loginid=975d5428764bcee5451c191f464cb5ad; 200001dc6ccf3da4c61484899a31aaf741de=true; abcd1234=true; login=false" +// var cookieStr = "vindex==39=16=0AB00=0R; supportLang=cn%2Cen; lang=cn; sessionid=200001dc6ccf3da4c61484899a31aaf741de; loginid=975d5428764bcee5451c191f464cb5ad; 200001dc6ccf3da4c61484899a31aaf741de=true; abcd1234=true; login=false" -func FW_Job() { - job := cron.New(cron.WithSeconds()) +// func FW_Job() { +// job := cron.New(cron.WithSeconds()) - j := &myJob{ - t: time.Now(), - } - j1 := &myJob1{ - t: time.Now(), - } - job.Schedule(cron.Every(3*60*time.Second), j) - job.Schedule(cron.Every(3*time.Second), j1) - job.Start() - select {} -} +// j := &myJob{ +// t: time.Now(), +// } +// j1 := &myJob1{ +// t: time.Now(), +// } +// job.Schedule(cron.Every(3*60*time.Second), j) +// job.Schedule(cron.Every(3*time.Second), j1) +// job.Start() +// select {} +// } -type myJob struct { - i int - t time.Time -} +// type myJob struct { +// i int +// t time.Time +// } -func (j *myJob) Run() { //心跳//三分钟触发一次 - //当前时间 - // EndTime := time.Unix(tool.Timestamp("second"), 0).Format("2006-01-02T15:04:05") - // //今天0点 - // StartTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Now().Location()).Format("2006-01-02T15:04:05") - // 构建 x-www-form-urlencoded 格式的请求体 - // values := url.Values{} - // values.Add("xml", "1"+StartTime+""+EndTime+"1200{"SrcZoneName":"Untrust","DestZoneName":"Trust"}") - // values.Add("req_menu", "M_Monitor/M_AtkLog/M_ThreatLog") - header := map[string]string{ - // "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", - "referer": "https://11.2.68.146/wnm/frame/index.php", - "cookie": cookieStr, - } - datas := conn.DT_POST("https://11.2.68.146/wnm/keepalive.j", header, nil) - // var a map[string]interface{} - // for v, k := range datas.([]interface{}) { - // b := k.(map[string]interface{})["OutputJSON"].(string) - // if err := json.Unmarshal([]byte(b), &a); err != nil { - // log.Fatalf("Failed to unmarshal JSON: %v", err) - // } - // fmt.Println(v, a) - // // fmt.Printf("序号:%d,攻击时间:[%s],安全域:%s-%s##攻击源IP:%s#目的源IP:%s:%s,攻击类型:%s,应用协议:%s,请求域名:%s\n", v, a["Time"], a["SrcZoneName"], a["DestZoneName"], a["SrcIPAddr"], a["DestIPAddr"], strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64), a["ThreatName"], a["Application"], a["HttpHost"]) - // } - log.Println(datas) - //################################# - j.i++ - now := time.Now() - sub := now.Sub(j.t) - j.t = now - fmt.Printf("心跳: %d, duraction : %d ms %f \n", j.i, sub.Milliseconds(), sub.Minutes()) -} +// func (j *myJob) Run() { //心跳//三分钟触发一次 +// //当前时间 +// // EndTime := time.Unix(tool.Timestamp("second"), 0).Format("2006-01-02T15:04:05") +// // //今天0点 +// // StartTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Now().Location()).Format("2006-01-02T15:04:05") +// // 构建 x-www-form-urlencoded 格式的请求体 +// // values := url.Values{} +// // values.Add("xml", "1"+StartTime+""+EndTime+"1200{"SrcZoneName":"Untrust","DestZoneName":"Trust"}") +// // values.Add("req_menu", "M_Monitor/M_AtkLog/M_ThreatLog") +// header := map[string]string{ +// // "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", +// "referer": "https://11.2.68.146/wnm/frame/index.php", +// "cookie": cookieStr, +// } +// datas := conn.DT_POST("https://11.2.68.146/wnm/keepalive.j", header, nil) +// // var a map[string]interface{} +// // for v, k := range datas.([]interface{}) { +// // b := k.(map[string]interface{})["OutputJSON"].(string) +// // if err := json.Unmarshal([]byte(b), &a); err != nil { +// // log.Fatalf("Failed to unmarshal JSON: %v", err) +// // } +// // fmt.Println(v, a) +// // // fmt.Printf("序号:%d,攻击时间:[%s],安全域:%s-%s##攻击源IP:%s#目的源IP:%s:%s,攻击类型:%s,应用协议:%s,请求域名:%s\n", v, a["Time"], a["SrcZoneName"], a["DestZoneName"], a["SrcIPAddr"], a["DestIPAddr"], strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64), a["ThreatName"], a["Application"], a["HttpHost"]) +// // } +// log.Println(datas) +// //################################# +// j.i++ +// now := time.Now() +// sub := now.Sub(j.t) +// j.t = now +// fmt.Printf("心跳: %d, duraction : %d ms %f \n", j.i, sub.Milliseconds(), sub.Minutes()) +// } -type myJob1 struct { - i int - t time.Time -} +// type myJob1 struct { +// i int +// t time.Time +// } -func (j1 *myJob1) Run() { //定时任务1小时执行一次,获取威胁数据 - now := time.Now() - // 当前时间 - EndTime := time.Unix(tool.Timestamp("second"), 0).Format("2006-01-02T15:04:05") - h, _ := time.ParseDuration("-1h") - h1 := now.Add(1 * h).Format("2006-01-02T15:04:05") - log.Println(EndTime) - fmt.Println(h1) - // //今天0点 - // StartTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Now().Location()).Format("2006-01-02T15:04:05") - // // 构建 x-www-form-urlencoded 格式的请求体 - // values := url.Values{} - // values.Add("xml", "1"+StartTime+""+EndTime+"1200{"SrcZoneName":"Untrust","DestZoneName":"Trust"}") - // values.Add("req_menu", "M_Monitor/M_AtkLog/M_ThreatLog") - // header := map[string]string{ - // "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", - // "referer": "https://11.2.68.146/wnm/frame/index.php", - // "cookie": cookieStr, - // } - // datas := conn.DT_POST("https://11.2.68.146/wnm/get.j", header, bytes.NewBufferString(values.Encode()))["NTOP"].(map[string]interface{})["LogPaging"] - // var a map[string]interface{} - // for v, k := range datas.([]interface{}) { - // b := k.(map[string]interface{})["OutputJSON"].(string) - // if err := json.Unmarshal([]byte(b), &a); err != nil { - // log.Fatalf("Failed to unmarshal JSON: %v", err) - // } - // fmt.Println(v, a) - // fmt.Printf("序号:%d,攻击时间:[%s],安全域:%s-%s##攻击源IP:%s#目的源IP:%s:%s,攻击类型:%s,应用协议:%s,请求域名:%s\n", v, a["Time"], a["SrcZoneName"], a["DestZoneName"], a["SrcIPAddr"], a["DestIPAddr"], strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64), a["ThreatName"], a["Application"], a["HttpHost"]) - // } - // ############################################### - j1.i++ - // now := time.Now() - sub := now.Sub(j1.t) - j1.t = now - fmt.Printf("获取数据: %d, duraction : %d ms %f\n", j1.i, sub.Milliseconds(), sub.Hours()) +// func (j1 *myJob1) Run() { //定时任务1小时执行一次,获取威胁数据 +// now := time.Now() +// // 当前时间 +// EndTime := time.Unix(tool.Timestamp("second"), 0).Format("2006-01-02T15:04:05") +// h, _ := time.ParseDuration("-1h") +// h1 := now.Add(1 * h).Format("2006-01-02T15:04:05") +// log.Println(EndTime) +// fmt.Println(h1) +// // //今天0点 +// // StartTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.Now().Location()).Format("2006-01-02T15:04:05") +// // // 构建 x-www-form-urlencoded 格式的请求体 +// // values := url.Values{} +// // values.Add("xml", "1"+StartTime+""+EndTime+"1200{"SrcZoneName":"Untrust","DestZoneName":"Trust"}") +// // values.Add("req_menu", "M_Monitor/M_AtkLog/M_ThreatLog") +// // header := map[string]string{ +// // "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", +// // "referer": "https://11.2.68.146/wnm/frame/index.php", +// // "cookie": cookieStr, +// // } +// // datas := conn.DT_POST("https://11.2.68.146/wnm/get.j", header, bytes.NewBufferString(values.Encode()))["NTOP"].(map[string]interface{})["LogPaging"] +// // var a map[string]interface{} +// // for v, k := range datas.([]interface{}) { +// // b := k.(map[string]interface{})["OutputJSON"].(string) +// // if err := json.Unmarshal([]byte(b), &a); err != nil { +// // log.Fatalf("Failed to unmarshal JSON: %v", err) +// // } +// // fmt.Println(v, a) +// // fmt.Printf("序号:%d,攻击时间:[%s],安全域:%s-%s##攻击源IP:%s#目的源IP:%s:%s,攻击类型:%s,应用协议:%s,请求域名:%s\n", v, a["Time"], a["SrcZoneName"], a["DestZoneName"], a["SrcIPAddr"], a["DestIPAddr"], strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64), a["ThreatName"], a["Application"], a["HttpHost"]) +// // } +// // ############################################### +// j1.i++ +// // now := time.Now() +// sub := now.Sub(j1.t) +// j1.t = now +// fmt.Printf("获取数据: %d, duraction : %d ms %f\n", j1.i, sub.Milliseconds(), sub.Hours()) -} +// } diff --git a/go.mod b/go.mod index 106e451..f21b662 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/go-sql-driver/mysql v1.9.0 github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c github.com/playwright-community/playwright-go v0.5001.0 - github.com/robfig/cron/v3 v3.0.1 github.com/super-l/machine-code v0.0.0-20241121142923-4cb40646deba ) diff --git a/go.sum b/go.sum index 4ec0cc9..c758ab3 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,6 @@ github.com/playwright-community/playwright-go v0.5001.0 h1:EY3oB+rU9cUp6CLHguWE8 github.com/playwright-community/playwright-go v0.5001.0/go.mod h1:kBNWs/w2aJ2ZUp1wEOOFLXgOqvppFngM5OS+qyhl+ZM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= diff --git a/main.go b/main.go index 3682874..52b48ae 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,7 @@ package main import ( - "dt_automate/method" "dt_automate/tool" - "dt_automate/wps" "flag" "fmt" "log" @@ -91,18 +89,19 @@ func main() { log.Printf("授权未到期,剩余时间:%d天 %d小时 %d分钟 %d秒", days, hours, minutes, secod) //可执行程序位置 // 互联网区 - method.HW_FAC1() //截取流量清洗的图片 - method.HW_FW1() //截取防火墙的图片 - method.HW_TSGZ() //截取态势感知的图片 - method.HW_DTCLOUD() //截取运维中心的图片 - wps.HW_SYS_Word() //运维平台word文档生成 - //政务网区 - method.ZWW_FW1() //截取防火墙的图片 - method.ZWW_TSGZ() //截取态势感知的图片 - method.ZWW_DTCLOUD() //截取运维中心的图片 - wps.ZWW_SYS_Word() //运维平台word文档生成 - //安全巡检文档生成 - wps.SAFET_Word() //安全巡检文档生成 + // method.HW_FAC1() //截取流量清洗的图片 + // method.HW_FW1() //截取防火墙的图片 + // method.HW_TSGZ() //截取态势感知的图片 + // method.HW_DTCLOUD() //截取运维中心的图片 + // wps.HW_SYS_Word() //运维平台word文档生成 + // //政务网区 + // method.ZWW_FW1() //截取防火墙的图片 + // method.ZWW_TSGZ() //截取态势感知的图片 + // method.ZWW_DTCLOUD() //截取运维中心的图片 + // wps.ZWW_SYS_Word() //运维平台word文档生成 + // //安全巡检文档生成 + // wps.SAFET_Word() //安全巡检文档生成 + // attackevent.Fw_event("cookie") //防火墙安全事件表生成 } } else { log.Println("没有授权") diff --git a/method/hw_fw1.go b/method/hw_fw1.go index f82912d..85bbb9c 100644 --- a/method/hw_fw1.go +++ b/method/hw_fw1.go @@ -1,6 +1,7 @@ package method import ( + attackevent "dt_automate/attack_event" "dt_automate/tool" "fmt" "log" @@ -114,7 +115,7 @@ func HW_FW1() { log.Printf("Cookie %d: %+v", i, cookie) } log.Println(cookieStr) - + attackevent.Fw_event(cookieStr) // StartBlocker() page.WaitForTimeout(5000) } diff --git a/modified_example.xlsx b/modified_example.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..f38740be59759a4c2583a49db2161db456f5f516 GIT binary patch literal 4590 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 time.Minute { - logger.Info("delay", "duration", dur) - } - j.Run() - }) - } -} - -// SkipIfStillRunning skips an invocation of the Job if a previous invocation is -// still running. It logs skips to the given logger at Info level. -func SkipIfStillRunning(logger Logger) JobWrapper { - return func(j Job) Job { - var ch = make(chan struct{}, 1) - ch <- struct{}{} - return FuncJob(func() { - select { - case v := <-ch: - j.Run() - ch <- v - default: - logger.Info("skip") - } - }) - } -} diff --git a/vendor/github.com/robfig/cron/v3/constantdelay.go b/vendor/github.com/robfig/cron/v3/constantdelay.go deleted file mode 100644 index cd6e7b1..0000000 --- a/vendor/github.com/robfig/cron/v3/constantdelay.go +++ /dev/null @@ -1,27 +0,0 @@ -package cron - -import "time" - -// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes". -// It does not support jobs more frequent than once a second. -type ConstantDelaySchedule struct { - Delay time.Duration -} - -// Every returns a crontab Schedule that activates once every duration. -// Delays of less than a second are not supported (will round up to 1 second). -// Any fields less than a Second are truncated. -func Every(duration time.Duration) ConstantDelaySchedule { - if duration < time.Second { - duration = time.Second - } - return ConstantDelaySchedule{ - Delay: duration - time.Duration(duration.Nanoseconds())%time.Second, - } -} - -// Next returns the next time this should be run. -// This rounds so that the next activation time will be on the second. -func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time { - return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond) -} diff --git a/vendor/github.com/robfig/cron/v3/cron.go b/vendor/github.com/robfig/cron/v3/cron.go deleted file mode 100644 index c7e9176..0000000 --- a/vendor/github.com/robfig/cron/v3/cron.go +++ /dev/null @@ -1,355 +0,0 @@ -package cron - -import ( - "context" - "sort" - "sync" - "time" -) - -// Cron keeps track of any number of entries, invoking the associated func as -// specified by the schedule. It may be started, stopped, and the entries may -// be inspected while running. -type Cron struct { - entries []*Entry - chain Chain - stop chan struct{} - add chan *Entry - remove chan EntryID - snapshot chan chan []Entry - running bool - logger Logger - runningMu sync.Mutex - location *time.Location - parser ScheduleParser - nextID EntryID - jobWaiter sync.WaitGroup -} - -// ScheduleParser is an interface for schedule spec parsers that return a Schedule -type ScheduleParser interface { - Parse(spec string) (Schedule, error) -} - -// Job is an interface for submitted cron jobs. -type Job interface { - Run() -} - -// Schedule describes a job's duty cycle. -type Schedule interface { - // Next returns the next activation time, later than the given time. - // Next is invoked initially, and then each time the job is run. - Next(time.Time) time.Time -} - -// EntryID identifies an entry within a Cron instance -type EntryID int - -// Entry consists of a schedule and the func to execute on that schedule. -type Entry struct { - // ID is the cron-assigned ID of this entry, which may be used to look up a - // snapshot or remove it. - ID EntryID - - // Schedule on which this job should be run. - Schedule Schedule - - // Next time the job will run, or the zero time if Cron has not been - // started or this entry's schedule is unsatisfiable - Next time.Time - - // Prev is the last time this job was run, or the zero time if never. - Prev time.Time - - // WrappedJob is the thing to run when the Schedule is activated. - WrappedJob Job - - // Job is the thing that was submitted to cron. - // It is kept around so that user code that needs to get at the job later, - // e.g. via Entries() can do so. - Job Job -} - -// Valid returns true if this is not the zero entry. -func (e Entry) Valid() bool { return e.ID != 0 } - -// byTime is a wrapper for sorting the entry array by time -// (with zero time at the end). -type byTime []*Entry - -func (s byTime) Len() int { return len(s) } -func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s byTime) Less(i, j int) bool { - // Two zero times should return false. - // Otherwise, zero is "greater" than any other time. - // (To sort it at the end of the list.) - if s[i].Next.IsZero() { - return false - } - if s[j].Next.IsZero() { - return true - } - return s[i].Next.Before(s[j].Next) -} - -// New returns a new Cron job runner, modified by the given options. -// -// Available Settings -// -// Time Zone -// Description: The time zone in which schedules are interpreted -// Default: time.Local -// -// Parser -// Description: Parser converts cron spec strings into cron.Schedules. -// Default: Accepts this spec: https://en.wikipedia.org/wiki/Cron -// -// Chain -// Description: Wrap submitted jobs to customize behavior. -// Default: A chain that recovers panics and logs them to stderr. -// -// See "cron.With*" to modify the default behavior. -func New(opts ...Option) *Cron { - c := &Cron{ - entries: nil, - chain: NewChain(), - add: make(chan *Entry), - stop: make(chan struct{}), - snapshot: make(chan chan []Entry), - remove: make(chan EntryID), - running: false, - runningMu: sync.Mutex{}, - logger: DefaultLogger, - location: time.Local, - parser: standardParser, - } - for _, opt := range opts { - opt(c) - } - return c -} - -// FuncJob is a wrapper that turns a func() into a cron.Job -type FuncJob func() - -func (f FuncJob) Run() { f() } - -// AddFunc adds a func to the Cron to be run on the given schedule. -// The spec is parsed using the time zone of this Cron instance as the default. -// An opaque ID is returned that can be used to later remove it. -func (c *Cron) AddFunc(spec string, cmd func()) (EntryID, error) { - return c.AddJob(spec, FuncJob(cmd)) -} - -// AddJob adds a Job to the Cron to be run on the given schedule. -// The spec is parsed using the time zone of this Cron instance as the default. -// An opaque ID is returned that can be used to later remove it. -func (c *Cron) AddJob(spec string, cmd Job) (EntryID, error) { - schedule, err := c.parser.Parse(spec) - if err != nil { - return 0, err - } - return c.Schedule(schedule, cmd), nil -} - -// Schedule adds a Job to the Cron to be run on the given schedule. -// The job is wrapped with the configured Chain. -func (c *Cron) Schedule(schedule Schedule, cmd Job) EntryID { - c.runningMu.Lock() - defer c.runningMu.Unlock() - c.nextID++ - entry := &Entry{ - ID: c.nextID, - Schedule: schedule, - WrappedJob: c.chain.Then(cmd), - Job: cmd, - } - if !c.running { - c.entries = append(c.entries, entry) - } else { - c.add <- entry - } - return entry.ID -} - -// Entries returns a snapshot of the cron entries. -func (c *Cron) Entries() []Entry { - c.runningMu.Lock() - defer c.runningMu.Unlock() - if c.running { - replyChan := make(chan []Entry, 1) - c.snapshot <- replyChan - return <-replyChan - } - return c.entrySnapshot() -} - -// Location gets the time zone location -func (c *Cron) Location() *time.Location { - return c.location -} - -// Entry returns a snapshot of the given entry, or nil if it couldn't be found. -func (c *Cron) Entry(id EntryID) Entry { - for _, entry := range c.Entries() { - if id == entry.ID { - return entry - } - } - return Entry{} -} - -// Remove an entry from being run in the future. -func (c *Cron) Remove(id EntryID) { - c.runningMu.Lock() - defer c.runningMu.Unlock() - if c.running { - c.remove <- id - } else { - c.removeEntry(id) - } -} - -// Start the cron scheduler in its own goroutine, or no-op if already started. -func (c *Cron) Start() { - c.runningMu.Lock() - defer c.runningMu.Unlock() - if c.running { - return - } - c.running = true - go c.run() -} - -// Run the cron scheduler, or no-op if already running. -func (c *Cron) Run() { - c.runningMu.Lock() - if c.running { - c.runningMu.Unlock() - return - } - c.running = true - c.runningMu.Unlock() - c.run() -} - -// run the scheduler.. this is private just due to the need to synchronize -// access to the 'running' state variable. -func (c *Cron) run() { - c.logger.Info("start") - - // Figure out the next activation times for each entry. - now := c.now() - for _, entry := range c.entries { - entry.Next = entry.Schedule.Next(now) - c.logger.Info("schedule", "now", now, "entry", entry.ID, "next", entry.Next) - } - - for { - // Determine the next entry to run. - sort.Sort(byTime(c.entries)) - - var timer *time.Timer - if len(c.entries) == 0 || c.entries[0].Next.IsZero() { - // If there are no entries yet, just sleep - it still handles new entries - // and stop requests. - timer = time.NewTimer(100000 * time.Hour) - } else { - timer = time.NewTimer(c.entries[0].Next.Sub(now)) - } - - for { - select { - case now = <-timer.C: - now = now.In(c.location) - c.logger.Info("wake", "now", now) - - // Run every entry whose next time was less than now - for _, e := range c.entries { - if e.Next.After(now) || e.Next.IsZero() { - break - } - c.startJob(e.WrappedJob) - e.Prev = e.Next - e.Next = e.Schedule.Next(now) - c.logger.Info("run", "now", now, "entry", e.ID, "next", e.Next) - } - - case newEntry := <-c.add: - timer.Stop() - now = c.now() - newEntry.Next = newEntry.Schedule.Next(now) - c.entries = append(c.entries, newEntry) - c.logger.Info("added", "now", now, "entry", newEntry.ID, "next", newEntry.Next) - - case replyChan := <-c.snapshot: - replyChan <- c.entrySnapshot() - continue - - case <-c.stop: - timer.Stop() - c.logger.Info("stop") - return - - case id := <-c.remove: - timer.Stop() - now = c.now() - c.removeEntry(id) - c.logger.Info("removed", "entry", id) - } - - break - } - } -} - -// startJob runs the given job in a new goroutine. -func (c *Cron) startJob(j Job) { - c.jobWaiter.Add(1) - go func() { - defer c.jobWaiter.Done() - j.Run() - }() -} - -// now returns current time in c location -func (c *Cron) now() time.Time { - return time.Now().In(c.location) -} - -// Stop stops the cron scheduler if it is running; otherwise it does nothing. -// A context is returned so the caller can wait for running jobs to complete. -func (c *Cron) Stop() context.Context { - c.runningMu.Lock() - defer c.runningMu.Unlock() - if c.running { - c.stop <- struct{}{} - c.running = false - } - ctx, cancel := context.WithCancel(context.Background()) - go func() { - c.jobWaiter.Wait() - cancel() - }() - return ctx -} - -// entrySnapshot returns a copy of the current cron entry list. -func (c *Cron) entrySnapshot() []Entry { - var entries = make([]Entry, len(c.entries)) - for i, e := range c.entries { - entries[i] = *e - } - return entries -} - -func (c *Cron) removeEntry(id EntryID) { - var entries []*Entry - for _, e := range c.entries { - if e.ID != id { - entries = append(entries, e) - } - } - c.entries = entries -} diff --git a/vendor/github.com/robfig/cron/v3/doc.go b/vendor/github.com/robfig/cron/v3/doc.go deleted file mode 100644 index fa5d08b..0000000 --- a/vendor/github.com/robfig/cron/v3/doc.go +++ /dev/null @@ -1,231 +0,0 @@ -/* -Package cron implements a cron spec parser and job runner. - -Installation - -To download the specific tagged release, run: - - go get github.com/robfig/cron/v3@v3.0.0 - -Import it in your program as: - - import "github.com/robfig/cron/v3" - -It requires Go 1.11 or later due to usage of Go Modules. - -Usage - -Callers may register Funcs to be invoked on a given schedule. Cron will run -them in their own goroutines. - - c := cron.New() - c.AddFunc("30 * * * *", func() { fmt.Println("Every hour on the half hour") }) - c.AddFunc("30 3-6,20-23 * * *", func() { fmt.Println(".. in the range 3-6am, 8-11pm") }) - c.AddFunc("CRON_TZ=Asia/Tokyo 30 04 * * *", func() { fmt.Println("Runs at 04:30 Tokyo time every day") }) - c.AddFunc("@hourly", func() { fmt.Println("Every hour, starting an hour from now") }) - c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty, starting an hour thirty from now") }) - c.Start() - .. - // Funcs are invoked in their own goroutine, asynchronously. - ... - // Funcs may also be added to a running Cron - c.AddFunc("@daily", func() { fmt.Println("Every day") }) - .. - // Inspect the cron job entries' next and previous run times. - inspect(c.Entries()) - .. - c.Stop() // Stop the scheduler (does not stop any jobs already running). - -CRON Expression Format - -A cron expression represents a set of times, using 5 space-separated fields. - - Field name | Mandatory? | Allowed values | Allowed special characters - ---------- | ---------- | -------------- | -------------------------- - Minutes | Yes | 0-59 | * / , - - Hours | Yes | 0-23 | * / , - - Day of month | Yes | 1-31 | * / , - ? - Month | Yes | 1-12 or JAN-DEC | * / , - - Day of week | Yes | 0-6 or SUN-SAT | * / , - ? - -Month and Day-of-week field values are case insensitive. "SUN", "Sun", and -"sun" are equally accepted. - -The specific interpretation of the format is based on the Cron Wikipedia page: -https://en.wikipedia.org/wiki/Cron - -Alternative Formats - -Alternative Cron expression formats support other fields like seconds. You can -implement that by creating a custom Parser as follows. - - cron.New( - cron.WithParser( - cron.NewParser( - cron.SecondOptional | cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor))) - -Since adding Seconds is the most common modification to the standard cron spec, -cron provides a builtin function to do that, which is equivalent to the custom -parser you saw earlier, except that its seconds field is REQUIRED: - - cron.New(cron.WithSeconds()) - -That emulates Quartz, the most popular alternative Cron schedule format: -http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/crontrigger.html - -Special Characters - -Asterisk ( * ) - -The asterisk indicates that the cron expression will match for all values of the -field; e.g., using an asterisk in the 5th field (month) would indicate every -month. - -Slash ( / ) - -Slashes are used to describe increments of ranges. For example 3-59/15 in the -1st field (minutes) would indicate the 3rd minute of the hour and every 15 -minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...", -that is, an increment over the largest possible range of the field. The form -"N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the -increment until the end of that specific range. It does not wrap around. - -Comma ( , ) - -Commas are used to separate items of a list. For example, using "MON,WED,FRI" in -the 5th field (day of week) would mean Mondays, Wednesdays and Fridays. - -Hyphen ( - ) - -Hyphens are used to define ranges. For example, 9-17 would indicate every -hour between 9am and 5pm inclusive. - -Question mark ( ? ) - -Question mark may be used instead of '*' for leaving either day-of-month or -day-of-week blank. - -Predefined schedules - -You may use one of several pre-defined schedules in place of a cron expression. - - Entry | Description | Equivalent To - ----- | ----------- | ------------- - @yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 1 1 * - @monthly | Run once a month, midnight, first of month | 0 0 1 * * - @weekly | Run once a week, midnight between Sat/Sun | 0 0 * * 0 - @daily (or @midnight) | Run once a day, midnight | 0 0 * * * - @hourly | Run once an hour, beginning of hour | 0 * * * * - -Intervals - -You may also schedule a job to execute at fixed intervals, starting at the time it's added -or cron is run. This is supported by formatting the cron spec like this: - - @every - -where "duration" is a string accepted by time.ParseDuration -(http://golang.org/pkg/time/#ParseDuration). - -For example, "@every 1h30m10s" would indicate a schedule that activates after -1 hour, 30 minutes, 10 seconds, and then every interval after that. - -Note: The interval does not take the job runtime into account. For example, -if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes, -it will have only 2 minutes of idle time between each run. - -Time zones - -By default, all interpretation and scheduling is done in the machine's local -time zone (time.Local). You can specify a different time zone on construction: - - cron.New( - cron.WithLocation(time.UTC)) - -Individual cron schedules may also override the time zone they are to be -interpreted in by providing an additional space-separated field at the beginning -of the cron spec, of the form "CRON_TZ=Asia/Tokyo". - -For example: - - # Runs at 6am in time.Local - cron.New().AddFunc("0 6 * * ?", ...) - - # Runs at 6am in America/New_York - nyc, _ := time.LoadLocation("America/New_York") - c := cron.New(cron.WithLocation(nyc)) - c.AddFunc("0 6 * * ?", ...) - - # Runs at 6am in Asia/Tokyo - cron.New().AddFunc("CRON_TZ=Asia/Tokyo 0 6 * * ?", ...) - - # Runs at 6am in Asia/Tokyo - c := cron.New(cron.WithLocation(nyc)) - c.SetLocation("America/New_York") - c.AddFunc("CRON_TZ=Asia/Tokyo 0 6 * * ?", ...) - -The prefix "TZ=(TIME ZONE)" is also supported for legacy compatibility. - -Be aware that jobs scheduled during daylight-savings leap-ahead transitions will -not be run! - -Job Wrappers - -A Cron runner may be configured with a chain of job wrappers to add -cross-cutting functionality to all submitted jobs. For example, they may be used -to achieve the following effects: - - - Recover any panics from jobs (activated by default) - - Delay a job's execution if the previous run hasn't completed yet - - Skip a job's execution if the previous run hasn't completed yet - - Log each job's invocations - -Install wrappers for all jobs added to a cron using the `cron.WithChain` option: - - cron.New(cron.WithChain( - cron.SkipIfStillRunning(logger), - )) - -Install wrappers for individual jobs by explicitly wrapping them: - - job = cron.NewChain( - cron.SkipIfStillRunning(logger), - ).Then(job) - -Thread safety - -Since the Cron service runs concurrently with the calling code, some amount of -care must be taken to ensure proper synchronization. - -All cron methods are designed to be correctly synchronized as long as the caller -ensures that invocations have a clear happens-before ordering between them. - -Logging - -Cron defines a Logger interface that is a subset of the one defined in -github.com/go-logr/logr. It has two logging levels (Info and Error), and -parameters are key/value pairs. This makes it possible for cron logging to plug -into structured logging systems. An adapter, [Verbose]PrintfLogger, is provided -to wrap the standard library *log.Logger. - -For additional insight into Cron operations, verbose logging may be activated -which will record job runs, scheduling decisions, and added or removed jobs. -Activate it with a one-off logger as follows: - - cron.New( - cron.WithLogger( - cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags)))) - - -Implementation - -Cron entries are stored in an array, sorted by their next activation time. Cron -sleeps until the next job is due to be run. - -Upon waking: - - it runs each entry that is active on that second - - it calculates the next run times for the jobs that were run - - it re-sorts the array of entries by next activation time. - - it goes to sleep until the soonest job. -*/ -package cron diff --git a/vendor/github.com/robfig/cron/v3/logger.go b/vendor/github.com/robfig/cron/v3/logger.go deleted file mode 100644 index b4efcc0..0000000 --- a/vendor/github.com/robfig/cron/v3/logger.go +++ /dev/null @@ -1,86 +0,0 @@ -package cron - -import ( - "io/ioutil" - "log" - "os" - "strings" - "time" -) - -// DefaultLogger is used by Cron if none is specified. -var DefaultLogger Logger = PrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags)) - -// DiscardLogger can be used by callers to discard all log messages. -var DiscardLogger Logger = PrintfLogger(log.New(ioutil.Discard, "", 0)) - -// Logger is the interface used in this package for logging, so that any backend -// can be plugged in. It is a subset of the github.com/go-logr/logr interface. -type Logger interface { - // Info logs routine messages about cron's operation. - Info(msg string, keysAndValues ...interface{}) - // Error logs an error condition. - Error(err error, msg string, keysAndValues ...interface{}) -} - -// PrintfLogger wraps a Printf-based logger (such as the standard library "log") -// into an implementation of the Logger interface which logs errors only. -func PrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger { - return printfLogger{l, false} -} - -// VerbosePrintfLogger wraps a Printf-based logger (such as the standard library -// "log") into an implementation of the Logger interface which logs everything. -func VerbosePrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger { - return printfLogger{l, true} -} - -type printfLogger struct { - logger interface{ Printf(string, ...interface{}) } - logInfo bool -} - -func (pl printfLogger) Info(msg string, keysAndValues ...interface{}) { - if pl.logInfo { - keysAndValues = formatTimes(keysAndValues) - pl.logger.Printf( - formatString(len(keysAndValues)), - append([]interface{}{msg}, keysAndValues...)...) - } -} - -func (pl printfLogger) Error(err error, msg string, keysAndValues ...interface{}) { - keysAndValues = formatTimes(keysAndValues) - pl.logger.Printf( - formatString(len(keysAndValues)+2), - append([]interface{}{msg, "error", err}, keysAndValues...)...) -} - -// formatString returns a logfmt-like format string for the number of -// key/values. -func formatString(numKeysAndValues int) string { - var sb strings.Builder - sb.WriteString("%s") - if numKeysAndValues > 0 { - sb.WriteString(", ") - } - for i := 0; i < numKeysAndValues/2; i++ { - if i > 0 { - sb.WriteString(", ") - } - sb.WriteString("%v=%v") - } - return sb.String() -} - -// formatTimes formats any time.Time values as RFC3339. -func formatTimes(keysAndValues []interface{}) []interface{} { - var formattedArgs []interface{} - for _, arg := range keysAndValues { - if t, ok := arg.(time.Time); ok { - arg = t.Format(time.RFC3339) - } - formattedArgs = append(formattedArgs, arg) - } - return formattedArgs -} diff --git a/vendor/github.com/robfig/cron/v3/option.go b/vendor/github.com/robfig/cron/v3/option.go deleted file mode 100644 index 09e4278..0000000 --- a/vendor/github.com/robfig/cron/v3/option.go +++ /dev/null @@ -1,45 +0,0 @@ -package cron - -import ( - "time" -) - -// Option represents a modification to the default behavior of a Cron. -type Option func(*Cron) - -// WithLocation overrides the timezone of the cron instance. -func WithLocation(loc *time.Location) Option { - return func(c *Cron) { - c.location = loc - } -} - -// WithSeconds overrides the parser used for interpreting job schedules to -// include a seconds field as the first one. -func WithSeconds() Option { - return WithParser(NewParser( - Second | Minute | Hour | Dom | Month | Dow | Descriptor, - )) -} - -// WithParser overrides the parser used for interpreting job schedules. -func WithParser(p ScheduleParser) Option { - return func(c *Cron) { - c.parser = p - } -} - -// WithChain specifies Job wrappers to apply to all jobs added to this cron. -// Refer to the Chain* functions in this package for provided wrappers. -func WithChain(wrappers ...JobWrapper) Option { - return func(c *Cron) { - c.chain = NewChain(wrappers...) - } -} - -// WithLogger uses the provided logger. -func WithLogger(logger Logger) Option { - return func(c *Cron) { - c.logger = logger - } -} diff --git a/vendor/github.com/robfig/cron/v3/parser.go b/vendor/github.com/robfig/cron/v3/parser.go deleted file mode 100644 index 3cf8879..0000000 --- a/vendor/github.com/robfig/cron/v3/parser.go +++ /dev/null @@ -1,434 +0,0 @@ -package cron - -import ( - "fmt" - "math" - "strconv" - "strings" - "time" -) - -// Configuration options for creating a parser. Most options specify which -// fields should be included, while others enable features. If a field is not -// included the parser will assume a default value. These options do not change -// the order fields are parse in. -type ParseOption int - -const ( - Second ParseOption = 1 << iota // Seconds field, default 0 - SecondOptional // Optional seconds field, default 0 - Minute // Minutes field, default 0 - Hour // Hours field, default 0 - Dom // Day of month field, default * - Month // Month field, default * - Dow // Day of week field, default * - DowOptional // Optional day of week field, default * - Descriptor // Allow descriptors such as @monthly, @weekly, etc. -) - -var places = []ParseOption{ - Second, - Minute, - Hour, - Dom, - Month, - Dow, -} - -var defaults = []string{ - "0", - "0", - "0", - "*", - "*", - "*", -} - -// A custom Parser that can be configured. -type Parser struct { - options ParseOption -} - -// NewParser creates a Parser with custom options. -// -// It panics if more than one Optional is given, since it would be impossible to -// correctly infer which optional is provided or missing in general. -// -// Examples -// -// // Standard parser without descriptors -// specParser := NewParser(Minute | Hour | Dom | Month | Dow) -// sched, err := specParser.Parse("0 0 15 */3 *") -// -// // Same as above, just excludes time fields -// subsParser := NewParser(Dom | Month | Dow) -// sched, err := specParser.Parse("15 */3 *") -// -// // Same as above, just makes Dow optional -// subsParser := NewParser(Dom | Month | DowOptional) -// sched, err := specParser.Parse("15 */3") -// -func NewParser(options ParseOption) Parser { - optionals := 0 - if options&DowOptional > 0 { - optionals++ - } - if options&SecondOptional > 0 { - optionals++ - } - if optionals > 1 { - panic("multiple optionals may not be configured") - } - return Parser{options} -} - -// Parse returns a new crontab schedule representing the given spec. -// It returns a descriptive error if the spec is not valid. -// It accepts crontab specs and features configured by NewParser. -func (p Parser) Parse(spec string) (Schedule, error) { - if len(spec) == 0 { - return nil, fmt.Errorf("empty spec string") - } - - // Extract timezone if present - var loc = time.Local - if strings.HasPrefix(spec, "TZ=") || strings.HasPrefix(spec, "CRON_TZ=") { - var err error - i := strings.Index(spec, " ") - eq := strings.Index(spec, "=") - if loc, err = time.LoadLocation(spec[eq+1 : i]); err != nil { - return nil, fmt.Errorf("provided bad location %s: %v", spec[eq+1:i], err) - } - spec = strings.TrimSpace(spec[i:]) - } - - // Handle named schedules (descriptors), if configured - if strings.HasPrefix(spec, "@") { - if p.options&Descriptor == 0 { - return nil, fmt.Errorf("parser does not accept descriptors: %v", spec) - } - return parseDescriptor(spec, loc) - } - - // Split on whitespace. - fields := strings.Fields(spec) - - // Validate & fill in any omitted or optional fields - var err error - fields, err = normalizeFields(fields, p.options) - if err != nil { - return nil, err - } - - field := func(field string, r bounds) uint64 { - if err != nil { - return 0 - } - var bits uint64 - bits, err = getField(field, r) - return bits - } - - var ( - second = field(fields[0], seconds) - minute = field(fields[1], minutes) - hour = field(fields[2], hours) - dayofmonth = field(fields[3], dom) - month = field(fields[4], months) - dayofweek = field(fields[5], dow) - ) - if err != nil { - return nil, err - } - - return &SpecSchedule{ - Second: second, - Minute: minute, - Hour: hour, - Dom: dayofmonth, - Month: month, - Dow: dayofweek, - Location: loc, - }, nil -} - -// normalizeFields takes a subset set of the time fields and returns the full set -// with defaults (zeroes) populated for unset fields. -// -// As part of performing this function, it also validates that the provided -// fields are compatible with the configured options. -func normalizeFields(fields []string, options ParseOption) ([]string, error) { - // Validate optionals & add their field to options - optionals := 0 - if options&SecondOptional > 0 { - options |= Second - optionals++ - } - if options&DowOptional > 0 { - options |= Dow - optionals++ - } - if optionals > 1 { - return nil, fmt.Errorf("multiple optionals may not be configured") - } - - // Figure out how many fields we need - max := 0 - for _, place := range places { - if options&place > 0 { - max++ - } - } - min := max - optionals - - // Validate number of fields - if count := len(fields); count < min || count > max { - if min == max { - return nil, fmt.Errorf("expected exactly %d fields, found %d: %s", min, count, fields) - } - return nil, fmt.Errorf("expected %d to %d fields, found %d: %s", min, max, count, fields) - } - - // Populate the optional field if not provided - if min < max && len(fields) == min { - switch { - case options&DowOptional > 0: - fields = append(fields, defaults[5]) // TODO: improve access to default - case options&SecondOptional > 0: - fields = append([]string{defaults[0]}, fields...) - default: - return nil, fmt.Errorf("unknown optional field") - } - } - - // Populate all fields not part of options with their defaults - n := 0 - expandedFields := make([]string, len(places)) - copy(expandedFields, defaults) - for i, place := range places { - if options&place > 0 { - expandedFields[i] = fields[n] - n++ - } - } - return expandedFields, nil -} - -var standardParser = NewParser( - Minute | Hour | Dom | Month | Dow | Descriptor, -) - -// ParseStandard returns a new crontab schedule representing the given -// standardSpec (https://en.wikipedia.org/wiki/Cron). It requires 5 entries -// representing: minute, hour, day of month, month and day of week, in that -// order. It returns a descriptive error if the spec is not valid. -// -// It accepts -// - Standard crontab specs, e.g. "* * * * ?" -// - Descriptors, e.g. "@midnight", "@every 1h30m" -func ParseStandard(standardSpec string) (Schedule, error) { - return standardParser.Parse(standardSpec) -} - -// getField returns an Int with the bits set representing all of the times that -// the field represents or error parsing field value. A "field" is a comma-separated -// list of "ranges". -func getField(field string, r bounds) (uint64, error) { - var bits uint64 - ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' }) - for _, expr := range ranges { - bit, err := getRange(expr, r) - if err != nil { - return bits, err - } - bits |= bit - } - return bits, nil -} - -// getRange returns the bits indicated by the given expression: -// number | number "-" number [ "/" number ] -// or error parsing range. -func getRange(expr string, r bounds) (uint64, error) { - var ( - start, end, step uint - rangeAndStep = strings.Split(expr, "/") - lowAndHigh = strings.Split(rangeAndStep[0], "-") - singleDigit = len(lowAndHigh) == 1 - err error - ) - - var extra uint64 - if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" { - start = r.min - end = r.max - extra = starBit - } else { - start, err = parseIntOrName(lowAndHigh[0], r.names) - if err != nil { - return 0, err - } - switch len(lowAndHigh) { - case 1: - end = start - case 2: - end, err = parseIntOrName(lowAndHigh[1], r.names) - if err != nil { - return 0, err - } - default: - return 0, fmt.Errorf("too many hyphens: %s", expr) - } - } - - switch len(rangeAndStep) { - case 1: - step = 1 - case 2: - step, err = mustParseInt(rangeAndStep[1]) - if err != nil { - return 0, err - } - - // Special handling: "N/step" means "N-max/step". - if singleDigit { - end = r.max - } - if step > 1 { - extra = 0 - } - default: - return 0, fmt.Errorf("too many slashes: %s", expr) - } - - if start < r.min { - return 0, fmt.Errorf("beginning of range (%d) below minimum (%d): %s", start, r.min, expr) - } - if end > r.max { - return 0, fmt.Errorf("end of range (%d) above maximum (%d): %s", end, r.max, expr) - } - if start > end { - return 0, fmt.Errorf("beginning of range (%d) beyond end of range (%d): %s", start, end, expr) - } - if step == 0 { - return 0, fmt.Errorf("step of range should be a positive number: %s", expr) - } - - return getBits(start, end, step) | extra, nil -} - -// parseIntOrName returns the (possibly-named) integer contained in expr. -func parseIntOrName(expr string, names map[string]uint) (uint, error) { - if names != nil { - if namedInt, ok := names[strings.ToLower(expr)]; ok { - return namedInt, nil - } - } - return mustParseInt(expr) -} - -// mustParseInt parses the given expression as an int or returns an error. -func mustParseInt(expr string) (uint, error) { - num, err := strconv.Atoi(expr) - if err != nil { - return 0, fmt.Errorf("failed to parse int from %s: %s", expr, err) - } - if num < 0 { - return 0, fmt.Errorf("negative number (%d) not allowed: %s", num, expr) - } - - return uint(num), nil -} - -// getBits sets all bits in the range [min, max], modulo the given step size. -func getBits(min, max, step uint) uint64 { - var bits uint64 - - // If step is 1, use shifts. - if step == 1 { - return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min) - } - - // Else, use a simple loop. - for i := min; i <= max; i += step { - bits |= 1 << i - } - return bits -} - -// all returns all bits within the given bounds. (plus the star bit) -func all(r bounds) uint64 { - return getBits(r.min, r.max, 1) | starBit -} - -// parseDescriptor returns a predefined schedule for the expression, or error if none matches. -func parseDescriptor(descriptor string, loc *time.Location) (Schedule, error) { - switch descriptor { - case "@yearly", "@annually": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: 1 << hours.min, - Dom: 1 << dom.min, - Month: 1 << months.min, - Dow: all(dow), - Location: loc, - }, nil - - case "@monthly": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: 1 << hours.min, - Dom: 1 << dom.min, - Month: all(months), - Dow: all(dow), - Location: loc, - }, nil - - case "@weekly": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: 1 << hours.min, - Dom: all(dom), - Month: all(months), - Dow: 1 << dow.min, - Location: loc, - }, nil - - case "@daily", "@midnight": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: 1 << hours.min, - Dom: all(dom), - Month: all(months), - Dow: all(dow), - Location: loc, - }, nil - - case "@hourly": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: all(hours), - Dom: all(dom), - Month: all(months), - Dow: all(dow), - Location: loc, - }, nil - - } - - const every = "@every " - if strings.HasPrefix(descriptor, every) { - duration, err := time.ParseDuration(descriptor[len(every):]) - if err != nil { - return nil, fmt.Errorf("failed to parse duration %s: %s", descriptor, err) - } - return Every(duration), nil - } - - return nil, fmt.Errorf("unrecognized descriptor: %s", descriptor) -} diff --git a/vendor/github.com/robfig/cron/v3/spec.go b/vendor/github.com/robfig/cron/v3/spec.go deleted file mode 100644 index fa1e241..0000000 --- a/vendor/github.com/robfig/cron/v3/spec.go +++ /dev/null @@ -1,188 +0,0 @@ -package cron - -import "time" - -// SpecSchedule specifies a duty cycle (to the second granularity), based on a -// traditional crontab specification. It is computed initially and stored as bit sets. -type SpecSchedule struct { - Second, Minute, Hour, Dom, Month, Dow uint64 - - // Override location for this schedule. - Location *time.Location -} - -// bounds provides a range of acceptable values (plus a map of name to value). -type bounds struct { - min, max uint - names map[string]uint -} - -// The bounds for each field. -var ( - seconds = bounds{0, 59, nil} - minutes = bounds{0, 59, nil} - hours = bounds{0, 23, nil} - dom = bounds{1, 31, nil} - months = bounds{1, 12, map[string]uint{ - "jan": 1, - "feb": 2, - "mar": 3, - "apr": 4, - "may": 5, - "jun": 6, - "jul": 7, - "aug": 8, - "sep": 9, - "oct": 10, - "nov": 11, - "dec": 12, - }} - dow = bounds{0, 6, map[string]uint{ - "sun": 0, - "mon": 1, - "tue": 2, - "wed": 3, - "thu": 4, - "fri": 5, - "sat": 6, - }} -) - -const ( - // Set the top bit if a star was included in the expression. - starBit = 1 << 63 -) - -// Next returns the next time this schedule is activated, greater than the given -// time. If no time can be found to satisfy the schedule, return the zero time. -func (s *SpecSchedule) Next(t time.Time) time.Time { - // General approach - // - // For Month, Day, Hour, Minute, Second: - // Check if the time value matches. If yes, continue to the next field. - // If the field doesn't match the schedule, then increment the field until it matches. - // While incrementing the field, a wrap-around brings it back to the beginning - // of the field list (since it is necessary to re-verify previous field - // values) - - // Convert the given time into the schedule's timezone, if one is specified. - // Save the original timezone so we can convert back after we find a time. - // Note that schedules without a time zone specified (time.Local) are treated - // as local to the time provided. - origLocation := t.Location() - loc := s.Location - if loc == time.Local { - loc = t.Location() - } - if s.Location != time.Local { - t = t.In(s.Location) - } - - // Start at the earliest possible time (the upcoming second). - t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond) - - // This flag indicates whether a field has been incremented. - added := false - - // If no time is found within five years, return zero. - yearLimit := t.Year() + 5 - -WRAP: - if t.Year() > yearLimit { - return time.Time{} - } - - // Find the first applicable month. - // If it's this month, then do nothing. - for 1< 12 { - t = t.Add(time.Duration(24-t.Hour()) * time.Hour) - } else { - t = t.Add(time.Duration(-t.Hour()) * time.Hour) - } - } - - if t.Day() == 1 { - goto WRAP - } - } - - for 1< 0 - dowMatch bool = 1< 0 - ) - if s.Dom&starBit > 0 || s.Dow&starBit > 0 { - return domMatch && dowMatch - } - return domMatch || dowMatch -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 198a56d..d67e4e0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -76,9 +76,6 @@ github.com/lxn/win ## explicit; go 1.22 github.com/playwright-community/playwright-go github.com/playwright-community/playwright-go/internal/safe -# github.com/robfig/cron/v3 v3.0.1 -## explicit; go 1.12 -github.com/robfig/cron/v3 # github.com/stretchr/testify v1.9.0 ## explicit; go 1.17 # github.com/super-l/machine-code v0.0.0-20241121142923-4cb40646deba