master
兔子 1 year ago
parent 66828b2c23
commit b342ed0dbc

@ -3,6 +3,19 @@ module b612.me/sdk/candy
go 1.20
require (
b612.me/stardb v1.1.3
b612.me/startimer v0.0.0-20230501080256-b0fd8947f0dc
b612.me/stardb v1.1.4
b612.me/startimer v0.0.1
github.com/glebarez/go-sqlite v1.21.1
)
require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
golang.org/x/sys v0.4.0 // indirect
modernc.org/libc v1.22.3 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.21.1 // indirect
)

@ -1,4 +1,27 @@
b612.me/stardb v1.1.3 h1:cx16v64FmfCh+cCF6GDDiVUF+ZISpBxBH3t2GkBkeJY=
b612.me/stardb v1.1.3/go.mod h1:qtGEu+joEQxFESl3tse5xqiD767f6sAmHD284+Xoy48=
b612.me/startimer v0.0.0-20230501080256-b0fd8947f0dc h1:WO8jZiLVssi3myTWX5Oo/+/i9vk+Alo4ymJhHi4TXp0=
b612.me/startimer v0.0.0-20230501080256-b0fd8947f0dc/go.mod h1:8fw+OU7SnxzuLkNCYSbRKmvs4WtHs6SbCHuTf5F6s+U=
b612.me/stardb v1.1.4 h1:Ic+CwGZpDKtgHTkDJ5/1kxgEEGM9Hj5xu9i0n6CbXfs=
b612.me/stardb v1.1.4/go.mod h1:qtGEu+joEQxFESl3tse5xqiD767f6sAmHD284+Xoy48=
b612.me/startimer v0.0.1 h1:7Q4hzkXZR1iFSWyEoTBjUiDx1HsROIvIel3HdfhIhxo=
b612.me/startimer v0.0.1/go.mod h1:7YlIWMVBIxLObVI0Ls+CMCCVZJ+4DdTaqF2TshthZjk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY=
github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU=
modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI=

