diff options
Diffstat (limited to 'internal/ap/extract.go')
-rw-r--r-- | internal/ap/extract.go | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/internal/ap/extract.go b/internal/ap/extract.go index 21ff20235..4cefd22dc 100644 --- a/internal/ap/extract.go +++ b/internal/ap/extract.go @@ -28,12 +28,53 @@ import ( "time" "github.com/superseriousbusiness/activity/pub" + "github.com/superseriousbusiness/activity/streams/vocab" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/text" "github.com/superseriousbusiness/gotosocial/internal/util" ) +// ExtractObject will extract an object vocab.Type from given implementing interface. +func ExtractObject(with WithObject) vocab.Type { + // Extract the attached object (if any). + obj := with.GetActivityStreamsObject() + if obj == nil { + return nil + } + + // Only support single + // objects (for now...) + if obj.Len() != 1 { + return nil + } + + // Extract object vocab.Type. + return obj.At(0).GetType() +} + +// ExtractActivityData will extract the usable data type (e.g. Note, Question, etc) and corresponding JSON, from activity. +func ExtractActivityData(activity pub.Activity, rawJSON map[string]any) (vocab.Type, map[string]any, bool) { + switch typeName := activity.GetTypeName(); { + // Activity (has "object"). + case isActivity(typeName): + objType := ExtractObject(activity) + if objType == nil { + return nil, nil, false + } + objJSON, _ := rawJSON["object"].(map[string]any) + return objType, objJSON, true + + // IntransitiveAcitivity (no "object"). + case isIntransitiveActivity(typeName): + return activity, rawJSON, false + + // Unknown. + default: + return nil, nil, false + } +} + // ExtractPreferredUsername returns a string representation of // an interface's preferredUsername property. Will return an // error if preferredUsername is nil, not a string, or empty. @@ -497,6 +538,38 @@ func ExtractContent(i WithContent) string { return "" } +// ExtractAttachments attempts to extract barebones MediaAttachment objects from given AS interface type. +func ExtractAttachments(i WithAttachment) ([]*gtsmodel.MediaAttachment, error) { + attachmentProp := i.GetActivityStreamsAttachment() + if attachmentProp == nil { + return nil, nil + } + + var errs gtserror.MultiError + + attachments := make([]*gtsmodel.MediaAttachment, 0, attachmentProp.Len()) + for iter := attachmentProp.Begin(); iter != attachmentProp.End(); iter = iter.Next() { + t := iter.GetType() + if t == nil { + errs.Appendf("nil attachment type") + continue + } + attachmentable, ok := t.(Attachmentable) + if !ok { + errs.Appendf("incorrect attachment type: %T", t) + continue + } + attachment, err := ExtractAttachment(attachmentable) + if err != nil { + errs.Appendf("error extracting attachment: %w", err) + continue + } + attachments = append(attachments, attachment) + } + + return attachments, errs.Combine() +} + // ExtractAttachment extracts a minimal gtsmodel.Attachment // (just remote URL, description, and blurhash) from the given // Attachmentable interface, or an error if no remote URL is set. @@ -913,6 +986,52 @@ func ExtractSharedInbox(withEndpoints WithEndpoints) *url.URL { return nil } +// IterateOneOf will attempt to extract oneOf property from given interface, and passes each iterated item to function. +func IterateOneOf(withOneOf WithOneOf, foreach func(vocab.ActivityStreamsOneOfPropertyIterator)) { + if foreach == nil { + // nil check outside loop. + panic("nil function") + } + + // Extract the one-of property from interface. + oneOfProp := withOneOf.GetActivityStreamsOneOf() + if oneOfProp == nil { + return + } + + // Get start and end of iter. + start := oneOfProp.Begin() + end := oneOfProp.End() + + // Pass iterated oneOf entries to given function. + for iter := start; iter != end; iter = iter.Next() { + foreach(iter) + } +} + +// IterateAnyOf will attempt to extract anyOf property from given interface, and passes each iterated item to function. +func IterateAnyOf(withAnyOf WithAnyOf, foreach func(vocab.ActivityStreamsAnyOfPropertyIterator)) { + if foreach == nil { + // nil check outside loop. + panic("nil function") + } + + // Extract the any-of property from interface. + anyOfProp := withAnyOf.GetActivityStreamsAnyOf() + if anyOfProp == nil { + return + } + + // Get start and end of iter. + start := anyOfProp.Begin() + end := anyOfProp.End() + + // Pass iterated anyOf entries to given function. + for iter := start; iter != end; iter = iter.Next() { + foreach(iter) + } +} + // isPublic checks if at least one entry in the given // uris slice equals the activitystreams public uri. func isPublic(uris []*url.URL) bool { |