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