157 lines
4.4 KiB
Go
157 lines
4.4 KiB
Go
|
package controllers
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net/http"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/go-fed/activity/streams"
|
||
|
"github.com/go-fed/activity/streams/vocab"
|
||
|
"github.com/owncast/owncast/activitypub/apmodels"
|
||
|
"github.com/owncast/owncast/activitypub/crypto"
|
||
|
"github.com/owncast/owncast/activitypub/persistence"
|
||
|
"github.com/owncast/owncast/activitypub/requests"
|
||
|
"github.com/pkg/errors"
|
||
|
log "github.com/sirupsen/logrus"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
outboxPageSize = 50
|
||
|
)
|
||
|
|
||
|
// OutboxHandler will handle requests for the local ActivityPub outbox.
|
||
|
func OutboxHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
if r.Method != http.MethodGet {
|
||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var response interface{}
|
||
|
var err error
|
||
|
if r.URL.Query().Get("page") != "" {
|
||
|
response, err = getOutboxPage(r.URL.Query().Get("page"), r)
|
||
|
} else {
|
||
|
response, err = getInitialOutboxHandler(r)
|
||
|
}
|
||
|
|
||
|
if response == nil {
|
||
|
w.WriteHeader(http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if err != nil {
|
||
|
_, _ = w.Write([]byte(err.Error()))
|
||
|
w.WriteHeader(http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
pathComponents := strings.Split(r.URL.Path, "/")
|
||
|
accountName := pathComponents[3]
|
||
|
actorIRI := apmodels.MakeLocalIRIForAccount(accountName)
|
||
|
publicKey := crypto.GetPublicKey(actorIRI)
|
||
|
|
||
|
if err := requests.WriteStreamResponse(response.(vocab.Type), w, publicKey); err != nil {
|
||
|
log.Errorln("unable to write stream response for outbox handler", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ActorObjectHandler will handle the request for a single ActivityPub object.
|
||
|
func ActorObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||
|
object, _, _, err := persistence.GetObjectByIRI(r.URL.Path)
|
||
|
if err != nil {
|
||
|
w.WriteHeader(http.StatusNotFound)
|
||
|
return
|
||
|
// controllers.WriteSimpleResponse(w, false, err.Error())
|
||
|
}
|
||
|
|
||
|
if _, err := w.Write([]byte(object)); err != nil {
|
||
|
log.Errorln(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func getInitialOutboxHandler(r *http.Request) (vocab.ActivityStreamsOrderedCollection, error) {
|
||
|
collection := streams.NewActivityStreamsOrderedCollection()
|
||
|
|
||
|
idProperty := streams.NewJSONLDIdProperty()
|
||
|
id, err := createPageURL(r, nil)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to create followers page property")
|
||
|
}
|
||
|
idProperty.SetIRI(id)
|
||
|
collection.SetJSONLDId(idProperty)
|
||
|
|
||
|
totalPosts, err := persistence.GetOutboxPostCount()
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to get outbox post count")
|
||
|
}
|
||
|
totalItemsProperty := streams.NewActivityStreamsTotalItemsProperty()
|
||
|
totalItemsProperty.Set(int(totalPosts))
|
||
|
collection.SetActivityStreamsTotalItems(totalItemsProperty)
|
||
|
|
||
|
first := streams.NewActivityStreamsFirstProperty()
|
||
|
page := "1"
|
||
|
firstIRI, err := createPageURL(r, &page)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to create first page property")
|
||
|
}
|
||
|
|
||
|
first.SetIRI(firstIRI)
|
||
|
collection.SetActivityStreamsFirst(first)
|
||
|
|
||
|
return collection, nil
|
||
|
}
|
||
|
|
||
|
func getOutboxPage(page string, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) {
|
||
|
pageInt, err := strconv.Atoi(page)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to parse page number")
|
||
|
}
|
||
|
|
||
|
postCount, err := persistence.GetOutboxPostCount()
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to get outbox post count")
|
||
|
}
|
||
|
|
||
|
collectionPage := streams.NewActivityStreamsOrderedCollectionPage()
|
||
|
idProperty := streams.NewJSONLDIdProperty()
|
||
|
id, err := createPageURL(r, &page)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to create followers page ID")
|
||
|
}
|
||
|
idProperty.SetIRI(id)
|
||
|
collectionPage.SetJSONLDId(idProperty)
|
||
|
|
||
|
orderedItems := streams.NewActivityStreamsOrderedItemsProperty()
|
||
|
|
||
|
outboxItems, err := persistence.GetOutbox(outboxPageSize, (pageInt-1)*outboxPageSize)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to get federation followers")
|
||
|
}
|
||
|
orderedItems.AppendActivityStreamsOrderedCollection(outboxItems)
|
||
|
collectionPage.SetActivityStreamsOrderedItems(orderedItems)
|
||
|
|
||
|
partOf := streams.NewActivityStreamsPartOfProperty()
|
||
|
partOfIRI, err := createPageURL(r, nil)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to create partOf property for outbox page")
|
||
|
}
|
||
|
|
||
|
partOf.SetIRI(partOfIRI)
|
||
|
collectionPage.SetActivityStreamsPartOf(partOf)
|
||
|
|
||
|
if pageInt*followersPageSize < int(postCount) {
|
||
|
next := streams.NewActivityStreamsNextProperty()
|
||
|
nextPage := fmt.Sprintf("%d", pageInt+1)
|
||
|
nextIRI, err := createPageURL(r, &nextPage)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "unable to create next page property")
|
||
|
}
|
||
|
|
||
|
next.SetIRI(nextIRI)
|
||
|
collectionPage.SetActivityStreamsNext(next)
|
||
|
}
|
||
|
|
||
|
return collectionPage, nil
|
||
|
}
|