backend/pkg/post/domain/entity/comment.go

115 lines
3.3 KiB
Go
Raw Permalink Normal View History

2025-11-19 05:33:06 +00:00
package entity
import (
"errors"
"time"
"backend/pkg/post/domain/post"
"github.com/gocql/gocql"
)
// Comment represents a comment entity on a post.
// Comments can be nested (replies to comments).
type Comment struct {
ID gocql.UUID `db:"id" partition_key:"true"` // Comment unique identifier
PostID gocql.UUID `db:"post_id" clustering_key:"true"` // Post ID (clustering key for sorting)
AuthorUID string `db:"author_uid"` // Author user UID
ParentID *gocql.UUID `db:"parent_id,omitempty" clustering_key:"true"` // Parent comment ID (for nested comments)
Content string `db:"content"` // Comment content
Status post.CommentStatus `db:"status"` // Comment status
LikeCount int64 `db:"like_count"` // Number of likes
ReplyCount int64 `db:"reply_count"` // Number of replies
CreatedAt int64 `db:"created_at" clustering_key:"true"` // Creation timestamp (for sorting)
UpdatedAt int64 `db:"updated_at"` // Last update timestamp
}
// TableName returns the Cassandra table name for Comment entities.
func (c *Comment) TableName() string {
return "comments"
}
// Validate validates the Comment entity
func (c *Comment) Validate() error {
var zeroUUID gocql.UUID
if c.PostID == zeroUUID {
return errors.New("post_id is required")
}
if c.AuthorUID == "" {
return errors.New("author_uid is required")
}
if len(c.Content) < 1 || len(c.Content) > 2000 {
return errors.New("content length must be between 1 and 2000 characters")
}
if !c.Status.IsValid() {
return errors.New("invalid comment status")
}
return nil
}
// SetTimestamps sets the create and update timestamps
func (c *Comment) SetTimestamps() {
now := time.Now().UTC().UnixNano() / 1e6 // milliseconds
if c.CreatedAt == 0 {
c.CreatedAt = now
}
c.UpdatedAt = now
}
// IsNew returns true if this is a new comment (no ID set)
func (c *Comment) IsNew() bool {
var zeroUUID gocql.UUID
return c.ID == zeroUUID
}
// IsReply returns true if this comment is a reply to another comment
func (c *Comment) IsReply() bool {
var zeroUUID gocql.UUID
return c.ParentID != nil && *c.ParentID != zeroUUID
}
// Delete marks the comment as deleted (soft delete)
func (c *Comment) Delete() {
c.Status = post.CommentStatusDeleted
c.SetTimestamps()
}
// Hide hides the comment
func (c *Comment) Hide() {
c.Status = post.CommentStatusHidden
c.SetTimestamps()
}
// IsVisible returns true if the comment is visible to public
func (c *Comment) IsVisible() bool {
return c.Status.IsVisible()
}
// IncrementLikeCount increments the like count
func (c *Comment) IncrementLikeCount() {
c.LikeCount++
c.SetTimestamps()
}
// DecrementLikeCount decrements the like count
func (c *Comment) DecrementLikeCount() {
if c.LikeCount > 0 {
c.LikeCount--
c.SetTimestamps()
}
}
// IncrementReplyCount increments the reply count
func (c *Comment) IncrementReplyCount() {
c.ReplyCount++
c.SetTimestamps()
}
// DecrementReplyCount decrements the reply count
func (c *Comment) DecrementReplyCount() {
if c.ReplyCount > 0 {
c.ReplyCount--
c.SetTimestamps()
}
}