ZeroBot-Plugin/manager/timer.go
2021-06-06 01:19:48 +08:00

201 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package manager
import (
"fmt"
"os"
"strconv"
"strings"
"time"
"unicode"
tm "github.com/Yiwen-Chan/ZeroBot-Plugin/api/timer"
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/utils"
)
type TimeStamp = tm.Timer
var (
//记录每个定时器以便取消
timersmap tm.TimersMap
timers = timersmap.Timers
//定时器存储位置
BOTPATH = utils.PathExecute() // 当前bot运行目录
DATAPATH = BOTPATH + "data/manager/" // 数据目录
PBFILE = DATAPATH + "timers.pb"
)
func init() {
utils.CreatePath(DATAPATH)
}
func timer(ts TimeStamp, onTimeReached func()) {
key := getTimerInfo(&ts)
fmt.Printf("[群管]注册计时器: %s\n", key)
t, ok := timers[key]
if ok { //避免重复注册定时器
t.Enable = false
}
timers[key] = &ts
saveTimers()
judgeHM := func() {
if ts.Hour < 0 || ts.Hour == int32(time.Now().Hour()) {
if ts.Minute < 0 || ts.Minute == int32(time.Now().Minute()) {
onTimeReached()
}
}
}
for ts.Enable {
if ts.Month < 0 || ts.Month == int32(time.Now().Month()) {
if ts.Day < 0 || ts.Day == int32(time.Now().Day()) {
judgeHM()
} else if ts.Day == 0 {
if ts.Week < 0 || ts.Week == int32(time.Now().Weekday()) {
judgeHM()
}
}
}
time.Sleep(time.Minute)
}
}
func saveTimers() error {
data, err := timersmap.Marshal()
if err != nil {
return err
} else if utils.PathExists(DATAPATH) {
f, err1 := os.OpenFile(PBFILE, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 != nil {
return err1
} else {
defer f.Close()
_, err2 := f.Write(data)
return err2
}
} else {
return nil
}
}
//获得标准化定时字符串
func getTimerInfo(ts *TimeStamp) string {
return fmt.Sprintf("%d月%d日%d周%d:%d", ts.Month, ts.Day, ts.Week, ts.Hour, ts.Minute)
}
//获得填充好的ts
func getFilledTimeStamp(dateStrs []string, matchDateOnly bool) TimeStamp {
monthStr := []rune(dateStrs[1])
dayWeekStr := []rune(dateStrs[2])
hourStr := []rune(dateStrs[3])
minuteStr := []rune(dateStrs[4])
var ts TimeStamp
ts.Month = chineseNum2Int(monthStr)
if (ts.Month != -1 && ts.Month <= 0) || ts.Month > 12 { //月份非法
fmt.Println("[群管]月份非法!")
return ts
}
lenOfDW := len(dayWeekStr)
if lenOfDW == 4 { //包括末尾的"日"
dayWeekStr = []rune{dayWeekStr[0], dayWeekStr[2]} //去除中间的十
ts.Day = chineseNum2Int(dayWeekStr)
if (ts.Day != -1 && ts.Day <= 0) || ts.Day > 31 { //日期非法
fmt.Println("[群管]日期非法1")
return ts
}
} else if dayWeekStr[lenOfDW-1] == rune('日') { //xx日
dayWeekStr = dayWeekStr[:lenOfDW-1]
ts.Day = chineseNum2Int(dayWeekStr)
if (ts.Day != -1 && ts.Day <= 0) || ts.Day > 31 { //日期非法
fmt.Println("[群管]日期非法2")
return ts
}
} else if dayWeekStr[0] == rune('每') { //每周
ts.Week = -1
} else { //周x
ts.Week = chineseNum2Int(dayWeekStr[1:])
if ts.Week == 7 { //周天是0
ts.Week = 0
}
if ts.Week < 0 || ts.Week > 6 { //星期非法
ts.Week = -11
fmt.Println("[群管]星期非法!")
return ts
}
}
if len(hourStr) == 3 {
hourStr = []rune{hourStr[0], hourStr[2]} //去除中间的十
}
ts.Hour = chineseNum2Int(hourStr)
if ts.Hour < -1 || ts.Hour > 23 { //小时非法
fmt.Println("[群管]小时非法!")
return ts
}
if len(minuteStr) == 3 {
minuteStr = []rune{minuteStr[0], minuteStr[2]} //去除中间的十
}
ts.Minute = chineseNum2Int(minuteStr)
if ts.Minute < -1 || ts.Minute > 59 { //分钟非法
fmt.Println("[群管]分钟非法!")
return ts
}
if !matchDateOnly {
urlStr := dateStrs[5]
if urlStr != "" { //是图片url
ts.Url = urlStr[3:] //utf-8下用为3字节
fmt.Println("[群管]" + ts.Url)
if !strings.HasPrefix(ts.Url, "http") {
ts.Url = "illegal"
fmt.Println("[群管]url非法")
return ts
}
}
ts.Alert = dateStrs[6]
ts.Enable = true
}
return ts
}
//汉字数字转int仅支持-1099最多两位数其中"每"解释为-1"每两"为-2以此类推
func chineseNum2Int(rs []rune) int32 {
r := -1
l := len(rs)
mai := rune('每')
if unicode.IsDigit(rs[0]) { //默认可能存在的第二位也为int
r, _ = strconv.Atoi(string(rs))
} else {
if rs[0] == mai {
if l == 2 {
r = -chineseChar2Int(rs[1])
}
} else if l == 1 {
r = chineseChar2Int(rs[0])
} else {
ten := chineseChar2Int(rs[0])
if ten != 10 {
ten *= 10
}
ge := chineseChar2Int(rs[1])
if ge == 10 {
ge = 0
}
r = ten + ge
}
}
return int32(r)
}
//处理单个字符的映射0~10
func chineseChar2Int(c rune) int {
if c == rune('日') || c == rune('天') { //周日/周天
return 7
} else {
match := []rune("零一二三四五六七八九十")
for i, m := range match {
if c == m {
return i
}
}
return 0
}
}