You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
4.7 KiB
164 lines
4.7 KiB
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 |
|
resolved := false |
|
|
|
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 |
|
} |
|
|
|
applicationCallback := func(c context.Context, s vocab.ActivityStreamsApplication) error { |
|
apActor = apmodels.MakeActorFromApplication(s) |
|
resolved = true |
|
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, applicationCallback); e != nil { |
|
err = e |
|
} |
|
} else if iter.IsActivityStreamsPerson() { |
|
person := iter.GetActivityStreamsPerson() |
|
apActor = apmodels.MakeActorFromPerson(person) |
|
resolved = true |
|
} else if iter.IsActivityStreamsService() { |
|
person := iter.GetActivityStreamsService() |
|
apActor = apmodels.MakeActorFromService(person) |
|
resolved = true |
|
} else if iter.IsActivityStreamsApplication() { |
|
person := iter.GetActivityStreamsApplication() |
|
apActor = apmodels.MakeActorFromApplication(person) |
|
resolved = true |
|
} |
|
} |
|
|
|
if err != nil { |
|
err = errors.Wrap(err, "error resolving actor from property value") |
|
} |
|
|
|
if !resolved { |
|
err = errors.New("error resolving actor from property value") |
|
} |
|
return apActor, err |
|
} |
|
|
|
// 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 |
|
resolved := false |
|
personCallback := func(c context.Context, person vocab.ActivityStreamsPerson) error { |
|
apActor = apmodels.MakeActorFromPerson(person) |
|
resolved = true |
|
return nil |
|
} |
|
|
|
serviceCallback := func(c context.Context, s vocab.ActivityStreamsService) error { |
|
apActor = apmodels.MakeActorFromService(s) |
|
resolved = true |
|
return nil |
|
} |
|
|
|
applicationCallback := func(c context.Context, s vocab.ActivityStreamsApplication) error { |
|
apActor = apmodels.MakeActorFromApplication(s) |
|
resolved = true |
|
return nil |
|
} |
|
|
|
if e := ResolveIRI(context.Background(), personOrServiceIRI, personCallback, serviceCallback, applicationCallback); e != nil { |
|
err = e |
|
} |
|
|
|
if err != nil { |
|
err = errors.Wrap(err, "error resolving actor from property value") |
|
} |
|
|
|
if !resolved { |
|
err = errors.New("error resolving actor from property value") |
|
} |
|
|
|
return apActor, err |
|
}
|
|
|