mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 12:17:24 +00:00
Improve Comment model to support multiple comment type.
This commit is contained in:
@@ -11,14 +11,16 @@ import (
|
||||
|
||||
func AddCommentRoutes(router fiber.Router) {
|
||||
api := router.Group("/comments")
|
||||
api.Post("/:resourceID", createComment)
|
||||
api.Get("/:resourceID", listComments)
|
||||
api.Get("/user/:username", listCommentsWithUser)
|
||||
api.Post("/resource/:resourceID", createResourceComment)
|
||||
api.Post("/reply/:commentID", createReplyComment)
|
||||
api.Get("/resource/:resourceID", listResourceComments)
|
||||
api.Get("/reply/:commentID", listResourceComments)
|
||||
api.Get("/user/:username", listCommentsByUser)
|
||||
api.Put("/:commentID", updateComment)
|
||||
api.Delete("/:commentID", deleteComment)
|
||||
}
|
||||
|
||||
func createComment(c fiber.Ctx) error {
|
||||
func createResourceComment(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("uid").(uint)
|
||||
if !ok {
|
||||
return model.NewRequestError("You must be logged in to comment")
|
||||
@@ -38,7 +40,7 @@ func createComment(c fiber.Ctx) error {
|
||||
return model.NewRequestError("Content cannot be empty")
|
||||
}
|
||||
|
||||
comment, err := service.CreateComment(req, userID, uint(resourceID), c.IP())
|
||||
comment, err := service.CreateComment(req, userID, uint(resourceID), c.IP(), model.CommentTypeResource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -49,7 +51,38 @@ func createComment(c fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
func listComments(c fiber.Ctx) error {
|
||||
func createReplyComment(c fiber.Ctx) error {
|
||||
userID, ok := c.Locals("uid").(uint)
|
||||
if !ok {
|
||||
return model.NewRequestError("You must be logged in to reply")
|
||||
}
|
||||
commentIDStr := c.Params("commentID")
|
||||
commentID, err := strconv.Atoi(commentIDStr)
|
||||
if err != nil {
|
||||
return model.NewRequestError("Invalid comment ID")
|
||||
}
|
||||
|
||||
var req service.CommentRequest
|
||||
if err := c.Bind().JSON(&req); err != nil {
|
||||
return model.NewRequestError("Invalid request format")
|
||||
}
|
||||
|
||||
if req.Content == "" {
|
||||
return model.NewRequestError("Content cannot be empty")
|
||||
}
|
||||
|
||||
comment, err := service.CreateComment(req, userID, uint(commentID), c.IP(), model.CommentTypeReply)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.Status(fiber.StatusCreated).JSON(model.Response[model.CommentView]{
|
||||
Success: true,
|
||||
Data: *comment,
|
||||
Message: "Reply created successfully",
|
||||
})
|
||||
}
|
||||
|
||||
func listResourceComments(c fiber.Ctx) error {
|
||||
resourceIDStr := c.Params("resourceID")
|
||||
resourceID, err := strconv.Atoi(resourceIDStr)
|
||||
if err != nil {
|
||||
@@ -60,7 +93,7 @@ func listComments(c fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return model.NewRequestError("Invalid page number")
|
||||
}
|
||||
comments, totalPages, err := service.ListComments(uint(resourceID), page)
|
||||
comments, totalPages, err := service.ListResourceComments(uint(resourceID), page)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -72,7 +105,7 @@ func listComments(c fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
func listCommentsWithUser(c fiber.Ctx) error {
|
||||
func listCommentsByUser(c fiber.Ctx) error {
|
||||
username := c.Params("username")
|
||||
if username == "" {
|
||||
return model.NewRequestError("Username is required")
|
||||
|
@@ -6,13 +6,14 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateComment(content string, userID uint, resourceID uint, imageIDs []uint) (model.Comment, error) {
|
||||
func CreateComment(content string, userID uint, resourceID uint, imageIDs []uint, cType model.CommentType) (model.Comment, error) {
|
||||
var comment model.Comment
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
comment = model.Comment{
|
||||
Content: content,
|
||||
UserID: userID,
|
||||
ResourceID: resourceID,
|
||||
Content: content,
|
||||
UserID: userID,
|
||||
RefID: resourceID,
|
||||
Type: cType,
|
||||
}
|
||||
if err := tx.Create(&comment).Error; err != nil {
|
||||
return err
|
||||
@@ -49,11 +50,24 @@ func GetCommentByResourceID(resourceID uint, page, pageSize int) ([]model.Commen
|
||||
var comments []model.Comment
|
||||
var total int64
|
||||
|
||||
if err := db.Model(&model.Comment{}).Where("resource_id = ?", resourceID).Count(&total).Error; err != nil {
|
||||
if err := db.
|
||||
Model(&model.Comment{}).
|
||||
Where("type = ?", model.CommentTypeResource).
|
||||
Where("ref_id = ?", resourceID).
|
||||
Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
if err := db.Where("resource_id = ?", resourceID).Offset((page - 1) * pageSize).Limit(pageSize).Preload("User").Preload("Images").Order("created_at DESC").Find(&comments).Error; err != nil {
|
||||
if err := db.
|
||||
Model(&model.Comment{}).
|
||||
Where("type = ?", model.CommentTypeResource).
|
||||
Where("ref_id = ?", resourceID).
|
||||
Offset((page - 1) * pageSize).
|
||||
Limit(pageSize).
|
||||
Preload("User").
|
||||
Preload("Images").
|
||||
Order("created_at DESC").
|
||||
Find(&comments).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
@@ -70,10 +84,22 @@ func GetCommentsWithUser(username string, page, pageSize int) ([]model.Comment,
|
||||
}
|
||||
var comments []model.Comment
|
||||
var total int64
|
||||
if err := db.Model(&model.Comment{}).Where("user_id = ?", user.ID).Count(&total).Error; err != nil {
|
||||
if err := db.
|
||||
Model(&model.Comment{}).
|
||||
Where("type = ?", model.CommentTypeResource).
|
||||
Where("user_id = ?", user.ID).
|
||||
Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := db.Where("user_id = ?", user.ID).Offset((page - 1) * pageSize).Limit(pageSize).Preload("User").Preload("Resource").Preload("Images").Order("created_at DESC").Find(&comments).Error; err != nil {
|
||||
if err := db.
|
||||
Model(&model.Comment{}).
|
||||
Where("type = ?", model.CommentTypeResource).
|
||||
Where("user_id = ?", user.ID).
|
||||
Offset((page - 1) * pageSize).
|
||||
Limit(pageSize).Preload("User").
|
||||
Preload("Images").
|
||||
Order("created_at DESC").
|
||||
Find(&comments).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
totalPages := (int(total) + pageSize - 1) / pageSize
|
||||
@@ -82,7 +108,7 @@ func GetCommentsWithUser(username string, page, pageSize int) ([]model.Comment,
|
||||
|
||||
func GetCommentByID(commentID uint) (*model.Comment, error) {
|
||||
var comment model.Comment
|
||||
if err := db.Preload("User").Preload("Resource").Preload("Images").First(&comment, commentID).Error; err != nil {
|
||||
if err := db.Preload("User").Preload("Images").First(&comment, commentID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &comment, nil
|
||||
|
@@ -8,14 +8,21 @@ import (
|
||||
|
||||
type Comment struct {
|
||||
gorm.Model
|
||||
Content string `gorm:"not null"`
|
||||
ResourceID uint `gorm:"not null"`
|
||||
UserID uint `gorm:"not null"`
|
||||
User User `gorm:"foreignKey:UserID"`
|
||||
Resource Resource `gorm:"foreignKey:ResourceID"`
|
||||
Images []Image `gorm:"many2many:comment_images;"`
|
||||
Content string `gorm:"not null"`
|
||||
RefID uint `gorm:"not null;index:idx_refid_type,priority:1"`
|
||||
Type CommentType `gorm:"not null;index:idx_refid_type,priority:2"`
|
||||
UserID uint `gorm:"not null"`
|
||||
User User `gorm:"foreignKey:UserID"`
|
||||
Images []Image `gorm:"many2many:comment_images;"`
|
||||
}
|
||||
|
||||
type CommentType uint
|
||||
|
||||
const (
|
||||
CommentTypeResource CommentType = iota + 1
|
||||
CommentTypeReply
|
||||
)
|
||||
|
||||
type CommentView struct {
|
||||
ID uint `json:"id"`
|
||||
Content string `json:"content"`
|
||||
@@ -48,7 +55,7 @@ type CommentWithResourceView struct {
|
||||
Images []ImageView `json:"images"`
|
||||
}
|
||||
|
||||
func (c *Comment) ToViewWithResource() *CommentWithResourceView {
|
||||
func (c *Comment) ToViewWithResource(r *Resource) *CommentWithResourceView {
|
||||
imageViews := make([]ImageView, 0, len(c.Images))
|
||||
for _, img := range c.Images {
|
||||
imageViews = append(imageViews, img.ToView())
|
||||
@@ -58,7 +65,7 @@ func (c *Comment) ToViewWithResource() *CommentWithResourceView {
|
||||
ID: c.ID,
|
||||
Content: c.Content,
|
||||
CreatedAt: c.CreatedAt,
|
||||
Resource: c.Resource.ToView(),
|
||||
Resource: r.ToView(),
|
||||
User: c.User.ToView(),
|
||||
Images: imageViews,
|
||||
}
|
||||
|
@@ -27,7 +27,11 @@ func GetActivityList(page int) ([]model.ActivityView, int, error) {
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
comment = c.ToViewWithResource()
|
||||
r, err := dao.GetResourceByID(c.RefID)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
comment = c.ToViewWithResource(&r)
|
||||
} else if activity.Type == model.ActivityTypeNewResource || activity.Type == model.ActivityTypeUpdateResource {
|
||||
r, err := dao.GetResourceByID(activity.RefID)
|
||||
if err != nil {
|
||||
|
@@ -24,7 +24,7 @@ type CommentRequest struct {
|
||||
Images []uint `json:"images"`
|
||||
}
|
||||
|
||||
func CreateComment(req CommentRequest, userID uint, resourceID uint, ip string) (*model.CommentView, error) {
|
||||
func CreateComment(req CommentRequest, userID uint, refID uint, ip string, cType model.CommentType) (*model.CommentView, error) {
|
||||
if !commentsLimiter.AllowRequest(ip) {
|
||||
log.Warnf("IP %s has exceeded the comment limit of %d comments per day", ip, maxCommentsPerIP)
|
||||
return nil, model.NewRequestError("Too many comments from this IP address, please try again later")
|
||||
@@ -40,7 +40,7 @@ func CreateComment(req CommentRequest, userID uint, resourceID uint, ip string)
|
||||
if len(req.Images) > maxImagePerComment {
|
||||
return nil, model.NewRequestError("Too many images, maximum is 9")
|
||||
}
|
||||
resourceExists, err := dao.ExistsResource(resourceID)
|
||||
resourceExists, err := dao.ExistsResource(refID)
|
||||
if err != nil {
|
||||
log.Error("Error checking resource existence:", err)
|
||||
return nil, model.NewInternalServerError("Error checking resource existence")
|
||||
@@ -56,7 +56,7 @@ func CreateComment(req CommentRequest, userID uint, resourceID uint, ip string)
|
||||
if !userExists {
|
||||
return nil, model.NewNotFoundError("User not found")
|
||||
}
|
||||
c, err := dao.CreateComment(req.Content, userID, resourceID, req.Images)
|
||||
c, err := dao.CreateComment(req.Content, userID, refID, req.Images, cType)
|
||||
if err != nil {
|
||||
log.Error("Error creating comment:", err)
|
||||
return nil, model.NewInternalServerError("Error creating comment")
|
||||
@@ -68,7 +68,7 @@ func CreateComment(req CommentRequest, userID uint, resourceID uint, ip string)
|
||||
return c.ToView(), nil
|
||||
}
|
||||
|
||||
func ListComments(resourceID uint, page int) ([]model.CommentView, int, error) {
|
||||
func ListResourceComments(resourceID uint, page int) ([]model.CommentView, int, error) {
|
||||
resourceExists, err := dao.ExistsResource(resourceID)
|
||||
if err != nil {
|
||||
log.Error("Error checking resource existence:", err)
|
||||
@@ -97,7 +97,12 @@ func ListCommentsWithUser(username string, page int) ([]model.CommentWithResourc
|
||||
}
|
||||
res := make([]model.CommentWithResourceView, 0, len(comments))
|
||||
for _, c := range comments {
|
||||
res = append(res, *c.ToViewWithResource())
|
||||
r, err := dao.GetResourceByID(c.RefID)
|
||||
if err != nil {
|
||||
log.Error("Error getting resource for comment:", err)
|
||||
return nil, 0, model.NewInternalServerError("Error getting resource for comment")
|
||||
}
|
||||
res = append(res, *c.ToViewWithResource(&r))
|
||||
}
|
||||
return res, totalPages, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user