This repository has been archived on 2022-11-27. You can view files and clone it, but cannot push or open issues or pull requests.
activitypub/helpers.go

355 lines
7.6 KiB
Go

package activitypub
import (
"fmt"
)
type withLinkFn func (*Link) error
type withObjectFn func (*Object) error
type withActivityFn func (*Activity) error
type withIntransitiveActivityFn func (*IntransitiveActivity) error
type withQuestionFn func (*Question) error
type withActorFn func (*Actor) error
type withCollectionInterfaceFn func (collection CollectionInterface) error
type withCollectionFn func (collection *Collection) error
type withCollectionPageFn func (*CollectionPage) error
type withOrderedCollectionFn func (*OrderedCollection) error
type withOrderedCollectionPageFn func (*OrderedCollectionPage) error
type withItemCollectionFn func (collection *ItemCollection) error
// OnLink
func OnLink(it Item, fn withLinkFn) error {
ob, err := ToLink(it)
if err != nil {
return err
}
return fn(ob)
}
// OnObject
func OnObject(it Item, fn withObjectFn) error {
if IsItemCollection(it) {
return OnItemCollection(it, func(col *ItemCollection) error {
for _, it := range *col {
if err := OnObject(it, fn); err != nil {
return err
}
}
return nil
})
}
ob, err := ToObject(it)
if err != nil {
return err
}
return fn(ob)
}
// OnActivity
func OnActivity(it Item, fn withActivityFn) error {
if IsItemCollection(it) {
return OnItemCollection(it, func(col *ItemCollection) error {
for _, it := range *col {
if err := OnActivity(it, fn); err != nil {
return err
}
}
return nil
})
}
act, err := ToActivity(it)
if err != nil {
return err
}
return fn(act)
}
// OnIntransitiveActivity
func OnIntransitiveActivity(it Item, fn withIntransitiveActivityFn) error {
if IsItemCollection(it) {
return OnItemCollection(it, func(col *ItemCollection) error {
for _, it := range *col {
if err := OnIntransitiveActivity(it, fn); err != nil {
return err
}
}
return nil
})
}
act, err := ToIntransitiveActivity(it)
if err != nil {
return err
}
return fn(act)
}
// OnQuestion
func OnQuestion(it Item, fn withQuestionFn) error {
if IsItemCollection(it) {
return OnItemCollection(it, func(col *ItemCollection) error {
for _, it := range *col {
if err := OnQuestion(it, fn); err != nil {
return err
}
}
return nil
})
}
act, err := ToQuestion(it)
if err != nil {
return err
}
return fn(act)
}
// OnActor
func OnActor(it Item, fn withActorFn) error {
if IsItemCollection(it) {
return OnItemCollection(it, func(col *ItemCollection) error {
for _, it := range *col {
if err := OnActor(it, fn); err != nil {
return err
}
}
return nil
})
}
act, err := ToActor(it)
if err != nil {
return err
}
return fn(act)
}
// OnCollection
func OnCollection (it Item, fn withCollectionFn) error {
col, err := ToCollection(it)
if err != nil {
return err
}
return fn(col)
}
// OnCollectionIntf
func OnCollectionIntf(it Item, fn withCollectionInterfaceFn) error {
switch it.GetType() {
case CollectionOfItems:
col, err := ToItemCollection(it)
if err != nil {
return err
}
return fn(col)
case CollectionType:
col, err := ToCollection(it)
if err != nil {
return err
}
return fn(col)
case CollectionPageType:
return OnCollectionPage(it, func(p *CollectionPage) error {
col, err := ToCollectionPage(p)
if err != nil {
return err
}
return fn(col)
})
case OrderedCollectionType:
col, err := ToOrderedCollection(it)
if err != nil {
return err
}
return fn(col)
case OrderedCollectionPageType:
return OnOrderedCollectionPage(it, func(p *OrderedCollectionPage) error {
col, err := ToOrderedCollectionPage(p)
if err != nil {
return err
}
return fn(col)
})
default:
return fmt.Errorf("%T[%s] can't be converted to Collection", it, it.GetType())
}
}
// OnCollectionPage
func OnCollectionPage(it Item, fn withCollectionPageFn) error {
col, err := ToCollectionPage(it)
if err != nil {
return err
}
return fn(col)
}
// OnOrderedCollection
func OnOrderedCollection(it Item, fn withOrderedCollectionFn) error {
col, err := ToOrderedCollection(it)
if err != nil {
return err
}
return fn(col)
}
// OnOrderedCollectionPage executes a function on an ordered collection page type item
func OnOrderedCollectionPage(it Item, fn withOrderedCollectionPageFn) error {
col, err := ToOrderedCollectionPage(it)
if err != nil {
return err
}
return fn(col)
}
// OnItemCollection executes a function on a collection type item
func OnItemCollection(it Item, fn withItemCollectionFn) error {
col, err := ToItemCollection(it)
if err != nil {
return err
}
return fn(col)
}
// ItemOrderTimestamp is used for ordering a ItemCollection slice using the slice.Sort function
// It orders i1 and i2 based on their Published and Updated timestamps.
func ItemOrderTimestamp(i1, i2 Item) bool {
o1, e1 := ToObject(i1)
o2, e2 := ToObject(i2)
if e1 != nil || e2 != nil {
return false
}
t1 := o1.Published
if !o1.Updated.IsZero() {
t1 = o1.Updated
}
t2 := o2.Published
if !o2.Updated.IsZero() {
t2 = o2.Updated
}
return t1.Sub(t2) > 0
}
func notEmptyLink (l *Link) bool {
return len(l.ID) > 0 ||
LinkTypes.Contains(l.Type) ||
len(l.MediaType) > 0 ||
l.Preview != nil ||
l.Name != nil ||
len(l.Href) > 0 ||
len(l.Rel) > 0 ||
len(l.HrefLang) > 0 ||
l.Height > 0 ||
l.Width > 0
}
func notEmptyObject(o *Object) bool {
if o == nil {
return false
}
return len(o.ID) > 0 ||
ActivityTypes.Contains(o.Type) ||
o.Content != nil ||
o.Attachment != nil ||
o.AttributedTo != nil ||
o.Audience != nil ||
o.BCC != nil ||
o.Bto != nil ||
o.CC != nil ||
o.Context != nil ||
o.Duration > 0 ||
!o.EndTime.IsZero() ||
o.Generator != nil ||
o.Icon != nil ||
o.Image != nil ||
o.InReplyTo != nil ||
o.Likes != nil ||
o.Location != nil ||
len(o.MediaType) > 0 ||
o.Name != nil ||
o.Preview != nil ||
!o.Published.IsZero() ||
o.Replies != nil ||
o.Shares != nil ||
o.Source.MediaType != "" ||
o.Source.Content != nil ||
!o.StartTime.IsZero() ||
o.Summary != nil ||
o.Tag != nil ||
o.To != nil ||
!o.Updated.IsZero() ||
o.URL != nil
}
func notEmptyInstransitiveActivity (i *IntransitiveActivity) bool {
return i.Actor != nil ||
i.Target != nil ||
i.Result != nil ||
i.Origin != nil ||
i.Instrument != nil
}
func notEmptyActivity(a *Activity) bool {
var notEmpty bool
OnIntransitiveActivity(a, func(i *IntransitiveActivity) error {
notEmpty = notEmptyInstransitiveActivity(i)
return nil
})
return notEmpty || a.Object != nil
}
func notEmptyActor(a *Actor) bool {
var notEmpty bool
OnObject(a, func(o *Object) error {
notEmpty = notEmptyObject(o)
return nil
})
return notEmpty ||
a.Inbox != nil ||
a.Outbox != nil ||
a.Following != nil ||
a.Followers != nil ||
a.Liked != nil ||
a.PreferredUsername != nil ||
a.Endpoints != nil ||
a.Streams != nil ||
len(a.PublicKey.ID) > 0 ||
(a.PublicKey.Owner != nil &&
len(a.PublicKey.PublicKeyPem) > 0)
}
// NotEmpty
func NotEmpty(i Item) bool {
if IsNil(i) {
return false
}
var notEmpty bool
if IsIRI(i) {
notEmpty = len(i.GetLink()) > 0
}
if i.IsCollection() {
OnCollectionIntf(i, func(c CollectionInterface) error {
notEmpty = c != nil || len(c.Collection()) > 0
return nil
})
}
if ActivityTypes.Contains(i.GetType()) {
OnActivity(i, func(a *Activity) error {
notEmpty = notEmptyActivity(a)
return nil
})
} else if ActorTypes.Contains(i.GetType()) {
OnActor(i, func(a *Actor) error {
notEmpty = notEmptyActor(a)
return nil
})
} else if i.IsLink() {
OnLink(i, func(l *Link) error {
notEmpty = notEmptyLink(l)
return nil
})
} else {
OnObject(i, func(o *Object) error {
notEmpty = notEmptyObject(o)
return nil
})
}
return notEmpty
}