implemented federation
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user