2019-08-20 19:43:36 +00:00
|
|
|
package activitypub
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
)
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// WithLinkFn represents a function type that can be used as a parameter for OnLink helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithLinkFn func(*Link) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithObjectFn represents a function type that can be used as a parameter for OnObject helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithObjectFn func(*Object) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithActivityFn represents a function type that can be used as a parameter for OnActivity helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithActivityFn func(*Activity) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithIntransitiveActivityFn represents a function type that can be used as a parameter for OnIntransitiveActivity helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithIntransitiveActivityFn func(*IntransitiveActivity) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithQuestionFn represents a function type that can be used as a parameter for OnQuestion helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithQuestionFn func(*Question) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithActorFn represents a function type that can be used as a parameter for OnActor helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithActorFn func(*Actor) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithCollectionInterfaceFn represents a function type that can be used as a parameter for OnCollectionIntf helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithCollectionInterfaceFn func(CollectionInterface) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithCollectionFn represents a function type that can be used as a parameter for OnCollection helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithCollectionFn func(*Collection) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithCollectionPageFn represents a function type that can be used as a parameter for OnCollectionPage helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithCollectionPageFn func(*CollectionPage) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithOrderedCollectionFn represents a function type that can be used as a parameter for OnOrderedCollection helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithOrderedCollectionFn func(*OrderedCollection) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithOrderedCollectionPageFn represents a function type that can be used as a parameter for OnOrderedCollectionPage helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithOrderedCollectionPageFn func(*OrderedCollectionPage) error
|
2021-11-12 18:10:31 +00:00
|
|
|
|
|
|
|
// WithItemCollectionFn represents a function type that can be used as a parameter for OnItemCollection helper function
|
2021-07-21 16:38:41 +00:00
|
|
|
type WithItemCollectionFn func(*ItemCollection) error
|
2019-08-20 19:43:36 +00:00
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnLink calls function fn on it Item if it can be asserted to type Link
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnLink(it Item, fn WithLinkFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2020-12-28 13:58:56 +00:00
|
|
|
ob, err := ToLink(it)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(ob)
|
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnObject calls function fn on it Item if it can be asserted to type Object
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnObject(it Item, fn WithObjectFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-01-31 12:30:40 +00:00
|
|
|
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
|
|
|
|
})
|
|
|
|
}
|
2020-12-28 13:58:56 +00:00
|
|
|
ob, err := ToObject(it)
|
2019-12-05 15:42:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2019-08-20 19:43:36 +00:00
|
|
|
}
|
2019-12-05 15:42:27 +00:00
|
|
|
return fn(ob)
|
2019-08-20 19:43:36 +00:00
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnActivity calls function fn on it Item if it can be asserted to type Activity
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnActivity(it Item, fn WithActivityFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-01-31 12:30:40 +00:00
|
|
|
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)
|
2019-08-20 19:43:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(act)
|
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnIntransitiveActivity calls function fn on it Item if it can be asserted to type IntransitiveActivity
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnIntransitiveActivity(it Item, fn WithIntransitiveActivityFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-01-31 12:30:40 +00:00
|
|
|
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)
|
2019-08-20 20:02:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(act)
|
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnQuestion calls function fn on it Item if it can be asserted to type Question
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnQuestion(it Item, fn WithQuestionFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-01-31 12:30:40 +00:00
|
|
|
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)
|
2019-08-20 20:02:37 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(act)
|
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnActor calls function fn on it Item if it can be asserted to type Actor
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnActor(it Item, fn WithActorFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-01-31 12:30:40 +00:00
|
|
|
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)
|
2019-08-20 19:43:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-12-05 15:42:27 +00:00
|
|
|
return fn(act)
|
2019-08-20 19:43:36 +00:00
|
|
|
}
|
2021-09-12 10:52:27 +00:00
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnCollection calls function fn on it Item if it can be asserted to type Collection
|
2021-09-12 10:52:27 +00:00
|
|
|
func OnCollection(it Item, fn WithCollectionFn) error {
|
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2020-01-14 19:57:42 +00:00
|
|
|
col, err := ToCollection(it)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(col)
|
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnCollectionIntf calls function fn on it Item if it can be asserted to one of the Collection types
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnCollectionIntf(it Item, fn WithCollectionInterfaceFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2019-08-29 10:49:01 +00:00
|
|
|
switch it.GetType() {
|
2019-12-03 16:23:59 +00:00
|
|
|
case CollectionOfItems:
|
|
|
|
col, err := ToItemCollection(it)
|
2019-12-01 18:49:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-03-29 16:26:30 +00:00
|
|
|
return fn(col)
|
2019-12-03 16:23:59 +00:00
|
|
|
case CollectionType:
|
|
|
|
col, err := ToCollection(it)
|
2019-08-29 10:49:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(col)
|
2019-12-03 16:23:59 +00:00
|
|
|
case CollectionPageType:
|
|
|
|
return OnCollectionPage(it, func(p *CollectionPage) error {
|
2020-08-30 12:46:49 +00:00
|
|
|
col, err := ToCollectionPage(p)
|
2019-08-29 10:49:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(col)
|
|
|
|
})
|
2020-03-23 10:27:27 +00:00
|
|
|
case OrderedCollectionType:
|
|
|
|
col, err := ToOrderedCollection(it)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(col)
|
|
|
|
case OrderedCollectionPageType:
|
|
|
|
return OnOrderedCollectionPage(it, func(p *OrderedCollectionPage) error {
|
2020-08-30 12:46:49 +00:00
|
|
|
col, err := ToOrderedCollectionPage(p)
|
2020-03-23 10:27:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(col)
|
|
|
|
})
|
2019-08-29 10:49:01 +00:00
|
|
|
default:
|
2021-11-12 18:10:31 +00:00
|
|
|
return fmt.Errorf("%T[%s] can't be converted to a Collection type", it, it.GetType())
|
2019-08-21 20:32:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnCollectionPage calls function fn on it Item if it can be asserted to type CollectionPage
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnCollectionPage(it Item, fn WithCollectionPageFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-01-31 12:30:40 +00:00
|
|
|
col, err := ToCollectionPage(it)
|
2019-08-21 20:32:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(col)
|
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnOrderedCollection calls function fn on it Item if it can be asserted to type OrderedCollection
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnOrderedCollection(it Item, fn WithOrderedCollectionFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2019-12-05 15:42:27 +00:00
|
|
|
col, err := ToOrderedCollection(it)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2019-08-21 20:32:53 +00:00
|
|
|
}
|
2019-12-05 15:42:27 +00:00
|
|
|
return fn(col)
|
2019-08-21 20:32:53 +00:00
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnOrderedCollectionPage calls function fn on it Item if it can be asserted to type OrderedCollectionPage
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnOrderedCollectionPage(it Item, fn WithOrderedCollectionPageFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-01-31 12:30:40 +00:00
|
|
|
col, err := ToOrderedCollectionPage(it)
|
2019-08-21 20:32:53 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(col)
|
|
|
|
}
|
2019-12-01 18:49:47 +00:00
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// OnItemCollection calls function fn on it Item if it can be asserted to type ItemCollection
|
2021-07-21 16:38:41 +00:00
|
|
|
func OnItemCollection(it Item, fn WithItemCollectionFn) error {
|
2021-09-12 10:52:27 +00:00
|
|
|
if it == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2021-01-31 12:30:40 +00:00
|
|
|
col, err := ToItemCollection(it)
|
2019-12-01 18:49:47 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return fn(col)
|
|
|
|
}
|
2019-12-31 07:55:21 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|
2021-01-09 17:37:38 +00:00
|
|
|
|
2021-09-12 10:52:27 +00:00
|
|
|
func notEmptyLink(l *Link) bool {
|
2021-01-09 17:37:38 +00:00
|
|
|
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 ||
|
2021-08-14 16:34:16 +00:00
|
|
|
len(o.Type) > 0 ||
|
2021-01-09 17:37:38 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-09-12 10:52:27 +00:00
|
|
|
func notEmptyInstransitiveActivity(i *IntransitiveActivity) bool {
|
2021-08-14 16:34:16 +00:00
|
|
|
notEmpty := i.Actor != nil ||
|
2021-01-09 17:37:38 +00:00
|
|
|
i.Target != nil ||
|
|
|
|
i.Result != nil ||
|
|
|
|
i.Origin != nil ||
|
|
|
|
i.Instrument != nil
|
2021-08-14 16:34:16 +00:00
|
|
|
if notEmpty {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
OnObject(i, func(ob *Object) error {
|
|
|
|
notEmpty = notEmptyObject(ob)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return notEmpty
|
2021-01-09 17:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 ||
|
2022-01-02 15:20:23 +00:00
|
|
|
len(a.PublicKey.ID)+len(a.PublicKey.Owner)+len(a.PublicKey.PublicKeyPem) > 0
|
2021-01-09 17:37:38 +00:00
|
|
|
}
|
|
|
|
|
2021-11-12 18:10:31 +00:00
|
|
|
// NotEmpty tells us if a Item interface value has a non nil value for various types
|
|
|
|
// that implement
|
2021-01-09 17:37:38 +00:00
|
|
|
func NotEmpty(i Item) bool {
|
2021-02-02 13:18:16 +00:00
|
|
|
if IsNil(i) {
|
2021-01-09 17:37:38 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
var notEmpty bool
|
2021-09-12 10:52:27 +00:00
|
|
|
if IsIRI(i) {
|
2021-01-09 17:37:38 +00:00
|
|
|
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
|
2021-01-31 12:30:40 +00:00
|
|
|
}
|