diff options
author | 2025-02-19 18:09:54 +0100 | |
---|---|---|
committer | 2025-02-19 18:09:54 +0100 | |
commit | 96716e4f43341beb3431a7caad10d48e6ca844ae (patch) | |
tree | 49e0771a80c5ecdf2cfc42969036fa6044382209 /internal/ap | |
parent | adds more code comments and some small code formatting tweaks (#3799) (diff) | |
download | gotosocial-96716e4f43341beb3431a7caad10d48e6ca844ae.tar.xz |
[feature] Forward-compatibility with Approval objects (#3807)
* vendor
* [feature] Forward-compatibility with Approval objects
* vendor the thing
* fix leetle bug
* lil syntax tweak for beloved kimb
Diffstat (limited to 'internal/ap')
-rw-r--r-- | internal/ap/activitystreams.go | 5 | ||||
-rw-r--r-- | internal/ap/interfaces.go | 50 | ||||
-rw-r--r-- | internal/ap/resolve.go | 58 |
3 files changed, 70 insertions, 43 deletions
diff --git a/internal/ap/activitystreams.go b/internal/ap/activitystreams.go index 50955ce2c..3851d0efb 100644 --- a/internal/ap/activitystreams.go +++ b/internal/ap/activitystreams.go @@ -97,6 +97,11 @@ const ( // Not in the AS spec, just used internally to indicate // that we don't *yet* know what type of Object something is. ObjectUnknown = "Unknown" + + // Extensions and unofficial additions. + ObjectLikeApproval = "LikeApproval" + ObjectReplyApproval = "ReplyApproval" + ObjectAnnounceApproval = "AnnounceApproval" ) // isActivity returns whether AS type name is of an Activity (NOT IntransitiveActivity). diff --git a/internal/ap/interfaces.go b/internal/ap/interfaces.go index fdd5e4a0b..acc799640 100644 --- a/internal/ap/interfaces.go +++ b/internal/ap/interfaces.go @@ -128,16 +128,13 @@ func ToPollOptionable(t vocab.Type) (PollOptionable, bool) { } // IsAccept returns whether AS vocab type name -// is something that can be cast to Accept. +// is something that can be cast to Acceptable. func IsAcceptable(typeName string) bool { return typeName == ActivityAccept } -// ToAcceptable safely tries to cast vocab.Type as vocab.ActivityStreamsAccept. -// -// TODO: Add additional "Accept" types here, eg., "ApproveReply" from -// https://codeberg.org/fediverse/fep/src/branch/main/fep/5624/fep-5624.md -func ToAcceptable(t vocab.Type) (vocab.ActivityStreamsAccept, bool) { +// ToAcceptable safely tries to cast vocab.Type as Acceptable. +func ToAcceptable(t vocab.Type) (Acceptable, bool) { acceptable, ok := t.(vocab.ActivityStreamsAccept) if !ok || !IsAcceptable(t.GetTypeName()) { return nil, false @@ -145,6 +142,28 @@ func ToAcceptable(t vocab.Type) (vocab.ActivityStreamsAccept, bool) { return acceptable, true } +// IsApprovable returns whether AS vocab type name +// is something that can be cast to Approvable. +func IsApprovable(typeName string) bool { + switch typeName { + case ObjectLikeApproval, + ObjectReplyApproval, + ObjectAnnounceApproval: + return true + default: + return false + } +} + +// ToAcceptable safely tries to cast vocab.Type as Approvable. +func ToApprovable(t vocab.Type) (Approvable, bool) { + approvable, ok := t.(Approvable) + if !ok || !IsApprovable(t.GetTypeName()) { + return nil, false + } + return approvable, true +} + // Activityable represents the minimum activitypub interface for representing an 'activity'. // (see: IsActivityable() for types implementing this, though you MUST make sure to check // the typeName as this bare interface may be implementable by non-Activityable types). @@ -247,6 +266,19 @@ type PollOptionable interface { // interface for representing an Accept. type Acceptable interface { Activityable + + WithTarget + WithResult +} + +// Approvable represents the minimum activitypub interface +// for a LikeApproval, ReplyApproval, or AnnounceApproval. +type Approvable interface { + vocab.Type + + WithAttributedTo + WithObject + WithTarget } // Attachmentable represents the minimum activitypub interface for representing a 'mediaAttachment'. (see: IsAttachmentable). @@ -708,3 +740,9 @@ type WithApprovedBy interface { GetGoToSocialApprovedBy() vocab.GoToSocialApprovedByProperty SetGoToSocialApprovedBy(vocab.GoToSocialApprovedByProperty) } + +// WithVotersCount represents an activity or object the result property. +type WithResult interface { + GetActivityStreamsResult() vocab.ActivityStreamsResultProperty + SetActivityStreamsResult(vocab.ActivityStreamsResultProperty) +} diff --git a/internal/ap/resolve.go b/internal/ap/resolve.go index 76a8809c3..82a242710 100644 --- a/internal/ap/resolve.go +++ b/internal/ap/resolve.go @@ -198,48 +198,12 @@ func ResolveCollectionPage(ctx context.Context, body io.ReadCloser) (CollectionP return ToCollectionPageIterator(t) } -// ResolveAcceptable tries to resolve the given reader -// into an ActivityStreams Acceptable representation. -func ResolveAcceptable( - ctx context.Context, - body io.ReadCloser, -) (Acceptable, error) { - // Get "raw" map - // destination. - raw := getMap() - // Release. - defer putMap(raw) - - // Decode data as JSON into 'raw' map - // and get the resolved AS vocab.Type. - // (this handles close of given body). - t, err := decodeType(ctx, body, raw) - if err != nil { - return nil, gtserror.SetWrongType(err) - } - - // Attempt to cast as acceptable. - acceptable, ok := ToAcceptable(t) - if !ok { - err := gtserror.Newf("cannot resolve vocab type %T as acceptable", t) - return nil, gtserror.SetWrongType(err) - } - - return acceptable, nil -} - // emptydest is an empty JSON decode // destination useful for "noop" decodes // to check underlying reader is empty. var emptydest = &struct{}{} -// decodeType tries to read and parse the data -// at provided io.ReadCloser as a JSON ActivityPub -// type, failing if not parseable as JSON or not -// resolveable as one of our known AS types. -// -// NOTE: this function handles closing -// given body when it is finished with. +// decodeType is the package-internal version of DecodeType. // // The given map pointer will also be populated with // the 'raw' JSON data, for further processing. @@ -284,3 +248,23 @@ func decodeType( return t, nil } + +// DecodeType tries to read and parse the data +// at provided io.ReadCloser as a JSON ActivityPub +// type, failing if not parseable as JSON or not +// resolveable as one of our known AS types. +// +// NOTE: this function handles closing +// given body when it is finished with. +func DecodeType( + ctx context.Context, + body io.ReadCloser, +) (vocab.Type, error) { + // Get "raw" map + // destination. + raw := getMap() + // Release. + defer putMap(raw) + + return decodeType(ctx, body, raw) +} |