@ -5,18 +5,19 @@ import (
"b612.me/stardb"
"b612.me/startimer"
"errors"
"fmt"
"sync"
"time"
)
type Remind struct {
db *stardb.StarDB
tasks map[int]RemindTask
tasks map[int]Task
mu sync.RWMutex
callback func(remind RemindTask)
callback func(remind Task)
}
type RemindTask struct {
type Task struct {
ID int `db:"id"`
Origin string `db:"text"`
timer *startimer.StarTimer
@ -32,7 +33,7 @@ func getCreateSql() []string {
}
}
func NewRemind(db *stardb.StarDB, callback func(task RemindTask)) (*Remind, error) {
func NewRemind(db *stardb.StarDB, callback func(task Task)) (*Remind, error) {
if db == nil || db.Db == nil {
return nil, errors.New("Invalid hanlder of database")
}
@ -48,13 +49,14 @@ func NewRemind(db *stardb.StarDB, callback func(task RemindTask)) (*Remind, erro
return innerLoadDB(db, callback)
}
func innerLoadDB(db *stardb.StarDB, callback func(task RemindTask)) (*Remind, error) {
func innerLoadDB(db *stardb.StarDB, callback func(task Task)) (*Remind, error) {
var rem = Remind{
db: db,
mu: sync.RWMutex{},
callback: callback,
tasks: make(map[int]Task),
}
var res []RemindTask
var res []Task
data, err := db.Query("select * from remind")
if err != nil {
return nil, err
@ -64,7 +66,7 @@ func innerLoadDB(db *stardb.StarDB, callback func(task RemindTask)) (*Remind, er
return nil, err
}
if len(res) != 0 {
rem.tasks = make(map[int]RemindTask, len(res))
rem.tasks = make(map[int]Task, len(res))
for _, task := range res {
tmr := startimer.NewTimer(time.Now())
err = tmr.ImportRepeats(task.TmrInfo)
@ -85,23 +87,28 @@ func innerLoadDB(db *stardb.StarDB, callback func(task RemindTask)) (*Remind, er
return &rem, nil
}
func (t RemindTask) GetTimer() startimer.StarTimer {
return *t.timer
func (t Task) GetTimer() *startimer.StarTimer {
return t.timer
}
func (r *Remind) callbackFn(task RemindTask) {
r.callback(task)
func (r *Remind) callbackFn(task Task) {
if r.callback != nil {
r.callback(task)
}
if !task.GetTimer().IsRunning() {
r.DeleteTask(task.ID)
}
}
func (r *Remind) AddTask(taskStr, key string, msg []byte) (RemindTask, error) {
func (r *Remind) AddTask(taskStr, key string, msg []byte) (Task, error) {
tmr, err := when.WhenWithPeriod(taskStr)
if err != nil {
return RemindTask{}, err
return Task{}, err
}
exp, err := tmr.ExportRepeats()
if err != nil {
return RemindTask{}, err
return Task{}, err
}
var rmt = RemindTask{
var rmt = Task{
Origin: taskStr,
TmrInfo: exp,
Key: key,
@ -113,17 +120,23 @@ func (r *Remind) AddTask(taskStr, key string, msg []byte) (RemindTask, error) {
})
res, err := r.db.Insert(rmt, "remind", "id")
if err != nil {
return RemindTask{}, err
return Task{}, err
}
id, err := res.LastInsertId()
if err != nil {
return RemindTask{}, err
return Task{}, err
}
rmt.ID = int(id)
r.mu.Lock()
r.tasks[rmt.ID] = rmt
r.mu.Unlock()
rmt.timer.Run()
fmt.Println(tmr.ExportRepeats())
err = rmt.timer.Run()
time.Sleep(time.Microsecond * 100)
if err != nil || !rmt.timer.IsRunning() {
r.DeleteTask(rmt.ID)
return Task{}, err
}
return rmt, nil
}
@ -147,3 +160,42 @@ func (r *Remind) DeleteTask(id int) error {
delete(r.tasks, id)
return nil
}
func (r *Remind) ListTasks() []Task {
var res = make([]Task, 0, len(r.tasks))
r.mu.RLock()
defer r.mu.RUnlock()
for _, tk := range r.tasks {
res = append(res, tk)
}
return res
}
func (r *Remind) GetTasksByKey(key string) []Task {
var res []Task
r.mu.RLock()
defer r.mu.RUnlock()
for _, tk := range r.tasks {
if tk.Key == key {
res = append(res, tk)
}
}
return res
}
func (r *Remind) Stop() error {
for _, task := range r.tasks {
task.GetTimer().Stop()
}
return nil
}
func (r *Remind) Reset() error {
for _, task := range r.tasks {
err := r.DeleteTask(task.ID)
if err != nil {
return err
}
}
return nil
}

@ -0,0 +1,58 @@
package remind
import (
"b612.me/stardb"
"fmt"
_ "github.com/glebarez/go-sqlite"
"os"
"testing"
"time"
)
func exists(path string) bool {
_, err := os.Stat(path)
if os.IsNotExist(err) {
return false
}
return err == nil
}
func TestRemind(t *testing.T) {
var db stardb.StarDB
err := db.Open("sqlite", "./remind.db")
if err != nil {
t.Fatal(err)
}
sign := make(chan int)
r, err := NewRemind(&db, func(task Task) {
fmt.Println("hello world!", time.Now(), task.ID, task.Key, task.TmrInfo, task.Msg, task.Origin)
sign <- 1
})
if err != nil {
t.Fatal(err)
}
fmt.Println("length of remind", len(r.ListTasks()))
if len(r.ListTasks()) < 2 {
tk, err := r.AddTask("每8秒提醒我吃饭", "干饭", []byte{1, 2, 3})
if err != nil {
t.Fatal(err)
}
tmr := tk.GetTimer()
fmt.Println(tmr.NextTimer())
}
i := 0
for {
select {
case <-sign:
i++
break
case <-time.After(time.Second * 15):
t.FailNow()
}
time.Sleep(time.Second)
fmt.Println(len(r.ListTasks()))
if i == 3 {
break
}
}
}

@ -13,9 +13,10 @@ func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, erro
str = transChn(str)
var rpt startimer.Repeats
var duration time.Duration
reg := regexp.MustCompile(`(每隔|每)?(\d{1,4}年)?(\d{1,5}个?月)?(\d{1,4}[明后大]{0,4}[日号天])?([上中下午夜早凌清晨傍晚里]+)?(\d{1,4}个?[点小时钟:]+)?(\d{1,4}[分:])?(\d{1,10}秒?)?(后)?`)
reg := regexp.MustCompile(`(每隔|每)?(\d{0,4}年)?(\d{0,5}个?月)?(\d{0,4}[明后大]{0,4}[日号天])?([上中下午夜早凌清晨傍晚里]+)?(\d{1,4}个?[点小时钟:]+)?(\d{1,4}[分:])?(\d{1,10}秒?)?(后)?`)
if reg.MatchString(str) {
pts := reg.FindStringSubmatch(str)
setAsDate := false
var timeParse = pts[5]
count := 1
if pts[1] != "" {
@ -26,19 +27,31 @@ func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, erro
if !rpt.Every {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_YEAR, Value: uint32(getNumbers(pts[2]))})
} else {
duration += time.Hour * 24 * 365 * time.Duration(getNumbers(pts[2]))
if getNumbers(pts[2]) == 0 {
setAsDate = true
} else {
duration += time.Hour * 24 * 365 * time.Duration(getNumbers(pts[2]))
}
}
}
if pts[3] != "" {
if !rpt.Every {
if !rpt.Every || setAsDate {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MONTH, Value: uint32(getNumbers(pts[3]))})
} else {
duration += time.Hour * 24 * 30 * time.Duration(getNumbers(pts[3]))
if getNumbers(pts[3]) == 0 {
setAsDate = true
} else {
duration += time.Hour * 24 * 30 * time.Duration(getNumbers(pts[3]))
}
}
}
if pts[4] != "" {
now := time.Now()
switch pts[4] {
case "天":
if rpt.Every {
setAsDate = true
}
case "明天":
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(now.Add(time.Hour * 24).Day())})
case "后天":
@ -48,27 +61,28 @@ func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, erro
case "大大后天":
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(now.Add(time.Hour * 96).Day())})
default:
if !rpt.Every {
if setAsDate == rpt.Every {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_DAY, Value: uint32(getNumbers(pts[4]))})
} else {
duration += time.Hour * 24 * time.Duration(getNumbers(pts[4]))
}
}
}
setAsDate := false
if rpt.Every && timeParse != "" {
setAsDate = true
} else if rpt.Every && !strings.Contains(pts[6], "小时") {
setAsDate = true
base = time.Date(base.Year(), base.Month(), base.Day(), 0, 0, 0, 0, base.Location())
}
//else if rpt.Every && !strings.Contains(pts[6], "小时") {
// setAsDate = true
// base = time.Date(base.Year(), base.Month(), base.Day(), 0, 0, 0, 0, base.Location())
// }
var hour uint32
if pts[6] != "" {
hour = uint32(getNumbers(pts[6]))
if timeParse == "下午" || strings.Contains(timeParse, "晚") || strings.Contains(timeParse, "夜") {
hour += 12
}
if !setAsDate && !rpt.Every {
if rpt.Every == setAsDate {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_HOUR, Value: hour})
} else if rpt.Every && !setAsDate {
duration += time.Hour * time.Duration(hour)
@ -99,7 +113,7 @@ func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, erro
}
}
if pts[7] != "" {
if !setAsDate && !rpt.Every {
if rpt.Every == setAsDate {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: uint32(getNumbers(pts[7]))})
} else if rpt.Every && !setAsDate {
duration += time.Minute * time.Duration(uint32(getNumbers(pts[7])))
@ -107,13 +121,13 @@ func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, erro
base.Add(time.Minute * time.Duration(uint32(getNumbers(pts[7]))))
}
} else if hour != 0 {
if !rpt.Every && !setAsDate {
if rpt.Every == setAsDate {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_MINUTE, Value: 0})
}
}
if pts[8] != "" {
if !setAsDate && !rpt.Every {
if rpt.Every == setAsDate {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(getNumbers(pts[8]))})
} else if rpt.Every && !setAsDate {
duration += time.Second * time.Duration(uint32(getNumbers(pts[8])))
@ -121,7 +135,7 @@ func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, erro
base.Add(time.Second * time.Duration(uint32(getNumbers(pts[8]))))
}
} else if hour != 0 {
if !rpt.Every && !setAsDate {
if rpt.Every == setAsDate {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: 0})
}
}
@ -151,6 +165,9 @@ func matchPeriodPattern01(base time.Time, str string) (startimer.StarTimer, erro
if duration.Seconds() > 0 {
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_SECOND, Value: uint32(duration.Seconds())})
}
if rpt.Every == setAsDate {
rpt.Every = false
}
return startimer.NewTimer(base, startimer.WithRepeats(&rpt), startimer.WithRunCountLimit(count)), nil
}
return startimer.StarTimer{}, errors.New("no Match")
@ -182,6 +199,9 @@ func matchPeroidPattern02(base time.Time, str string) (startimer.StarTimer, erro
}
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_WEEK, Value: uint32(num)})
}
} else {
wkNum := getNumbers(wk)
rpt.Repeat = append(rpt.Repeat, startimer.Repeat{Unit: startimer.STAR_WEEK, Value: uint32(wkNum)})
}
}

