701475b6e0
This was uncovered during writing tests where both the Social and Federative APIs are enabled. The actorObject interface was overused partially due to my earlier confusion; the introduction of the internal actor interface resolved this. Finally, the HttpClient interface was introduced to be able to mock out calls in testing. It may also prove useful for future applications using this library.
157 行
3.7 KiB
Go
157 行
3.7 KiB
Go
package pub
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/go-fed/activity/streams"
|
|
"github.com/go-fed/activity/vocab"
|
|
"net/url"
|
|
)
|
|
|
|
// ToPubObject transforms a json-deserialized ActivityStream object into a
|
|
// PubObject for use with the pub library. Note that for an object to be an
|
|
// ActivityPub object, it must have an 'id' and at least one 'type'.
|
|
func ToPubObject(m map[string]interface{}) (t []PubObject, e error) {
|
|
r := &streams.Resolver{
|
|
AnyObjectCallback: func(i vocab.ObjectType) error {
|
|
if !i.HasId() {
|
|
return fmt.Errorf("object type does not have an id: %q", i)
|
|
} else if i.TypeLen() == 0 {
|
|
return fmt.Errorf("object type does not have a type: %q", i)
|
|
}
|
|
t = append(t, i)
|
|
return nil
|
|
},
|
|
AnyLinkCallback: func(i vocab.LinkType) error {
|
|
if !i.HasId() {
|
|
return fmt.Errorf("link type does not have an id: %q", i)
|
|
} else if i.TypeLen() == 0 {
|
|
return fmt.Errorf("link type does not have a type: %q", i)
|
|
}
|
|
t = append(t, i)
|
|
return nil
|
|
},
|
|
}
|
|
e = r.Deserialize(m)
|
|
return t, e
|
|
}
|
|
|
|
func getActorObject(m map[string]interface{}) (actorObject, error) {
|
|
var a actorObject
|
|
err := toActorObjectResolver(&a).Deserialize(m)
|
|
return a, err
|
|
}
|
|
|
|
func toActorObjectResolver(a *actorObject) *streams.Resolver {
|
|
return &streams.Resolver{
|
|
AnyObjectCallback: func(i vocab.ObjectType) error {
|
|
if o, ok := i.(actorObject); ok {
|
|
*a = o
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func toActorResolver(a *actor) *streams.Resolver {
|
|
return &streams.Resolver{
|
|
AnyObjectCallback: func(i vocab.ObjectType) error {
|
|
if o, ok := i.(actor); ok {
|
|
*a = o
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func toActorCollectionResolver(a *actor, c **streams.Collection, oc **streams.OrderedCollection, cp **streams.CollectionPage, ocp **streams.OrderedCollectionPage) *streams.Resolver {
|
|
r := toActorResolver(a)
|
|
r.CollectionCallback = func(i *streams.Collection) error {
|
|
*c = i
|
|
return nil
|
|
}
|
|
r.OrderedCollectionCallback = func(i *streams.OrderedCollection) error {
|
|
*oc = i
|
|
return nil
|
|
}
|
|
r.CollectionPageCallback = func(i *streams.CollectionPage) error {
|
|
*cp = i
|
|
return nil
|
|
}
|
|
r.OrderedCollectionPageCallback = func(i *streams.OrderedCollectionPage) error {
|
|
*ocp = i
|
|
return nil
|
|
}
|
|
return r
|
|
}
|
|
|
|
func toIdResolver(ok *bool, u *url.URL) *streams.Resolver {
|
|
return &streams.Resolver{
|
|
AnyObjectCallback: func(i vocab.ObjectType) error {
|
|
*ok = i.HasId()
|
|
if *ok {
|
|
*u = i.GetId()
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func toCollectionPage(m map[string]interface{}) (c *streams.CollectionPage, err error) {
|
|
r := &streams.Resolver{
|
|
CollectionPageCallback: func(i *streams.CollectionPage) error {
|
|
c = i
|
|
return nil
|
|
},
|
|
}
|
|
err = r.Deserialize(m)
|
|
return
|
|
}
|
|
|
|
func toOrderedCollectionPage(m map[string]interface{}) (c *streams.OrderedCollectionPage, err error) {
|
|
r := &streams.Resolver{
|
|
OrderedCollectionPageCallback: func(i *streams.OrderedCollectionPage) error {
|
|
c = i
|
|
return nil
|
|
},
|
|
}
|
|
err = r.Deserialize(m)
|
|
return
|
|
}
|
|
|
|
func toTypeIder(m map[string]interface{}) (tid typeIder, err error) {
|
|
var t []typeIder
|
|
r := &streams.Resolver{
|
|
AnyObjectCallback: func(i vocab.ObjectType) error {
|
|
t = append(t, i)
|
|
return nil
|
|
},
|
|
AnyLinkCallback: func(i vocab.LinkType) error {
|
|
t = append(t, i)
|
|
return nil
|
|
},
|
|
}
|
|
err = r.Deserialize(m)
|
|
if err != nil {
|
|
return
|
|
}
|
|
// TODO: Support more than one, which will enable creating multiple
|
|
// objects simultaneously.
|
|
if len(t) != 1 {
|
|
err = fmt.Errorf("too many object/links: %d", len(t))
|
|
return
|
|
}
|
|
tid = t[0]
|
|
return
|
|
}
|
|
|
|
func toAnyActivity(m map[string]interface{}) (o vocab.ActivityType, err error) {
|
|
r := &streams.Resolver{
|
|
AnyActivityCallback: func(i vocab.ActivityType) error {
|
|
o = i
|
|
return nil
|
|
},
|
|
}
|
|
err = r.Deserialize(m)
|
|
return
|
|
}
|