package sql import ( "context" "git.sleepycat.moe/sam/mercury/internal/database" "github.com/keegancsmith/sqlf" "github.com/oklog/ulid/v2" ) // TimelineStore is the interface to post timelines in the database. type TimelineStore struct { q Querier } // NewTimelineStore creates a new TimelineStore instance. func NewTimelineStore(q Querier) *TimelineStore { return &TimelineStore{q: q} } type TimelinePost struct { database.Post database.Blog } func (s *TimelineStore) Home(ctx context.Context, accountID ulid.ULID, limit int, before, after *ulid.ULID) ([]TimelinePost, error) { q := sqlf.Sprintf("SELECT p.*, b.account_id, b.name, b.domain FROM posts p JOIN blogs b ON b.id = p.blog_id") q = sqlf.Sprintf("%v WHERE (blog_id IN (%s) OR blog_id IN (%s))", q, sqlf.Sprintf("SELECT id FROM blogs WHERE account_id = %s", accountID), sqlf.Sprintf("SELECT blog_id FROM account_follows WHERE account_id = %s", accountID)) if before != nil { q = sqlf.Sprintf("%v AND id < %s", q, *before) } if after != nil { q = sqlf.Sprintf("%v AND id > %s", q, *after) } q = sqlf.Sprintf("%v AND (visibility != %s OR (b.account_id = %s OR %s IN (%s)))", q, database.DirectVisibility, accountID, accountID, sqlf.Sprintf("SELECT account_id FROM blogs WHERE id IN (SELECT blog_id FROM post_recipients WHERE post_id = p.id)")) if limit <= 0 || limit > 100 { limit = 100 } q = sqlf.Sprintf("%v ORDER BY id DESC LIMIT %d", q, limit) return Select[TimelinePost](ctx, s.q, q) }