.. | ||
gen_accept.go | ||
gen_activity.go | ||
gen_add.go | ||
gen_announce.go | ||
gen_application.go | ||
gen_arrive.go | ||
gen_article.go | ||
gen_audio.go | ||
gen_block.go | ||
gen_collection.go | ||
gen_collectionpage.go | ||
gen_create.go | ||
gen_delete.go | ||
gen_dislike.go | ||
gen_document.go | ||
gen_event.go | ||
gen_flag.go | ||
gen_follow.go | ||
gen_group.go | ||
gen_ignore.go | ||
gen_image.go | ||
gen_intransitiveactivity.go | ||
gen_invite.go | ||
gen_join.go | ||
gen_leave.go | ||
gen_like.go | ||
gen_link.go | ||
gen_listen.go | ||
gen_mention.go | ||
gen_move.go | ||
gen_note.go | ||
gen_object.go | ||
gen_offer.go | ||
gen_orderedcollection.go | ||
gen_orderedcollectionpage.go | ||
gen_organization.go | ||
gen_page.go | ||
gen_person.go | ||
gen_place.go | ||
gen_profile.go | ||
gen_question.go | ||
gen_read.go | ||
gen_reject.go | ||
gen_relationship.go | ||
gen_remove.go | ||
gen_service.go | ||
gen_streams.go | ||
gen_tentativeaccept.go | ||
gen_tentativereject.go | ||
gen_tombstone.go | ||
gen_travel.go | ||
gen_undo.go | ||
gen_update.go | ||
gen_video.go | ||
gen_view.go | ||
README.md | ||
streams_data_test.go | ||
streams_test.go |
streams
Please read the README.md
in the go-fed/activity/vocab
package first. This
library is a convenience layer on top of the go-fed/activity/vocab
library, so
this README builds off of that one.
This library is entirely code-generated by the
go-fed/activity/tools/streams/gen
library and go-fed/activity/tools/streams
tool. Run go generate
to refresh the library, which requires $GOPATH/bin
to
be on your $PATH
.
The go-fed.org website has a tutorial. It also hosts godoc documentation for every version of this library.
What it does
This library provides a Resolver
, which is simply a collection of callbacks
that clients can specify to handle specific ActivtyStream data types. The
Resolver.Deserialize
method turns a JSON-decoded map[string]interface{}
into its proper type, passed to the corresponding callback.
For example, given the data:
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Note",
"name": "Equivalent Exchange",
"content": "I'll give half of my life to you and you give half of yours to me!",
"attachment": "https://example.com/attachment"
}
in b []byte
one can do the following:
var m map[string]interface{}
if err := json.Unmarshal(b, &m); err != nil {
return err
}
r := &Resolver {
NoteCallback: func(n *Note) error {
// 1) Use the Note concrete type here
// 2) Errors are propagated transparently
},
}
if handled, err := r.Deserialize(m); err != nil {
// 3) Any errors from #2 can be handled, or the payload is an unknown type.
return err
} else if !handled {
// 4) The callback to handle the concrete type was not set.
}
Only set the callbacks that are interesting. There is no need to set every callback, unless your application requires it.
Using concrete types
The convenience layer provides easy access to properties with specific types. However, because ActivityStreams is fundamentally built off of JSON-LD and still permits large degree of freedom when it comes to obtaining a concrete type for a property, the convenience API is built to give clients the freedom to choose how best to federate.
For every type in this package (except Resolver
), there is an equivalent type
in the activity/vocab
package. It takes only a call to Raw
to go from this
convenience API to the full API:
r := &Resolver {
NoteCallback: func(n *Note) error {
// Raw is available for all ActivityStream types
vocabNote := n.Raw()
},
}
To determine whether the call to Raw
is needed, the "get" and "has" methods
use Resolution
and Presence
types to inform client code. The client is free
to support as many types as is feasible within the specific application.
Reusing the Note
example above that has an attachment
, the following is
client code that tries to handle every possible type that attachment
can
take. The W3C does not require client applications to support all of these
use cases.
r := &Resolver {}
r.NoteCallback = func(n *Note) error {
if n.LenAttachment() == 1 {
if presence := n.HasAttachment(0); p == ConvenientPresence {
// A new or existing Resolver can be used. This is the convenient getter.
if resolution, err := n.ResolveAttachment(r, 0); err != nil {
return err
} else if resolution == RawResolutionNeeded {
vocabNote := n.Raw()
// Use the full API
if vocabNote.IsAttachmentIRI(0) {
...
} else ...
}
} else if p == RawPresence {
vocabNote := n.Raw()
// Use the full API
if vocabNote.IsAttachmentIRI(0) {
...
} else ...
}
}
}
Serializing data
Creating a raw type and serializing it is straightforward:
n := &Note{}
n.AddName("I'll see you again")
n.AddContent("You don't have to be alone when I leave")
// The "type" property is automatically handled...
m, err := n.Serialize()
if err != nil {
return err
}
// ...but "@context" is not.
m["@context"] = "https://www.w3.org/ns/activitystreams"
b, err := json.Marshal(m)
The only caveat is that clients must set "@context"
manually at this time.
What it doesn't do
Please see the same section in the go-fed/activity/vocab
package.
Other considerations
This library is entirely code-generated. Please see the same section in the
go-fed/activity/vocab
package for more details.