Begin porting C2S side effect behaviors.
このコミットが含まれているのは:
コミット
0f7dce6839
@ -125,10 +125,8 @@ type FederatingWrappedCallbacks struct {
|
||||
// db is the Database the FederatingWrappedCallbacks should use.
|
||||
db Database
|
||||
// inboxIRI is the inboxIRI that is handling this callback.
|
||||
// TODO: Populate
|
||||
inboxIRI *url.URL
|
||||
// newTransport creates a new Transport.
|
||||
// TODO: Populate
|
||||
newTransport func(c context.Context, actorBoxIRI *url.URL, gofedAgent string) (t Transport, err error)
|
||||
}
|
||||
|
||||
@ -820,7 +818,7 @@ func (w FederatingWrappedCallbacks) announce(c context.Context, a vocab.Activity
|
||||
}
|
||||
// Get 'shares' value, defaulting to a collection.
|
||||
sharesT := shares.GetType()
|
||||
if sharesT== nil {
|
||||
if sharesT == nil {
|
||||
col := streams.NewActivityStreamsCollection()
|
||||
sharesT = col
|
||||
shares.SetActivityStreamsCollection(col)
|
||||
|
@ -2,6 +2,7 @@ package pub
|
||||
|
||||
import (
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// inReplyToer is an ActivityStreams type with a 'inReplyTo' property
|
||||
@ -49,26 +50,31 @@ type publisheder interface {
|
||||
// toer is an ActivityStreams type with a 'to' property
|
||||
type toer interface {
|
||||
GetActivityStreamsTo() vocab.ActivityStreamsToProperty
|
||||
SetActivityStreamsTo(i vocab.ActivityStreamsToProperty)
|
||||
}
|
||||
|
||||
// btoer is an ActivityStreams type with a 'bto' property
|
||||
type btoer interface {
|
||||
GetActivityStreamsBto() vocab.ActivityStreamsBtoProperty
|
||||
SetActivityStreamsBto(i vocab.ActivityStreamsBtoProperty)
|
||||
}
|
||||
|
||||
// ccer is an ActivityStreams type with a 'cc' property
|
||||
type ccer interface {
|
||||
GetActivityStreamsCc() vocab.ActivityStreamsCcProperty
|
||||
SetActivityStreamsCc(i vocab.ActivityStreamsCcProperty)
|
||||
}
|
||||
|
||||
// bccer is an ActivityStreams type with a 'bcc' property
|
||||
type bccer interface {
|
||||
GetActivityStreamsBcc() vocab.ActivityStreamsBccProperty
|
||||
SetActivityStreamsBcc(i vocab.ActivityStreamsBccProperty)
|
||||
}
|
||||
|
||||
// audiencer is an ActivityStreams type with a 'audience' property
|
||||
type audiencer interface {
|
||||
GetActivityStreamsAudience() vocab.ActivityStreamsAudienceProperty
|
||||
SetActivityStreamsAudience(i vocab.ActivityStreamsAudienceProperty)
|
||||
}
|
||||
|
||||
// inboxer is an ActivityStreams type with a 'inbox' property
|
||||
@ -79,6 +85,7 @@ type inboxer interface {
|
||||
// attributedToer is an ActivityStreams type with a 'attributedTo' property
|
||||
type attributedToer interface {
|
||||
GetActivityStreamsAttributedTo() vocab.ActivityStreamsAttributedToProperty
|
||||
SetActivityStreamsAttributedTo(i vocab.ActivityStreamsAttributedToProperty)
|
||||
}
|
||||
|
||||
// likeser is an ActivityStreams type with a 'likes' property
|
||||
@ -98,3 +105,8 @@ type actorer interface {
|
||||
GetActivityStreamsActor() vocab.ActivityStreamsActorProperty
|
||||
SetActivityStreamsActor(i vocab.ActivityStreamsActorProperty)
|
||||
}
|
||||
|
||||
// appendIRIer is an ActivityStreams type that can Append IRIs.
|
||||
type appendIRIer interface {
|
||||
AppendIRI(v *url.URL)
|
||||
}
|
||||
|
@ -99,8 +99,8 @@ func (a *sideEffectActor) PostInbox(c context.Context, inboxIRI *url.URL, activi
|
||||
wrapped, other := a.s2s.Callbacks(c)
|
||||
// Populate side channels.
|
||||
wrapped.db = a.db
|
||||
wrapped.inboxIRI= inboxIRI
|
||||
wrapped.newTransport= a.s2s.NewTransport
|
||||
wrapped.inboxIRI = inboxIRI
|
||||
wrapped.newTransport = a.s2s.NewTransport
|
||||
if err = wrapped.disjoint(other); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -2,7 +2,10 @@ package pub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/go-fed/activity/streams"
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// SocialWrappedCallbacks lists the callback functions that already have some
|
||||
@ -15,8 +18,7 @@ type SocialWrappedCallbacks struct {
|
||||
//
|
||||
// The wrapping callback for the Social Protocol copies the actor(s) to
|
||||
// the 'attributedTo' property, copying recipients between the Create
|
||||
// activity and all objects, save the entry in the database, and adds it
|
||||
// to the outbox.
|
||||
// activity and all objects. It then saves the entry in the database.
|
||||
Create func(context.Context, vocab.ActivityStreamsCreate) error
|
||||
// Update handles additional side effects for the Update ActivityStreams
|
||||
// type.
|
||||
@ -58,9 +60,16 @@ type SocialWrappedCallbacks struct {
|
||||
//
|
||||
// TODO: Describe
|
||||
Block func(context.Context, vocab.ActivityStreamsBlock) error
|
||||
|
||||
// Sidechannel data -- this is set at request handling time. These must
|
||||
// be set before the callbacks are used.
|
||||
|
||||
// db is the Database the SocialWrappedCallbacks should use. It must be
|
||||
// set before calling the callbacks.
|
||||
db Database
|
||||
// deliverable is a sidechannel out, indicating if the handled activity
|
||||
// should be delivered to a peer.
|
||||
deliverable bool
|
||||
}
|
||||
|
||||
// disjoint ensures that the functions given do not share a type signature with
|
||||
@ -104,8 +113,6 @@ func (w SocialWrappedCallbacks) callbacks() []interface{} {
|
||||
w.update,
|
||||
w.deleteFn,
|
||||
w.follow,
|
||||
w.accept,
|
||||
w.reject,
|
||||
w.add,
|
||||
w.remove,
|
||||
w.like,
|
||||
@ -116,120 +123,85 @@ func (w SocialWrappedCallbacks) callbacks() []interface{} {
|
||||
|
||||
// create implements the social Create activity side effects.
|
||||
func (w SocialWrappedCallbacks) create(c context.Context, a vocab.ActivityStreamsCreate) error {
|
||||
*deliverable = true
|
||||
if s.LenObject() == 0 {
|
||||
return errObjectRequired
|
||||
w.deliverable = true
|
||||
op := a.GetActivityStreamsObject()
|
||||
if op == nil || op.Len() == 0 {
|
||||
return ErrObjectRequired
|
||||
}
|
||||
c = s.Raw()
|
||||
// When a Create activity is posted, the actor of the activity
|
||||
// SHOULD be copied onto the object's attributedTo field.
|
||||
// Presumably only if it doesn't already exist, to prevent
|
||||
// duplicate deliveries.
|
||||
createActorIds := make(map[string]interface{})
|
||||
for i := 0; i < c.ActorLen(); i++ {
|
||||
if c.IsActorObject(i) {
|
||||
obj := c.GetActorObject(i)
|
||||
id := obj.GetId()
|
||||
createActorIds[id.String()] = obj
|
||||
} else if c.IsActorLink(i) {
|
||||
l := c.GetActorLink(i)
|
||||
href := l.GetHref()
|
||||
createActorIds[href.String()] = l
|
||||
} else if c.IsActorIRI(i) {
|
||||
iri := c.GetActorIRI(i)
|
||||
createActorIds[iri.String()] = iri
|
||||
// Obtain all actor IRIs.
|
||||
actors := a.GetActivityStreamsActor()
|
||||
createActorIds := make(map[string]*url.URL, actors.Len())
|
||||
for iter := actors.Begin(); iter != actors.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
createActorIds[id.String()] = id
|
||||
}
|
||||
var obj []vocab.ObjectType
|
||||
for i := 0; i < c.ObjectLen(); i++ {
|
||||
if !c.IsObject(i) {
|
||||
return fmt.Errorf("unsupported: Create Activity with 'object' that is only an IRI")
|
||||
}
|
||||
obj = append(obj, c.GetObject(i))
|
||||
}
|
||||
objectAttributedToIds := make([]map[string]interface{}, len(obj))
|
||||
// Obtain each object's 'attributedTo' IRIs.
|
||||
objectAttributedToIds := make([]map[string]*url.URL, op.Len())
|
||||
for i := range objectAttributedToIds {
|
||||
objectAttributedToIds[i] = make(map[string]interface{})
|
||||
objectAttributedToIds[i] = make(map[string]*url.URL)
|
||||
}
|
||||
for k, o := range obj {
|
||||
for i := 0; i < o.AttributedToLen(); i++ {
|
||||
if o.IsAttributedToObject(i) {
|
||||
at := o.GetAttributedToObject(i)
|
||||
id := o.GetId()
|
||||
objectAttributedToIds[k][id.String()] = at
|
||||
} else if o.IsAttributedToLink(i) {
|
||||
at := o.GetAttributedToLink(i)
|
||||
href := at.GetHref()
|
||||
objectAttributedToIds[k][href.String()] = at
|
||||
} else if o.IsAttributedToIRI(i) {
|
||||
iri := o.GetAttributedToIRI(i)
|
||||
objectAttributedToIds[k][iri.String()] = iri
|
||||
for i := 0; i < op.Len(); i++ {
|
||||
t := op.At(i).GetType()
|
||||
attrToer, ok := t.(attributedToer)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
attr := attrToer.GetActivityStreamsAttributedTo()
|
||||
if attr == nil {
|
||||
attr = streams.NewActivityStreamsAttributedToProperty()
|
||||
attrToer.SetActivityStreamsAttributedTo(attr)
|
||||
}
|
||||
for iter := attr.Begin(); iter != attr.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objectAttributedToIds[i][id.String()] = id
|
||||
}
|
||||
}
|
||||
// Put all missing actor IRIs onto all object attributedTo properties.
|
||||
for k, v := range createActorIds {
|
||||
for i, attributedToMap := range objectAttributedToIds {
|
||||
if _, ok := attributedToMap[k]; !ok {
|
||||
var iri *url.URL
|
||||
if vObj, ok := v.(vocab.ObjectType); ok {
|
||||
if !vObj.HasId() {
|
||||
return fmt.Errorf("create actor object missing id")
|
||||
}
|
||||
iri = vObj.GetId()
|
||||
} else if vLink, ok := v.(vocab.LinkType); ok {
|
||||
if !vLink.HasHref() {
|
||||
return fmt.Errorf("create actor link missing href")
|
||||
}
|
||||
iri = vLink.GetHref()
|
||||
} else if vIRI, ok := v.(*url.URL); ok {
|
||||
iri = vIRI
|
||||
t := op.At(i).GetType()
|
||||
attrToer, ok := t.(attributedToer)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
obj[i].AppendAttributedToIRI(iri)
|
||||
attr := attrToer.GetActivityStreamsAttributedTo()
|
||||
attr.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Put all missing object attributedTo IRIs onto the actor property.
|
||||
for _, attributedToMap := range objectAttributedToIds {
|
||||
for k, v := range attributedToMap {
|
||||
if _, ok := createActorIds[k]; !ok {
|
||||
var iri *url.URL
|
||||
if vObj, ok := v.(vocab.ObjectType); ok {
|
||||
if !vObj.HasId() {
|
||||
return fmt.Errorf("attributedTo object missing id")
|
||||
}
|
||||
iri = vObj.GetId()
|
||||
} else if vLink, ok := v.(vocab.LinkType); ok {
|
||||
if !vLink.HasHref() {
|
||||
return fmt.Errorf("attributedTo link missing href")
|
||||
}
|
||||
iri = vLink.GetHref()
|
||||
} else if vIRI, ok := v.(*url.URL); ok {
|
||||
iri = vIRI
|
||||
}
|
||||
c.AppendActorIRI(iri)
|
||||
actors.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
// As such, a server SHOULD copy any recipients of the Create activity to its
|
||||
// object upon initial distribution, and likewise with copying recipients from
|
||||
// the object to the wrapping Create activity.
|
||||
if err := f.sameRecipients(c); err != nil {
|
||||
// Copy over the 'to', 'bto', 'cc', 'bcc', and 'audience' recipients
|
||||
// between the activity and all child objects and vice versa.
|
||||
if err := normalizeRecipients(a); err != nil {
|
||||
return err
|
||||
}
|
||||
// Create requires the client application to persist the 'object' that
|
||||
// was created.
|
||||
for _, o := range obj {
|
||||
if err := f.App.Set(ctx, o); err != nil {
|
||||
// Persist all objects we've created, which will include sensitive
|
||||
// recipients such as 'bcc' and 'bto'.
|
||||
for i := 0; i < op.Len(); i++ {
|
||||
obj := op.At(i).GetType()
|
||||
// TODO: Lock
|
||||
if err := w.db.Create(c, obj); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Persist the above changes in the outbox
|
||||
var err error
|
||||
*toAddToOutbox = make(map[string]interface{})
|
||||
*toAddToOutbox, err = c.Serialize()
|
||||
if err != nil {
|
||||
return err
|
||||
if w.Create != nil {
|
||||
return w.Create(c, a)
|
||||
}
|
||||
return f.ClientCallbacker.Create(ctx, s)
|
||||
return nil
|
||||
}
|
||||
|
||||
// update implements the social Update activity side effects.
|
||||
|
261
pub/util.go
261
pub/util.go
@ -539,3 +539,264 @@ func mustHaveActivityActorsMatchObjectActors(a vocab.ActivityType) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// normalizeRecipients ensures the activity and object have the same 'to',
|
||||
// 'bto', 'cc', 'bcc', and 'audience' properties. Copy the Activity's recipients
|
||||
// to objects, and the objects to the activity, but does NOT copy objects'
|
||||
// recipients to each other.
|
||||
func normalizeRecipients(a vocab.ActivityStreamsCreate) error {
|
||||
// Phase 0: Acquire all recipients on the activity.
|
||||
//
|
||||
// Obtain the actorTo map
|
||||
actorToMap := make(map[string]interface{})
|
||||
actorTo := a.GetActivityStreamsTo()
|
||||
if actorTo == nil {
|
||||
actorTo = streams.NewActivityStreamsToProperty()
|
||||
a.SetActivityStreamsTo(actorTo)
|
||||
}
|
||||
for iter := actorTo.Begin(); iter != actorTo.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
actorToMap[id.String()] = id
|
||||
}
|
||||
// Obtain the actorBto map
|
||||
actorBtoMap := make(map[string]interface{})
|
||||
actorBto := a.GetActivityStreamsBto()
|
||||
if actorBto == nil {
|
||||
actorBto = streams.NewActivityStreamsBtoProperty()
|
||||
a.SetActivityStreamsBto(actorBto)
|
||||
}
|
||||
for iter := actorBto.Begin(); iter != actorBto.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
actorBtoMap[id.String()] = id
|
||||
}
|
||||
// Obtain the actorCc map
|
||||
actorCcMap := make(map[string]interface{})
|
||||
actorCc := a.GetActivityStreamsCc()
|
||||
if actorCc == nil {
|
||||
actorCc = streams.NewActivityStreamsCcProperty()
|
||||
a.SetActivityStreamsCc(actorCc)
|
||||
}
|
||||
for iter := actorCc.Begin(); iter != actorCc.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
actorCcMap[id.String()] = id
|
||||
}
|
||||
// Obtain the actorBcc map
|
||||
actorBccMap := make(map[string]interface{})
|
||||
actorBcc := a.GetActivityStreamsBcc()
|
||||
if actorBcc == nil {
|
||||
actorBcc = streams.NewActivityStreamsBccProperty()
|
||||
a.SetActivityStreamsBcc(actorBcc)
|
||||
}
|
||||
for iter := actorBcc.Begin(); iter != actorBcc.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
actorBccMap[id.String()] = id
|
||||
}
|
||||
// Obtain the actorAudience map
|
||||
actorAudienceMap := make(map[string]interface{})
|
||||
actorAudience := a.GetActivityStreamsAudience()
|
||||
if actorAudience == nil {
|
||||
actorAudience = streams.NewActivityStreamsAudienceProperty()
|
||||
a.SetActivityStreamsAudience(actorAudience)
|
||||
}
|
||||
for iter := actorAudience.Begin(); iter != actorAudience.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
actorAudienceMap[id.String()] = id
|
||||
}
|
||||
// Obtain the objects maps for each recipient type.
|
||||
o := a.GetActivityStreamsObject()
|
||||
objsTo := make([]map[string]interface{}, o.Len())
|
||||
objsBto := make([]map[string]interface{}, o.Len())
|
||||
objsCco := make([]map[string]interface{}, o.Len())
|
||||
objsBcc := make([]map[string]interface{}, o.Len())
|
||||
objsAudience := make([]map[string]interface{}, o.Len())
|
||||
for i := 0; i < o.Len(); i++ {
|
||||
// Phase 1: Acquire all existing recipients on the object.
|
||||
//
|
||||
// Object to
|
||||
objsTo[i] = make(map[string]interface{})
|
||||
var oTo vocab.ActivityStreamsToProperty
|
||||
if tr, ok := o.At(i).(toer); !ok {
|
||||
return fmt.Errorf("the Create object at %d has no 'to' property", i)
|
||||
} else {
|
||||
oTo = tr.GetActivityStreamsTo()
|
||||
if oTo == nil {
|
||||
oTo = streams.NewActivityStreamsToProperty()
|
||||
tr.SetActivityStreamsTo(oTo)
|
||||
}
|
||||
}
|
||||
for iter := oTo.Begin(); iter != oTo.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objsTo[i][id.String()] = id
|
||||
}
|
||||
// Object bto
|
||||
objsBto[i] = make(map[string]interface{})
|
||||
var oBto vocab.ActivityStreamsBtoProperty
|
||||
if tr, ok := o.At(i).(btoer); !ok {
|
||||
return fmt.Errorf("the Create object at %d has no 'bto' property", i)
|
||||
} else {
|
||||
oBto = tr.GetActivityStreamsBto()
|
||||
if oBto == nil {
|
||||
oBto = streams.NewActivityStreamsBtoProperty()
|
||||
tr.SetActivityStreamsBto(oBto)
|
||||
}
|
||||
}
|
||||
for iter := oBto.Begin(); iter != oBto.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objsBto[i][id.String()] = id
|
||||
}
|
||||
// Object cc
|
||||
objsCc[i] = make(map[string]interface{})
|
||||
var oCc vocab.ActivityStreamsCcProperty
|
||||
if tr, ok := o.At(i).(ccer); !ok {
|
||||
return fmt.Errorf("the Create object at %d has no 'cc' property", i)
|
||||
} else {
|
||||
oCc = tr.GetActivityStreamsCc()
|
||||
if oCc == nil {
|
||||
oCc = streams.NewActivityStreamsCcProperty()
|
||||
tr.SetActivityStreamsCc(oCc)
|
||||
}
|
||||
}
|
||||
for iter := oCc.Begin(); iter != oCc.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objsCc[i][id.String()] = id
|
||||
}
|
||||
// Object bcc
|
||||
objsBcc[i] = make(map[string]interface{})
|
||||
var oBcc vocab.ActivityStreamsBccProperty
|
||||
if tr, ok := o.At(i).(bccer); !ok {
|
||||
return fmt.Errorf("the Create object at %d has no 'bcc' property", i)
|
||||
} else {
|
||||
oBcc = tr.GetActivityStreamsBcc()
|
||||
if oBcc == nil {
|
||||
oBcc = streams.NewActivityStreamsBccProperty()
|
||||
tr.SetActivityStreamsBcc(oBcc)
|
||||
}
|
||||
}
|
||||
for iter := oBcc.Begin(); iter != oBcc.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objsBcc[i][id.String()] = id
|
||||
}
|
||||
// Object audience
|
||||
objsAudience[i] = make(map[string]interface{})
|
||||
var oAudience vocab.ActivityStreamsAudienceProperty
|
||||
if tr, ok := o.At(i).(audiencer); !ok {
|
||||
return fmt.Errorf("the Create object at %d has no 'audience' property", i)
|
||||
} else {
|
||||
oAudience = tr.GetActivityStreamsAudience()
|
||||
if oAudience == nil {
|
||||
oAudience = streams.NewActivityStreamsAudienceProperty()
|
||||
tr.SetActivityStreamsAudience(oAudience)
|
||||
}
|
||||
}
|
||||
for iter := oAudience.Begin(); iter != oAudience.End(); iter = iter.Next() {
|
||||
id, err := ToId(iter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objsAudience[i][id.String()] = id
|
||||
}
|
||||
// Phase 2: Apply missing recipients to the object from the
|
||||
// activity.
|
||||
//
|
||||
// Activity to -> Object to
|
||||
for k, v := range actorToMap {
|
||||
if _, ok := objsTo[i][k]; !ok {
|
||||
oTo.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
// Activity bto -> Object bto
|
||||
for k, v := range actorBtoMap {
|
||||
if _, ok := objsBto[i][k]; !ok {
|
||||
oBto.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
// Activity cc -> Object cc
|
||||
for k, v := range actorCcMap {
|
||||
if _, ok := objsCc[i][k]; !ok {
|
||||
oCc.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
// Activity bcc -> Object bcc
|
||||
for k, v := range actorBccMap {
|
||||
if _, ok := objsBcc[i][k]; !ok {
|
||||
oBcc.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
// Activity audience -> Object audience
|
||||
for k, v := range actorAudienceMap {
|
||||
if _, ok := objsAudience[i][k]; !ok {
|
||||
oAudience.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Phase 3: Apply missing recipients to the activity from the objects.
|
||||
//
|
||||
// Object to -> Activity to
|
||||
for i := 0; i < len(objsTo); i++ {
|
||||
for k, v := range objsTo[i] {
|
||||
if _, ok := actorToMap[k]; !ok {
|
||||
actorTo.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Object bto -> Activity bto
|
||||
for i := 0; i < len(objsBto); i++ {
|
||||
for k, v := range objsBto[i] {
|
||||
if _, ok := actorBtoMap[k]; !ok {
|
||||
actorBto.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Object cc -> Activity cc
|
||||
for i := 0; i < len(objsCc); i++ {
|
||||
for k, v := range objsCc[i] {
|
||||
if _, ok := actorCcMap[k]; !ok {
|
||||
actorCc.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Object bcc -> Activity bcc
|
||||
for i := 0; i < len(objsBcc); i++ {
|
||||
for k, v := range objsBcc[i] {
|
||||
if _, ok := actorBccMap[k]; !ok {
|
||||
actorBcc.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Object audience -> Activity audience
|
||||
for i := 0; i < len(objsAudience); i++ {
|
||||
for k, v := range objsAudience[i] {
|
||||
if _, ok := actorAudienceMap[k]; !ok {
|
||||
actorAudience.AppendIRI(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
読み込み中…
新しいイシューから参照
ユーザーをブロックする