Overhaul of interfaces, begin detailed Activity handling.
このコミットが含まれているのは:
コミット
683a26f6c1
857
pub/fed.go
857
pub/fed.go
ファイル差分が大きすぎるため省略します
差分を読み込み
@ -1,21 +1,97 @@
|
||||
package pub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/go-fed/activity/vocab"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HandlerFunc returns true if it was able to handle the request as an
|
||||
// ActivityPub request. If it handled the request then the error should be
|
||||
// checked. The response will have already been written to when handled. Client
|
||||
// applications can freely choose how to handle the request if this function
|
||||
// does not handle it.
|
||||
// checked. The response will have already been written to when handled and
|
||||
// there was no error. Client applications can freely choose how to handle the
|
||||
// request if this function does not handle it.
|
||||
//
|
||||
// Note that if the handler attempted to handle the request but returned an
|
||||
// error, it is up to the client application to determine what headers and
|
||||
// response to send to the requester.
|
||||
type HandlerFunc func(http.ResponseWriter, *http.Request) (bool, error)
|
||||
type HandlerFunc func(context.Context, http.ResponseWriter, *http.Request) (bool, error)
|
||||
|
||||
// Clock determines the time.
|
||||
type Clock interface {
|
||||
Now() time.Time
|
||||
}
|
||||
|
||||
// Application is provided by users of this library in order to implement a
|
||||
// social-federative-web application.
|
||||
//
|
||||
// The contexts provided in these calls are passed through this library without
|
||||
// modification, allowing implementations to pass-through request-scoped data in
|
||||
// order to properly handle the request.
|
||||
type Application interface {
|
||||
// Get fetches the ActivityStream representation of the given id.
|
||||
Get(c context.Context, id url.URL) (PubObject, error)
|
||||
// Set should write or overwrite the value of the provided object for
|
||||
// its 'id'.
|
||||
Set(c context.Context, o PubObject) error
|
||||
// GetInbox returns the OrderedCollection inbox of the actor with the
|
||||
// provided ID. It is up to the implementation to provide the correct
|
||||
// collection for the kind of authorization given in the request.
|
||||
GetInbox(c context.Context, r *http.Request) (vocab.OrderedCollectionType, error)
|
||||
// GetOutbox returns the OrderedCollection inbox of the actor with the
|
||||
// provided ID. It is up to the implementation to provide the correct
|
||||
// collection for the kind of authorization given in the request.
|
||||
GetOutbox(c context.Context, r *http.Request) (vocab.OrderedCollectionType, error)
|
||||
// PostOutboxAuthorized determines whether the request is able to post
|
||||
// an Activity to the outbox.
|
||||
PostOutboxAuthorized(c context.Context, r *http.Request) (bool, error)
|
||||
// NewId takes in a client id token and returns an ActivityStreams IRI
|
||||
// id for a new Activity posted to the outbox. The object is provided
|
||||
// as a Typer so clients can use it to decide how to generate the IRI.
|
||||
NewId(c context.Context, t Typer) url.URL
|
||||
// AddToOutboxResolver(c context.Context) (*streams.Resolver, error)
|
||||
// ActorIRI returns the actor's IRI associated with the given request.
|
||||
ActorIRI(c context.Context, r *http.Request) (url.URL, error)
|
||||
}
|
||||
|
||||
// SocialApp is provided by users of this library and designed to handle
|
||||
// receiving messages from ActivityPub clients through the Social API.
|
||||
type SocialApp interface {
|
||||
// Owns returns true if the provided id is owned by this server.
|
||||
Owns(c context.Context, id url.URL) bool
|
||||
// CanAdd returns true if the provided object is allowed to be added to
|
||||
// the given target collection.
|
||||
CanAdd(c context.Context, o vocab.ObjectType, t vocab.ObjectType) bool
|
||||
// CanRemove returns true if the provided object is allowed to be
|
||||
// removed from the given target collection.
|
||||
CanRemove(c context.Context, o vocab.ObjectType, t vocab.ObjectType) bool
|
||||
}
|
||||
|
||||
// PubObject is an ActivityPub Object.
|
||||
type PubObject interface {
|
||||
GetId() url.URL
|
||||
SetId(url.URL)
|
||||
HasId() bool
|
||||
TypeLen() int
|
||||
GetType(int) interface{}
|
||||
AddType(interface{})
|
||||
RemoveType(int)
|
||||
}
|
||||
|
||||
// Typer is an object that has a type.
|
||||
type Typer interface {
|
||||
TypeLen() (l int)
|
||||
GetType(index int) (v interface{})
|
||||
}
|
||||
|
||||
// typeIder is a Typer with additional generic capabilities.
|
||||
type typeIder interface {
|
||||
Typer
|
||||
SetId(v url.URL)
|
||||
Serialize() (m map[string]interface{}, e error)
|
||||
}
|
||||
|
||||
// actorObject is an object that has "actor" or "attributedTo" properties,
|
||||
// representing the author or originator of the object.
|
||||
|
131
pub/internal.go
131
pub/internal.go
@ -705,6 +705,137 @@ func getURIsInOrderedItemer(i orderedItemer) []url.URL {
|
||||
return u
|
||||
}
|
||||
|
||||
type activityWithObject interface {
|
||||
ObjectLen() (l int)
|
||||
IsObject(index int) (ok bool)
|
||||
GetObject(index int) (v vocab.ObjectType)
|
||||
IsObjectIRI(index int) (ok bool)
|
||||
GetObjectIRI(index int) (v url.URL)
|
||||
}
|
||||
|
||||
func getObjectIds(a activityWithObject) (u []url.URL, e error) {
|
||||
for i := 0; i < a.ObjectLen(); i++ {
|
||||
if a.IsObject(i) {
|
||||
obj := a.GetObject(i)
|
||||
if !obj.HasId() {
|
||||
e = fmt.Errorf("object has no id: %v", obj)
|
||||
return
|
||||
}
|
||||
u = append(u, obj.GetId())
|
||||
} else if a.IsObjectIRI(i) {
|
||||
u = append(u, a.GetObjectIRI(i))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type activityWithTarget interface {
|
||||
TargetLen() (l int)
|
||||
IsTargetObject(index int) (ok bool)
|
||||
GetTargetObject(index int) (v vocab.ObjectType)
|
||||
IsTargetIRI(index int) (ok bool)
|
||||
GetTargetIRI(index int) (v url.URL)
|
||||
}
|
||||
|
||||
func getTargetIds(a activityWithTarget) (u []url.URL, e error) {
|
||||
for i := 0; i < a.TargetLen(); i++ {
|
||||
if a.IsTargetObject(i) {
|
||||
obj := a.GetTargetObject(i)
|
||||
if !obj.HasId() {
|
||||
e = fmt.Errorf("object has no id: %v", obj)
|
||||
return
|
||||
}
|
||||
u = append(u, obj.GetId())
|
||||
} else if a.IsTargetIRI(i) {
|
||||
u = append(u, a.GetTargetIRI(i))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func removeCollectionItemWithId(c vocab.CollectionType, iri url.URL) {
|
||||
for i := 0; i < c.ItemsLen(); i++ {
|
||||
if c.IsItemsObject(i) {
|
||||
o := c.GetItemsObject(i)
|
||||
if !o.HasId() {
|
||||
continue
|
||||
}
|
||||
if o.GetId() == iri {
|
||||
c.RemoveItemsObject(i)
|
||||
return
|
||||
}
|
||||
} else if c.IsItemsLink(i) {
|
||||
l := c.GetItemsLink(i)
|
||||
if !l.HasHref() {
|
||||
continue
|
||||
}
|
||||
if l.GetHref() == iri {
|
||||
c.RemoveItemsLink(i)
|
||||
return
|
||||
}
|
||||
} else if c.IsItemsIRI(i) {
|
||||
if c.GetItemsIRI(i) == iri {
|
||||
c.RemoveItemsIRI(i)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func removeOrderedCollectionItemWithId(c vocab.OrderedCollectionType, iri url.URL) {
|
||||
for i := 0; i < c.OrderedItemsLen(); i++ {
|
||||
if c.IsOrderedItemsObject(i) {
|
||||
o := c.GetOrderedItemsObject(i)
|
||||
if !o.HasId() {
|
||||
continue
|
||||
}
|
||||
if o.GetId() == iri {
|
||||
c.RemoveOrderedItemsObject(i)
|
||||
return
|
||||
}
|
||||
} else if c.IsOrderedItemsLink(i) {
|
||||
l := c.GetOrderedItemsLink(i)
|
||||
if !l.HasHref() {
|
||||
continue
|
||||
}
|
||||
if l.GetHref() == iri {
|
||||
c.RemoveOrderedItemsLink(i)
|
||||
return
|
||||
}
|
||||
} else if c.IsOrderedItemsIRI(i) {
|
||||
if c.GetOrderedItemsIRI(i) == iri {
|
||||
c.RemoveOrderedItemsIRI(i)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// toTombstone creates a Tombstone for the given object.
|
||||
func toTombstone(obj vocab.ObjectType, id url.URL, now time.Time) vocab.TombstoneType {
|
||||
tomb := &vocab.Tombstone{}
|
||||
tomb.SetId(id)
|
||||
for i := 0; i < obj.TypeLen(); i++ {
|
||||
if s, ok := obj.GetType(i).(string); ok {
|
||||
tomb.AddFormerTypeString(s)
|
||||
} else if fObj, ok := obj.GetType(i).(vocab.ObjectType); ok {
|
||||
tomb.AddFormerTypeObject(fObj)
|
||||
}
|
||||
}
|
||||
if obj.IsPublished() {
|
||||
tomb.SetPublished(obj.GetPublished())
|
||||
} else if obj.IsPublishedIRI() {
|
||||
tomb.SetPublishedIRI(obj.GetPublishedIRI())
|
||||
}
|
||||
if obj.IsUpdated() {
|
||||
tomb.SetUpdated(obj.GetUpdated())
|
||||
} else if obj.IsUpdatedIRI() {
|
||||
tomb.SetUpdatedIRI(obj.GetUpdatedIRI())
|
||||
}
|
||||
tomb.SetDeleted(now)
|
||||
return tomb
|
||||
}
|
||||
|
||||
// TODO: Move this to vocab package.
|
||||
var activityTypes = []string{"Accept", "Add", "Announce", "Arrive", "Block", "Create", "Delete", "Dislike", "Flag", "Follow", "Ignore", "Invite", "Join", "Leave", "Like", "Listen", "Move", "Offer", "Question", "Reject", "Read", "Remove", "TentativeReject", "TentativeAccept", "Travel", "Undo", "Update", "View"}
|
||||
|
||||
|
@ -7,6 +7,34 @@ import (
|
||||
"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 toActorResolver(a *actorObject) *streams.Resolver {
|
||||
return &streams.Resolver{
|
||||
AnyObjectCallback: func(i vocab.ObjectType) error {
|
||||
|
読み込み中…
新しいイシューから参照
ユーザーをブロックする