115 lines
3.3 KiB
Go
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
|
|
}
|
|
}
|