package visit import ( "context" "hkdj-web-server/app/middleware/reptilerecord" "hkdj-web-server/pub/common/enum/consts" "hkdj-web-server/pub/common/enum/redisconst" "hkdj-web-server/pub/common/ipaddr" "hkdj-web-server/pub/common/srvdef" "hkdj-web-server/pub/common/useragent" "hkdj-web-server/pub/common/utils" "hkdj-web-server/pub/models/usermod" "hkdj-web-server/pub/models/uservisitlog" "hkdj-web-server/pub/redis" "strings" "time" "github.com/gin-gonic/gin" "go.mongodb.org/mongo-driver/bson/primitive" ) // Visit 用户日活访问中间件:每天首次访问写入 user_visit_log func Visit(ctx *gin.Context) { if reptilerecord.IsBot(ctx) { return } val, ok := ctx.Get(consts.CtxUA) if !ok { return } ua, ok := val.(useragent.UA) if !ok { return } RecordDailyVisit(ctx, ctx.GetInt64(consts.CtxUserID), ua, ipaddr.ResolveClientIP(ctx)) } // RecordDailyVisit 当天首次访问写入 user_visit_log,游客新建成功后也会立刻记一笔。 func RecordDailyVisit(ctx context.Context, userId int64, ua useragent.UA, ip string) { if userId <= 0 { return } now := time.Now() userVisitLogKey := redisconst.UserVisitLogKey(userId, now) exist, err := redis.Exists(userVisitLogKey) if err != nil || exist { return } visitInfo := &uservisitlog.UserVisitLog{ Id: primitive.NewObjectID(), UserId: userId, SysType: ua.SysType, DevType: ua.DevType, DevID: ua.DevID, Version: ua.Ver, IP: ip, VisitAt: now, } if serr := uservisitlog.InsertOneVisitLog(ctx, visitInfo); serr != nil { return } if serr := userVisitStatus(ctx, userId, ua, visitInfo.IP, visitInfo.VisitAt); serr != nil { return } _ = redis.Set(userVisitLogKey, "1", utils.BeginOfToday().Add(24*time.Hour).Sub(now)+5*time.Minute) } func userVisitStatus(ctx context.Context, uId int64, ua useragent.UA, ip string, visitTime time.Time) *srvdef.SrvErr { uFilter := primitive.M{usermod.FN.User.Id: uId} user, serr := usermod.FindOneUser(ctx, uFilter) if serr != nil { return serr } todayZero := utils.BeginOfToday() yesterdayZero := todayZero.AddDate(0, 0, -1) setDoc := primitive.M{ usermod.FN.User.AppVer: ua.Ver, usermod.FN.User.SysType: ua.SysType, usermod.FN.User.Device: ua.DevType, usermod.FN.User.LastIp: ip, usermod.FN.User.LastLoginAt: visitTime, } mergeUAExtFields(setDoc, user, ua) var updateDoc primitive.M if user.LastLoginAt.Before(todayZero) && user.LastLoginAt.After(yesterdayZero) { updateDoc = primitive.M{ "$inc": primitive.M{usermod.FN.User.ConsecutiveLogin: 1}, "$set": setDoc, } } else { setDoc[usermod.FN.User.ConsecutiveLogin] = int64(1) updateDoc = primitive.M{"$set": setDoc} } return usermod.UpdateOneUser(ctx, uFilter, updateDoc) } func mergeUAExtFields(setDoc primitive.M, user *usermod.User, ua useragent.UA) { if v := strings.TrimSpace(ua.SessionID); v != "" && v != user.SessionID { setDoc[usermod.FN.User.SessionID] = v } if v := strings.TrimSpace(ua.DeviceBrand); v != "" && v != user.DeviceBrand { setDoc[usermod.FN.User.DeviceBrand] = v } if v := strings.TrimSpace(ua.DeviceModel); v != "" && v != user.DeviceModel { setDoc[usermod.FN.User.DeviceModel] = v } if v := strings.TrimSpace(ua.SystemName); v != "" && v != user.SystemName { setDoc[usermod.FN.User.SystemName] = v } if v := strings.TrimSpace(ua.SystemVersion); v != "" && v != user.SystemVersion { setDoc[usermod.FN.User.SystemVersion] = v } }