Files
2026-10-26 16:28:14 +08:00

203 lines
7.2 KiB
Go

package models
import (
"context"
"fmt"
"time"
"videoweb/pub/common/log"
"videoweb/pub/common/srvdef"
"videoweb/pub/models/actress"
"videoweb/pub/models/announcementmod"
"videoweb/pub/models/cfg"
"videoweb/pub/models/commentlikemod"
"videoweb/pub/models/commentmod"
"videoweb/pub/models/contactusmod"
"videoweb/pub/models/contenttagmod"
"videoweb/pub/models/detailnavmod"
"videoweb/pub/models/esmod"
"videoweb/pub/models/eventmod"
"videoweb/pub/models/homebannermod"
"videoweb/pub/models/hotnavmod"
"videoweb/pub/models/ipblackmod"
"videoweb/pub/models/ipdailystatmod"
"videoweb/pub/models/m3u8requestlogmod"
"videoweb/pub/models/mwacc"
"videoweb/pub/models/oplog"
"videoweb/pub/models/playletbackflowstatmod"
"videoweb/pub/models/playletcategorymod"
"videoweb/pub/models/playletchaptermod"
"videoweb/pub/models/playletfavoritemod"
"videoweb/pub/models/playlethomeconfigmod"
"videoweb/pub/models/playletlikemod"
"videoweb/pub/models/playletmod"
"videoweb/pub/models/playlettagmod"
"videoweb/pub/models/playletthememod"
"videoweb/pub/models/questionnairemod"
"videoweb/pub/models/richtextcontentmod"
"videoweb/pub/models/seopushmod"
"videoweb/pub/models/syncfilemod"
"videoweb/pub/models/translationcategorymod"
"videoweb/pub/models/translationmod"
"videoweb/pub/models/userlogin"
"videoweb/pub/models/usermod"
"videoweb/pub/models/videocategorymod"
"videoweb/pub/models/videocollectionmediamod"
"videoweb/pub/models/videocreatermod"
"videoweb/pub/models/videofavoritemod"
"videoweb/pub/mongos"
"videoweb/pub/models/videoinformationmod"
"videoweb/pub/models/videolikemod"
"videoweb/pub/models/videotagmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func Init() {
log.Info("models init start..")
ctx := context.Background()
cfg.Init(ctx)
mwacc.Init(ctx)
oplog.Init(ctx)
m3u8requestlogmod.Init(ctx)
videocategorymod.Init(ctx)
videoinformationmod.Init(ctx)
videofavoritemod.Init(ctx)
videolikemod.Init(ctx)
videotagmod.Init(ctx)
translationcategorymod.Init(ctx)
translationmod.Init(ctx)
contenttagmod.Init(ctx)
playletcategorymod.Init(ctx)
playlethomeconfigmod.Init(ctx)
playlettagmod.Init(ctx)
playletthememod.Init(ctx)
playletmod.Init(ctx)
playletbackflowstatmod.Init(ctx)
playletchaptermod.Init(ctx)
playletlikemod.Init(ctx)
playletfavoritemod.Init(ctx)
initWatchHistory(ctx)
videocategorymod.Init(ctx)
videocreatermod.Init(ctx)
videotagmod.Init(ctx)
videoinformationmod.Init(ctx)
videocreatermod.Init(ctx)
syncfilemod.Init(ctx)
seopushmod.Init(ctx)
richtextcontentmod.Init(ctx)
announcementmod.Init(ctx)
commentmod.Init(ctx)
commentlikemod.Init(ctx)
videocollectionmediamod.Init(ctx)
ipblackmod.Init(ctx)
esmod.Init(ctx)
actress.Init(ctx)
contactusmod.Init(ctx)
detailnavmod.Init(ctx)
hotnavmod.Init(ctx)
homebannermod.Init(ctx)
eventmod.Init(ctx)
usermod.Init(ctx)
userlogin.Init(ctx)
questionnairemod.Init(ctx)
ipdailystatmod.Init(ctx)
log.Info("models init end")
}
const (
WatchHistoryTypePlaylet int64 = 1
WatchHistoryTypeVideo int64 = 2
WatchHistoryRetentionDays = 60
watchHistoryCollectionName = "watch_history"
WatchHistoryCollectionName = watchHistoryCollectionName
WatchHistoryUserID = "userId"
WatchHistoryDataType = "dataType"
WatchHistoryContentID = "contentId"
WatchHistoryChapterID = "chapterId"
WatchHistoryEpisode = "episode"
WatchHistoryCreatedAt = "createdAt"
WatchHistoryUpdatedAt = "updatedAt"
)
// WatchHistory 保存当前用户最近观看的内容
type WatchHistory struct {
UserID int64 `bson:"userId"`
DataType int64 `bson:"dataType"`
ContentID int64 `bson:"contentId"`
ChapterID int64 `bson:"chapterId"`
Episode int64 `bson:"episode"`
CreatedAt time.Time `bson:"createdAt"`
UpdatedAt time.Time `bson:"updatedAt"`
}
var watchHistoryColl *mongos.Collection
// initWatchHistory 初始化观看历史及 60 天 TTL 索引
func initWatchHistory(ctx context.Context) {
watchHistoryColl = mongos.Shop.Coll(watchHistoryCollectionName)
indexes := []mongo.IndexModel{
{Keys: bson.D{{Key: WatchHistoryUserID, Value: 1}, {Key: WatchHistoryDataType, Value: 1}, {Key: WatchHistoryContentID, Value: 1}}, Options: options.Index().SetUnique(true)},
{Keys: bson.D{{Key: WatchHistoryUserID, Value: 1}, {Key: WatchHistoryDataType, Value: 1}, {Key: WatchHistoryUpdatedAt, Value: -1}, {Key: "_id", Value: -1}}},
{Keys: bson.D{{Key: WatchHistoryUpdatedAt, Value: 1}}, Options: options.Index().SetExpireAfterSeconds(WatchHistoryRetentionDays * 24 * 60 * 60)},
}
if _, err := watchHistoryColl.CreateIndex(ctx, indexes); err != nil {
panic(fmt.Sprintf("(models:initWatchHistory) Create Index failed! err:%+v:", err))
}
}
// TouchWatchHistory 从已验证的播放清单刷新历史
func TouchWatchHistory(ctx context.Context, item WatchHistory) *srvdef.SrvErr {
filter := bson.M{WatchHistoryUserID: item.UserID, WatchHistoryDataType: item.DataType, WatchHistoryContentID: item.ContentID}
if item.DataType == WatchHistoryTypePlaylet {
sameChapter := bson.M{WatchHistoryUserID: item.UserID, WatchHistoryDataType: item.DataType, WatchHistoryContentID: item.ContentID, WatchHistoryChapterID: item.ChapterID}
result, err := watchHistoryColl.UpdateOne(ctx, sameChapter, bson.M{"$set": bson.M{WatchHistoryUpdatedAt: item.UpdatedAt, WatchHistoryEpisode: item.Episode}})
if err != nil {
log.Warn("TouchWatchHistory failed", log.Any("filter", sameChapter), log.E(err))
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
if result.MatchedCount > 0 {
return nil
}
}
update := bson.M{
"$set": bson.M{WatchHistoryChapterID: item.ChapterID, WatchHistoryEpisode: item.Episode, WatchHistoryUpdatedAt: item.UpdatedAt},
"$setOnInsert": bson.M{WatchHistoryUserID: item.UserID, WatchHistoryDataType: item.DataType, WatchHistoryContentID: item.ContentID, WatchHistoryCreatedAt: item.CreatedAt},
}
if _, err := watchHistoryColl.UpdateOne(ctx, filter, update, options.Update().SetUpsert(true)); err != nil {
if mongo.IsDuplicateKeyError(err) {
_, err = watchHistoryColl.UpdateOne(ctx, filter, bson.M{"$set": update["$set"]})
if err == nil {
return nil
}
}
log.Warn("TouchWatchHistory failed", log.Any("filter", filter), log.E(err))
return srvdef.New(srvdef.ErrDbUpdateError, "", "")
}
return nil
}
// AggregateWatchHistory 聚合查询观看历史
func AggregateWatchHistory(ctx context.Context, bind interface{}, pipeline []bson.M) *srvdef.SrvErr {
if err := watchHistoryColl.Aggregate(ctx, bind, pipeline); err != nil {
log.Warn("AggregateWatchHistory failed", log.Any("pipeline", pipeline), log.E(err))
return srvdef.New(srvdef.ErrDbQueryError, "", "")
}
return nil
}
// DeleteWatchHistory 删除当前用户指定类型的观看历史
func DeleteWatchHistory(ctx context.Context, userID, dataType int64) (int64, *srvdef.SrvErr) {
filter := bson.M{WatchHistoryUserID: userID, WatchHistoryDataType: dataType}
count, err := watchHistoryColl.DeleteMany(ctx, filter)
if err != nil {
log.Warn("DeleteWatchHistory failed", log.Any("filter", filter), log.E(err))
return 0, srvdef.New(srvdef.ErrDbDeleteError, "", "")
}
return count, nil
}