151 lines
4.0 KiB
Go
151 lines
4.0 KiB
Go
package job
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"91porn-server/common/enum/imad"
|
|
"91porn-server/common/log"
|
|
"91porn-server/common/stderr"
|
|
"91porn-server/models/cache/sysconfdata"
|
|
"91porn-server/models/v/sysconfmod"
|
|
"91porn-server/skd/skdg"
|
|
"91porn-server/services/srv_im"
|
|
)
|
|
|
|
const (
|
|
imAdNotifyLockKey = "skd:im_ad_notify:online:lock"
|
|
imAdNotifyLastRunKey = "skd:im_ad_notify:online:last_run"
|
|
imAdNotifyLockTTL = 10 * time.Minute
|
|
)
|
|
|
|
type imAdNotifyConfig struct {
|
|
Enable bool
|
|
IntervalMinutes int64
|
|
Positions []string
|
|
MaxUsers int
|
|
}
|
|
|
|
// IMAdNotifyOnline 按 sysconf.imConfig 定时向当前 IM 在线用户透传广告刷新通知。
|
|
func IMAdNotifyOnline() {
|
|
if err := imAdNotifyOnline(); err != nil {
|
|
log.Error("IMAdNotifyOnline failed", log.E(err))
|
|
}
|
|
}
|
|
|
|
func imAdNotifyOnline() error {
|
|
conf := loadIMAdNotifyConfig()
|
|
now := time.Now()
|
|
lastRunAt, err := loadIMAdNotifyLastRunAt()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !shouldRunIMAdNotify(conf, lastRunAt, now) {
|
|
return nil
|
|
}
|
|
|
|
acquired, err := skdg.Redis.Setnx_NewOK(imAdNotifyLockKey, 1, imAdNotifyLockTTL)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !acquired {
|
|
log.Info("IMAdNotifyOnline skipped: lock held")
|
|
return nil
|
|
}
|
|
defer func() {
|
|
if _, err := skdg.Redis.Del(imAdNotifyLockKey); err != nil {
|
|
log.Warn("IMAdNotifyOnline release lock failed", log.E(err))
|
|
}
|
|
}()
|
|
|
|
lastRunAt, err = loadIMAdNotifyLastRunAt()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !shouldRunIMAdNotify(conf, lastRunAt, now) {
|
|
return nil
|
|
}
|
|
|
|
resp, code, msg := srv_im.SendAdNotify(srv_im.AdNotifyReq{
|
|
Target: "online",
|
|
Positions: conf.Positions,
|
|
MaxUsers: conf.MaxUsers,
|
|
})
|
|
if code != stderr.Success {
|
|
return fmt.Errorf("im ad notify failed: code=%d msg=%s", code, msg)
|
|
}
|
|
log.Info("IMAdNotifyOnline done", log.Any("resp", resp))
|
|
return saveIMAdNotifyLastRunAt(now)
|
|
}
|
|
|
|
func loadIMAdNotifyConfig() imAdNotifyConfig {
|
|
conf := imAdNotifyConfig{IntervalMinutes: 60, MaxUsers: 1000}
|
|
all, err := sysconfdata.GetAllFromCache()
|
|
if err != nil {
|
|
log.Warn("load im sysconf failed", log.E(err))
|
|
return conf
|
|
}
|
|
conf.Enable = all.GetBool(sysconfmod.VCodeIMAdEnable)
|
|
if v := all.GetInt(sysconfmod.VCodeIMAdIntervalMinutes); v > 0 {
|
|
conf.IntervalMinutes = v
|
|
}
|
|
if v := all.GetInt(sysconfmod.VCodeIMAdMaxUsers); v > 0 {
|
|
conf.MaxUsers = int(v)
|
|
}
|
|
// 每个广告位独立开关,开了就加进去
|
|
conf.Positions = collectEnabledIMAdPositions(all)
|
|
return conf
|
|
}
|
|
|
|
// collectEnabledIMAdPositions 把启用了的广告位 code 收集成列表
|
|
func collectEnabledIMAdPositions(all sysconfmod.ConfMap) []string {
|
|
positions := make([]string, 0, 4)
|
|
if all.GetBool(sysconfmod.VCodeIMAdPosChatNotificationBar) {
|
|
positions = append(positions, imad.ChatNotificationBar)
|
|
}
|
|
if all.GetBool(sysconfmod.VCodeIMAdPosChatFloatingGifBall) {
|
|
positions = append(positions, imad.ChatFloatingGifBall)
|
|
}
|
|
if all.GetBool(sysconfmod.VCodeIMAdPosListFeedNative) {
|
|
positions = append(positions, imad.ListFeedNative)
|
|
}
|
|
if all.GetBool(sysconfmod.VCodeIMAdPosListBanner) {
|
|
positions = append(positions, imad.ListBanner)
|
|
}
|
|
return positions
|
|
}
|
|
|
|
func shouldRunIMAdNotify(conf imAdNotifyConfig, lastRunAt time.Time, now time.Time) bool {
|
|
if !conf.Enable || len(conf.Positions) == 0 {
|
|
return false
|
|
}
|
|
if lastRunAt.IsZero() {
|
|
return true
|
|
}
|
|
return !now.Before(lastRunAt.Add(normalizeIMAdNotifyInterval(conf.IntervalMinutes)))
|
|
}
|
|
|
|
func normalizeIMAdNotifyInterval(intervalMinutes int64) time.Duration {
|
|
if intervalMinutes <= 0 {
|
|
intervalMinutes = 60
|
|
}
|
|
return time.Duration(intervalMinutes) * time.Minute
|
|
}
|
|
|
|
func loadIMAdNotifyLastRunAt() (time.Time, error) {
|
|
val, err := skdg.Redis.Get(imAdNotifyLastRunKey)
|
|
if err != nil || val == nil || *val == "" {
|
|
return time.Time{}, err
|
|
}
|
|
unixSec, err := strconv.ParseInt(*val, 10, 64)
|
|
if err != nil || unixSec <= 0 {
|
|
return time.Time{}, nil
|
|
}
|
|
return time.Unix(unixSec, 0), nil
|
|
}
|
|
|
|
func saveIMAdNotifyLastRunAt(now time.Time) error {
|
|
return skdg.Redis.Set(imAdNotifyLastRunKey, strconv.FormatInt(now.Unix(), 10), 0)
|
|
}
|