You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sonic/service/assembler/comment_base.go

220 lines
7.2 KiB
Go

package assembler
import (
"context"
"go.uber.org/zap"
"github.com/go-sonic/sonic/log"
"github.com/go-sonic/sonic/model/dto"
"github.com/go-sonic/sonic/model/entity"
"github.com/go-sonic/sonic/model/param"
"github.com/go-sonic/sonic/model/property"
"github.com/go-sonic/sonic/model/vo"
"github.com/go-sonic/sonic/service"
"github.com/go-sonic/sonic/util"
)
type BaseCommentAssembler interface {
ConvertToDTO(ctx context.Context, comment *entity.Comment) (*dto.Comment, error)
ConvertToDTOList(ctx context.Context, comments []*entity.Comment) ([]*dto.Comment, error)
PageConvertToVOs(ctx context.Context, comments []*entity.Comment, page param.Page) ([]*vo.Comment, int64, error)
ConvertToWithParentVO(ctx context.Context, comments []*entity.Comment) ([]*vo.CommentWithParent, error)
ConvertToWithHasChildren(ctx context.Context, comments []*entity.Comment) ([]*vo.CommentWithHasChildren, error)
ClearSensitiveField(ctx context.Context, comments []*entity.Comment) []*entity.Comment
}
func NewBaseCommentAssembler(
optionService service.OptionService,
baseCommentService service.BaseCommentService,
) BaseCommentAssembler {
return &baseCommentAssembler{
OptionService: optionService,
BaseCommentService: baseCommentService,
}
}
type baseCommentAssembler struct {
OptionService service.OptionService
BaseCommentService service.BaseCommentService
}
func (*baseCommentAssembler) ClearSensitiveField(ctx context.Context, comments []*entity.Comment) []*entity.Comment {
for _, comment := range comments {
comment.Email = ""
comment.IPAddress = ""
}
return comments
}
func (b *baseCommentAssembler) ConvertToWithHasChildren(ctx context.Context, comments []*entity.Comment) ([]*vo.CommentWithHasChildren, error) {
parentIDs := make([]int32, 0)
for _, comment := range comments {
parentIDs = append(parentIDs, comment.ID)
}
dtos, err := b.ConvertToDTOList(ctx, comments)
if err != nil {
return nil, err
}
countMap, err := b.BaseCommentService.CountChildren(ctx, parentIDs)
if err != nil {
return nil, err
}
result := make([]*vo.CommentWithHasChildren, 0, len(comments))
for _, commentDTO := range dtos {
commentWithHasChildren := &vo.CommentWithHasChildren{
Comment: commentDTO,
}
if count, ok := countMap[commentDTO.ID]; ok && count > 0 {
commentWithHasChildren.HasChildren = true
} else {
commentWithHasChildren.HasChildren = false
}
result = append(result, commentWithHasChildren)
}
return result, nil
}
func (b *baseCommentAssembler) ConvertToDTO(ctx context.Context, comment *entity.Comment) (*dto.Comment, error) {
commentDTO := &dto.Comment{
ID: comment.ID,
Author: comment.Author,
Email: comment.Email,
IPAddress: comment.IPAddress,
AuthorURL: comment.AuthorURL,
GravatarMD5: comment.GravatarMd5,
Content: comment.Content,
Status: comment.Status,
UserAgent: comment.UserAgent,
ParentID: comment.ParentID,
IsAdmin: comment.IsAdmin,
AllowNotification: comment.AllowNotification,
CreateTime: comment.CreateTime.UnixMilli(),
}
avatarURL, err := b.BaseCommentService.BuildAvatarURL(ctx, comment.GravatarMd5, nil, nil)
if err != nil {
return nil, err
}
commentDTO.Avatar = avatarURL
return commentDTO, nil
}
func (b *baseCommentAssembler) ConvertToDTOList(ctx context.Context, comments []*entity.Comment) ([]*dto.Comment, error) {
gravatarSource, err := b.OptionService.GetOrByDefaultWithErr(ctx, property.CommentGravatarSource, property.CommentGravatarSource.DefaultValue)
if err != nil {
return nil, err
}
gravatarDefault, err := b.OptionService.GetOrByDefaultWithErr(ctx, property.CommentGravatarDefault, property.CommentGravatarDefault.DefaultValue)
if err != nil {
return nil, err
}
result := make([]*dto.Comment, 0, len(comments))
for _, comment := range comments {
commentDTO := &dto.Comment{
ID: comment.ID,
Author: comment.Author,
Email: comment.Email,
IPAddress: comment.IPAddress,
AuthorURL: comment.AuthorURL,
GravatarMD5: comment.GravatarMd5,
Content: comment.Content,
Status: comment.Status,
UserAgent: comment.UserAgent,
ParentID: comment.ParentID,
IsAdmin: comment.IsAdmin,
AllowNotification: comment.AllowNotification,
CreateTime: comment.CreateTime.UnixMilli(),
}
avatarURL, err := b.BaseCommentService.BuildAvatarURL(ctx, comment.GravatarMd5, util.StringPtr(gravatarSource.(string)), util.StringPtr(gravatarDefault.(string)))
if err != nil {
return nil, err
}
commentDTO.Avatar = avatarURL
result = append(result, commentDTO)
}
return result, nil
}
func (b *baseCommentAssembler) buildCommentTree(ctx context.Context, comments []*entity.Comment) ([]*vo.Comment, error) {
commentIDMap := make(map[int32]*vo.Comment)
commentDTOs, err := b.ConvertToDTOList(ctx, comments)
if err != nil {
return nil, err
}
for _, commentDTO := range commentDTOs {
commentVO := &vo.Comment{
Comment: commentDTO,
Children: make([]*vo.Comment, 0),
}
commentIDMap[commentDTO.ID] = commentVO
}
topComments := make([]*vo.Comment, 0)
for _, comment := range comments {
if comment.ParentID != 0 {
parentComment, ok := commentIDMap[comment.ParentID]
if !ok {
log.CtxWarn(ctx, "parent comment does not exist", zap.Int32("postID", comment.PostID), zap.Int32("parentID", comment.ParentID))
continue
}
parentComment.Children = append(parentComment.Children, commentIDMap[comment.ID])
} else {
topComments = append(topComments, commentIDMap[comment.ID])
}
}
return topComments, nil
}
func (b *baseCommentAssembler) PageConvertToVOs(ctx context.Context, allComments []*entity.Comment, page param.Page) ([]*vo.Comment, int64, error) {
topComments, err := b.buildCommentTree(ctx, allComments)
if err != nil {
return nil, 0, err
}
startIndex := page.PageNum * page.PageSize
endIndex := startIndex + page.PageSize
if startIndex > len(topComments) || startIndex < 0 {
return make([]*vo.Comment, 0), 0, nil
}
if endIndex > len(topComments) {
endIndex = len(topComments)
}
return topComments[startIndex:endIndex], int64(len(topComments)), nil
}
func (b *baseCommentAssembler) ConvertToWithParentVO(ctx context.Context, comments []*entity.Comment) ([]*vo.CommentWithParent, error) {
parentIDs := make([]int32, 0)
for _, comment := range comments {
if comment.ParentID != 0 {
parentIDs = append(parentIDs, comment.ParentID)
}
}
dtos, err := b.ConvertToDTOList(ctx, comments)
if err != nil {
return nil, err
}
parentDTOMap := make(map[int32]*dto.Comment)
if len(parentIDs) > 0 {
parents, err := b.BaseCommentService.LGetByIDs(ctx, parentIDs)
if err != nil {
return nil, err
}
parentDTOs, err := b.ConvertToDTOList(ctx, parents)
if err != nil {
return nil, err
}
for _, parentDTO := range parentDTOs {
parentDTOMap[parentDTO.ID] = parentDTO
}
}
result := make([]*vo.CommentWithParent, 0, len(comments))
for _, commentDTO := range dtos {
commentWithParent := &vo.CommentWithParent{
Comment: commentDTO,
}
if parent, ok := parentDTOMap[commentDTO.ParentID]; ok {
commentWithParent.Parent = parent
}
result = append(result, commentWithParent)
}
return result, nil
}