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{} }