mirror of https://github.com/go-sonic/sonic.git
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.
343 lines
12 KiB
Go
343 lines
12 KiB
Go
package impl
|
|
|
|
import (
|
|
"context"
|
|
|
|
"gorm.io/gen/field"
|
|
|
|
"github.com/go-sonic/sonic/consts"
|
|
"github.com/go-sonic/sonic/dal"
|
|
"github.com/go-sonic/sonic/event"
|
|
"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/service"
|
|
"github.com/go-sonic/sonic/util"
|
|
"github.com/go-sonic/sonic/util/xerr"
|
|
)
|
|
|
|
type baseCommentServiceImpl struct {
|
|
UserService service.UserService
|
|
OptionService service.OptionService
|
|
Event event.Bus
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) LGetByIDs(ctx context.Context, commentIDs []int32) ([]*entity.Comment, error) {
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
comments, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.In(commentIDs...)).Find()
|
|
return comments, WrapDBErr(err)
|
|
}
|
|
|
|
func NewBaseCommentService(userService service.UserService, optionService service.OptionService, event event.Bus) service.BaseCommentService {
|
|
return &baseCommentServiceImpl{
|
|
UserService: userService,
|
|
OptionService: optionService,
|
|
Event: event,
|
|
}
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) Page(ctx context.Context, commentQuery param.CommentQuery, commentType consts.CommentType) ([]*entity.Comment, int64, error) {
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
commentDO := commentDAL.WithContext(ctx).Where(commentDAL.Type.Eq(commentType))
|
|
err := BuildSort(commentQuery.Sort, &commentDAL, &commentDO)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
if commentQuery.Keyword != nil && *commentQuery.Keyword != "" {
|
|
commentDO.Where(commentDAL.Content.Like("%" + *commentQuery.Keyword + "%"))
|
|
}
|
|
if commentQuery.CommentStatus != nil {
|
|
commentDO.Where(commentDAL.Status.Eq(*commentQuery.CommentStatus))
|
|
}
|
|
if commentQuery.ParentID != nil {
|
|
commentDO.Where(commentDAL.ParentID.Eq(*commentQuery.ParentID))
|
|
}
|
|
if commentQuery.ContentID != nil {
|
|
commentDO.Where(commentDAL.PostID.Eq(*commentQuery.ContentID))
|
|
}
|
|
comments, totalCount, err := commentDO.FindByPage(commentQuery.PageNum*commentQuery.PageSize, commentQuery.PageSize)
|
|
if err != nil {
|
|
return nil, 0, WrapDBErr(err)
|
|
}
|
|
return comments, totalCount, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) Update(ctx context.Context, comment *entity.Comment) (*entity.Comment, error) {
|
|
if comment.ID == 0 {
|
|
return nil, nil
|
|
}
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
updateResult, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.Eq(comment.ID)).Updates(comment)
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
if updateResult.RowsAffected != 1 {
|
|
return nil, xerr.NoType.New("").WithMsg("update comment failed")
|
|
}
|
|
updatedComment, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.Eq(comment.ID)).First()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
return updatedComment, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) GetByID(ctx context.Context, commentID int32) (*entity.Comment, error) {
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
comment, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.Eq(commentID)).First()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
return comment, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) GetByContentID(ctx context.Context, contentID int32, commentType consts.CommentType, sort *param.Sort) ([]*entity.Comment, error) {
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
commentDO := commentDAL.WithContext(ctx).Where(commentDAL.PostID.Eq(contentID), commentDAL.Type.Eq(commentType))
|
|
|
|
err := BuildSort(sort, &commentDAL, &commentDO)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
comments, err := commentDO.Find()
|
|
return comments, WrapDBErr(err)
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) DeleteBatch(ctx context.Context, commentIDs []int32) error {
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
deleteResult, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.In(commentIDs...)).Delete()
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
if deleteResult.RowsAffected != 1 {
|
|
return xerr.NoType.New("").WithMsg("delete comment failed")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) Delete(ctx context.Context, commentID int32) error {
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
deleteResult, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.Eq(commentID)).Delete()
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
if deleteResult.RowsAffected != 1 {
|
|
return xerr.NoType.New("").WithMsg("delete comment failed")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) UpdateStatusBatch(ctx context.Context, commentIDs []int32, commentStatus consts.CommentStatus) ([]*entity.Comment, error) {
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
_, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.In(commentIDs...)).UpdateSimple(commentDAL.Status.Value(commentStatus))
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
comments, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.In(commentIDs...)).Find()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
return comments, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) UpdateStatus(ctx context.Context, commentID int32, commentStatus consts.CommentStatus) (*entity.Comment, error) {
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
comment, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.Eq(commentID)).First()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
updateResult, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.Eq(commentID)).UpdateSimple(commentDAL.Status.Value(commentStatus))
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
if updateResult.RowsAffected != 1 {
|
|
return nil, xerr.NoType.New("").WithMsg("update comment status failed")
|
|
}
|
|
comment.Status = commentStatus
|
|
if comment.ParentID != 0 {
|
|
go func() {
|
|
b.Event.Publish(context.TODO(), &event.CommentReplyEvent{
|
|
Comment: comment,
|
|
})
|
|
}()
|
|
}
|
|
return comment, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) Create(ctx context.Context, comment *entity.Comment) (*entity.Comment, error) {
|
|
if comment == nil {
|
|
return nil, xerr.BadParam.New("comment can not be empty")
|
|
}
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
if comment.ParentID != 0 {
|
|
_, err := commentDAL.WithContext(ctx).Where(commentDAL.ID.Eq(comment.ParentID)).First()
|
|
err = WrapDBErr(err)
|
|
if xerr.GetType(err) == xerr.NoRecord {
|
|
return nil, xerr.WithMsg(err, "parent comment does not exist").WithStatus(xerr.StatusNotFound)
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
comment.IPAddress = util.GetClientIP(ctx)
|
|
comment.UserAgent = util.GetUserAgent(ctx)
|
|
if comment.GravatarMd5 == "" {
|
|
comment.GravatarMd5 = util.Md5Hex(comment.Email)
|
|
}
|
|
|
|
authentication, _ := GetAuthorizedUser(ctx)
|
|
if authentication == nil {
|
|
comment.IsAdmin = false
|
|
needCheck, err := b.OptionService.GetOrByDefaultWithErr(ctx, property.CommentNewNeedCheck, true)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if needCheck.(bool) {
|
|
comment.Status = consts.CommentStatusAuditing
|
|
} else {
|
|
comment.Status = consts.CommentStatusPublished
|
|
}
|
|
} else {
|
|
comment.Email = authentication.Email
|
|
comment.Author = util.IfElse(authentication.Nickname == "", authentication.Username, authentication.Nickname).(string)
|
|
blogURL, err := b.OptionService.GetBlogBaseURL(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
comment.AuthorURL = blogURL
|
|
comment.IsAdmin = true
|
|
comment.Status = consts.CommentStatusPublished
|
|
}
|
|
comment.GravatarMd5 = util.Md5Hex(comment.Email)
|
|
err := commentDAL.WithContext(ctx).Select(field.Star).Omit(commentDAL.UpdateTime).Create(comment)
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
if comment.ParentID != 0 {
|
|
go func() {
|
|
b.Event.Publish(context.TODO(), &event.CommentReplyEvent{
|
|
Comment: comment,
|
|
})
|
|
}()
|
|
|
|
} else {
|
|
go func() {
|
|
b.Event.Publish(context.TODO(), &event.CommentNewEvent{
|
|
Comment: comment,
|
|
})
|
|
}()
|
|
}
|
|
return comment, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) BuildAvatarURL(ctx context.Context, gravatarMD5 string, gravatarSource, gravatarDefault *string) (string, error) {
|
|
var gs, gd string
|
|
if gravatarSource == nil {
|
|
temp, err := b.OptionService.GetOrByDefaultWithErr(ctx, property.CommentGravatarSource, property.CommentGravatarSource.DefaultValue)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
gs = temp.(string)
|
|
} else {
|
|
gs = *gravatarSource
|
|
}
|
|
if gravatarDefault == nil {
|
|
temp, err := b.OptionService.GetOrByDefaultWithErr(ctx, property.CommentGravatarDefault, property.CommentGravatarDefault.DefaultValue)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
gd = temp.(string)
|
|
} else {
|
|
gd = *gravatarDefault
|
|
}
|
|
|
|
return gs + gravatarMD5 + "?s=256&d=" + gd, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) ConvertParam(commentParam *param.Comment) *entity.Comment {
|
|
comment := &entity.Comment{
|
|
Author: commentParam.Author,
|
|
Email: commentParam.Email,
|
|
AuthorURL: commentParam.AuthorURL,
|
|
Content: commentParam.Content,
|
|
PostID: commentParam.PostID,
|
|
ParentID: commentParam.ParentID,
|
|
Type: commentParam.CommentType,
|
|
AllowNotification: commentParam.AllowNotification,
|
|
}
|
|
|
|
return comment
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) CountByContentID(ctx context.Context, contentID int32, commentType consts.CommentType, status consts.CommentStatus) (int64, error) {
|
|
postCommentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
count, err := postCommentDAL.WithContext(ctx).Where(postCommentDAL.PostID.Eq(contentID), postCommentDAL.Type.Eq(commentType), postCommentDAL.Status.Eq(status)).Count()
|
|
if err != nil {
|
|
return 0, WrapDBErr(err)
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) CountByStatusAndContentIDs(ctx context.Context, status consts.CommentStatus, contentIDs []int32) (map[int32]int64, error) {
|
|
var projections []struct {
|
|
PostID int32
|
|
CommentCount int64 `gorm:"column:comment_count"`
|
|
}
|
|
|
|
postCommentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
err := postCommentDAL.WithContext(ctx).Select(postCommentDAL.PostID, postCommentDAL.ID.Count().As("comment_count")).Where(postCommentDAL.Status.Eq(status), postCommentDAL.PostID.In(contentIDs...)).Group(postCommentDAL.PostID).Scan(&projections)
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
result := make(map[int32]int64)
|
|
for _, projection := range projections {
|
|
result[projection.PostID] = projection.CommentCount
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (b baseCommentServiceImpl) CreateBy(ctx context.Context, commentParam *param.Comment) (*entity.Comment, error) {
|
|
comment := b.ConvertParam(commentParam)
|
|
return b.Create(ctx, comment)
|
|
}
|
|
|
|
func (*baseCommentServiceImpl) CountChildren(ctx context.Context, parentCommentIDs []int32) (map[int32]int64, error) {
|
|
var projections []struct {
|
|
ParentID int32
|
|
CommentCount int64
|
|
}
|
|
|
|
commentDAL := dal.GetQueryByCtx(ctx).Comment
|
|
err := commentDAL.WithContext(ctx).Select(commentDAL.ParentID, commentDAL.ID.Count()).Where(commentDAL.Status.Eq(consts.CommentStatusPublished), commentDAL.ID.In(parentCommentIDs...)).Group(commentDAL.ParentID).Scan(&projections)
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
result := make(map[int32]int64)
|
|
for _, projection := range projections {
|
|
result[projection.ParentID] = projection.CommentCount
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (b *baseCommentServiceImpl) GetChildren(ctx context.Context, parentCommentID int32, contentID int32, commentType consts.CommentType) ([]*entity.Comment, error) {
|
|
allComments, err := b.GetByContentID(ctx, int32(contentID), commentType, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
children := make([]*entity.Comment, 0)
|
|
parentIDMap := make(map[int32][]*entity.Comment, 0)
|
|
for _, comment := range allComments {
|
|
parentIDMap[comment.ParentID] = append(parentIDMap[comment.ParentID], comment)
|
|
}
|
|
queue := util.NewQueue[int32]()
|
|
queue.Push(parentCommentID)
|
|
for !queue.IsEmpty() {
|
|
parentID := queue.Next()
|
|
children = append(children, parentIDMap[parentID]...)
|
|
for _, child := range parentIDMap[parentID] {
|
|
queue.Push(child.ID)
|
|
}
|
|
}
|
|
return children, nil
|
|
}
|