197 lines
4.7 KiB
Go
197 lines
4.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
type config struct {
|
|
Jobs []jobconfig `yaml:"jobs"`
|
|
Notification []notificationConfig `yaml:"notification"`
|
|
}
|
|
|
|
type jobconfig struct {
|
|
Name string `yaml:"name"`
|
|
Hour string `yaml:"hour"`
|
|
Minute string `yaml:"minute"`
|
|
Weekday string `yaml:"weekday"`
|
|
Command string `yaml:"command"`
|
|
Notification string `yaml:"notification,omitempty"`
|
|
}
|
|
|
|
type notificationConfig struct {
|
|
Name string `yaml:"name"`
|
|
Success notification `yaml:"success,omitempty"`
|
|
Error notification `yaml:"error,omitempty"`
|
|
}
|
|
|
|
type notification struct {
|
|
Gotify gotifyConfig `yaml:"gotify,omitempty"`
|
|
Smtp smtpConfig `yaml:"smtp,omitempty"`
|
|
}
|
|
|
|
type gotifyConfig struct {
|
|
URL string `yaml:"url"`
|
|
}
|
|
|
|
type smtpConfig struct {
|
|
Host string `yaml:"host"`
|
|
Port int `yaml:"port"`
|
|
Username string `yaml:"username,omitempty"`
|
|
Password string `yaml:"password,omitempty"`
|
|
From string `yaml:"from"`
|
|
To string `yaml:"to"`
|
|
UseSSL bool `yaml:"use_ssl,omitempty"`
|
|
}
|
|
|
|
func ReadFromFile(path string) (config, error) {
|
|
f, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return config{}, fmt.Errorf(ErrWrapTemplate, ErrCantReadConfigFile, err)
|
|
}
|
|
|
|
c := config{}
|
|
err = yaml.Unmarshal(f, &c)
|
|
if err != nil {
|
|
return config{}, fmt.Errorf(ErrWrapTemplate, ErrCantParseConfigFile, err)
|
|
}
|
|
|
|
return c, nil
|
|
}
|
|
|
|
func (jc jobconfig) MatchCurrentTime(t time.Time) (bool, error) {
|
|
fmt.Println("weekday", jc.Weekday)
|
|
matchWeekDay, err := matchTime(jc.Weekday, int(t.Weekday()))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !matchWeekDay {
|
|
return false, nil
|
|
}
|
|
|
|
matchHour, err := matchTime(jc.Hour, t.Hour())
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !matchHour {
|
|
return false, nil
|
|
}
|
|
|
|
matchMinute, err := matchTime(jc.Minute, t.Minute())
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !matchMinute {
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func matchTime(pattern string, currentValue int) (bool, error) {
|
|
pattern = strings.TrimSpace(pattern)
|
|
log.Debug().Str("pattern", pattern).Int("currentValue", currentValue).Msg("Check if Pattern match current Value")
|
|
// All numbers
|
|
if pattern == "*" {
|
|
return true, nil
|
|
}
|
|
|
|
// Multible arguments
|
|
details := strings.Split(pattern, ",")
|
|
if len(details) > 1 {
|
|
for i := range details {
|
|
res, err := matchTime(details[i], currentValue)
|
|
if err != nil {
|
|
return false, fmt.Errorf(ErrWrapTemplate, ErrCantParseTimePattern, err)
|
|
}
|
|
if res {
|
|
return res, nil
|
|
}
|
|
}
|
|
|
|
return false, nil // Non of the part match so nothing will match
|
|
}
|
|
// Singel number
|
|
valueAsInt, err := strconv.Atoi(pattern)
|
|
if err == nil {
|
|
if valueAsInt == currentValue {
|
|
return true, nil
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
// Normal ranges no ranges with defision
|
|
if strings.Contains(pattern, "-") && !strings.Contains(pattern, "/") {
|
|
smallNumber, largeNumber, err := getNumbersOfRange(pattern)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if smallNumber < currentValue && largeNumber > currentValue {
|
|
return true, nil
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
if strings.Contains(pattern, "/") {
|
|
numbers := strings.Split(pattern, "/")
|
|
if len(numbers) != 2 {
|
|
return false, fmt.Errorf(ErrWrapTemplate, ErrCantParseTimePattern, "pattern dont include 2 numbers")
|
|
}
|
|
numberDivisor, err := strconv.Atoi(numbers[1])
|
|
if err != nil {
|
|
return false, fmt.Errorf(ErrWrapTemplate, ErrCantParseTimePattern, err)
|
|
}
|
|
if numbers[0] == "*" {
|
|
res := currentValue % numberDivisor
|
|
if res == 0 {
|
|
return true, nil
|
|
}
|
|
return false, nil
|
|
}
|
|
if strings.Contains(numbers[0], "-") {
|
|
smallNumber, largeNumber, err := getNumbersOfRange(numbers[0])
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !(smallNumber < currentValue && largeNumber > currentValue) {
|
|
return false, nil
|
|
}
|
|
|
|
newValue := currentValue - smallNumber
|
|
res := newValue % numberDivisor
|
|
if res == 0 {
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
}
|
|
|
|
// Cant Parse the time
|
|
return false, ErrCantParseTimePattern
|
|
}
|
|
|
|
func getNumbersOfRange(pattern string) (int, int, error) {
|
|
numbers := strings.Split(pattern, "-")
|
|
if len(numbers) != 2 {
|
|
return 0, 0, fmt.Errorf(ErrWrapTemplate, ErrCantParseTimePattern, "range include more than 2 parameter")
|
|
}
|
|
smallNumber, err := strconv.Atoi(strings.TrimSpace(numbers[0]))
|
|
if err != nil {
|
|
return 0, 0, fmt.Errorf(ErrWrapTemplate, ErrCantParseTimePattern, err)
|
|
}
|
|
largeNumber, err := strconv.Atoi(strings.TrimSpace(numbers[1]))
|
|
if err != nil {
|
|
return 0, 0, fmt.Errorf(ErrWrapTemplate, ErrCantParseTimePattern, err)
|
|
}
|
|
if smallNumber >= largeNumber {
|
|
return 0, 0, fmt.Errorf(ErrWrapTemplate, ErrCantParseTimePattern, "smaler number should be first")
|
|
}
|
|
return smallNumber, largeNumber, nil
|
|
}
|