diff --git a/internal/controller/v1/comment.go b/internal/controller/v1/comment.go index ff9bd9f..fbfe06a 100644 --- a/internal/controller/v1/comment.go +++ b/internal/controller/v1/comment.go @@ -31,6 +31,7 @@ func (cc *CommentController) CreateComment(ctx context.Context, c *app.RequestCo resps.BadRequest(c, err.Error()) return } + req.RemoteAddr = c.RemoteAddr().String() commentID, err := cc.service.CreateComment(ctx, &req) if err != nil { serviceErr := errs.AsServiceError(err) diff --git a/internal/dto/comment.go b/internal/dto/comment.go index d55d44f..7a26f67 100644 --- a/internal/dto/comment.go +++ b/internal/dto/comment.go @@ -22,6 +22,7 @@ type CreateCommentReq struct { Content string `json:"content" binding:"required"` // 评论内容 ReplyID uint `json:"reply_id"` // 回复的评论ID IsPrivate bool `json:"is_private"` // 是否私密评论,默认false + RemoteAddr string `json:"remote_addr"` // 远程地址 } type UpdateCommentReq struct { diff --git a/internal/model/comment.go b/internal/model/comment.go index 9685d67..902d953 100644 --- a/internal/model/comment.go +++ b/internal/model/comment.go @@ -14,6 +14,7 @@ type Comment struct { Content string `gorm:"type:text"` // 评论内容 Depth int `gorm:"default:0"` // 评论的层级深度,从0开始计数 IsPrivate bool `gorm:"default:false"` // 是否为私密评论,私密评论只有评论者和被评论对象所有者可见 + RemoteAddr string `gorm:"type:text"` // 远程地址 LikeCount uint64 CommentCount uint64 } diff --git a/internal/router/apiv1/comment.go b/internal/router/apiv1/comment.go index 13909c8..4079c7b 100644 --- a/internal/router/apiv1/comment.go +++ b/internal/router/apiv1/comment.go @@ -14,7 +14,7 @@ func registerCommentRoutes(group *route.RouterGroup) { commentGroup.POST("/c", commentController.CreateComment) commentGroup.PUT("/c/:id", commentController.UpdateComment) commentGroup.DELETE("/c/:id", commentController.DeleteComment) - commentGroup.PUT("/c/:id/react", commentController.ReactComment) // 暂时先不写 + commentGroup.PUT("/c/:id/react", commentController.ReactComment) commentGroupWithoutAuth.GET("/c/:id", commentController.GetComment) commentGroupWithoutAuth.GET("/list", commentController.GetCommentList) } diff --git a/internal/service/comment.go b/internal/service/comment.go index b4ebf77..a839aea 100644 --- a/internal/service/comment.go +++ b/internal/service/comment.go @@ -1,177 +1,178 @@ package service import ( - "context" - "strconv" + "context" + "strconv" - "github.com/snowykami/neo-blog/pkg/constant" + "github.com/snowykami/neo-blog/pkg/constant" - "github.com/snowykami/neo-blog/internal/ctxutils" - "github.com/snowykami/neo-blog/internal/dto" - "github.com/snowykami/neo-blog/internal/model" - "github.com/snowykami/neo-blog/internal/repo" - "github.com/snowykami/neo-blog/pkg/errs" + "github.com/snowykami/neo-blog/internal/ctxutils" + "github.com/snowykami/neo-blog/internal/dto" + "github.com/snowykami/neo-blog/internal/model" + "github.com/snowykami/neo-blog/internal/repo" + "github.com/snowykami/neo-blog/pkg/errs" ) type CommentService struct{} func NewCommentService() *CommentService { - return &CommentService{} + return &CommentService{} } func (cs *CommentService) CreateComment(ctx context.Context, req *dto.CreateCommentReq) (uint, error) { - currentUser, ok := ctxutils.GetCurrentUser(ctx) - if !ok { - return 0, errs.ErrUnauthorized - } + currentUser, ok := ctxutils.GetCurrentUser(ctx) + if !ok { + return 0, errs.ErrUnauthorized + } - if ok, err := cs.checkTargetExists(req.TargetID, req.TargetType); !ok { - if err != nil { - return 0, errs.New(errs.ErrBadRequest.Code, "target not found", err) - } - return 0, errs.ErrBadRequest - } + if ok, err := cs.checkTargetExists(req.TargetID, req.TargetType); !ok { + if err != nil { + return 0, errs.New(errs.ErrBadRequest.Code, "target not found", err) + } + return 0, errs.ErrBadRequest + } - comment := &model.Comment{ - Content: req.Content, - ReplyID: req.ReplyID, - TargetID: req.TargetID, - TargetType: req.TargetType, - UserID: currentUser.ID, - IsPrivate: req.IsPrivate, - } + comment := &model.Comment{ + Content: req.Content, + ReplyID: req.ReplyID, + TargetID: req.TargetID, + TargetType: req.TargetType, + UserID: currentUser.ID, + IsPrivate: req.IsPrivate, + RemoteAddr: req.RemoteAddr, + } - commentID, err := repo.Comment.CreateComment(comment) + commentID, err := repo.Comment.CreateComment(comment) - if err != nil { - return 0, err - } + if err != nil { + return 0, err + } - return commentID, nil + return commentID, nil } func (cs *CommentService) UpdateComment(ctx context.Context, req *dto.UpdateCommentReq) error { - currentUser, ok := ctxutils.GetCurrentUser(ctx) - if !ok { - return errs.ErrUnauthorized - } + currentUser, ok := ctxutils.GetCurrentUser(ctx) + if !ok { + return errs.ErrUnauthorized + } - comment, err := repo.Comment.GetComment(strconv.Itoa(int(req.CommentID))) - if err != nil { - return err - } + comment, err := repo.Comment.GetComment(strconv.Itoa(int(req.CommentID))) + if err != nil { + return err + } - if currentUser.ID != comment.UserID { - return errs.ErrForbidden - } + if currentUser.ID != comment.UserID { + return errs.ErrForbidden + } - comment.Content = req.Content - comment.IsPrivate = req.IsPrivate + comment.Content = req.Content + comment.IsPrivate = req.IsPrivate - err = repo.Comment.UpdateComment(comment) + err = repo.Comment.UpdateComment(comment) - if err != nil { - return err - } + if err != nil { + return err + } - return nil + return nil } func (cs *CommentService) DeleteComment(ctx context.Context, commentID string) error { - currentUser, ok := ctxutils.GetCurrentUser(ctx) - if !ok { - return errs.ErrUnauthorized - } - if commentID == "" { - return errs.ErrBadRequest - } + currentUser, ok := ctxutils.GetCurrentUser(ctx) + if !ok { + return errs.ErrUnauthorized + } + if commentID == "" { + return errs.ErrBadRequest + } - comment, err := repo.Comment.GetComment(commentID) - if err != nil { - return errs.New(errs.ErrNotFound.Code, "comment not found", err) - } + comment, err := repo.Comment.GetComment(commentID) + if err != nil { + return errs.New(errs.ErrNotFound.Code, "comment not found", err) + } - if comment.UserID != currentUser.ID { - return errs.ErrForbidden - } + if comment.UserID != currentUser.ID { + return errs.ErrForbidden + } - if err := repo.Comment.DeleteComment(commentID); err != nil { - return err - } + if err := repo.Comment.DeleteComment(commentID); err != nil { + return err + } - return nil + return nil } func (cs *CommentService) GetComment(ctx context.Context, commentID string) (*dto.CommentDto, error) { - comment, err := repo.Comment.GetComment(commentID) + comment, err := repo.Comment.GetComment(commentID) - if err != nil { - return nil, errs.New(errs.ErrNotFound.Code, "comment not found", err) - } + if err != nil { + return nil, errs.New(errs.ErrNotFound.Code, "comment not found", err) + } - commentDto := dto.CommentDto{ - ID: comment.ID, - TargetID: comment.TargetID, - TargetType: comment.TargetType, - Content: comment.Content, - ReplyID: comment.ReplyID, - Depth: comment.Depth, - CreatedAt: comment.CreatedAt.String(), - UpdatedAt: comment.UpdatedAt.String(), - User: comment.User.ToDto(), - } + commentDto := dto.CommentDto{ + ID: comment.ID, + TargetID: comment.TargetID, + TargetType: comment.TargetType, + Content: comment.Content, + ReplyID: comment.ReplyID, + Depth: comment.Depth, + CreatedAt: comment.CreatedAt.String(), + UpdatedAt: comment.UpdatedAt.String(), + User: comment.User.ToDto(), + } - return &commentDto, err + return &commentDto, err } func (cs *CommentService) GetCommentList(ctx context.Context, req *dto.GetCommentListReq) ([]dto.CommentDto, error) { - currentUserID := uint(0) - if currentUser, ok := ctxutils.GetCurrentUser(ctx); ok { - currentUserID = currentUser.ID - } + currentUserID := uint(0) + if currentUser, ok := ctxutils.GetCurrentUser(ctx); ok { + currentUserID = currentUser.ID + } - comments, err := repo.Comment.ListComments(currentUserID, req.TargetID, req.CommentID, req.TargetType, req.Page, req.Size, req.OrderBy, req.Desc, req.Depth) - if err != nil { - return nil, errs.New(errs.ErrInternalServer.Code, "failed to list comments", err) - } + comments, err := repo.Comment.ListComments(currentUserID, req.TargetID, req.CommentID, req.TargetType, req.Page, req.Size, req.OrderBy, req.Desc, req.Depth) + if err != nil { + return nil, errs.New(errs.ErrInternalServer.Code, "failed to list comments", err) + } - commentDtos := make([]dto.CommentDto, 0) + commentDtos := make([]dto.CommentDto, 0) - for _, comment := range comments { - //replyCount, _ := repo.Comment.CountReplyComments(currentUserID, comment.ID) - isLiked := false - if currentUserID != 0 { - isLiked, _ = repo.Like.IsLiked(currentUserID, comment.ID, constant.TargetTypeComment) - } + for _, comment := range comments { + //replyCount, _ := repo.Comment.CountReplyComments(currentUserID, comment.ID) + isLiked := false + if currentUserID != 0 { + isLiked, _ = repo.Like.IsLiked(currentUserID, comment.ID, constant.TargetTypeComment) + } - commentDto := dto.CommentDto{ - ID: comment.ID, - Content: comment.Content, - TargetID: comment.TargetID, - TargetType: comment.TargetType, - ReplyID: comment.ReplyID, - CreatedAt: comment.CreatedAt.String(), - UpdatedAt: comment.UpdatedAt.String(), - Depth: comment.Depth, - User: comment.User.ToDto(), - ReplyCount: comment.CommentCount, - LikeCount: comment.LikeCount, - IsLiked: isLiked, - IsPrivate: comment.IsPrivate, - } - commentDtos = append(commentDtos, commentDto) - } - return commentDtos, nil + commentDto := dto.CommentDto{ + ID: comment.ID, + Content: comment.Content, + TargetID: comment.TargetID, + TargetType: comment.TargetType, + ReplyID: comment.ReplyID, + CreatedAt: comment.CreatedAt.String(), + UpdatedAt: comment.UpdatedAt.String(), + Depth: comment.Depth, + User: comment.User.ToDto(), + ReplyCount: comment.CommentCount, + LikeCount: comment.LikeCount, + IsLiked: isLiked, + IsPrivate: comment.IsPrivate, + } + commentDtos = append(commentDtos, commentDto) + } + return commentDtos, nil } func (cs *CommentService) checkTargetExists(targetID uint, targetType string) (bool, error) { - switch targetType { - case constant.TargetTypePost: - if _, err := repo.Post.GetPostByID(strconv.Itoa(int(targetID))); err != nil { - return false, errs.New(errs.ErrNotFound.Code, "post not found", err) - } - default: - return false, errs.New(errs.ErrBadRequest.Code, "invalid target type", nil) - } - return true, nil + switch targetType { + case constant.TargetTypePost: + if _, err := repo.Post.GetPostByID(strconv.Itoa(int(targetID))); err != nil { + return false, errs.New(errs.ErrNotFound.Code, "post not found", err) + } + default: + return false, errs.New(errs.ErrBadRequest.Code, "invalid target type", nil) + } + return true, nil }