gameShield.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package task
  2. import (
  3. "context"
  4. "github.com/go-nunu/nunu-layout-advanced/internal/repository"
  5. "go.uber.org/zap"
  6. "strconv"
  7. "time"
  8. )
  9. type GameShieldTask interface {
  10. CheckGameShield(ctx context.Context) error
  11. SyncAllExpireTimeFromHost(ctx context.Context) error
  12. }
  13. func NewGameShieldTask(
  14. task *Task,
  15. gameShieldRepo repository.GameShieldRepository,
  16. ) GameShieldTask {
  17. return &gameShieldTask{
  18. Task: task,
  19. gameShieldRepo: gameShieldRepo,
  20. }
  21. }
  22. type gameShieldTask struct {
  23. *Task
  24. gameShieldRepo repository.GameShieldRepository
  25. }
  26. // 检查已过期的记录
  27. func (t gameShieldTask) CheckExpiredGameShields(ctx context.Context) error {
  28. // 获取已过期的商品
  29. expiredShields, err := t.gameShieldRepo.GetExpiredGameShields(ctx)
  30. if err != nil {
  31. t.logger.Error("查询已过期的游戏盾失败", zap.Error(err))
  32. return err
  33. }
  34. t.logger.Info("找到已过期的游戏盾商品", zap.Int("数量", len(expiredShields)))
  35. // 遍历已过期的商品
  36. for _, shield := range expiredShields {
  37. t.logger.Info("已过期商品",
  38. zap.Int("ID", shield.Id),
  39. zap.Int("用户ID", shield.Uid),
  40. zap.String("商品", shield.AppName),
  41. zap.Time("过期时间", time.Unix(shield.ExpireTime, 0)))
  42. // 检查用户是否已续费(检查nextduedate字段)
  43. nextduedate, err := t.gameShieldRepo.GetGameShieldNextduedate(ctx, int64(shield.Uid), shield.HostId)
  44. if err != nil {
  45. t.logger.Error("获取nextduedate失败", zap.Int("用户ID", shield.Uid), zap.Error(err))
  46. continue
  47. }
  48. nextduedateTime, err := strconv.ParseInt(nextduedate, 10, 64)
  49. if err != nil {
  50. t.logger.Error("解析nextduedate失败", zap.Error(err))
  51. continue
  52. }
  53. currentTime := time.Now().Unix()
  54. renewed := nextduedateTime > currentTime
  55. if renewed {
  56. // 已过期但已续费,更新过期时间
  57. shield.ExpireTime = nextduedateTime
  58. if err := t.gameShieldRepo.UpdateGameShield(ctx, shield); err != nil {
  59. t.logger.Error("更新过期游戏盾的过期时间失败",
  60. zap.String("商品", shield.AppName),
  61. zap.Error(err))
  62. continue
  63. }
  64. t.logger.Info("已过期商品续期成功",
  65. zap.Int("用户ID", shield.Uid),
  66. zap.String("商品", shield.AppName),
  67. zap.Time("新过期时间", time.Unix(nextduedateTime, 0)))
  68. } else {
  69. // 已过期且未续费,执行过期操作
  70. t.logger.Info("商品已过期且未续费",
  71. zap.Int("用户ID", shield.Uid),
  72. zap.String("商品", shield.AppName))
  73. // TODO: 添加您的过期处理逻辑,例如:
  74. // - 发送过期通知
  75. // - 禁用服务
  76. // - 标记记录状态
  77. }
  78. }
  79. return nil
  80. }
  81. // CheckSoonExpiredGameShields 检查即将过期的记录并处理续费
  82. func (t gameShieldTask) CheckSoonExpiredGameShields(ctx context.Context) error {
  83. // 获取7天内即将过期的商品
  84. soonExpiredShields, err := t.gameShieldRepo.GetSoonExpiredGameShields(ctx, 7)
  85. if err != nil {
  86. t.logger.Error("查询即将过期的游戏盾失败", zap.Error(err))
  87. return err
  88. }
  89. t.logger.Info("找到 %d 个即将过期的游戏盾商品", zap.Int("数量", len(soonExpiredShields)))
  90. // 遍历即将过期的商品
  91. for _, shield := range soonExpiredShields {
  92. t.logger.Info("即将过期商品",
  93. zap.Int("ID", shield.Id),
  94. zap.Int("用户ID", shield.Uid),
  95. zap.String("商品", shield.AppName),
  96. zap.Time("过期时间", time.Unix(shield.ExpireTime, 0)))
  97. currentTime := time.Now().Unix()
  98. // 检查用户是否已续费(检查nextduedate字段)
  99. nextduedate, err := t.gameShieldRepo.GetGameShieldNextduedate(ctx, int64(shield.Uid), shield.HostId)
  100. nextduedateTime, err := strconv.ParseInt(nextduedate, 10, 64)
  101. if err != nil {
  102. t.logger.Error("解析nextduedate失败", zap.Error(err))
  103. continue
  104. }
  105. renewed := nextduedateTime > currentTime
  106. if renewed {
  107. // 用户已续费,更新shd_game_shield表中的ExpireTime字段
  108. // 使用shd_host表中的nextduedate作为新的过期时间
  109. shield.ExpireTime = nextduedateTime
  110. if err := t.gameShieldRepo.UpdateGameShield(ctx, shield); err != nil {
  111. t.logger.Error("更新shd_game_shield表失败: %v", zap.Error(err))
  112. continue
  113. }
  114. t.logger.Info("自动续期成功: 用户ID=%d, 商品=%s, 新过期时间=%v",
  115. zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Time("新过期时间", time.Unix(shield.ExpireTime, 0)))
  116. } else {
  117. // 用户未续费,可以发送提醒通知
  118. t.logger.Info("用户未续费: 用户ID=%d, 商品=%s", zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName))
  119. }
  120. }
  121. return nil
  122. }
  123. // SyncAllExpireTimeFromHost 同步所有记录的过期时间
  124. func (t gameShieldTask) SyncAllExpireTimeFromHost(ctx context.Context) error {
  125. // 获取所有游戏盾记录
  126. shields, err := t.gameShieldRepo.GetAllGameShield(ctx)
  127. if err != nil {
  128. t.logger.Error("查询所有游戏盾记录失败", zap.Error(err))
  129. return err
  130. }
  131. t.logger.Info("找到 %d 条游戏盾记录", zap.Int("数量", len(shields)))
  132. // 同步每条记录的过期时间
  133. for _, shield := range shields {
  134. if err := t.gameShieldRepo.SyncExpireTimeFromHostNextDueDate(ctx, shield.Uid, shield.HostId); err != nil {
  135. t.logger.Error("同步记录 ID=%d 的过期时间失败: %v", zap.Int("ID", shield.Id), zap.Error(err))
  136. continue
  137. }
  138. t.logger.Info("同步记录 ID=%d 的过期时间成功", zap.Int("ID", shield.Id))
  139. }
  140. return nil
  141. }
  142. // 综合处理已过期和即将过期的记录
  143. func (t gameShieldTask) CheckGameShield(ctx context.Context) error {
  144. // 先检查已过期的记录
  145. if err := t.CheckExpiredGameShields(ctx); err != nil {
  146. return err
  147. }
  148. // 再检查即将过期的记录
  149. if err := t.CheckSoonExpiredGameShields(ctx); err != nil {
  150. return err
  151. }
  152. return nil
  153. }