131 lines
3.0 KiB
Go
131 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
|
|
db *database.DB
|
|
}
|
|
|
|
// NewBuilder creates a new forum post builder
|
|
func NewBuilder(db *database.DB) *Builder {
|
|
now := time.Now().Unix()
|
|
return &Builder{
|
|
forum: &Forum{
|
|
db: db,
|
|
Posted: now,
|
|
LastPost: now, // Default to same as posted time
|
|
Parent: 0, // Default to thread (no parent)
|
|
Replies: 0, // Default to no replies
|
|
},
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
// 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 := b.db.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
|
|
} |