群管增加定时器保存功能

This commit is contained in:
fumiama 2021-06-06 14:27:16 +08:00
parent 84b0525f74
commit 42b62f0463
8 changed files with 152 additions and 73 deletions

5
.gitignore vendored
View File

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

View File

@ -10,6 +10,8 @@ import (
"net/http"
"os"
"strings"
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/utils"
)
// urlCache 缓存并返回缓存路径
@ -20,9 +22,9 @@ func (this *Illust) PixivPicDown(path string) (savePath string, err error) {
url = strings.ReplaceAll(url, "_p0", "_p0_master1200")
url = strings.ReplaceAll(url, ".png", ".jpg")
// 文件名为url的hash值
savePath = path + Int2Str(pid) + ".jpg"
savePath = path + utils.Int2Str(pid) + ".jpg"
// 文件存在或文件大小大于10kb
if PathExists(savePath) && FileSize(savePath) > 10240 {
if utils.PathExists(savePath) && utils.FileSize(savePath) > 10240 {
return savePath, nil
}
@ -80,9 +82,9 @@ func (this *Illust) RmPic(path string) (err error) {
url = strings.ReplaceAll(url, "_p0", "_p0_master1200")
url = strings.ReplaceAll(url, ".png", ".jpg")
// 文件名为url的hash值
savePath := path + Int2Str(pid) + ".jpg"
savePath := path + utils.Int2Str(pid) + ".jpg"
// 文件存在或文件大小大于10kb
if PathExists(savePath) {
if utils.PathExists(savePath) {
return os.Remove(savePath)
} else {
return nil

View File

@ -1,23 +1,29 @@
package manager
package timer
import (
"fmt"
"io"
"os"
"strconv"
"strings"
"time"
"unicode"
tm "github.com/Yiwen-Chan/ZeroBot-Plugin/api/timer"
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/msgext"
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/utils"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
type TimeStamp = tm.Timer
type (
TimeStamp = Timer
Ctx = zero.Ctx
)
var (
//记录每个定时器以便取消
timersmap tm.TimersMap
timers = timersmap.Timers
timersmap TimersMap
Timers *(map[string]*Timer)
//定时器存储位置
BOTPATH = utils.PathExecute() // 当前bot运行目录
DATAPATH = BOTPATH + "data/manager/" // 数据目录
@ -25,32 +31,49 @@ var (
)
func init() {
go func() {
time.Sleep(time.Second)
utils.CreatePath(DATAPATH)
loadTimers()
Timers = &timersmap.Timers
}()
}
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() {
func judgeHM(ts *TimeStamp) {
if ts.Hour < 0 || ts.Hour == int32(time.Now().Hour()) {
if ts.Minute < 0 || ts.Minute == int32(time.Now().Minute()) {
onTimeReached()
zero.RangeBot(func(id int64, ctx *zero.Ctx) bool {
ctx.Event = new(zero.Event)
ctx.Event.GroupID = int64(ts.Grpid)
if ts.Url == "" {
ctx.SendChain(msgext.AtAll(), message.Text(ts.Alert))
} else {
ctx.SendChain(msgext.AtAll(), message.Text(ts.Alert), msgext.ImageNoCache(ts.Url))
}
return false
})
}
}
}
func RegisterTimer(ts *TimeStamp, save bool) {
key := GetTimerInfo(ts)
t, ok := (*Timers)[key]
if t != ts && ok { //避免重复注册定时器
t.Enable = false
}
(*Timers)[key] = ts
if save {
SaveTimers()
}
fmt.Printf("[群管]注册计时器[%t]%s\n", ts.Enable, key)
for ts.Enable {
if ts.Month < 0 || ts.Month == int32(time.Now().Month()) {
if ts.Day < 0 || ts.Day == int32(time.Now().Day()) {
judgeHM()
judgeHM(ts)
} else if ts.Day == 0 {
if ts.Week < 0 || ts.Week == int32(time.Now().Weekday()) {
judgeHM()
judgeHM(ts)
}
}
}
@ -58,7 +81,7 @@ func timer(ts TimeStamp, onTimeReached func()) {
}
}
func saveTimers() error {
func SaveTimers() error {
data, err := timersmap.Marshal()
if err != nil {
return err
@ -76,13 +99,32 @@ func saveTimers() error {
}
}
func loadTimers() {
if utils.PathExists(PBFILE) {
f, err := os.Open(PBFILE)
if err == nil {
data, err1 := io.ReadAll(f)
if err1 == nil {
if len(data) > 0 {
timersmap.Unmarshal(data)
for _, t := range timersmap.Timers {
go RegisterTimer(t, false)
}
return
}
}
}
}
timersmap.Timers = make(map[string]*Timer)
}
//获得标准化定时字符串
func getTimerInfo(ts *TimeStamp) string {
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 {
func GetFilledTimeStamp(dateStrs []string, matchDateOnly bool) *TimeStamp {
monthStr := []rune(dateStrs[1])
dayWeekStr := []rune(dateStrs[2])
hourStr := []rune(dateStrs[3])
@ -92,7 +134,7 @@ func getFilledTimeStamp(dateStrs []string, matchDateOnly bool) TimeStamp {
ts.Month = chineseNum2Int(monthStr)
if (ts.Month != -1 && ts.Month <= 0) || ts.Month > 12 { //月份非法
fmt.Println("[群管]月份非法!")
return ts
return &ts
}
lenOfDW := len(dayWeekStr)
if lenOfDW == 4 { //包括末尾的"日"
@ -100,14 +142,14 @@ func getFilledTimeStamp(dateStrs []string, matchDateOnly bool) TimeStamp {
ts.Day = chineseNum2Int(dayWeekStr)
if (ts.Day != -1 && ts.Day <= 0) || ts.Day > 31 { //日期非法
fmt.Println("[群管]日期非法1")
return ts
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
return &ts
}
} else if dayWeekStr[0] == rune('每') { //每周
ts.Week = -1
@ -119,7 +161,7 @@ func getFilledTimeStamp(dateStrs []string, matchDateOnly bool) TimeStamp {
if ts.Week < 0 || ts.Week > 6 { //星期非法
ts.Week = -11
fmt.Println("[群管]星期非法!")
return ts
return &ts
}
}
if len(hourStr) == 3 {
@ -128,7 +170,7 @@ func getFilledTimeStamp(dateStrs []string, matchDateOnly bool) TimeStamp {
ts.Hour = chineseNum2Int(hourStr)
if ts.Hour < -1 || ts.Hour > 23 { //小时非法
fmt.Println("[群管]小时非法!")
return ts
return &ts
}
if len(minuteStr) == 3 {
minuteStr = []rune{minuteStr[0], minuteStr[2]} //去除中间的十
@ -136,7 +178,7 @@ func getFilledTimeStamp(dateStrs []string, matchDateOnly bool) TimeStamp {
ts.Minute = chineseNum2Int(minuteStr)
if ts.Minute < -1 || ts.Minute > 59 { //分钟非法
fmt.Println("[群管]分钟非法!")
return ts
return &ts
}
if !matchDateOnly {
urlStr := dateStrs[5]
@ -146,13 +188,13 @@ func getFilledTimeStamp(dateStrs []string, matchDateOnly bool) TimeStamp {
if !strings.HasPrefix(ts.Url, "http") {
ts.Url = "illegal"
fmt.Println("[群管]url非法")
return ts
return &ts
}
}
ts.Alert = dateStrs[6]
ts.Enable = true
}
return ts
return &ts
}
//汉字数字转int仅支持-1099最多两位数其中"每"解释为-1"每两"为-2以此类推

View File

@ -31,6 +31,7 @@ type Timer struct {
Week int32 `protobuf:"zigzag32,6,opt,name=week,proto3" json:"week,omitempty"`
Hour int32 `protobuf:"zigzag32,7,opt,name=hour,proto3" json:"hour,omitempty"`
Minute int32 `protobuf:"zigzag32,8,opt,name=minute,proto3" json:"minute,omitempty"`
Grpid uint64 `protobuf:"varint,9,opt,name=grpid,proto3" json:"grpid,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -125,6 +126,13 @@ func (m *Timer) GetMinute() int32 {
return 0
}
func (m *Timer) GetGrpid() uint64 {
if m != nil {
return m.Grpid
}
return 0
}
type TimersMap struct {
Timers map[string]*Timer `protobuf:"bytes,1,rep,name=timers,proto3" json:"timers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
@ -181,24 +189,25 @@ func init() {
func init() { proto.RegisterFile("timer.proto", fileDescriptor_ad0307ee16b652d2) }
var fileDescriptor_ad0307ee16b652d2 = []byte{
// 267 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0x4f, 0x4a, 0xc3, 0x40,
0x14, 0xc6, 0x7d, 0x4d, 0x27, 0x36, 0x2f, 0x2e, 0xea, 0x20, 0x32, 0x88, 0x84, 0x90, 0x55, 0x56,
0x5d, 0x54, 0x17, 0xe2, 0x52, 0x10, 0x57, 0x6e, 0x06, 0x2f, 0x30, 0xc5, 0x81, 0x96, 0xe6, 0x4f,
0x99, 0x4e, 0x94, 0x5c, 0xc1, 0x13, 0x78, 0x0b, 0xaf, 0xe1, 0xd2, 0x23, 0x48, 0xbc, 0x88, 0xbc,
0x37, 0xa1, 0x74, 0xf7, 0xfb, 0x7e, 0xf9, 0x08, 0xef, 0x1b, 0x4c, 0xfd, 0xa6, 0xb6, 0x6e, 0xb1,
0x73, 0xad, 0x6f, 0xa5, 0xe0, 0x50, 0x7c, 0x01, 0x8a, 0x17, 0x22, 0x79, 0x89, 0xb1, 0x6d, 0xcc,
0xaa, 0xb2, 0x0a, 0x72, 0x28, 0x67, 0x7a, 0x4c, 0xf2, 0x02, 0x85, 0xa9, 0xac, 0xf3, 0x6a, 0x92,
0x43, 0x99, 0xe8, 0x10, 0xe4, 0x1c, 0xa3, 0xce, 0x55, 0x2a, 0x62, 0x47, 0x48, 0xbd, 0xba, 0x6d,
0xfc, 0x5a, 0x4d, 0x73, 0x28, 0xcf, 0x75, 0x08, 0xd4, 0x7b, 0x35, 0xbd, 0x12, 0xec, 0x08, 0xa5,
0xc4, 0xe9, 0xbb, 0xb5, 0x5b, 0x15, 0xb3, 0x62, 0x26, 0xb7, 0x6e, 0x3b, 0xa7, 0x4e, 0x83, 0x23,
0xa6, 0x7b, 0xea, 0x4d, 0xd3, 0x79, 0xab, 0x66, 0x6c, 0xc7, 0x54, 0x7c, 0x00, 0x26, 0x7c, 0xf1,
0xfe, 0xd9, 0xec, 0xe4, 0x2d, 0xc6, 0x3c, 0x64, 0xaf, 0x20, 0x8f, 0xca, 0x74, 0x79, 0xbd, 0x08,
0x23, 0x0f, 0x8d, 0x91, 0x1e, 0x1b, 0xef, 0x7a, 0x3d, 0x76, 0xaf, 0x9e, 0x30, 0x3d, 0xd2, 0x74,
0xe4, 0xd6, 0xf6, 0xbc, 0x3b, 0xd1, 0x84, 0xb2, 0x40, 0xf1, 0x66, 0xaa, 0xce, 0xf2, 0xe8, 0x74,
0x79, 0x76, 0xfc, 0x57, 0x1d, 0x3e, 0xdd, 0x4f, 0xee, 0xe0, 0x61, 0xfe, 0x3d, 0x64, 0xf0, 0x33,
0x64, 0xf0, 0x3b, 0x64, 0xf0, 0xf9, 0x97, 0x9d, 0xac, 0x62, 0x7e, 0xde, 0x9b, 0xff, 0x00, 0x00,
0x00, 0xff, 0xff, 0x8f, 0x73, 0x63, 0x18, 0x6d, 0x01, 0x00, 0x00,
// 278 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xcd, 0x4a, 0xc3, 0x40,
0x10, 0xc7, 0x9d, 0xe6, 0xc3, 0x66, 0xe3, 0xa1, 0x2e, 0x22, 0x83, 0x48, 0x08, 0x39, 0xe5, 0xd4,
0x43, 0xf5, 0x20, 0x1e, 0x05, 0xf1, 0xe4, 0x65, 0xf1, 0x05, 0x52, 0xba, 0xd8, 0xd0, 0x7c, 0xb1,
0xdd, 0x28, 0x79, 0x05, 0x9f, 0xc0, 0x17, 0x12, 0x3c, 0xfa, 0x08, 0x12, 0x5f, 0x44, 0x66, 0x36,
0x94, 0xde, 0x7e, 0xff, 0x5f, 0xfe, 0x64, 0x67, 0x46, 0xc4, 0xb6, 0xac, 0xb5, 0x59, 0x76, 0xa6,
0xb5, 0xad, 0x0c, 0x38, 0x64, 0x5f, 0x20, 0x82, 0x17, 0x22, 0x79, 0x29, 0x42, 0xdd, 0x14, 0xeb,
0x4a, 0x23, 0xa4, 0x90, 0xcf, 0xd5, 0x94, 0xe4, 0x85, 0x08, 0x8a, 0x4a, 0x1b, 0x8b, 0xb3, 0x14,
0xf2, 0x48, 0xb9, 0x20, 0x17, 0xc2, 0xeb, 0x4d, 0x85, 0x1e, 0x3b, 0x42, 0xea, 0xd5, 0x6d, 0x63,
0xb7, 0xe8, 0xa7, 0x90, 0x9f, 0x2b, 0x17, 0xa8, 0xb7, 0x29, 0x06, 0x0c, 0xd8, 0x11, 0x4a, 0x29,
0xfc, 0x77, 0xad, 0x77, 0x18, 0xb2, 0x62, 0x26, 0xb7, 0x6d, 0x7b, 0x83, 0xa7, 0xce, 0x11, 0xd3,
0x3c, 0x75, 0xd9, 0xf4, 0x56, 0xe3, 0x9c, 0xed, 0x94, 0xe8, 0x9d, 0x57, 0xd3, 0x95, 0x1b, 0x8c,
0x52, 0xc8, 0x7d, 0xe5, 0x42, 0xf6, 0x01, 0x22, 0xe2, 0x3d, 0xf6, 0xcf, 0x45, 0x27, 0x6f, 0x45,
0xc8, 0xeb, 0xed, 0x11, 0x52, 0x2f, 0x8f, 0x57, 0xd7, 0x4b, 0xb7, 0xfa, 0xa1, 0x31, 0xd1, 0x63,
0x63, 0xcd, 0xa0, 0xa6, 0xee, 0xd5, 0x93, 0x88, 0x8f, 0x34, 0x8d, 0xbe, 0xd3, 0x03, 0x5f, 0x23,
0x52, 0x84, 0x32, 0x13, 0xc1, 0x5b, 0x51, 0xf5, 0x9a, 0x4f, 0x11, 0xaf, 0xce, 0x8e, 0xff, 0xaa,
0xdc, 0xa7, 0xfb, 0xd9, 0x1d, 0x3c, 0x2c, 0xbe, 0xc7, 0x04, 0x7e, 0xc6, 0x04, 0x7e, 0xc7, 0x04,
0x3e, 0xff, 0x92, 0x93, 0x75, 0xc8, 0x47, 0xbf, 0xf9, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xe0, 0xc7,
0xad, 0xf8, 0x83, 0x01, 0x00, 0x00,
}
func (m *Timer) Marshal() (dAtA []byte, err error) {
@ -225,6 +234,11 @@ func (m *Timer) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if m.Grpid != 0 {
i = encodeVarintTimer(dAtA, i, uint64(m.Grpid))
i--
dAtA[i] = 0x48
}
if m.Minute != 0 {
i = encodeVarintTimer(dAtA, i, uint64((uint32(m.Minute)<<1)^uint32((m.Minute>>31))))
i--
@ -373,6 +387,9 @@ func (m *Timer) Size() (n int) {
if m.Minute != 0 {
n += 1 + sozTimer(uint64(m.Minute))
}
if m.Grpid != 0 {
n += 1 + sovTimer(uint64(m.Grpid))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
@ -628,6 +645,25 @@ func (m *Timer) Unmarshal(dAtA []byte) error {
}
v = int32((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31))
m.Minute = v
case 9:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Grpid", wireType)
}
m.Grpid = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTimer
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Grpid |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipTimer(dAtA[iNdEx:])

View File

@ -10,6 +10,7 @@ message Timer {
sint32 week = 6;
sint32 hour = 7;
sint32 minute = 8;
uint64 grpid = 9;
}
message TimersMap {

View File

@ -53,7 +53,7 @@ func main() {
CommandPrefix: "/",
SuperUsers: os.Args[1:], // 必须修改,否则无权限
Driver: []zero.Driver{
driver.NewWebSocketClient("127.0.0.1", "6700", ""),
driver.NewWebSocketClient("ws://192.168.8.1:6700/", ""),
},
})
// 帮助

View File

@ -4,7 +4,7 @@ import (
"strconv"
"strings"
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/msgext"
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/timer"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
@ -235,15 +235,10 @@ func init() { // 插件主体
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)
ts := timer.GetFilledTimeStamp(dateStrs, false)
ts.Grpid = uint64(ctx.Event.GroupID)
if ts.Enable {
go timer(ts, func() {
if ts.Url == "" {
ctx.SendChain(msgext.AtAll(), message.Text(ts.Alert))
} else {
ctx.SendChain(msgext.AtAll(), message.Text(ts.Alert), msgext.ImageNoCache(ts.Url))
}
})
go timer.RegisterTimer(ts, true)
ctx.Send("记住了~")
} else {
ctx.Send("参数非法!")
@ -254,12 +249,13 @@ func init() { // 插件主体
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]
ts := timer.GetFilledTimeStamp(dateStrs, true)
ti := timer.GetTimerInfo(ts)
t, ok := (*timer.Timers)[ti]
if ok {
t.Enable = false
delete(timers, ti) //避免重复取消
delete(*timer.Timers, ti) //避免重复取消
timer.SaveTimers()
ctx.Send("取消成功~")
} else {
ctx.Send("没有这个定时器哦~")

View File

@ -10,17 +10,18 @@ import (
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/Yiwen-Chan/ZeroBot-Plugin/api/pixiv"
apiutils "github.com/Yiwen-Chan/ZeroBot-Plugin/api/utils"
utils "github.com/Yiwen-Chan/ZeroBot-Plugin/picsearcher/utils"
)
var CACHEPATH = "/tmp/picsch/" // 缓冲图片路径
func init() { // 插件主体
pixiv.CreatePath(CACHEPATH)
apiutils.CreatePath(CACHEPATH)
// 根据PID搜图
zero.OnRegex(`^搜图(\d+)$`).SetBlock(true).SetPriority(30).
Handle(func(ctx *zero.Ctx) {
id := pixiv.Str2Int(ctx.State["regex_matched"].([]string)[1])
id := apiutils.Str2Int(ctx.State["regex_matched"].([]string)[1])
ctx.Send("少女祈祷中......")
// 获取P站插图信息
illust := &pixiv.Illust{}