85 lines
2.2 KiB
Go
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
|
|
}
|