418 lines
12 KiB
Go
418 lines
12 KiB
Go
package srv_commend
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"time"
|
|
"videoweb/pub/common/enum/redisconst"
|
|
"videoweb/pub/common/log"
|
|
"videoweb/pub/common/srvdef"
|
|
"videoweb/pub/models/commentlikemod"
|
|
"videoweb/pub/models/commentmod"
|
|
"videoweb/pub/models/playletchaptermod"
|
|
"videoweb/pub/models/playletmod"
|
|
"videoweb/pub/models/videoinformationmod"
|
|
"videoweb/pub/mongos"
|
|
"videoweb/pub/pubdef"
|
|
"videoweb/pub/redis"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
func SearchComandList(ctx context.Context, param *CommendSearch) (*CommendSearchResp, *srvdef.SrvErr) {
|
|
|
|
filter := bson.M{}
|
|
opt := &options.FindOptions{}
|
|
|
|
if param.ObjectId != nil {
|
|
filter[commentmod.FN.Comment.ObjectId] = *param.ObjectId
|
|
}
|
|
if param.ObjectType != nil {
|
|
filter[commentmod.FN.Comment.ObjectType] = *param.ObjectType
|
|
}
|
|
if param.Level != nil {
|
|
filter[commentmod.FN.Comment.Level] = *param.Level
|
|
}
|
|
|
|
if param.UserName != nil {
|
|
filter[commentmod.FN.Comment.UserName] = bson.M{"$regex": *param.UserName}
|
|
}
|
|
if param.Text != nil {
|
|
filter[commentmod.FN.Comment.Text] = bson.M{"$regex": *param.Text}
|
|
}
|
|
|
|
if param.ReviewStatus != nil {
|
|
filter[commentmod.FN.Comment.ReviewStatus] = *param.ReviewStatus
|
|
}
|
|
|
|
sort := bson.D{
|
|
{commentmod.FN.Comment.TopRank, -1},
|
|
{commentmod.FN.Comment.CreatedAt, -1},
|
|
}
|
|
|
|
opt.SetSort(sort)
|
|
skip := (param.PageNum - 1) * param.PageSize
|
|
opt.SetSkip(skip)
|
|
opt.SetLimit(param.PageSize)
|
|
|
|
total, serr := commentmod.CountComments(ctx, filter)
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
if total == 0 {
|
|
return &CommendSearchResp{}, nil
|
|
}
|
|
|
|
commends, serr := commentmod.FindManyComment(ctx, filter, opt)
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
|
|
resp := &CommendSearchResp{
|
|
Total: total,
|
|
List: make([]*PostCommentInfo, 0),
|
|
}
|
|
|
|
for _, commendInfo := range commends {
|
|
tmp := &PostCommentInfo{
|
|
Id: commendInfo.Id,
|
|
ObjectId: commendInfo.ObjectId,
|
|
ObjectName: commendInfo.ObjectName,
|
|
UserName: commendInfo.UserName,
|
|
Level: commendInfo.Level,
|
|
ParentsId: commendInfo.ParentsId,
|
|
ReplyUserName: commendInfo.ReplyUserName,
|
|
Text: commendInfo.Text,
|
|
ReviewStatus: commendInfo.ReviewStatus,
|
|
UpdatedAt: commendInfo.UpdatedAt,
|
|
Ip: commendInfo.Ip,
|
|
CreatedAt: commendInfo.CreatedAt,
|
|
ObjectType: commendInfo.ObjectType,
|
|
Likes: commendInfo.CountLike,
|
|
}
|
|
resp.List = append(resp.List, tmp)
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
// DelCommend 删除一条评论
|
|
func DelCommend(ctx context.Context, commendId int64) *srvdef.SrvErr {
|
|
commendInfo, serr := commentmod.FindOneComment(ctx, bson.M{commentmod.FN.Comment.Id: commendId})
|
|
if serr != nil {
|
|
return serr
|
|
}
|
|
_, serr = commentmod.DelOneComment(ctx, bson.M{commentmod.FN.Comment.Id: commendId})
|
|
if serr != nil {
|
|
return serr
|
|
}
|
|
if serr = commentlikemod.DeleteByCommentIds(ctx, []int64{commendId}); serr != nil {
|
|
return serr
|
|
}
|
|
clearCommentListCacheByComments(commentmod.CommentModelList{commendInfo})
|
|
|
|
if err := refreshParentReplyCounts(ctx, commentmod.CommentModelList{commendInfo}); err != nil {
|
|
return err
|
|
}
|
|
return updateCommentCountByComments(ctx, commentmod.CommentModelList{commendInfo})
|
|
}
|
|
|
|
// DelCommend 删除用户所有评论
|
|
func DelUserCommend(ctx context.Context, ip string) *srvdef.SrvErr {
|
|
commendList, serr := commentmod.FindManyComment(ctx, bson.M{commentmod.FN.Comment.Ip: ip})
|
|
if serr != nil {
|
|
return serr
|
|
}
|
|
_, serr = commentmod.DelManyComment(ctx, bson.M{commentmod.FN.Comment.Ip: ip})
|
|
if serr != nil {
|
|
return serr
|
|
}
|
|
if serr = commentlikemod.DeleteByCommentIds(ctx, commentIdsFromModels(commendList)); serr != nil {
|
|
return serr
|
|
}
|
|
clearCommentListCacheByComments(commendList)
|
|
|
|
if err := refreshParentReplyCounts(ctx, commendList); err != nil {
|
|
return err
|
|
}
|
|
return updateCommentCountByComments(ctx, commendList)
|
|
}
|
|
|
|
func commentIdsFromModels(comments commentmod.CommentModelList) []int64 {
|
|
ids := make([]int64, 0, len(comments))
|
|
for _, comment := range comments {
|
|
if comment != nil {
|
|
ids = append(ids, comment.Id)
|
|
}
|
|
}
|
|
return ids
|
|
}
|
|
|
|
// AddPostComment 发布评论
|
|
func AddPostComment(ctx context.Context, req *CommendReplay) *srvdef.SrvErr {
|
|
now := time.Now()
|
|
if req.Score > 10 {
|
|
log.Error("AddPostComment ErrParamError", log.Any("Score", req.Score))
|
|
return srvdef.New(srvdef.ErrParamError, "", "")
|
|
}
|
|
|
|
// 2. 生成评论相关信息
|
|
commentInfo := &commentmod.CommentModel{
|
|
Id: mongos.Lid.Comment.Get(),
|
|
ObjectId: req.ObjectId,
|
|
ObjectType: pubdef.CommentObjectTypeVideo,
|
|
ObjectName: pubdef.CommentObjectTypeName(pubdef.CommentObjectTypeVideo),
|
|
UserName: req.UserName,
|
|
ParentsId: req.ParentsId,
|
|
Text: req.Text,
|
|
Level: 1,
|
|
UpdatedAt: now,
|
|
CreatedAt: now,
|
|
}
|
|
|
|
if commentInfo.ParentsId > 0 {
|
|
commentInfo.Level = 2
|
|
} else {
|
|
commentInfo.Level = 1
|
|
}
|
|
commentInfo.ReviewStatus = 1 // 管理端的默认审核通过
|
|
|
|
// 3. 插入数据库
|
|
serr := commentmod.InsertOneComment(ctx, commentInfo)
|
|
if serr != nil {
|
|
log.Error("AddPostComment InsertOnePostComment", log.Any("req", req), log.Any("err", serr))
|
|
return serr
|
|
}
|
|
clearCommentListCacheByComments(commentmod.CommentModelList{commentInfo})
|
|
|
|
go func() {
|
|
_ = updateCommentCountByComments(ctx, commentmod.CommentModelList{commentInfo})
|
|
|
|
// 4. 修改回复条数
|
|
if req.ParentsId > 0 {
|
|
filter := bson.M{
|
|
commentmod.FN.Comment.Id: req.ParentsId,
|
|
}
|
|
updateDoc := bson.M{
|
|
"$inc": bson.M{
|
|
commentmod.FN.Comment.CommentCount: 1,
|
|
},
|
|
}
|
|
serr = commentmod.UpdateOneComment(ctx, filter, updateDoc)
|
|
if serr != nil {
|
|
log.Error("AddPostComment UpdateOnePostComment", log.Any("req", req), log.Any("err", serr))
|
|
return
|
|
}
|
|
}
|
|
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
// 置顶评论
|
|
func TopPostComment(ctx context.Context, id int64) *srvdef.SrvErr {
|
|
filter := bson.M{
|
|
commentmod.FN.Comment.Id: id,
|
|
}
|
|
comment, serr := commentmod.FindOneComment(ctx, filter)
|
|
if serr != nil {
|
|
return serr
|
|
}
|
|
//获取置顶的一条评论
|
|
topRankComment, serr := getTopRankComment(ctx, comment.ObjectId)
|
|
if serr != nil {
|
|
return serr
|
|
}
|
|
if topRankComment.Id == id && topRankComment.TopRank != 0 {
|
|
return nil
|
|
}
|
|
serr = commentmod.UpdateOneComment(ctx, filter, bson.M{
|
|
"$set": bson.M{
|
|
commentmod.FN.Comment.TopRank: topRankComment.TopRank + 1,
|
|
},
|
|
})
|
|
if serr != nil {
|
|
return serr
|
|
}
|
|
clearCommentListCacheByComments(commentmod.CommentModelList{comment})
|
|
return nil
|
|
}
|
|
|
|
func getTopRankComment(ctx context.Context, objectId int64) (*commentmod.CommentModel, *srvdef.SrvErr) {
|
|
filter := bson.M{
|
|
commentmod.FN.Comment.ObjectId: objectId,
|
|
}
|
|
opts := options.FindOne().SetSort(bson.M{
|
|
commentmod.FN.Comment.TopRank: -1,
|
|
})
|
|
comment, serr := commentmod.FindOneComment(ctx, filter, opts)
|
|
if serr != nil {
|
|
return nil, serr
|
|
}
|
|
return comment, nil
|
|
}
|
|
|
|
func ReviewComment(ctx context.Context, id int64, reviewStatus int) *srvdef.SrvErr {
|
|
comment, err := commentmod.FindOneComment(ctx, bson.M{commentmod.FN.Comment.Id: id})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
updateDoc := bson.M{
|
|
commentmod.FN.Comment.ReviewStatus: reviewStatus,
|
|
}
|
|
filter := bson.M{
|
|
commentmod.FN.Comment.Id: id,
|
|
}
|
|
serr := commentmod.UpdateOneComment(ctx, filter, bson.M{"$set": updateDoc})
|
|
if serr != nil {
|
|
log.Error("审核评论失败", log.Any("id", id), log.Any("reviewStatus", reviewStatus), log.Any("err", serr))
|
|
return serr
|
|
}
|
|
|
|
clearCommentListCacheByComments(commentmod.CommentModelList{comment})
|
|
if comment.ReviewStatus != reviewStatus {
|
|
if err := refreshParentReplyCounts(ctx, commentmod.CommentModelList{comment}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return updateCommentCountByComments(ctx, commentmod.CommentModelList{comment})
|
|
}
|
|
|
|
// ReviewCommendBatch 批量更新
|
|
func ReviewCommendBatch(ctx context.Context, commendIds *[]int64, reviewStatus int) *srvdef.SrvErr {
|
|
if commendIds == nil || len(*commendIds) == 0 {
|
|
return srvdef.New(srvdef.ErrParamError, "", "")
|
|
}
|
|
commentList, err := commentmod.FindManyComment(ctx, bson.M{
|
|
commentmod.FN.Comment.Id: bson.M{"$in": *commendIds},
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
updateDoc := bson.M{
|
|
commentmod.FN.Comment.ReviewStatus: reviewStatus,
|
|
}
|
|
filter := bson.M{commentmod.FN.Comment.Id: bson.M{"$in": commendIds}}
|
|
serr := commentmod.UpdateManyComment(ctx, filter, bson.M{"$set": updateDoc})
|
|
if serr != nil {
|
|
log.Error("批量审核评论失败", log.Any("commendId", *commendIds), log.Any("reviewStatus", reviewStatus), log.Any("err", serr))
|
|
return serr
|
|
}
|
|
|
|
clearCommentListCacheByComments(commentList)
|
|
if err := refreshParentReplyCounts(ctx, commentList); err != nil {
|
|
return err
|
|
}
|
|
return updateCommentCountByComments(ctx, commentList)
|
|
}
|
|
|
|
// refreshParentReplyCounts 按已审核的直接回复重算父评论回复数
|
|
func refreshParentReplyCounts(ctx context.Context, comments commentmod.CommentModelList) *srvdef.SrvErr {
|
|
seen := make(map[int64]struct{}, len(comments))
|
|
for _, comment := range comments {
|
|
if comment == nil || comment.ParentsId <= 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[comment.ParentsId]; ok {
|
|
continue
|
|
}
|
|
seen[comment.ParentsId] = struct{}{}
|
|
count, err := commentmod.CountComments(ctx, bson.M{
|
|
commentmod.FN.Comment.ParentsId: comment.ParentsId,
|
|
commentmod.FN.Comment.ReviewStatus: 1,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := commentmod.UpdateOneComment(ctx,
|
|
bson.M{commentmod.FN.Comment.Id: comment.ParentsId},
|
|
bson.M{"$set": bson.M{commentmod.FN.Comment.CommentCount: count}}); err != nil && err.Code != srvdef.ErrNoData {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// clearCommentListCacheByComments 按对象ID和对象类型精确清理评论列表缓存
|
|
func clearCommentListCacheByComments(commentList commentmod.CommentModelList) {
|
|
seen := make(map[string]struct{}, len(commentList))
|
|
for _, comment := range commentList {
|
|
if comment == nil {
|
|
continue
|
|
}
|
|
key := commentCacheUniqueKey(comment.ObjectId, comment.ObjectType)
|
|
if _, ok := seen[key]; ok {
|
|
continue
|
|
}
|
|
seen[key] = struct{}{}
|
|
cacheKey := redisconst.CommentListCacheKey(comment.ObjectId, comment.ObjectType)
|
|
if err := redis.Del(cacheKey); err != nil {
|
|
log.Warn("清理评论列表缓存失败", log.Any("cacheKey", cacheKey), log.E(err))
|
|
}
|
|
}
|
|
}
|
|
|
|
// commentCacheUniqueKey 生成对象维度去重key,避免批量审核时重复清理同一对象缓存
|
|
func commentCacheUniqueKey(objectId int64, objectType pubdef.CommentObjectType) string {
|
|
return strconv.FormatInt(objectId, 10) + "_" + strconv.FormatInt(int64(objectType), 10)
|
|
}
|
|
|
|
// UpdateCommentCount 评论审核通过/删除后,同步更新对应媒体内容的真实评论数
|
|
// objectType: 0=视频 4=短剧 11=短剧剧集
|
|
func UpdateCommentCount(ctx context.Context, commendIds []int64) *srvdef.SrvErr {
|
|
commentList, _ := commentmod.FindManyComment(ctx, bson.M{
|
|
commentmod.FN.Comment.Id: bson.M{"$in": commendIds},
|
|
})
|
|
return updateCommentCountByComments(ctx, commentList)
|
|
}
|
|
|
|
func updateCommentCountByComments(ctx context.Context, commentList commentmod.CommentModelList) *srvdef.SrvErr {
|
|
seen := make(map[string]struct{}, len(commentList))
|
|
for _, comment := range commentList {
|
|
if comment == nil {
|
|
continue
|
|
}
|
|
key := commentCacheUniqueKey(comment.ObjectId, comment.ObjectType)
|
|
if _, ok := seen[key]; ok {
|
|
continue
|
|
}
|
|
seen[key] = struct{}{}
|
|
count, countErr := commentmod.CountComments(ctx, bson.M{
|
|
commentmod.FN.Comment.ObjectId: comment.ObjectId,
|
|
commentmod.FN.Comment.ObjectType: comment.ObjectType,
|
|
commentmod.FN.Comment.ReviewStatus: 1,
|
|
})
|
|
if countErr != nil {
|
|
return countErr
|
|
}
|
|
var serr *srvdef.SrvErr
|
|
switch comment.ObjectType {
|
|
case pubdef.CommentObjectTypeVideo:
|
|
serr = videoinformationmod.UpdateOneVideoInformation(ctx,
|
|
bson.M{videoinformationmod.FN.VideoInformation.Id: comment.ObjectId},
|
|
bson.M{"$set": bson.M{videoinformationmod.FN.VideoInformation.Real.Comments: count}},
|
|
)
|
|
case pubdef.CommentObjectTypePlaylet:
|
|
serr = playletmod.UpdateOnePlaylet(ctx,
|
|
bson.M{playletmod.FN.Playlet.Id: comment.ObjectId},
|
|
bson.M{"$set": bson.M{playletmod.FN.Playlet.CountComment: count}},
|
|
)
|
|
case pubdef.CommentObjectTypePlayletChapter:
|
|
serr = playletchaptermod.UpdateOnePlayletChapter(ctx,
|
|
bson.M{playletchaptermod.FN.PlayletChapter.Id: comment.ObjectId},
|
|
bson.M{"$set": bson.M{playletchaptermod.FN.PlayletChapter.CountComment: count}},
|
|
)
|
|
}
|
|
if serr != nil {
|
|
log.Error("UpdateCommentCount 更新评论数失败",
|
|
log.Any("objectId", comment.ObjectId),
|
|
log.Any("objectType", comment.ObjectType),
|
|
log.Any("err", serr),
|
|
)
|
|
return serr
|
|
}
|
|
}
|
|
return nil
|
|
}
|