@ -8,8 +8,17 @@ import (
func TestParse(t *testing.T) {
for _, code := range []string{"一个小时后告诉我事情", "三个小时后爱我", "每两个小时提醒我吃饭",
"每五个月零二十五天三小时25分15秒告诉我时间", "5月23日上午3点24分12秒打我", "周四上午11点提醒我",
"每周一到周五上午8点提醒我吃饭"} {
"每五个月零二十五天三小时25分15秒告诉我时间", "5月23日上午3点24分12秒打我", "周五上午11点提醒我", "5时25分提醒我",
"每周一到周五上午8点提醒我吃饭", "每天晚上8点提醒我吃饭", "每月16号晚上8点提醒我吃饭"} {
a, _ := WhenWithPeriod(code)
//fmt.Println(a.Repeats()[0])
fmt.Println(a.NextTimer(), a.RunCountLimit(), code)
fmt.Println(a.NextTimerAfterDate(time.Now().Add(time.Hour * 72)))
}
}
func TestSigParse(t *testing.T) {
for _, code := range []string{"每月16号晚上8点提醒我吃饭"} {
a, _ := WhenWithPeriod(code)
//fmt.Println(a.Repeats()[0])
fmt.Println(a.NextTimer(), a.RunCountLimit(), code)

Loading…
Cancel
Save