90 lines
2.3 KiB
Go
90 lines
2.3 KiB
Go
package services
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"time"
|
|
|
|
"git.solsynth.dev/hypernet/interactive/pkg/internal/database"
|
|
"git.solsynth.dev/hypernet/interactive/pkg/internal/models"
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/samber/lo"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type FeedEntry struct {
|
|
Type string `json:"type"`
|
|
Data any `json:"data"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
func GetFeed(c *fiber.Ctx, limit int, user *uint, cursor *time.Time) ([]FeedEntry, error) {
|
|
// We got two types of data for now
|
|
// Plan to let each of them take 50% of the output
|
|
|
|
var feed []FeedEntry
|
|
|
|
interTx, err := UniversalPostFilter(c, database.C, UniversalPostFilterConfig{
|
|
TimeCursor: cursor,
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to prepare load interactive posts: %v", err)
|
|
}
|
|
interPosts, err := ListPostForFeed(interTx, limit/2, user)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load interactive posts: %v", err)
|
|
}
|
|
feed = append(feed, interPosts...)
|
|
|
|
fediTx := database.C
|
|
if cursor != nil {
|
|
fediTx = fediTx.Where("created_at < ?", *cursor)
|
|
}
|
|
fediPosts, err := ListFediversePostForFeed(fediTx, limit/2)
|
|
if err != nil {
|
|
return feed, fmt.Errorf("failed to load fediverse posts: %v", err)
|
|
}
|
|
feed = append(feed, fediPosts...)
|
|
|
|
sort.Slice(feed, func(i, j int) bool {
|
|
return feed[i].CreatedAt.After(feed[j].CreatedAt)
|
|
})
|
|
|
|
return feed, nil
|
|
}
|
|
|
|
// We assume the database context already handled the filtering and pagination
|
|
// Only manage to pulling the content only
|
|
|
|
func ListPostForFeed(tx *gorm.DB, limit int, user *uint) ([]FeedEntry, error) {
|
|
posts, err := ListPost(tx, limit, -1, "published_at DESC", user)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
entries := lo.Map(posts, func(post *models.Post, _ int) FeedEntry {
|
|
return FeedEntry{
|
|
Type: "interactive.post",
|
|
Data: post,
|
|
CreatedAt: post.CreatedAt,
|
|
}
|
|
})
|
|
return entries, nil
|
|
}
|
|
|
|
func ListFediversePostForFeed(tx *gorm.DB, limit int) ([]FeedEntry, error) {
|
|
var posts []models.FediversePost
|
|
if err := tx.
|
|
Preload("User").Limit(limit).
|
|
Find(&posts).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
entries := lo.Map(posts, func(post models.FediversePost, _ int) FeedEntry {
|
|
return FeedEntry{
|
|
Type: "fediverse.post",
|
|
Data: post,
|
|
CreatedAt: post.CreatedAt,
|
|
}
|
|
})
|
|
return entries, nil
|
|
}
|