170 lines
5.0 KiB
Go
170 lines
5.0 KiB
Go
package noticefmtmod
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"time"
|
|
|
|
"91porn-server/common/timeutil/timeslice"
|
|
)
|
|
|
|
// TimeSlice
|
|
type TimeSlice = timeslice.TimeSlice
|
|
|
|
// UIDSlice
|
|
type UIDSlice []uint64
|
|
|
|
func (u UIDSlice) Len() int {
|
|
return len(u)
|
|
}
|
|
|
|
func (u UIDSlice) Swap(i, j int) {
|
|
u[i], u[j] = u[j], u[i]
|
|
}
|
|
|
|
func (u UIDSlice) Less(i, j int) bool {
|
|
return u[i] < u[j]
|
|
}
|
|
|
|
// 定时通知 从指定的开始时间起,根据设置的时间间隔周期性通知
|
|
type RegularNotice struct {
|
|
StartAt *time.Time `bson:"regularStartAt,omitempty"` //开始时间
|
|
TimeUnit *TimeUnit `bson:"regularTimeUnit,omitempty"` //单位 分钟/小时/天/周
|
|
TimeCount *int64 `bson:"regularTimeCount,omitempty"` //量
|
|
}
|
|
|
|
func (t *RegularNotice) NextSendTimeList(current time.Time, lastSendAt time.Time) TimeSlice {
|
|
if t.StartAt == nil || t.TimeUnit == nil || t.TimeCount == nil {
|
|
return TimeSlice{}
|
|
}
|
|
if t.StartAt.After(current) {
|
|
return TimeSlice{}
|
|
}
|
|
per := t.TimeUnit.ToDuration() * time.Duration(*t.TimeCount)
|
|
if per == 0 {
|
|
return TimeSlice{}
|
|
}
|
|
curDelta := current.Sub(*t.StartAt)
|
|
nextSendTime := t.StartAt.Add(curDelta / per * per)
|
|
if lastSendAt.Before(nextSendTime) || lastSendAt.IsZero() {
|
|
return TimeSlice{nextSendTime}
|
|
}
|
|
return TimeSlice{}
|
|
}
|
|
|
|
func (t *RegularNotice) Rule() string {
|
|
nextSendTime := t.NextSendTimeList(time.Now(), time.Time{})
|
|
nextSendTimeStr := "无"
|
|
if nextSendTime.Len() != 0 {
|
|
nextSendTimeStr = nextSendTime[0].String()
|
|
}
|
|
return fmt.Sprintf("从 %s 开始, 每 %d %v, 发送消息\n 下次发送时间: %s", t.StartAt, t.TimeCount, t.TimeUnit, nextSendTimeStr)
|
|
}
|
|
|
|
// 计划通知 根据指定的开始时间、结束时间和通知次数发起通知
|
|
type PlanNotice struct {
|
|
StartAt *time.Time `bson:"planStartAt,omitempty"` //开始时间
|
|
EndAt *time.Time `bson:"planEndAt,omitempty"` //结束时间
|
|
PlanCount *int64 `bson:"planPlanCount,omitempty"` //执行次数
|
|
}
|
|
|
|
func (t *PlanNotice) NextSendTimeList(current time.Time, lastSendAt time.Time) TimeSlice {
|
|
if t.StartAt == nil || t.EndAt == nil || t.PlanCount == nil || *t.PlanCount == 0 {
|
|
return TimeSlice{}
|
|
}
|
|
if t.StartAt.After(current) || current.After(*t.EndAt) {
|
|
return TimeSlice{}
|
|
}
|
|
totalDelta := t.EndAt.Sub(*t.StartAt)
|
|
curDelta := t.EndAt.Sub(current)
|
|
per := totalDelta / time.Duration(*t.PlanCount)
|
|
nextSendTime := t.StartAt.Add(curDelta / per * per)
|
|
if lastSendAt.Before(nextSendTime) || lastSendAt.IsZero() {
|
|
return TimeSlice{nextSendTime}
|
|
}
|
|
return TimeSlice{}
|
|
}
|
|
|
|
func (t *PlanNotice) Rule() string {
|
|
nextSendTime := t.NextSendTimeList(time.Now(), time.Time{})
|
|
nextSendTimeStr := "无"
|
|
if nextSendTime.Len() != 0 {
|
|
nextSendTimeStr = nextSendTime[0].String()
|
|
}
|
|
return fmt.Sprintf("从 %s 开始 至 %s 结束, 计划发送 %d 次消息\n 下次发送时间: %s", t.StartAt, t.EndAt, t.PlanCount, nextSendTimeStr)
|
|
}
|
|
|
|
// 规定通知 到达指定的多个时间点时通知
|
|
type SpecifyNotice struct {
|
|
SpecifyTimeList TimeSlice `bson:"specifyTimeList,omitempty"` //指定执行时间数组
|
|
}
|
|
|
|
func (t *SpecifyNotice) NextSendTimeList(current time.Time, lastSendAt time.Time) TimeSlice {
|
|
if len(t.SpecifyTimeList) == 0 {
|
|
return TimeSlice{}
|
|
}
|
|
sort.Sort(t.SpecifyTimeList)
|
|
index := sort.Search(t.SpecifyTimeList.Len(), func(i int) bool {
|
|
return t.SpecifyTimeList[i].After(current)
|
|
})
|
|
index = index - 1 //前一个才是已经过去的时间
|
|
if index < 0 {
|
|
index = 0
|
|
}
|
|
nextSendTime := t.SpecifyTimeList[index]
|
|
if lastSendAt.Before(nextSendTime) || lastSendAt.IsZero() {
|
|
return TimeSlice{nextSendTime}
|
|
}
|
|
return TimeSlice{}
|
|
}
|
|
|
|
func (t *SpecifyNotice) Rule() string {
|
|
nextSendTime := t.NextSendTimeList(time.Now(), time.Time{})
|
|
nextSendTimeStr := "无"
|
|
if nextSendTime.Len() != 0 {
|
|
nextSendTimeStr = nextSendTime[0].String()
|
|
}
|
|
return fmt.Sprintf("指定时间: %+v 发送\n 下次发送时间: %s", t.SpecifyTimeList, nextSendTimeStr)
|
|
}
|
|
|
|
// 注册后通知 用户注册后开始计时, 消耗指定的时间后通知一次
|
|
type AfterRegistNotice struct {
|
|
TimeUnit *TimeUnit `bson:"afterTimeUnit,omitempty"` //单位 分钟/小时/天/周
|
|
TimeCount *int64 `bson:"afterTimeCount,omitempty"` //量
|
|
}
|
|
|
|
func (t *AfterRegistNotice) Rule() string {
|
|
return fmt.Sprintf("用户注册后 %d %v 发送", t.TimeCount, t.TimeUnit)
|
|
}
|
|
|
|
type AfterRegistNoticeEx struct {
|
|
AfterRegistNotice
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
func (a *AfterRegistNoticeEx) NextSendTimeList(current time.Time, lastSendAt time.Time) TimeSlice {
|
|
if a.TimeCount == nil {
|
|
return TimeSlice{}
|
|
}
|
|
interval := a.TimeUnit.ToDuration() * time.Duration(*a.TimeCount)
|
|
sendTime := a.CreatedAt.Add(interval)
|
|
if current.After(sendTime) && lastSendAt.IsZero() {
|
|
return TimeSlice{sendTime}
|
|
}
|
|
return TimeSlice{}
|
|
}
|
|
|
|
type MailNotice struct {
|
|
SendAt *time.Time `bson:"mailSendAt,omitempty"` //发送时间
|
|
}
|
|
|
|
func (m *MailNotice) NextSendTimeList(current time.Time, lastSendAt time.Time) TimeSlice {
|
|
if m.SendAt == nil {
|
|
return TimeSlice{}
|
|
}
|
|
if current.After(*m.SendAt) && lastSendAt.IsZero() {
|
|
return TimeSlice{*m.SendAt}
|
|
}
|
|
return TimeSlice{}
|
|
}
|