126 lines
3.7 KiB
Go
126 lines
3.7 KiB
Go
|
package resolvers
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"encoding/json"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
|
||
|
"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/core/data"
|
||
|
"github.com/pkg/errors"
|
||
|
log "github.com/sirupsen/logrus"
|
||
|
)
|
||
|
|
||
|
// Resolve will translate a raw ActivityPub payload and fire the callback associated with that activity type.
|
||
|
func Resolve(c context.Context, data []byte, callbacks ...interface{}) error {
|
||
|
jsonResolver, err := streams.NewJSONResolver(callbacks...)
|
||
|
if err != nil {
|
||
|
// Something in the setup was wrong. For example, a callback has an
|
||
|
// unsupported signature and would never be called
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
var jsonMap map[string]interface{}
|
||
|
if err = json.Unmarshal(data, &jsonMap); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
log.Debugln("Resolving payload...", string(data))
|
||
|
|
||
|
// The createCallback function will be called.
|
||
|
err = jsonResolver.Resolve(c, jsonMap)
|
||
|
if err != nil && !streams.IsUnmatchedErr(err) {
|
||
|
// Something went wrong
|
||
|
return err
|
||
|
} else if streams.IsUnmatchedErr(err) {
|
||
|
// Everything went right but the callback didn't match or the ActivityStreams
|
||
|
// type is one that wasn't code generated.
|
||
|
log.Debugln("No match: ", err)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// ResolveIRI will resolve an IRI ahd call the correct callback for the resolved type.
|
||
|
func ResolveIRI(c context.Context, iri string, callbacks ...interface{}) error {
|
||
|
log.Debugln("Resolving", iri)
|
||
|
|
||
|
req, _ := http.NewRequest("GET", iri, nil)
|
||
|
|
||
|
actor := apmodels.MakeLocalIRIForAccount(data.GetDefaultFederationUsername())
|
||
|
if err := crypto.SignRequest(req, nil, actor); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
response, err := http.DefaultClient.Do(req)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
defer response.Body.Close()
|
||
|
|
||
|
data, err := ioutil.ReadAll(response.Body)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// fmt.Println(string(data))
|
||
|
return Resolve(c, data, callbacks...)
|
||
|
}
|
||
|
|
||
|
// GetResolvedActorFromActorProperty resolve an actor property to a fully populated person.
|
||
|
func GetResolvedActorFromActorProperty(actor vocab.ActivityStreamsActorProperty) (apmodels.ActivityPubActor, error) {
|
||
|
var err error
|
||
|
var apActor apmodels.ActivityPubActor
|
||
|
|
||
|
personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error {
|
||
|
apActor = apmodels.MakeActorFromPerson(person)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
serviceCallback := func(c context.Context, s vocab.ActivityStreamsService) error {
|
||
|
apActor = apmodels.MakeActorFromService(s)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
for iter := actor.Begin(); iter != actor.End(); iter = iter.Next() {
|
||
|
if iter.IsIRI() {
|
||
|
iri := iter.GetIRI()
|
||
|
if e := ResolveIRI(context.Background(), iri.String(), personCallback, serviceCallback); e != nil {
|
||
|
err = e
|
||
|
}
|
||
|
} else if iter.IsActivityStreamsPerson() {
|
||
|
person := iter.GetActivityStreamsPerson()
|
||
|
apActor = apmodels.MakeActorFromPerson(person)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return apActor, errors.Wrap(err, "unable to resolve actor from actor property")
|
||
|
}
|
||
|
|
||
|
// GetResolvedActorFromIRI will resolve an IRI string to a fully populated actor.
|
||
|
func GetResolvedActorFromIRI(personOrServiceIRI string) (apmodels.ActivityPubActor, error) {
|
||
|
var err error
|
||
|
var apActor apmodels.ActivityPubActor
|
||
|
|
||
|
personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error {
|
||
|
apActor = apmodels.MakeActorFromPerson(person)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
serviceCallback := func(c context.Context, s vocab.ActivityStreamsService) error {
|
||
|
apActor = apmodels.MakeActorFromService(s)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
if e := ResolveIRI(context.Background(), personOrServiceIRI, personCallback, serviceCallback); e != nil {
|
||
|
err = e
|
||
|
}
|
||
|
|
||
|
return apActor, errors.Wrap(err, "unable to resolve actor from IRI string: "+personOrServiceIRI)
|
||
|
}
|