129 lines
3.0 KiB
Go

package forum
import (
"fmt"
"time"
"dk/internal/database"
"zombiezen.com/go/sqlite"
)
// Builder provides a fluent interface for creating forum posts
type Builder struct {
forum *Forum
}
// NewBuilder creates a new forum post builder
func NewBuilder() *Builder {
now := time.Now().Unix()
return &Builder{
forum: &Forum{
Posted: now,
LastPost: now, // Default to same as posted time
Parent: 0, // Default to thread (no parent)
Replies: 0, // Default to no replies
},
}
}
// WithAuthor sets the author user ID
func (b *Builder) WithAuthor(authorID int) *Builder {
b.forum.Author = authorID
return b
}
// WithTitle sets the forum post title
func (b *Builder) WithTitle(title string) *Builder {
b.forum.Title = title
return b
}
// WithContent sets the forum post content
func (b *Builder) WithContent(content string) *Builder {
b.forum.Content = content
return b
}
// WithParent sets the parent post ID (for replies)
func (b *Builder) WithParent(parentID int) *Builder {
b.forum.Parent = parentID
return b
}
// AsReply is a convenience method to set this as a reply to another post
func (b *Builder) AsReply(parentID int) *Builder {
return b.WithParent(parentID)
}
// AsThread ensures this is a top-level thread (parent = 0)
func (b *Builder) AsThread() *Builder {
b.forum.Parent = 0
return b
}
// WithPosted sets the posted timestamp
func (b *Builder) WithPosted(posted int64) *Builder {
b.forum.Posted = posted
return b
}
// WithPostedTime sets the posted timestamp from a time.Time
func (b *Builder) WithPostedTime(t time.Time) *Builder {
b.forum.Posted = t.Unix()
return b
}
// WithLastPost sets the last post timestamp
func (b *Builder) WithLastPost(lastPost int64) *Builder {
b.forum.LastPost = lastPost
return b
}
// WithLastPostTime sets the last post timestamp from a time.Time
func (b *Builder) WithLastPostTime(t time.Time) *Builder {
b.forum.LastPost = t.Unix()
return b
}
// WithReplies sets the initial reply count
func (b *Builder) WithReplies(replies int) *Builder {
b.forum.Replies = replies
return b
}
// Create saves the forum post to the database and returns the created post with ID
func (b *Builder) Create() (*Forum, error) {
// Use a transaction to ensure we can get the ID
var forum *Forum
err := database.Transaction(func(tx *database.Tx) error {
query := `INSERT INTO forum (posted, last_post, author, parent, replies, title, content)
VALUES (?, ?, ?, ?, ?, ?, ?)`
if err := tx.Exec(query, b.forum.Posted, b.forum.LastPost, b.forum.Author,
b.forum.Parent, b.forum.Replies, b.forum.Title, b.forum.Content); err != nil {
return fmt.Errorf("failed to insert forum post: %w", err)
}
// Get the last insert ID
var id int
err := tx.Query("SELECT last_insert_rowid()", func(stmt *sqlite.Stmt) error {
id = stmt.ColumnInt(0)
return nil
})
if err != nil {
return fmt.Errorf("failed to get insert ID: %w", err)
}
b.forum.ID = id
forum = b.forum
return nil
})
if err != nil {
return nil, err
}
return forum, nil
}