Merge pull request #19 from fumiama/master

群管增加定时提醒功能
This commit is contained in:
Kanri 2021-05-09 22:36:11 -05:00 committed by GitHub
commit d1beead157
4 changed files with 196 additions and 0 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
data/chat/*
data/SetuTime/cache/*
main.exe
.DS_Store

View File

@ -45,6 +45,10 @@
- [x] 退出群聊[群号]
- [x] *入群欢迎
- [x] *退群通知
- [x] 在[月份]月[日期]日的[小时]点[分钟]分时(用[url])提醒大家[消息]
- [x] 在[月份]月[每周or周几]的[小时]点[分钟]分时(用[url])提醒大家[消息]
- [x] 取消在[月份]月[日期]日的[小时]点[分钟]分的提醒
- [x] 取消在[月份]月[每周or周几]的[小时]点[分钟]分的提醒
- [ ] 同意入群请求
- [ ] 同意好友请求
- [ ] 撤回[@xxx] [xxx]

View File

@ -230,6 +230,37 @@ func init() { // 插件主体
ctx.SendChain(message.Text("📧 --> " + ctx.State["regex_matched"].([]string)[1]))
return
})
// 定时提醒
zero.OnRegex(`^在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分时(用.+)?提醒大家(.*)`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
ts := getFilledTimeStamp(dateStrs, false)
go timer(ts, func() {
if ts.url == "" {
ctx.SendChain(AtAll(), message.Text(ts.alert))
} else {
ctx.SendChain(AtAll(), message.Text(ts.alert), ImageNoCache(ts.url))
}
})
ctx.Send("记住了~")
return
})
// 取消定时
zero.OnRegex(`^取消在(.{1,2})月(.{1,3}日|每?周.?)的(.{1,3})点(.{1,3})分的提醒`, zero.SuperUserPermission).SetBlock(true).SetPriority(40).
Handle(func(ctx *zero.Ctx) {
dateStrs := ctx.State["regex_matched"].([]string)
ts := getFilledTimeStamp(dateStrs, true)
ti := getTimerInfo(&ts)
t, ok := timers[ti]
if ok {
t.enable = false
delete(timers, ti) //避免重复取消
ctx.Send("取消成功~")
} else {
ctx.Send("没有这个定时器哦~")
}
return
})
// 入群欢迎
zero.OnNotice().SetBlock(false).SetPriority(40).
Handle(func(ctx *zero.Ctx) {

160
manager/timer.go Normal file
View File

@ -0,0 +1,160 @@
package manager
import (
"fmt"
"strconv"
"strings"
"time"
"unicode"
"github.com/wdvxdr1123/ZeroBot/message"
)
type TimeStamp struct {
enable bool
alert string
url string
month int8
day int8
week int8
hour int8
minute int8
}
//记录每个定时器以便取消
var timers = make(map[string]*TimeStamp)
func timer(ts TimeStamp, onTimeReached func()) {
key := getTimerInfo(&ts)
fmt.Printf("注册计时器: %s\n", key)
timers[key] = &ts
judgeHM := func() {
if ts.hour < 0 || ts.hour == int8(time.Now().Hour()) {
if ts.minute < 0 || ts.minute == int8(time.Now().Minute()) {
onTimeReached()
}
}
}
for ts.enable {
if ts.month < 0 || ts.month == int8(time.Now().Month()) {
if ts.day < 0 || ts.day == int8(time.Now().Day()) {
judgeHM()
} else if ts.day == 0 {
if ts.week < 0 || ts.week == int8(time.Now().Weekday()) {
judgeHM()
}
}
}
time.Sleep(time.Minute)
}
}
//获得标准化定时字符串
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)
lenOfDW := len(dayWeekStr)
if lenOfDW == 4 { //包括末尾的"日"
dayWeekStr = []rune{dayWeekStr[0], dayWeekStr[2]} //去除中间的十
ts.day = chineseNum2Int(dayWeekStr)
} else if dayWeekStr[lenOfDW-1] == rune('日') { //xx日
dayWeekStr = dayWeekStr[:lenOfDW-1]
ts.day = chineseNum2Int(dayWeekStr)
} else if dayWeekStr[0] == rune('每') { //每周
ts.week = -1
} else { //周x
ts.week = chineseNum2Int(dayWeekStr[1:])
}
if len(hourStr) == 3 {
hourStr = []rune{hourStr[0], hourStr[2]} //去除中间的十
}
ts.hour = chineseNum2Int(hourStr)
if len(minuteStr) == 3 {
minuteStr = []rune{minuteStr[0], minuteStr[2]} //去除中间的十
}
ts.minute = chineseNum2Int(minuteStr)
if !matchDateOnly {
urlStr := dateStrs[5]
if urlStr != "" { //是图片url
ts.url = urlStr[3:] //utf-8下用为3字节
if !strings.HasPrefix(ts.url, "http") {
ts.url = "illeagal"
return ts
}
}
ts.alert = dateStrs[6]
ts.enable = true
}
return ts
}
//汉字数字转int仅支持-1099最多两位数其中"每"解释为-1"每两"为-2以此类推
func chineseNum2Int(rs []rune) int8 {
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 int8(r)
}
//处理单个字符的映射0~10
func chineseChar2Int(c rune) int {
match := []rune("零一二三四五六七八九十")
for i, m := range match {
if c == m {
return i
}
}
return 0
}
//@全体成员
func AtAll() message.MessageSegment {
return message.MessageSegment{
Type: "at",
Data: map[string]string{
"qq": "all",
},
}
}
//无缓存发送图片
func ImageNoCache(url string) message.MessageSegment {
return message.MessageSegment{
Type: "image",
Data: map[string]string{
"file": url,
"cache": "0",
},
}
}