Files
2026-05-12 20:55:13 +02:00

85 lines
2.2 KiB
Go

package federation
import (
"xorm.io/xorm"
"github.com/forgeo/forgebucket/internal/models"
)
const activitiesPerPage = 20
// Collection builds an ActivityStreams OrderedCollection (or page) for an actor's outbox.
// page=0 returns the collection summary; page≥1 returns a paginated OrderedCollectionPage.
func Collection(db *xorm.Engine, actorAPID string, outboxURL string, page int) map[string]any {
total, _ := db.Where("actor_ap_id = ? AND direction = 'outbound'", actorAPID).
Count(&models.FederationActivity{})
if page == 0 {
return map[string]any{
"@context": "https://www.w3.org/ns/activitystreams",
"id": outboxURL,
"type": "OrderedCollection",
"totalItems": total,
"first": outboxURL + "?page=1",
}
}
offset := (page - 1) * activitiesPerPage
var activities []models.FederationActivity
db.Where("actor_ap_id = ? AND direction = 'outbound'", actorAPID).
Desc("published").
Limit(activitiesPerPage, offset).
Find(&activities)
items := make([]any, 0, len(activities))
for _, a := range activities {
items = append(items, rawJSON(a.ObjectJSON))
}
coll := map[string]any{
"@context": "https://www.w3.org/ns/activitystreams",
"id": outboxURL + "?page=" + itoa(page),
"type": "OrderedCollectionPage",
"partOf": outboxURL,
"orderedItems": items,
}
if int64(offset+activitiesPerPage) < total {
coll["next"] = outboxURL + "?page=" + itoa(page+1)
}
return coll
}
// StubCollection returns a minimal OrderedCollection with zero items.
// Used for followers/following until the social graph is implemented.
func StubCollection(collectionURL string) map[string]any {
return map[string]any{
"@context": "https://www.w3.org/ns/activitystreams",
"id": collectionURL,
"type": "OrderedCollection",
"totalItems": 0,
"orderedItems": []any{},
}
}
func itoa(n int) string {
if n == 0 {
return "0"
}
result := ""
for n > 0 {
result = string(rune('0'+n%10)) + result
n /= 10
}
return result
}
// rawJSON wraps a JSON string so it marshals as-is (not double-encoded).
type rawJSON string
func (r rawJSON) MarshalJSON() ([]byte, error) {
if r == "" {
return []byte("null"), nil
}
return []byte(r), nil
}