Files
web_hgdjb_server/app/middleware/visit/visit.go
T
2026-11-07 10:47:32 +08:00

115 lines
3.3 KiB
Go

package visit
import (
"context"
"strings"
"time"
"videoweb/app/middleware/reptilerecord"
"videoweb/pub/common/enum/consts"
"videoweb/pub/common/enum/redisconst"
"videoweb/pub/common/ipaddr"
"videoweb/pub/common/srvdef"
"videoweb/pub/common/useragent"
"videoweb/pub/common/utils"
"videoweb/pub/models/usermod"
"videoweb/pub/models/uservisitlog"
"videoweb/pub/redis"
"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
}
}