summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/api/swagger.yaml4
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--internal/ap/activitystreams.go29
-rw-r--r--internal/ap/ap_test.go10
-rw-r--r--internal/ap/extract.go28
-rw-r--r--internal/ap/interfaces.go115
-rw-r--r--internal/ap/properties.go179
-rw-r--r--internal/ap/serialize.go4
-rw-r--r--internal/api/activitypub/users/authorizationget.go56
-rw-r--r--internal/api/activitypub/users/inboxpost_test.go2
-rw-r--r--internal/api/activitypub/users/user.go3
-rw-r--r--internal/api/client/statuses/statusboost_test.go2
-rw-r--r--internal/api/client/statuses/statusfave_test.go2
-rw-r--r--internal/api/model/interaction.go2
-rw-r--r--internal/cache/db.go6
-rw-r--r--internal/cache/size.go19
-rw-r--r--internal/db/bundb/admin.go30
-rw-r--r--internal/db/bundb/interaction.go34
-rw-r--r--internal/db/bundb/interaction_test.go19
-rw-r--r--internal/db/bundb/migrations/20250715095446_int_pols_forward_compat.go328
-rw-r--r--internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/new/interactionrequest.go68
-rw-r--r--internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/old/interactionrequest.go39
-rw-r--r--internal/db/bundb/notification_test.go20
-rw-r--r--internal/db/interaction.go15
-rw-r--r--internal/federation/dereferencing/status_permitted.go220
-rw-r--r--internal/federation/dereferencing/status_test.go2
-rw-r--r--internal/federation/federatingactor_test.go40
-rw-r--r--internal/federation/federatingdb/accept.go369
-rw-r--r--internal/federation/federatingdb/accept_test.go120
-rw-r--r--internal/federation/federatingdb/block.go2
-rw-r--r--internal/federation/federatingdb/create.go45
-rw-r--r--internal/federation/federatingdb/interactionrequest.go572
-rw-r--r--internal/federation/federatingdb/interactionrequest_test.go289
-rw-r--r--internal/federation/federatingdb/like.go2
-rw-r--r--internal/federation/federatingdb/reject.go52
-rw-r--r--internal/federation/federatingdb/util.go59
-rw-r--r--internal/federation/federator.go3
-rw-r--r--internal/gtserror/error.go4
-rw-r--r--internal/gtsmodel/interaction.go154
-rw-r--r--internal/gtsmodel/status.go2
-rw-r--r--internal/id/ulid.go58
-rw-r--r--internal/processing/account/follow.go5
-rw-r--r--internal/processing/admin/rule.go9
-rw-r--r--internal/processing/application/create.go5
-rw-r--r--internal/processing/fedi/accept.go42
-rw-r--r--internal/processing/fedi/authorization.go57
-rw-r--r--internal/processing/fedi/common.go50
-rw-r--r--internal/processing/interactionrequests/accept.go14
-rw-r--r--internal/processing/interactionrequests/accept_test.go2
-rw-r--r--internal/processing/interactionrequests/reject.go4
-rw-r--r--internal/processing/search/get.go2
-rw-r--r--internal/processing/workers/federate.go18
-rw-r--r--internal/processing/workers/fromclientapi.go93
-rw-r--r--internal/processing/workers/fromfediapi.go503
-rw-r--r--internal/processing/workers/fromfediapi_test.go120
-rw-r--r--internal/processing/workers/util.go36
-rw-r--r--internal/transport/derefinstance.go22
-rw-r--r--internal/typeutils/astointernal.go4
-rw-r--r--internal/typeutils/internal.go70
-rw-r--r--internal/typeutils/internaltoas.go800
-rw-r--r--internal/typeutils/internaltoas_test.go429
-rw-r--r--internal/typeutils/internaltofrontend.go11
-rw-r--r--internal/typeutils/internaltofrontend_test.go2
-rw-r--r--internal/typeutils/wrap.go2
-rw-r--r--internal/uris/uri.go58
-rw-r--r--testrig/testmodels.go489
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/gen_consts.go9
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/gen_init.go6
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/gen_manager.go42
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/gen_pkg_gotosocial_property_constructors.go21
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_type_activitystreams_announce.go126
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_type_activitystreams_article.go118
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_type_activitystreams_audio.go122
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_type_activitystreams_document.go122
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_type_activitystreams_event.go118
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_type_activitystreams_image.go126
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_type_activitystreams_like.go42
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_type_activitystreams_note.go118
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_type_activitystreams_page.go122
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_type_activitystreams_place.go128
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_type_activitystreams_profile.go120
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_type_activitystreams_question.go134
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_pkg.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_type_activitystreams_video.go122
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_doc.go17
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_pkg.go15
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_property_gotosocial_announceAuthorization.go183
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_doc.go17
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_pkg.go15
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_property_gotosocial_likeAuthorization.go182
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_doc.go17
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_pkg.go15
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_property_gotosocial_replyAuthorization.go183
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_announceAuthorization_interface.go53
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_approvedBy_interface.go11
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesCcPublicFromUnauthedWeb_interface.go3
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesToPublicFromUnauthedWeb_interface.go3
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_likeAuthorization_interface.go52
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_replyAuthorization_interface.go53
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_announce_interface.go6
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_article_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_audio_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_document_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_event_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_image_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_like_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_note_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_page_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_place_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_profile_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_question_interface.go5
-rw-r--r--vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_video_interface.go5
-rw-r--r--vendor/modules.txt5
126 files changed, 6635 insertions, 1776 deletions
diff --git a/docs/api/swagger.yaml b/docs/api/swagger.yaml
index 6ee4db4ab..b84a3e21b 100644
--- a/docs/api/swagger.yaml
+++ b/docs/api/swagger.yaml
@@ -2402,10 +2402,6 @@ definitions:
`reblog` - Someone reblogged / boosted a status.
type: string
x-go-name: Type
- uri:
- description: URI of the Accept or Reject. Only set if accepted_at or rejected_at is set, else omitted.
- type: string
- x-go-name: URI
title: InteractionRequest represents a pending, approved, or rejected interaction of type favourite, reply, or reblog.
type: object
x-go-name: InteractionRequest
diff --git a/go.mod b/go.mod
index 6b64ae9b8..2915d9847 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ replace github.com/go-swagger/go-swagger => codeberg.org/superseriousbusiness/go
replace modernc.org/sqlite => gitlab.com/NyaaaWhatsUpDoc/sqlite v1.38.2-concurrency-workaround
require (
- code.superseriousbusiness.org/activity v1.16.0
+ code.superseriousbusiness.org/activity v1.17.0
code.superseriousbusiness.org/exif-terminator v0.11.0
code.superseriousbusiness.org/httpsig v1.4.0
code.superseriousbusiness.org/oauth2/v4 v4.5.4-0.20250812115401-3961e46a7384
diff --git a/go.sum b/go.sum
index 727cc45fc..de3bbb155 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,5 @@
-code.superseriousbusiness.org/activity v1.16.0 h1:6WHpKx2ggkwRlI6lqiK4+VHUdTYRVOcba3fCo1E6wWk=
-code.superseriousbusiness.org/activity v1.16.0/go.mod h1:BTMWJIAuwDH1w+ieRP5N+T5LipbXjw35U6KZy0V/xdg=
+code.superseriousbusiness.org/activity v1.17.0 h1:01x4LyvL5fzKgtce+o3mqYbR1O+RaL6j/z7v/B6ivqo=
+code.superseriousbusiness.org/activity v1.17.0/go.mod h1:BTMWJIAuwDH1w+ieRP5N+T5LipbXjw35U6KZy0V/xdg=
code.superseriousbusiness.org/exif-terminator v0.11.0 h1:Hof0MCcsa+1fS17gf86fTTZ8AQnMY9h9kzcc+2C6mVg=
code.superseriousbusiness.org/exif-terminator v0.11.0/go.mod h1:9sutT1axa/kSdlPLlRFjCNKmyo/KNx8eX3XZvWBlAEY=
code.superseriousbusiness.org/go-jpeg-image-structure/v2 v2.3.0 h1:r9uq8StaSHYKJ8DklR9Xy+E9c40G1Z8yj5TRGi8L6+4=
diff --git a/internal/ap/activitystreams.go b/internal/ap/activitystreams.go
index 56ebc4909..9c2464410 100644
--- a/internal/ap/activitystreams.go
+++ b/internal/ap/activitystreams.go
@@ -23,15 +23,18 @@ import (
"code.superseriousbusiness.org/activity/pub"
)
-// PublicURI returns a fresh copy of the *url.URL version of the
-// magic ActivityPub URI https://www.w3.org/ns/activitystreams#Public
-func PublicURI() *url.URL {
- publicURI, err := url.Parse(pub.PublicActivityPubIRI)
+// publicIRI is a pre-parsed global public IRI instance.
+var publicIRI = func() *url.URL {
+ url, err := url.Parse(pub.PublicActivityPubIRI)
if err != nil {
panic(err)
}
- return publicURI
-}
+ return url
+}()
+
+// PublicIRI returns a fresh copy of the *url.URL version of the
+// magic ActivityPub URI https://www.w3.org/ns/activitystreams#Public
+func PublicIRI() *url.URL { var u url.URL; u = *publicIRI; return &u }
// https://www.w3.org/TR/activitystreams-vocabulary
const (
@@ -102,9 +105,12 @@ const (
/* GtS stuff */
- ObjectLikeApproval = "LikeApproval"
- ObjectReplyApproval = "ReplyApproval"
- ObjectAnnounceApproval = "AnnounceApproval"
+ ActivityLikeRequest = "LikeRequest"
+ ActivityReplyRequest = "ReplyRequest"
+ ActivityAnnounceRequest = "AnnounceRequest"
+ ObjectLikeAuthorization = "LikeAuthorization"
+ ObjectReplyAuthorization = "ReplyAuthorization"
+ ObjectAnnounceAuthorization = "AnnounceAuthorization"
/* Funkwhale stuff */
@@ -138,7 +144,10 @@ func isActivity(typeName string) bool {
ActivityAnnounce,
ActivityBlock,
ActivityFlag,
- ActivityDislike:
+ ActivityDislike,
+ ActivityLikeRequest,
+ ActivityReplyRequest,
+ ActivityAnnounceRequest:
return true
default:
return false
diff --git a/internal/ap/ap_test.go b/internal/ap/ap_test.go
index 0956fee66..9f275434d 100644
--- a/internal/ap/ap_test.go
+++ b/internal/ap/ap_test.go
@@ -110,7 +110,7 @@ func noteWithMentions1() vocab.ActivityStreamsNote {
// Anyone can like.
canLikeAlwaysProp := streams.NewGoToSocialAlwaysProperty()
- canLikeAlwaysProp.AppendIRI(ap.PublicURI())
+ canLikeAlwaysProp.AppendIRI(ap.PublicIRI())
canLike.SetGoToSocialAlways(canLikeAlwaysProp)
// Empty approvalRequired.
@@ -127,7 +127,7 @@ func noteWithMentions1() vocab.ActivityStreamsNote {
// Anyone can reply.
canReplyAlwaysProp := streams.NewGoToSocialAlwaysProperty()
- canReplyAlwaysProp.AppendIRI(ap.PublicURI())
+ canReplyAlwaysProp.AppendIRI(ap.PublicIRI())
canReply.SetGoToSocialAlways(canReplyAlwaysProp)
// Set empty approvalRequired.
@@ -150,7 +150,7 @@ func noteWithMentions1() vocab.ActivityStreamsNote {
// Public requires approval to announce.
canAnnounceApprovalRequiredProp := streams.NewGoToSocialApprovalRequiredProperty()
- canAnnounceApprovalRequiredProp.AppendIRI(ap.PublicURI())
+ canAnnounceApprovalRequiredProp.AppendIRI(ap.PublicIRI())
canAnnounce.SetGoToSocialApprovalRequired(canAnnounceApprovalRequiredProp)
// Set canAnnounce on the policy.
@@ -265,7 +265,7 @@ func addressable1() ap.Addressable {
note := streams.NewActivityStreamsNote()
toProp := streams.NewActivityStreamsToProperty()
- toProp.AppendIRI(ap.PublicURI())
+ toProp.AppendIRI(ap.PublicIRI())
note.SetActivityStreamsTo(toProp)
@@ -287,7 +287,7 @@ func addressable2() ap.Addressable {
note.SetActivityStreamsTo(toProp)
ccProp := streams.NewActivityStreamsCcProperty()
- ccProp.AppendIRI(ap.PublicURI())
+ ccProp.AppendIRI(ap.PublicIRI())
note.SetActivityStreamsCc(ccProp)
diff --git a/internal/ap/extract.go b/internal/ap/extract.go
index 7a727b005..f26b02a82 100644
--- a/internal/ap/extract.go
+++ b/internal/ap/extract.go
@@ -36,7 +36,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/util"
)
-// ExtractObjects will extract object vocab.Types from given implementing interface.
+// ExtractObjects will extract object TypeOrIRIs from given implementing interface.
func ExtractObjects(with WithObject) []TypeOrIRI {
// Extract the attached object (if any).
objProp := with.GetActivityStreamsObject()
@@ -58,6 +58,28 @@ func ExtractObjects(with WithObject) []TypeOrIRI {
return objs
}
+// ExtractInstrument will extract instrument TypeOrIRIs from given implementing interface.
+func ExtractInstruments(with WithInstrument) []TypeOrIRI {
+ // Extract the attached instrument (if any).
+ instrProp := with.GetActivityStreamsInstrument()
+ if instrProp == nil {
+ return nil
+ }
+
+ // Check for invalid len.
+ if instrProp.Len() == 0 {
+ return nil
+ }
+
+ // Accumulate all of the instruments into a slice.
+ instrs := make([]TypeOrIRI, instrProp.Len())
+ for i := range instrProp.Len() {
+ instrs[i] = instrProp.At(i)
+ }
+
+ return instrs
+}
+
// 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) ([]TypeOrIRI, []any, bool) {
switch typeName := activity.GetTypeName(); {
@@ -1222,14 +1244,14 @@ func ExtractInteractionPolicy(
statusable Statusable,
owner *gtsmodel.Account,
) *gtsmodel.InteractionPolicy {
- ipa, ok := statusable.(InteractionPolicyAware)
+ wip, ok := statusable.(WithInteractionPolicy)
if !ok {
// Not a type with interaction
// policy properties settable.
return nil
}
- policyProp := ipa.GetGoToSocialInteractionPolicy()
+ policyProp := wip.GetGoToSocialInteractionPolicy()
if policyProp == nil || policyProp.Len() != 1 {
return nil
}
diff --git a/internal/ap/interfaces.go b/internal/ap/interfaces.go
index ec961f80b..3224cecc0 100644
--- a/internal/ap/interfaces.go
+++ b/internal/ap/interfaces.go
@@ -143,13 +143,13 @@ func ToAcceptable(t vocab.Type) (Acceptable, bool) {
return acceptable, true
}
-// IsApprovable returns whether AS vocab type name
-// is something that can be cast to Approvable.
-func IsApprovable(typeName string) bool {
+// IsAuthorizationable returns whether AS vocab type name
+// is something that can be cast to Authorizationable.
+func IsAuthorizationable(typeName string) bool {
switch typeName {
- case ObjectLikeApproval,
- ObjectReplyApproval,
- ObjectAnnounceApproval:
+ case ObjectLikeAuthorization,
+ ObjectReplyAuthorization,
+ ObjectAnnounceAuthorization:
return true
default:
return false
@@ -157,12 +157,12 @@ func IsApprovable(typeName string) bool {
}
// 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()) {
+func ToAuthorizationable(t vocab.Type) (Authorizationable, bool) {
+ authable, ok := t.(Authorizationable)
+ if !ok || !IsAuthorizationable(t.GetTypeName()) {
return nil, false
}
- return approvable, true
+ return authable, true
}
// IsAttachmentable returns whether AS vocab type name
@@ -188,6 +188,36 @@ func ToAttachmentable(t vocab.Type) (Attachmentable, bool) {
return attachmentable, true
}
+// IsAnnounceable returns whether AS vocab type name
+// is something that can be cast to vocab.ActivityStreamsAnnounce.
+func IsAnnounceable(typeName string) bool {
+ return typeName == ActivityAnnounce
+}
+
+// ToAnnounceable safely tries to cast vocab.Type as vocab.ActivityStreamsAnnounce.
+func ToAnnounceable(t vocab.Type) (vocab.ActivityStreamsAnnounce, bool) {
+ announceable, ok := t.(vocab.ActivityStreamsAnnounce)
+ if !ok || t.GetTypeName() != ActivityAnnounce {
+ return nil, false
+ }
+ return announceable, true
+}
+
+// IsLikeable returns whether AS vocab type name
+// is something that can be cast to vocab.ActivityStreamsLike.
+func IsLikeable(typeName string) bool {
+ return typeName == ActivityLike
+}
+
+// ToAnnouncToLikeableeable safely tries to cast vocab.Type as vocab.ActivityStreamsLike.
+func ToLikeable(t vocab.Type) (vocab.ActivityStreamsLike, bool) {
+ likeable, ok := t.(vocab.ActivityStreamsLike)
+ if !ok || t.GetTypeName() != ActivityLike {
+ return nil, false
+ }
+ return likeable, 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).
@@ -258,11 +288,6 @@ type Statusable interface {
WithReplies
}
-type InteractionPolicyAware interface {
- WithInteractionPolicy
- WithApprovedBy
-}
-
// Pollable represents the minimum activitypub interface for representing a 'poll' (it's a subset of a status).
// (see: IsPollable() for types implementing this, though you MUST make sure to check
// the typeName as this bare interface may be implementable by non-Pollable types).
@@ -299,14 +324,14 @@ type Acceptable interface {
WithResult
}
-// Approvable represents the minimum activitypub interface
-// for a LikeApproval, ReplyApproval, or AnnounceApproval.
-type Approvable interface {
+// Authorizationable represents the minimum interface for a
+// LikeAuthorization, ReplyAuthorization, AnnounceAuthorization.
+type Authorizationable interface {
vocab.Type
WithAttributedTo
- WithObject
- WithTarget
+ WithInteractingObject
+ WithInteractionTarget
}
// Attachmentable represents the minimum activitypub interface for representing a 'mediaAttachment'. (see: IsAttachmentable).
@@ -392,6 +417,16 @@ type ReplyToable interface {
WithInReplyTo
}
+// InteractionRequestable represents the minimum interface for an interaction request
+// activity, eg., LikeRequest, ReplyRequest, AnnounceRequest, QuoteRequest, etc..
+type InteractionRequestable interface {
+ vocab.Type
+
+ WithActor
+ WithObject
+ WithInstrument
+}
+
// CollectionIterator represents the minimum interface for interacting with a
// wrapped Collection or OrderedCollection in order to access next / prev items.
type CollectionIterator interface {
@@ -683,6 +718,12 @@ type WithObject interface {
SetActivityStreamsObject(vocab.ActivityStreamsObjectProperty)
}
+// WithInstrument represents an activity with ActivityStreamsInstrumentProperty
+type WithInstrument interface {
+ GetActivityStreamsInstrument() vocab.ActivityStreamsInstrumentProperty
+ SetActivityStreamsInstrument(vocab.ActivityStreamsInstrumentProperty)
+}
+
// WithTarget represents an activity with ActivityStreamsTargetProperty
type WithTarget interface {
GetActivityStreamsTarget() vocab.ActivityStreamsTargetProperty
@@ -775,14 +816,44 @@ type WithPolicyRules interface {
GetGoToSocialApprovalRequired() vocab.GoToSocialApprovalRequiredProperty // Deprecated
}
-// WithApprovedBy represents a Statusable with the approvedBy property.
+// WithApprovedBy represents an object with the approvedBy property.
type WithApprovedBy interface {
GetGoToSocialApprovedBy() vocab.GoToSocialApprovedByProperty
SetGoToSocialApprovedBy(vocab.GoToSocialApprovedByProperty)
}
-// WithVotersCount represents an activity or object the result property.
+// WithLikeAuthorization represents a Likeable with the likeAuthorization property.
+type WithLikeAuthorization interface {
+ GetGoToSocialLikeAuthorization() vocab.GoToSocialLikeAuthorizationProperty
+ SetGoToSocialLikeAuthorization(vocab.GoToSocialLikeAuthorizationProperty)
+}
+
+// WithReplyAuthorization represents a statusable with the replyAuthorization property.
+type WithReplyAuthorization interface {
+ GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty
+ SetGoToSocialReplyAuthorization(vocab.GoToSocialReplyAuthorizationProperty)
+}
+
+// WithAnnounceAuthorization represents an Announceable with the announceAuthorization property.
+type WithAnnounceAuthorization interface {
+ GetGoToSocialAnnounceAuthorization() vocab.GoToSocialAnnounceAuthorizationProperty
+ SetGoToSocialAnnounceAuthorization(vocab.GoToSocialAnnounceAuthorizationProperty)
+}
+
+// WithResult represents an activity or object with the result property.
type WithResult interface {
GetActivityStreamsResult() vocab.ActivityStreamsResultProperty
SetActivityStreamsResult(vocab.ActivityStreamsResultProperty)
}
+
+// WithInteractingObject represents an activity or object with the InteractingObject property.
+type WithInteractingObject interface {
+ GetGoToSocialInteractingObject() vocab.GoToSocialInteractingObjectProperty
+ SetGoToSocialInteractingObject(vocab.GoToSocialInteractingObjectProperty)
+}
+
+// WithInteractionTarget represents an activity or object with the InteractionTarget property.
+type WithInteractionTarget interface {
+ GetGoToSocialInteractionTarget() vocab.GoToSocialInteractionTargetProperty
+ SetGoToSocialInteractionTarget(vocab.GoToSocialInteractionTargetProperty)
+}
diff --git a/internal/ap/properties.go b/internal/ap/properties.go
index 3e064bae0..51e4ab1c0 100644
--- a/internal/ap/properties.go
+++ b/internal/ap/properties.go
@@ -226,6 +226,36 @@ func AppendObjectIRIs(with WithObject, object ...*url.URL) {
}, object...)
}
+// AppendInstrumentIRIs appends the given IRIs to the Instrument property of 'with'.
+func AppendInstrumentIRIs(with WithInstrument, instrument ...*url.URL) {
+ appendIRIs(func() Property[vocab.ActivityStreamsInstrumentPropertyIterator] {
+ instrumentProp := with.GetActivityStreamsInstrument()
+ if instrumentProp == nil {
+ instrumentProp = streams.NewActivityStreamsInstrumentProperty()
+ with.SetActivityStreamsInstrument(instrumentProp)
+ }
+ return instrumentProp
+ }, instrument...)
+}
+
+// GetResultIRIs returns the IRIs contained in the `result` property of 'with'.
+func GetResultIRIs(with WithResult) []*url.URL {
+ resultProp := with.GetActivityStreamsResult()
+ return extractIRIs(resultProp)
+}
+
+// AppendResultIRIs appends the given IRIs to the Result property of 'with'.
+func AppendResultIRIs(with WithResult, result ...*url.URL) {
+ appendIRIs(func() Property[vocab.ActivityStreamsResultPropertyIterator] {
+ resultProp := with.GetActivityStreamsResult()
+ if resultProp == nil {
+ resultProp = streams.NewActivityStreamsResultProperty()
+ with.SetActivityStreamsResult(resultProp)
+ }
+ return resultProp
+ }, result...)
+}
+
// GetTargetIRIs returns the IRIs contained in the Target property of 'with'.
func GetTargetIRIs(with WithTarget) []*url.URL {
targetProp := with.GetActivityStreamsTarget()
@@ -262,6 +292,42 @@ func AppendAttributedTo(with WithAttributedTo, attribTo ...*url.URL) {
}, attribTo...)
}
+// GetInteractingObject returns IRIs contained in the interactingObject property of 'with'.
+func GetInteractingObject(with WithInteractingObject) []*url.URL {
+ intObjProp := with.GetGoToSocialInteractingObject()
+ return getIRIs(intObjProp)
+}
+
+// AppendInteractingObject appends the given IRIs to the interactingObject property of 'with'.
+func AppendInteractingObject(with WithInteractingObject, interactingObject ...*url.URL) {
+ appendIRIs(func() Property[vocab.GoToSocialInteractingObjectPropertyIterator] {
+ intObjProp := with.GetGoToSocialInteractingObject()
+ if intObjProp == nil {
+ intObjProp = streams.NewGoToSocialInteractingObjectProperty()
+ with.SetGoToSocialInteractingObject(intObjProp)
+ }
+ return intObjProp
+ }, interactingObject...)
+}
+
+// GetInteractionTarget returns IRIs contained in the interactionTarget property of 'with'.
+func GetInteractionTarget(with WithInteractionTarget) []*url.URL {
+ intTargetProp := with.GetGoToSocialInteractionTarget()
+ return getIRIs(intTargetProp)
+}
+
+// AppendInteractionTarget appends the given IRIs to the interactionTarget property of 'with'.
+func AppendInteractionTarget(with WithInteractionTarget, interactionTarget ...*url.URL) {
+ appendIRIs(func() Property[vocab.GoToSocialInteractionTargetPropertyIterator] {
+ intTargetProp := with.GetGoToSocialInteractionTarget()
+ if intTargetProp == nil {
+ intTargetProp = streams.NewGoToSocialInteractionTargetProperty()
+ with.SetGoToSocialInteractionTarget(intTargetProp)
+ }
+ return intTargetProp
+ }, interactionTarget...)
+}
+
// GetInReplyTo returns the IRIs contained in the InReplyTo property of 'with'.
func GetInReplyTo(with WithInReplyTo) []*url.URL {
replyProp := with.GetActivityStreamsInReplyTo()
@@ -607,11 +673,11 @@ func SetHidesCcPublicFromUnauthedWeb(with WithHidesCcPublicFromUnauthedWeb, hide
// GetApprovedBy returns the URL contained in
// the ApprovedBy property of 'with', if set.
func GetApprovedBy(with WithApprovedBy) *url.URL {
- mafProp := with.GetGoToSocialApprovedBy()
- if mafProp == nil || !mafProp.IsIRI() {
+ abProp := with.GetGoToSocialApprovedBy()
+ if abProp == nil || !abProp.IsIRI() {
return nil
}
- return mafProp.Get()
+ return abProp.Get()
}
// SetApprovedBy sets the given url
@@ -625,6 +691,69 @@ func SetApprovedBy(with WithApprovedBy, approvedBy *url.URL) {
abProp.Set(approvedBy)
}
+// GetLikeAuthorization returns the URL contained in
+// the likeAuthorization property of 'with', if set.
+func GetLikeAuthorization(with WithLikeAuthorization) *url.URL {
+ laProp := with.GetGoToSocialLikeAuthorization()
+ if laProp == nil || !laProp.IsIRI() {
+ return nil
+ }
+ return laProp.Get()
+}
+
+// SetLikeAuthorization sets the given url on
+// the 'likeAuthorization' property of 'with'.
+func SetLikeAuthorization(with WithLikeAuthorization, likeAuthorization *url.URL) {
+ laProp := with.GetGoToSocialLikeAuthorization()
+ if laProp == nil {
+ laProp = streams.NewGoToSocialLikeAuthorizationProperty()
+ with.SetGoToSocialLikeAuthorization(laProp)
+ }
+ laProp.Set(likeAuthorization)
+}
+
+// GetReplyAuthorization returns the URL contained in
+// the replyAuthorization property of 'with', if set.
+func GetReplyAuthorization(with WithReplyAuthorization) *url.URL {
+ raProp := with.GetGoToSocialReplyAuthorization()
+ if raProp == nil || !raProp.IsIRI() {
+ return nil
+ }
+ return raProp.Get()
+}
+
+// SetReplyAuthorization sets the given url on
+// the 'replyAuthorization' property of 'with'.
+func SetReplyAuthorization(with WithReplyAuthorization, replyAuthorization *url.URL) {
+ raProp := with.GetGoToSocialReplyAuthorization()
+ if raProp == nil {
+ raProp = streams.NewGoToSocialReplyAuthorizationProperty()
+ with.SetGoToSocialReplyAuthorization(raProp)
+ }
+ raProp.Set(replyAuthorization)
+}
+
+// GetAnnounceAuthorization returns the URL contained in
+// the announceAuthorization property of 'with', if set.
+func GetAnnounceAuthorization(with WithAnnounceAuthorization) *url.URL {
+ aaProp := with.GetGoToSocialAnnounceAuthorization()
+ if aaProp == nil || !aaProp.IsIRI() {
+ return nil
+ }
+ return aaProp.Get()
+}
+
+// SetAnnounceAuthorization sets the given url on
+// the 'announceAuthorization' property of 'with'.
+func SetAnnounceAuthorization(with WithAnnounceAuthorization, announceAuthorization *url.URL) {
+ aaProp := with.GetGoToSocialAnnounceAuthorization()
+ if aaProp == nil {
+ aaProp = streams.NewGoToSocialAnnounceAuthorizationProperty()
+ with.SetGoToSocialAnnounceAuthorization(aaProp)
+ }
+ aaProp.Set(announceAuthorization)
+}
+
// GetMediaType returns the string contained in
// the MediaType property of 'with', if set.
func GetMediaType(with WithMediaType) string {
@@ -689,6 +818,50 @@ func SetBlurhash(with WithBlurhash, mediaType string) {
bProp.Set(mediaType)
}
+// AppendSensitive appends the given sensitive
+// boolean to the `sensitive` property of 'with'.
+func AppendSensitive(with WithSensitive, sensitive bool) {
+ sProp := with.GetActivityStreamsSensitive()
+ if sProp == nil {
+ sProp = streams.NewActivityStreamsSensitiveProperty()
+ with.SetActivityStreamsSensitive(sProp)
+ }
+ sProp.AppendXMLSchemaBoolean(sensitive)
+}
+
+// AppendContent appends the given content
+// string to the `content` property of 'with'.
+func AppendContent(with WithContent, content string) {
+ cProp := with.GetActivityStreamsContent()
+ if cProp == nil {
+ cProp = streams.NewActivityStreamsContentProperty()
+ with.SetActivityStreamsContent(cProp)
+ }
+ cProp.AppendXMLSchemaString(content)
+}
+
+// AppendContentMap appends the given content
+// language map to the `content` property of 'with'.
+func AppendContentMap(with WithContent, contentMap map[string]string) {
+ cProp := with.GetActivityStreamsContent()
+ if cProp == nil {
+ cProp = streams.NewActivityStreamsContentProperty()
+ with.SetActivityStreamsContent(cProp)
+ }
+ cProp.AppendRDFLangString(contentMap)
+}
+
+// SetReplies sets the given replies collection
+// to the `replies` property of 'with'.
+func SetReplies(with WithReplies, replies vocab.ActivityStreamsCollection) {
+ rProp := with.GetActivityStreamsReplies()
+ if rProp == nil {
+ rProp = streams.NewActivityStreamsRepliesProperty()
+ with.SetActivityStreamsReplies(rProp)
+ }
+ rProp.SetActivityStreamsCollection(replies)
+}
+
// extractIRIs extracts just the AP IRIs from an iterable
// property that may contain types (with IRIs) or just IRIs.
//
diff --git a/internal/ap/serialize.go b/internal/ap/serialize.go
index c64c14d75..10af16ea4 100644
--- a/internal/ap/serialize.go
+++ b/internal/ap/serialize.go
@@ -153,8 +153,8 @@ func serializeStatusable(t vocab.Type, includeContext bool) (map[string]interfac
NormalizeOutgoingAttachmentProp(statusable, data)
NormalizeOutgoingContentProp(statusable, data)
- if ipa, ok := statusable.(InteractionPolicyAware); ok {
- NormalizeOutgoingInteractionPolicyProp(ipa, data)
+ if wip, ok := statusable.(WithInteractionPolicy); ok {
+ NormalizeOutgoingInteractionPolicyProp(wip, data)
}
return data, nil
diff --git a/internal/api/activitypub/users/authorizationget.go b/internal/api/activitypub/users/authorizationget.go
new file mode 100644
index 000000000..a7f234854
--- /dev/null
+++ b/internal/api/activitypub/users/authorizationget.go
@@ -0,0 +1,56 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package users
+
+import (
+ "net/http"
+
+ apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util"
+ "code.superseriousbusiness.org/gotosocial/internal/gtserror"
+ "github.com/gin-gonic/gin"
+)
+
+// AuthorizationGETHandler serves an accepted interaction request as a
+// LikeAuthorization, ReplyAuthorization, or AnnounceAuthorization type.
+func (m *Module) AuthorizationGETHandler(c *gin.Context) {
+ username, errWithCode := apiutil.ParseUsername(c.Param(apiutil.UsernameKey))
+ if errWithCode != nil {
+ apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
+ return
+ }
+
+ reqID, errWithCode := apiutil.ParseID(c.Param(apiutil.IDKey))
+ if errWithCode != nil {
+ apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
+ return
+ }
+
+ contentType, err := apiutil.NegotiateAccept(c, apiutil.ActivityPubHeaders...)
+ if err != nil {
+ apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
+ return
+ }
+
+ resp, errWithCode := m.processor.Fedi().AuthorizationGet(c.Request.Context(), username, reqID)
+ if errWithCode != nil {
+ apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
+ return
+ }
+
+ apiutil.JSONType(c, http.StatusOK, contentType, resp)
+}
diff --git a/internal/api/activitypub/users/inboxpost_test.go b/internal/api/activitypub/users/inboxpost_test.go
index 81b21eafc..51df35672 100644
--- a/internal/api/activitypub/users/inboxpost_test.go
+++ b/internal/api/activitypub/users/inboxpost_test.go
@@ -192,7 +192,7 @@ func (suite *InboxPostTestSuite) newDelete(actorIRI string, objectIRI string, de
// Set the To of the delete as public
deleteTo := streams.NewActivityStreamsToProperty()
- deleteTo.AppendIRI(ap.PublicURI())
+ deleteTo.AppendIRI(ap.PublicIRI())
delete.SetActivityStreamsTo(deleteTo)
// set some random-ass ID for the activity
diff --git a/internal/api/activitypub/users/user.go b/internal/api/activitypub/users/user.go
index 7a06e6f03..7fb5f6aa5 100644
--- a/internal/api/activitypub/users/user.go
+++ b/internal/api/activitypub/users/user.go
@@ -58,6 +58,8 @@ const (
StatusRepliesPath = StatusPath + "/replies"
// AcceptPath is for serving accepts of a status.
AcceptPath = BasePath + "/" + uris.AcceptsPath + "/:" + apiutil.IDKey
+ // AuthorizationsPath is for serving authorizations of an interaction.
+ AuthorizationsPath = BasePath + "/" + uris.AuthorizationsPath + "/:" + apiutil.IDKey
)
type Module struct {
@@ -80,4 +82,5 @@ func (m *Module) Route(attachHandler func(method string, path string, f ...gin.H
attachHandler(http.MethodGet, StatusRepliesPath, m.StatusRepliesGETHandler)
attachHandler(http.MethodGet, OutboxPath, m.OutboxGETHandler)
attachHandler(http.MethodGet, AcceptPath, m.AcceptGETHandler)
+ attachHandler(http.MethodGet, AuthorizationsPath, m.AuthorizationGETHandler)
}
diff --git a/internal/api/client/statuses/statusboost_test.go b/internal/api/client/statuses/statusboost_test.go
index a108c436c..2b6925f3b 100644
--- a/internal/api/client/statuses/statusboost_test.go
+++ b/internal/api/client/statuses/statusboost_test.go
@@ -730,7 +730,7 @@ func (suite *StatusBoostTestSuite) TestPostBoostImplicitAccept() {
suite.FailNow(err.Error())
}
suite.NotZero(intReq.AcceptedAt)
- suite.NotEmpty(intReq.URI)
+ suite.NotEmpty(intReq.InteractionURI)
}
func TestStatusBoostTestSuite(t *testing.T) {
diff --git a/internal/api/client/statuses/statusfave_test.go b/internal/api/client/statuses/statusfave_test.go
index 515b66a3c..f1c6f8eae 100644
--- a/internal/api/client/statuses/statusfave_test.go
+++ b/internal/api/client/statuses/statusfave_test.go
@@ -337,7 +337,7 @@ func (suite *StatusFaveTestSuite) TestPostFaveImplicitAccept() {
suite.FailNow(err.Error())
}
suite.NotZero(intReq.AcceptedAt)
- suite.NotEmpty(intReq.URI)
+ suite.NotEmpty(intReq.InteractionURI)
// Check visibility of status to public after posting fave.
visible, err = visFilter.StatusVisible(ctx, nil, dbStatus)
diff --git a/internal/api/model/interaction.go b/internal/api/model/interaction.go
index b0543ce6b..0dea6cae9 100644
--- a/internal/api/model/interaction.go
+++ b/internal/api/model/interaction.go
@@ -41,6 +41,4 @@ type InteractionRequest struct {
AcceptedAt string `json:"accepted_at,omitempty"`
// The timestamp that the interaction request was rejected (ISO 8601 Datetime). Field omitted if request not rejected (yet).
RejectedAt string `json:"rejected_at,omitempty"`
- // URI of the Accept or Reject. Only set if accepted_at or rejected_at is set, else omitted.
- URI string `json:"uri,omitempty"`
}
diff --git a/internal/cache/db.go b/internal/cache/db.go
index 385c5bcbb..8a8f59539 100644
--- a/internal/cache/db.go
+++ b/internal/cache/db.go
@@ -944,7 +944,7 @@ func (c *Caches) initInteractionRequest() {
// Don't include ptr fields that
// will be populated separately.
// See internal/db/bundb/interaction.go.
- i2.Status = nil
+ i2.TargetStatus = nil
i2.TargetAccount = nil
i2.InteractingAccount = nil
i2.Like = nil
@@ -958,7 +958,9 @@ func (c *Caches) initInteractionRequest() {
Indices: []structr.IndexConfig{
{Fields: "ID"},
{Fields: "InteractionURI"},
- {Fields: "URI"},
+ {Fields: "InteractionRequestURI"},
+ {Fields: "ResponseURI"},
+ {Fields: "AuthorizationURI"},
},
MaxSize: cap,
IgnoreErr: ignoreErrors,
diff --git a/internal/cache/size.go b/internal/cache/size.go
index aa22b03d7..cf58cf075 100644
--- a/internal/cache/size.go
+++ b/internal/cache/size.go
@@ -418,15 +418,16 @@ func sizeofInstance() uintptr {
func sizeofInteractionRequest() uintptr {
return uintptr(size.Of(&gtsmodel.InteractionRequest{
- ID: exampleID,
- CreatedAt: exampleTime,
- StatusID: exampleID,
- TargetAccountID: exampleID,
- InteractingAccountID: exampleID,
- InteractionURI: exampleURI,
- InteractionType: gtsmodel.InteractionAnnounce,
- URI: exampleURI,
- AcceptedAt: exampleTime,
+ ID: exampleID,
+ TargetStatusID: exampleID,
+ TargetAccountID: exampleID,
+ InteractingAccountID: exampleID,
+ InteractionRequestURI: exampleURI,
+ InteractionURI: exampleURI,
+ InteractionType: gtsmodel.InteractionAnnounce,
+ AcceptedAt: exampleTime,
+ ResponseURI: exampleURI,
+ AuthorizationURI: exampleURI,
}))
}
diff --git a/internal/db/bundb/admin.go b/internal/db/bundb/admin.go
index dcf51c6a5..39b2c848f 100644
--- a/internal/db/bundb/admin.go
+++ b/internal/db/bundb/admin.go
@@ -106,12 +106,7 @@ func (a *adminDB) NewSignup(ctx context.Context, newSignup gtsmodel.NewSignup) (
// with this username, create one now.
if account == nil {
uris := uris.GenerateURIsForAccount(newSignup.Username)
-
- accountID, err := id.NewRandomULID()
- if err != nil {
- err := gtserror.Newf("error creating new account id: %w", err)
- return nil, err
- }
+ accountID := id.NewRandomULID()
privKey, err := rsa.GenerateKey(rand.Reader, rsaKeyBits)
if err != nil {
@@ -174,12 +169,9 @@ func (a *adminDB) NewSignup(ctx context.Context, newSignup gtsmodel.NewSignup) (
return user, nil
}
- // Had no user for this account, time to create one!
- newUserID, err := id.NewRandomULID()
- if err != nil {
- err := gtserror.Newf("error creating new user id: %w", err)
- return nil, err
- }
+ // Had no user for this
+ // account, time to create one!
+ newUserID := id.NewRandomULID()
encryptedPassword, err := bcrypt.GenerateFromPassword(
[]byte(newSignup.Password),
@@ -273,14 +265,9 @@ func (a *adminDB) CreateInstanceAccount(ctx context.Context) error {
return err
}
- aID, err := id.NewRandomULID()
- if err != nil {
- return err
- }
-
newAccountURIs := uris.GenerateURIsForAccount(username)
acct := &gtsmodel.Account{
- ID: aID,
+ ID: id.NewRandomULID(),
Username: username,
DisplayName: username,
URL: newAccountURIs.UserURL,
@@ -325,13 +312,8 @@ func (a *adminDB) CreateInstanceInstance(ctx context.Context) error {
return nil
}
- iID, err := id.NewRandomULID()
- if err != nil {
- return err
- }
-
i := &gtsmodel.Instance{
- ID: iID,
+ ID: id.NewRandomULID(),
Domain: host,
Title: host,
URI: fmt.Sprintf("%s://%s", protocol, host),
diff --git a/internal/db/bundb/interaction.go b/internal/db/bundb/interaction.go
index b42eb46f6..2128a7aa6 100644
--- a/internal/db/bundb/interaction.go
+++ b/internal/db/bundb/interaction.go
@@ -58,31 +58,45 @@ func (i *interactionDB) GetInteractionRequestByID(ctx context.Context, id string
)
}
-func (i *interactionDB) GetInteractionRequestByInteractionURI(ctx context.Context, uri string) (*gtsmodel.InteractionRequest, error) {
+func (i *interactionDB) GetInteractionRequestByInteractionURI(ctx context.Context, intURI string) (*gtsmodel.InteractionRequest, error) {
return i.getInteractionRequest(
ctx,
"InteractionURI",
func(request *gtsmodel.InteractionRequest) error {
return i.
newInteractionRequestQ(request).
- Where("? = ?", bun.Ident("interaction_request.interaction_uri"), uri).
+ Where("? = ?", bun.Ident("interaction_request.interaction_uri"), intURI).
Scan(ctx)
},
- uri,
+ intURI,
)
}
-func (i *interactionDB) GetInteractionRequestByURI(ctx context.Context, uri string) (*gtsmodel.InteractionRequest, error) {
+func (i *interactionDB) GetInteractionRequestByResponseURI(ctx context.Context, respURI string) (*gtsmodel.InteractionRequest, error) {
return i.getInteractionRequest(
ctx,
- "URI",
+ "ResponseURI",
func(request *gtsmodel.InteractionRequest) error {
return i.
newInteractionRequestQ(request).
- Where("? = ?", bun.Ident("interaction_request.uri"), uri).
+ Where("? = ?", bun.Ident("interaction_request.response_uri"), respURI).
Scan(ctx)
},
- uri,
+ respURI,
+ )
+}
+
+func (i *interactionDB) GetInteractionRequestByAuthorizationURI(ctx context.Context, authURI string) (*gtsmodel.InteractionRequest, error) {
+ return i.getInteractionRequest(
+ ctx,
+ "AuthorizationURI",
+ func(request *gtsmodel.InteractionRequest) error {
+ return i.
+ newInteractionRequestQ(request).
+ Where("? = ?", bun.Ident("interaction_request.authorization_uri"), authURI).
+ Scan(ctx)
+ },
+ authURI,
)
}
@@ -173,11 +187,11 @@ func (i *interactionDB) PopulateInteractionRequest(ctx context.Context, req *gts
errs = gtserror.NewMultiError(4)
)
- if req.Status == nil {
+ if req.TargetStatus == nil {
// Target status is not set, fetch from the database.
- req.Status, err = i.state.DB.GetStatusByID(
+ req.TargetStatus, err = i.state.DB.GetStatusByID(
gtscontext.SetBarebones(ctx),
- req.StatusID,
+ req.TargetStatusID,
)
if err != nil {
errs.Appendf("error populating interactionRequest target: %w", err)
diff --git a/internal/db/bundb/interaction_test.go b/internal/db/bundb/interaction_test.go
index 564b3a3f2..6a753dca8 100644
--- a/internal/db/bundb/interaction_test.go
+++ b/internal/db/bundb/interaction_test.go
@@ -57,9 +57,8 @@ func (suite *InteractionTestSuite) markInteractionsPending(
suite.FailNow(err.Error())
}
- // Put an interaction request
- // in the DB for this reply.
- req := typeutils.StatusToInteractionRequest(reply)
+ // Put an impolite interaction request in the DB for this reply.
+ req := typeutils.StatusToImpoliteInteractionRequest(reply)
if err := suite.state.DB.PutInteractionRequest(ctx, req); err != nil {
suite.FailNow(err.Error())
}
@@ -84,9 +83,8 @@ func (suite *InteractionTestSuite) markInteractionsPending(
suite.FailNow(err.Error())
}
- // Put an interaction request
- // in the DB for this boost.
- req := typeutils.StatusToInteractionRequest(boost)
+ // Put an impolite interaction request in the DB for this boost.
+ req := typeutils.StatusToImpoliteInteractionRequest(boost)
if err := suite.state.DB.PutInteractionRequest(ctx, req); err != nil {
suite.FailNow(err.Error())
}
@@ -111,9 +109,8 @@ func (suite *InteractionTestSuite) markInteractionsPending(
suite.FailNow(err.Error())
}
- // Put an interaction request
- // in the DB for this fave.
- req := typeutils.StatusFaveToInteractionRequest(fave)
+ // Put an impolite interaction request in the DB for this fave.
+ req := typeutils.StatusFaveToImpoliteInteractionRequest(fave)
if err := suite.state.DB.PutInteractionRequest(ctx, req); err != nil {
suite.FailNow(err.Error())
}
@@ -229,8 +226,8 @@ func (suite *InteractionTestSuite) TestInteractionRejected() {
// Update the interaction request to mark it rejected.
req.RejectedAt = time.Now()
- req.URI = "https://some.reject.uri"
- if err := suite.state.DB.UpdateInteractionRequest(ctx, req, "uri", "rejected_at"); err != nil {
+ req.ResponseURI = "https://some.reject.uri"
+ if err := suite.state.DB.UpdateInteractionRequest(ctx, req, "response_uri", "rejected_at"); err != nil {
suite.FailNow(err.Error())
}
diff --git a/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat.go b/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat.go
new file mode 100644
index 000000000..0df515082
--- /dev/null
+++ b/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat.go
@@ -0,0 +1,328 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package migrations
+
+import (
+ "context"
+ "database/sql"
+ "errors"
+ "net/url"
+ "strings"
+
+ "code.superseriousbusiness.org/gotosocial/internal/config"
+ "code.superseriousbusiness.org/gotosocial/internal/gtserror"
+ "code.superseriousbusiness.org/gotosocial/internal/id"
+ "code.superseriousbusiness.org/gotosocial/internal/log"
+ "code.superseriousbusiness.org/gotosocial/internal/util"
+ "github.com/uptrace/bun"
+ "github.com/uptrace/bun/dialect"
+
+ new_gtsmodel "code.superseriousbusiness.org/gotosocial/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/new"
+ old_gtsmodel "code.superseriousbusiness.org/gotosocial/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/old"
+)
+
+func init() {
+ up := func(ctx context.Context, db *bun.DB) error {
+ const tmpTableName = "new_interaction_requests"
+ const tableName = "interaction_requests"
+ var host = config.GetHost()
+ var accountDomain = config.GetAccountDomain()
+
+ // Count number of interaction
+ // requests we need to update.
+ total, err := db.NewSelect().
+ Table(tableName).
+ Count(ctx)
+ if err != nil {
+ return gtserror.Newf("error geting interaction requests table count: %w", err)
+ }
+
+ // Create new interaction_requests table and convert all existing into it.
+ if err := db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
+
+ log.Info(ctx, "creating new interaction_requests table")
+ if _, err := tx.NewCreateTable().
+ ModelTableExpr(tmpTableName).
+ Model((*new_gtsmodel.InteractionRequest)(nil)).
+ Exec(ctx); err != nil {
+ return gtserror.Newf("error creating new interaction requests table: %w", err)
+ }
+
+ // Conversion batch size.
+ const batchsz = 1000
+
+ var maxID string
+ var count int
+
+ // Start at largest
+ // possible ULID value.
+ maxID = id.Highest
+
+ // Preallocate interaction request slices to maximum possible size.
+ oldRequests := make([]*old_gtsmodel.InteractionRequest, 0, batchsz)
+ newRequests := make([]*new_gtsmodel.InteractionRequest, 0, batchsz)
+
+ log.Info(ctx, "migrating interaction requests to new table, this may take some time!")
+ outer:
+ for {
+ // Reset slices slices.
+ clear(oldRequests)
+ clear(newRequests)
+ oldRequests = oldRequests[:0]
+ newRequests = newRequests[:0]
+
+ // Select next batch of
+ // interaction requests.
+ if err := tx.NewSelect().
+ Model(&oldRequests).
+ Where("? < ?", bun.Ident("id"), maxID).
+ OrderExpr("? DESC", bun.Ident("id")).
+ Limit(batchsz).
+ Scan(ctx); err != nil && !errors.Is(err, sql.ErrNoRows) {
+ return gtserror.Newf("error selecting interaction requests: %w", err)
+ }
+
+ // Reached end of requests.
+ if len(oldRequests) == 0 {
+ break outer
+ }
+
+ // Set next maxID value from old requests.
+ maxID = oldRequests[len(oldRequests)-1].ID
+
+ inner:
+ // Convert old request models to new.
+ for _, oldRequest := range oldRequests {
+ newRequest := &new_gtsmodel.InteractionRequest{
+ ID: oldRequest.ID,
+ TargetStatusID: oldRequest.StatusID,
+ TargetAccountID: oldRequest.TargetAccountID,
+ InteractingAccountID: oldRequest.InteractingAccountID,
+ InteractionURI: oldRequest.InteractionURI,
+ InteractionType: int16(oldRequest.InteractionType), // #nosec G115
+ Polite: util.Ptr(false), // old requests were always impolite
+ AcceptedAt: oldRequest.AcceptedAt,
+ RejectedAt: oldRequest.RejectedAt,
+ ResponseURI: oldRequest.URI,
+ }
+
+ // Append new request to slice,
+ // though we continue operating on
+ // its ptr in the rest of this loop.
+ newRequests = append(newRequests,
+ newRequest)
+
+ // Re-use the original interaction URI to create
+ // a mock interaction request URI on the new model.
+ switch oldRequest.InteractionType {
+ case old_gtsmodel.InteractionLike:
+ newRequest.InteractionRequestURI = oldRequest.InteractionURI + new_gtsmodel.LikeRequestSuffix
+ case old_gtsmodel.InteractionReply:
+ newRequest.InteractionRequestURI = oldRequest.InteractionURI + new_gtsmodel.ReplyRequestSuffix
+ case old_gtsmodel.InteractionAnnounce:
+ newRequest.InteractionRequestURI = oldRequest.InteractionURI + new_gtsmodel.AnnounceRequestSuffix
+ }
+
+ // If the request was accepted by us, then generate an authorization
+ // URI for it, in order to be able to serve an Authorization if necessary.
+ if oldRequest.AcceptedAt.IsZero() || oldRequest.URI == "" {
+
+ // Wasn't accepted,
+ // nothing else to do.
+ continue inner
+ }
+
+ // Parse URI details of accept URI string.
+ acceptURI, err := url.Parse(oldRequest.URI)
+ if err != nil {
+ log.Warnf(ctx, "could not parse oldRequest.URI for interaction request %s,"+
+ " skipping forward-compat hack (don't worry, this is not a big deal): %v",
+ oldRequest.ID, err)
+ continue inner
+ }
+
+ // Check whether accept URI originated from this instance.
+ if !(acceptURI.Host == host || acceptURI.Host == accountDomain) {
+
+ // Not an accept from
+ // us, leave it alone.
+ continue inner
+ }
+
+ // Reuse the Accept URI to create an Authorization URI.
+ // Creates `https://example.org/users/aaa/authorizations/[ID]`
+ // from `https://example.org/users/aaa/accepts/[ID]`.
+ authorizationURI := strings.ReplaceAll(
+ oldRequest.URI,
+ "/accepts/"+oldRequest.ID,
+ "/authorizations/"+oldRequest.ID,
+ )
+ newRequest.AuthorizationURI = authorizationURI
+
+ var updateTableName string
+
+ // Determine which table will have corresponding approved_by_uri.
+ if oldRequest.InteractionType == old_gtsmodel.InteractionLike {
+ updateTableName = "status_faves"
+ } else {
+ updateTableName = "statuses"
+ }
+
+ // Update the corresponding interaction
+ // with generated authorization URI.
+ if _, err := tx.NewUpdate().
+ Table(updateTableName).
+ Set("? = ?", bun.Ident("approved_by_uri"), authorizationURI).
+ Where("? = ?", bun.Ident("uri"), oldRequest.InteractionURI).
+ Exec(ctx); err != nil {
+ return gtserror.Newf("error updating approved_by_uri: %w", err)
+ }
+ }
+
+ // Insert converted interaction
+ // request models to new table.
+ if _, err := tx.
+ NewInsert().
+ Model(&newRequests).
+ Exec(ctx); err != nil {
+ return gtserror.Newf("error inserting interaction requests: %w", err)
+ }
+
+ // Increment insert count.
+ count += len(newRequests)
+
+ log.Infof(ctx, "[%d of %d] converting interaction requests", count, total)
+ }
+
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ // Ensure that the above transaction
+ // has gone ahead without issues.
+ //
+ // Also placing this here might make
+ // breaking this into piecemeal steps
+ // easier if turns out necessary.
+ newTotal, err := db.NewSelect().
+ Table(tmpTableName).
+ Count(ctx)
+ if err != nil {
+ return gtserror.Newf("error geting new interaction requests table count: %w", err)
+ } else if total != newTotal {
+ return gtserror.Newf("new interaction requests table contains unexpected count %d, want %d", newTotal, total)
+ }
+
+ // Attempt to merge any sqlite write-ahead-log.
+ if err := doWALCheckpoint(ctx, db); err != nil {
+ return err
+ }
+
+ // Drop the old interaction requests table and rename new one to replace it.
+ if err := db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error {
+
+ log.Info(ctx, "dropping old interaction_requests table")
+ if _, err := tx.NewDropTable().
+ Table(tableName).
+ Exec(ctx); err != nil {
+ return gtserror.Newf("error dropping old interaction requests table: %w", err)
+ }
+
+ log.Info(ctx, "renaming new interaction_requests table to old")
+ if _, err := tx.NewRaw("ALTER TABLE ? RENAME TO ?",
+ bun.Ident(tmpTableName),
+ bun.Ident(tableName),
+ ).Exec(ctx); err != nil {
+ return gtserror.Newf("error renaming interaction requests table: %w", err)
+ }
+
+ // Create necessary indices on the new table.
+ for index, columns := range map[string][]string{
+ "interaction_requests_target_status_id_idx": {"target_status_id"},
+ "interaction_requests_interacting_account_id_idx": {"interacting_account_id"},
+ "interaction_requests_target_account_id_idx": {"target_account_id"},
+ "interaction_requests_accepted_at_idx": {"accepted_at"},
+ "interaction_requests_rejected_at_idx": {"rejected_at"},
+ } {
+ log.Infof(ctx, "recreating %s index", index)
+ if _, err := tx.NewCreateIndex().
+ Table(tableName).
+ Index(index).
+ Column(columns...).
+ Exec(ctx); err != nil {
+ return err
+ }
+ }
+
+ if tx.Dialect().Name() == dialect.PG {
+ // Rename postgres uniqueness constraints:
+ // "new_interaction_requests_*" -> "interaction_requests_*"
+ log.Info(ctx, "renaming interaction_requests constraints on new table")
+ for _, spec := range []struct {
+ old string
+ new string
+ }{
+ {
+ old: "new_interaction_requests_pkey",
+ new: "interaction_requests_pkey",
+ },
+ {
+ old: "new_interaction_requests_interaction_request_uri_key",
+ new: "interaction_requests_interaction_request_uri_key",
+ },
+ {
+ old: "new_interaction_requests_interaction_uri_key",
+ new: "interaction_requests_interaction_uri_key",
+ },
+ {
+ old: "new_interaction_requests_response_uri_key",
+ new: "interaction_requests_response_uri_key",
+ },
+ {
+ old: "new_interaction_requests_authorization_uri_key",
+ new: "interaction_requests_authorization_uri_key",
+ },
+ } {
+ if _, err := tx.NewRaw("ALTER TABLE ? RENAME CONSTRAINT ? TO ?",
+ bun.Ident(tableName),
+ bun.Safe(spec.old),
+ bun.Safe(spec.new),
+ ).Exec(ctx); err != nil {
+ return gtserror.Newf("error renaming postgres interaction requests constraint %s: %w", spec.new, err)
+ }
+ }
+ }
+
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ // Final sqlite write-ahead-log merge.
+ return doWALCheckpoint(ctx, db)
+ }
+
+ down := func(ctx context.Context, db *bun.DB) error {
+ return nil
+ }
+
+ if err := Migrations.Register(up, down); err != nil {
+ panic(err)
+ }
+}
diff --git a/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/new/interactionrequest.go b/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/new/interactionrequest.go
new file mode 100644
index 000000000..bdd2d5811
--- /dev/null
+++ b/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/new/interactionrequest.go
@@ -0,0 +1,68 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package gtsmodel
+
+import (
+ "time"
+
+ "github.com/uptrace/bun"
+)
+
+type InteractionRequest struct {
+ // Used only for migration.
+ bun.BaseModel `bun:"table:new_interaction_requests"`
+
+ ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"`
+
+ // Removed in new model.
+ // CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+
+ // Renamed from "StatusID" to "TargetStatusID" in new model.
+ TargetStatusID string `bun:"type:CHAR(26),nullzero,notnull"`
+
+ TargetAccountID string `bun:"type:CHAR(26),nullzero,notnull"`
+
+ InteractingAccountID string `bun:"type:CHAR(26),nullzero,notnull"`
+
+ // Added in new model.
+ InteractionRequestURI string `bun:",nullzero,notnull,unique"`
+
+ InteractionURI string `bun:",nullzero,notnull,unique"`
+
+ // Changed type from int to int16 in new model.
+ InteractionType int16 `bun:",notnull"`
+
+ // Added in new model.
+ Polite *bool `bun:",nullzero,notnull,default:false"`
+
+ AcceptedAt time.Time `bun:"type:timestamptz,nullzero"`
+
+ RejectedAt time.Time `bun:"type:timestamptz,nullzero"`
+
+ // Renamed from "URI" to "ResponseURI" in new model.
+ ResponseURI string `bun:",nullzero,unique"`
+
+ // Added in new model.
+ AuthorizationURI string `bun:",nullzero,unique"`
+}
+
+const (
+ LikeRequestSuffix = "#LikeRequest"
+ ReplyRequestSuffix = "#ReplyRequest"
+ AnnounceRequestSuffix = "#AnnounceRequest"
+)
diff --git a/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/old/interactionrequest.go b/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/old/interactionrequest.go
new file mode 100644
index 000000000..a341f4d5b
--- /dev/null
+++ b/internal/db/bundb/migrations/20250715095446_int_pols_forward_compat/old/interactionrequest.go
@@ -0,0 +1,39 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package gtsmodel
+
+import "time"
+
+type InteractionRequest struct {
+ ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"`
+ CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"`
+ StatusID string `bun:"type:CHAR(26),nullzero,notnull"`
+ TargetAccountID string `bun:"type:CHAR(26),nullzero,notnull"`
+ InteractingAccountID string `bun:"type:CHAR(26),nullzero,notnull"`
+ InteractionURI string `bun:",nullzero,notnull,unique"`
+ InteractionType int `bun:",notnull"`
+ AcceptedAt time.Time `bun:"type:timestamptz,nullzero"`
+ RejectedAt time.Time `bun:"type:timestamptz,nullzero"`
+ URI string `bun:",nullzero,unique"`
+}
+
+const (
+ InteractionLike int = 0
+ InteractionReply int = 1
+ InteractionAnnounce int = 2
+)
diff --git a/internal/db/bundb/notification_test.go b/internal/db/bundb/notification_test.go
index 10b82b7ce..5b67d4f58 100644
--- a/internal/db/bundb/notification_test.go
+++ b/internal/db/bundb/notification_test.go
@@ -46,21 +46,7 @@ func (suite *NotificationTestSuite) spamNotifs() {
if i%2 == 0 {
targetAccountID = zork.ID
} else {
- randomAssID, err := id.NewRandomULID()
- if err != nil {
- panic(err)
- }
- targetAccountID = randomAssID
- }
-
- statusID, err := id.NewRandomULID()
- if err != nil {
- panic(err)
- }
-
- originAccountID, err := id.NewRandomULID()
- if err != nil {
- panic(err)
+ targetAccountID = id.NewRandomULID()
}
notif := &gtsmodel.Notification{
@@ -68,8 +54,8 @@ func (suite *NotificationTestSuite) spamNotifs() {
NotificationType: gtsmodel.NotificationFavourite,
CreatedAt: time.Now(),
TargetAccountID: targetAccountID,
- OriginAccountID: originAccountID,
- StatusOrEditID: statusID,
+ OriginAccountID: id.NewRandomULID(),
+ StatusOrEditID: id.NewRandomULID(),
Read: util.Ptr(false),
}
diff --git a/internal/db/interaction.go b/internal/db/interaction.go
index 4a6ec7e2e..9b45a6ab4 100644
--- a/internal/db/interaction.go
+++ b/internal/db/interaction.go
@@ -28,12 +28,17 @@ type Interaction interface {
// GetInteractionRequestByID gets one request with the given id.
GetInteractionRequestByID(ctx context.Context, id string) (*gtsmodel.InteractionRequest, error)
- // GetInteractionRequestByID gets one request with the given interaction uri.
- GetInteractionRequestByInteractionURI(ctx context.Context, uri string) (*gtsmodel.InteractionRequest, error)
+ // GetInteractionRequestByID gets one request with the given interaction
+ // uri (ie., the URI of the requested like, reply, or announce).
+ GetInteractionRequestByInteractionURI(ctx context.Context, intURI string) (*gtsmodel.InteractionRequest, error)
- // GetInteractionRequestByURI returns one accepted or rejected
- // interaction request with the given URI, if it exists in the db.
- GetInteractionRequestByURI(ctx context.Context, uri string) (*gtsmodel.InteractionRequest, error)
+ // GetInteractionRequestByResponseURI returns one accepted or rejected
+ // interaction request with the given Accept or Reject URI.
+ GetInteractionRequestByResponseURI(ctx context.Context, respURI string) (*gtsmodel.InteractionRequest, error)
+
+ // GetInteractionRequestByAuthorizationURI returns one accepted
+ // interaction request with the given authorization URI.
+ GetInteractionRequestByAuthorizationURI(ctx context.Context, authURI string) (*gtsmodel.InteractionRequest, error)
// PopulateInteractionRequest ensures that the request's struct fields are populated.
PopulateInteractionRequest(ctx context.Context, request *gtsmodel.InteractionRequest) error
diff --git a/internal/federation/dereferencing/status_permitted.go b/internal/federation/dereferencing/status_permitted.go
index 848a821d1..5e53d56bc 100644
--- a/internal/federation/dereferencing/status_permitted.go
+++ b/internal/federation/dereferencing/status_permitted.go
@@ -70,7 +70,7 @@ func (d *Dereferencer) isPermittedStatus(
switch {
case status.Account.IsSuspended():
// we shouldn't reach this point, log to poke devs to investigate.
- log.Warnf(ctx, "status author suspended: %s", status.AccountURI)
+ log.Warnf(ctx, "should not have reached here, author suspended: %s", status.AccountURI)
permitted = false
case status.InReplyToURI != "":
@@ -111,7 +111,8 @@ func (d *Dereferencer) isPermittedStatus(
return
}
-// isPermittedReply ...
+// isPermittedReply checks whether the given status
+// is a permitted reply to its referenced inReplyTo.
func (d *Dereferencer) isPermittedReply(
ctx context.Context,
requestUser string,
@@ -119,20 +120,21 @@ func (d *Dereferencer) isPermittedReply(
) (bool, error) {
var (
- replyURI = reply.URI // Definitely set.
- inReplyToURI = reply.InReplyToURI // Definitely set.
- inReplyTo = reply.InReplyTo // Might not be set.
+ replyURI = reply.URI // Definitely set.
+
+ parentURI = reply.InReplyToURI // Definitely set.
+ parent = reply.InReplyTo // Might not be set.
+
approvedByURI = reply.ApprovedByURI // Might not be set.
)
// Check if we have a stored interaction request for parent status.
parentReq, err := d.state.DB.GetInteractionRequestByInteractionURI(
gtscontext.SetBarebones(ctx),
- inReplyToURI,
+ parentURI,
)
if err != nil && !errors.Is(err, db.ErrNoEntries) {
- err := gtserror.Newf("db error getting interaction request: %w", err)
- return false, err
+ return false, gtserror.Newf("db error getting interaction request: %w", err)
}
// Check if we have a stored interaction request for this reply.
@@ -141,8 +143,7 @@ func (d *Dereferencer) isPermittedReply(
replyURI,
)
if err != nil && !errors.Is(err, db.ErrNoEntries) {
- err := gtserror.Newf("db error getting interaction request: %w", err)
- return false, err
+ return false, gtserror.Newf("db error getting interaction request: %w", err)
}
parentRejected := (parentReq != nil && parentReq.IsRejected())
@@ -176,8 +177,7 @@ func (d *Dereferencer) isPermittedReply(
// it was rejected previously and now claims
// to be approved. Continue permission checks.
- if inReplyTo == nil {
-
+ if parent == nil {
// If we didn't have the replied-to status
// in our database (yet), we can't check
// right now if this reply is permitted.
@@ -191,24 +191,23 @@ func (d *Dereferencer) isPermittedReply(
}
// We have the replied-to status; ensure it's fully populated.
- if err := d.state.DB.PopulateStatus(ctx, inReplyTo); err != nil {
+ if err := d.state.DB.PopulateStatus(ctx, parent); err != nil {
return false, gtserror.Newf("error populating status %s: %w", reply.ID, err)
}
- // Make sure replied-to status is not
- // a boost wrapper, and make sure it's
- // actually visible to the requester.
- if inReplyTo.BoostOfID != "" {
- // We do not permit replies
- // to boost wrapper statuses.
- log.Info(ctx, "rejecting reply to boost wrapper status")
+ // Boost wrapper statuses
+ // cannot receive replies.
+ if parent.BoostOfID != "" {
+ log.Warn(ctx, "received reply to boost wrapper status: %s", parent.URI)
return false, nil
}
- if inReplyTo.IsLocal() {
+ // If parent is a local status
+ // check visibility to replyer.
+ if parent.IsLocal() {
visible, err := d.visFilter.StatusVisible(ctx,
reply.Account,
- inReplyTo,
+ parent,
)
if err != nil {
err := gtserror.Newf("error checking inReplyTo visibility: %w", err)
@@ -227,12 +226,12 @@ func (d *Dereferencer) isPermittedReply(
// approval and checking the return value.
// No further checks are required.
if approvedByURI != "" {
- return d.isPermittedByApprovedByIRI(
+ return d.isPermittedByAuthURI(
ctx,
gtsmodel.InteractionReply,
requestUser,
reply,
- inReplyTo,
+ parent,
thisReq,
approvedByURI,
)
@@ -243,7 +242,7 @@ func (d *Dereferencer) isPermittedReply(
// to see what we need to do with it.
replyable, err := d.intFilter.StatusReplyable(ctx,
reply.Account,
- inReplyTo,
+ parent,
)
if err != nil {
err := gtserror.Newf("error checking status replyability: %w", err)
@@ -260,7 +259,7 @@ func (d *Dereferencer) isPermittedReply(
return false, d.rejectedByPolicy(
ctx,
reply,
- inReplyTo,
+ parent,
thisReq,
)
}
@@ -279,7 +278,7 @@ func (d *Dereferencer) isPermittedReply(
// pending approval, though we know at this point
// that the status did not include an approvedBy URI.
- if !inReplyTo.IsLocal() {
+ if !parent.IsLocal() {
// If the replied-to status is remote, we should just
// drop this reply at this point, as we can't verify
// that the remote replied-to account approves it, and
@@ -359,7 +358,7 @@ func (d *Dereferencer) unpermittedByParent(
// This collapses the chain beyond the first
// rejected reply and allows us to avoid derefing
// further replies we already know we don't want.
- inReplyToID := parentReq.StatusID
+ inReplyToID := parentReq.TargetStatusID
targetAccountID := parentReq.TargetAccountID
// As nobody is actually Rejecting the reply
@@ -369,14 +368,16 @@ func (d *Dereferencer) unpermittedByParent(
uri := ""
rejection := &gtsmodel.InteractionRequest{
- ID: rejectID,
- StatusID: inReplyToID,
- TargetAccountID: targetAccountID,
- InteractingAccountID: reply.AccountID,
- InteractionURI: reply.URI,
- InteractionType: gtsmodel.InteractionReply,
- URI: uri,
- RejectedAt: time.Now(),
+ ID: rejectID,
+ TargetStatusID: inReplyToID,
+ TargetAccountID: targetAccountID,
+ InteractingAccountID: reply.AccountID,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(reply.URI, gtsmodel.ReplyRequestSuffix),
+ InteractionURI: reply.URI,
+ InteractionType: gtsmodel.InteractionReply,
+ Polite: util.Ptr(false),
+ ResponseURI: uri,
+ RejectedAt: time.Now(),
}
err := d.state.DB.PutInteractionRequest(ctx, rejection)
if err != nil && !errors.Is(err, db.ErrAlreadyExists) {
@@ -386,14 +387,14 @@ func (d *Dereferencer) unpermittedByParent(
return nil
}
-// isPermittedByApprovedByIRI checks whether the given URI
+// isPermittedByAuthURI checks whether the given URI
// can be dereferenced, and whether it returns either an
-// Accept activity or an approval object which permits the
-// given reply to the given inReplyTo status.
+// Accept activity or an authorization object that permits
+// the given reply to the given inReplyTo status.
//
// If yes, then thisReq will be updated to
// reflect the approval, if it's not nil.
-func (d *Dereferencer) isPermittedByApprovedByIRI(
+func (d *Dereferencer) isPermittedByAuthURI(
ctx context.Context,
interactionType gtsmodel.InteractionType,
requestUser string,
@@ -402,7 +403,7 @@ func (d *Dereferencer) isPermittedByApprovedByIRI(
thisReq *gtsmodel.InteractionRequest,
approvedByIRI string,
) (bool, error) {
- permitted, err := d.isValidApprovedByIRI(
+ permitted, err := d.isValidAuthURI(
ctx,
interactionType,
requestUser,
@@ -430,13 +431,13 @@ func (d *Dereferencer) isPermittedByApprovedByIRI(
// pending approval, clear that now.
reply.PendingApproval = util.Ptr(false)
if thisReq != nil {
- thisReq.URI = approvedByIRI
+ thisReq.ResponseURI = approvedByIRI
thisReq.AcceptedAt = time.Now()
thisReq.RejectedAt = time.Time{}
err := d.state.DB.UpdateInteractionRequest(
ctx,
thisReq,
- "uri",
+ "response_uri",
"accepted_at",
"rejected_at",
)
@@ -483,13 +484,13 @@ func (d *Dereferencer) rejectedByPolicy(
// request is marked as rejected.
thisReq.RejectedAt = time.Now()
thisReq.AcceptedAt = time.Time{}
- thisReq.URI = rejectURI
+ thisReq.ResponseURI = rejectURI
err := d.state.DB.UpdateInteractionRequest(
ctx,
thisReq,
"rejected_at",
"accepted_at",
- "uri",
+ "response_uri",
)
if err != nil {
return gtserror.Newf("db error updating interaction request: %w", err)
@@ -501,14 +502,16 @@ func (d *Dereferencer) rejectedByPolicy(
// We haven't stored a rejected interaction
// request for this status yet, do it now.
rejection := &gtsmodel.InteractionRequest{
- ID: rejectID,
- StatusID: inReplyTo.ID,
- TargetAccountID: inReplyTo.AccountID,
- InteractingAccountID: reply.AccountID,
- InteractionURI: reply.URI,
- InteractionType: gtsmodel.InteractionReply,
- URI: rejectURI,
- RejectedAt: time.Now(),
+ ID: rejectID,
+ TargetStatusID: inReplyTo.ID,
+ TargetAccountID: inReplyTo.AccountID,
+ InteractingAccountID: reply.AccountID,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(reply.URI, gtsmodel.ReplyRequestSuffix),
+ InteractionURI: reply.URI,
+ InteractionType: gtsmodel.InteractionReply,
+ Polite: util.Ptr(false),
+ ResponseURI: rejectURI,
+ RejectedAt: time.Now(),
}
err := d.state.DB.PutInteractionRequest(ctx, rejection)
if err != nil && !errors.Is(err, db.ErrAlreadyExists) {
@@ -611,7 +614,7 @@ func (d *Dereferencer) isPermittedBoost(
// Boost claims to be approved, check
// this by dereferencing the approvedBy
// and inspecting the return value.
- permitted, err := d.isValidApprovedByIRI(
+ permitted, err := d.isValidAuthURI(
ctx,
gtsmodel.InteractionAnnounce,
requestUser,
@@ -637,36 +640,36 @@ func (d *Dereferencer) isPermittedBoost(
return true, nil
}
-// isValidApprovedByIRI dereferences the activitystreams Accept or approval
-// at the specified IRI, and checks the Accept or approval for validity
-// against the provided expectedActor, expectedObject, and expectedTarget.
+// isValidAuthURI dereferences the activitystreams Accept or authorization
+// at the specified IRI, and checks it for validity against the provided
+// expectedActor, expectedObject, and expectedTarget.
//
// Will return either (true, nil) if everything looked OK, an error
// if something went wrong internally during deref, or (false, nil)
// if the dereferenced Accept/Approval did not meet expectations.
-func (d *Dereferencer) isValidApprovedByIRI(
+func (d *Dereferencer) isValidAuthURI(
ctx context.Context,
interactionType gtsmodel.InteractionType,
requestUser string,
- approvedByIRIStr string, // approval uri Eg., "https://example.org/users/someone/accepts/01J2736AWWJ3411CPR833F6D03"
+ authIRIStr string, // authorization uri Eg., "https://example.org/users/someone/accepts/01J2736AWWJ3411CPR833F6D03"
expectActorURIStr string, // actor Eg., "https://example.org/users/someone"
expectObjectURIStr string, // object Eg., "https://some.instance.example.org/users/someone_else/statuses/01J27414TWV9F7DC39FN8ABB5R"
expectTargetURIStr string, // target Eg., "https://example.org/users/someone/statuses/01JM4REQTJ1BZ1R4BPYP1W4R9E"
) (bool, error) {
l := log.
WithContext(ctx).
- WithField("approvedByIRI", approvedByIRIStr)
+ WithField("authIRI", authIRIStr)
- approvedByIRI, err := url.Parse(approvedByIRIStr)
+ authIRI, err := url.Parse(authIRIStr)
if err != nil {
// Real returnable error.
- err := gtserror.Newf("error parsing approvedByIRI: %w", err)
+ err := gtserror.Newf("error parsing authIRI: %w", err)
return false, err
}
// Don't make calls to the IRI if its
// domain is blocked, just return false.
- blocked, err := d.state.DB.IsDomainBlocked(ctx, approvedByIRI.Host)
+ blocked, err := d.state.DB.IsDomainBlocked(ctx, authIRI.Host)
if err != nil {
// Real returnable error.
err := gtserror.Newf("error checking domain block: %w", err)
@@ -674,7 +677,7 @@ func (d *Dereferencer) isValidApprovedByIRI(
}
if blocked {
- l.Info("approvedByIRI host is blocked")
+ l.Info("authIRI host is blocked")
return false, nil
}
@@ -685,12 +688,12 @@ func (d *Dereferencer) isValidApprovedByIRI(
return false, err
}
- // Make the call to the approvedByURI.
+ // Make the call to the authIRI.
// Log any error encountered here but don't
// return it as it's not *our* error.
- rsp, err := tsport.Dereference(ctx, approvedByIRI)
+ rsp, err := tsport.Dereference(ctx, authIRI)
if err != nil {
- l.Errorf("error dereferencing approvedByIRI: %v", err)
+ l.Errorf("error dereferencing authIRI: %v", err)
return false, nil
}
@@ -706,31 +709,31 @@ func (d *Dereferencer) isValidApprovedByIRI(
}
// Extract the URI/ID of the type.
- approvedByID := ap.GetJSONLDId(t)
- approvedByIDStr := approvedByID.String()
+ authID := ap.GetJSONLDId(t)
+ authIDStr := authID.String()
// Check whether input URI and final returned URI
// have changed (i.e. we followed some redirects).
rspURL := rsp.Request.URL
rspURLStr := rspURL.String()
- if rspURLStr != approvedByIRIStr {
+ if rspURLStr != authIRIStr {
// If rspURLStr != approvedByIRI, make sure final
// response URL is at least on the same host as
// what we expected (ie., we weren't redirected
// across domains), and make sure it's the same
// as the ID of the Accept we were returned.
switch {
- case rspURL.Host != approvedByIRI.Host:
+ case rspURL.Host != authIRI.Host:
l.Errorf(
- "final deref host %s did not match approvedByIRI host",
+ "final deref host %s did not match authIRI host",
rspURL.Host,
)
return false, nil
- case approvedByIDStr != rspURLStr:
+ case authIDStr != rspURLStr:
l.Errorf(
"final deref uri %s did not match returned ID %s",
- rspURLStr, approvedByIDStr,
+ rspURLStr, authIDStr,
)
return false, nil
}
@@ -739,13 +742,13 @@ func (d *Dereferencer) isValidApprovedByIRI(
// Response is superficially OK,
// check in more detail now.
- // First try to parse type as Approval stamp.
- if approvable, ok := ap.ToApprovable(t); ok {
- return isValidApprovable(
+ // First try to parse type as Authorization stamp.
+ if authable, ok := ap.ToAuthorizationable(t); ok {
+ return isValidAuthorization(
ctx,
interactionType,
- approvable,
- approvedByID,
+ authable,
+ authID,
expectActorURIStr, // actor
expectObjectURIStr, // object
expectTargetURIStr, // target
@@ -757,7 +760,7 @@ func (d *Dereferencer) isValidApprovedByIRI(
return isValidAcceptable(
ctx,
acceptable,
- approvedByID,
+ authID,
expectActorURIStr, // actor
expectObjectURIStr, // object
expectTargetURIStr, // target
@@ -767,8 +770,8 @@ func (d *Dereferencer) isValidApprovedByIRI(
// Type wasn't something we
// could do anything with!
l.Errorf(
- "%T at %s not approvable or acceptable",
- t, approvedByIRIStr,
+ "%T at %s not authorization or accept",
+ t, authIRIStr,
)
return false, nil
}
@@ -850,55 +853,55 @@ func isValidAcceptable(
return true, nil
}
-func isValidApprovable(
+func isValidAuthorization(
ctx context.Context,
interactionType gtsmodel.InteractionType,
- approvable ap.Approvable,
- approvalID *url.URL,
+ auth ap.Authorizationable,
+ authID *url.URL,
expectActorURIStr string, // actor Eg., "https://example.org/users/someone"
expectObjectURIStr string, // object Eg., "https://some.instance.example.org/users/someone_else/statuses/01J27414TWV9F7DC39FN8ABB5R"
expectTargetURIStr string, // target Eg., "https://example.org/users/someone/statuses/01JM4REQTJ1BZ1R4BPYP1W4R9E"
) (bool, error) {
l := log.
WithContext(ctx).
- WithField("approval", approvalID.String())
+ WithField("auth", authID.String())
- // Check that the type of the Approval
+ // Check that the type of the Authorization
// matches the interaction it's approving.
- switch tn := approvable.GetTypeName(); {
- case (tn == ap.ObjectLikeApproval && interactionType == gtsmodel.InteractionLike),
- (tn == ap.ObjectReplyApproval && interactionType == gtsmodel.InteractionReply),
- (tn == ap.ObjectAnnounceApproval && interactionType == gtsmodel.InteractionAnnounce):
+ switch tn := auth.GetTypeName(); {
+ case (tn == ap.ObjectLikeAuthorization && interactionType == gtsmodel.InteractionLike),
+ (tn == ap.ObjectReplyAuthorization && interactionType == gtsmodel.InteractionReply),
+ (tn == ap.ObjectAnnounceAuthorization && interactionType == gtsmodel.InteractionAnnounce):
// All good baby!
default:
// There's a mismatch.
l.Errorf(
- "approval type %s cannot approve %s",
+ "authorization type %s cannot approve %s",
tn, interactionType.String(),
)
return false, nil
}
// Extract the actor IRI and string from Approval.
- actorIRIs := ap.GetAttributedTo(approvable)
+ actorIRIs := ap.GetAttributedTo(auth)
actorIRI, actorIRIStr := extractIRI(actorIRIs)
switch {
case actorIRIStr == "":
- l.Error("Approval missing attributedTo IRI")
+ l.Error("authorization missing attributedTo IRI")
return false, nil
- // Ensure the Approval actor is on
+ // Ensure the authorization actor is on
// the instance hosting the Approval.
- case actorIRI.Host != approvalID.Host:
+ case actorIRI.Host != authID.Host:
l.Errorf(
- "actor %s not on the same host as Approval",
+ "actor %s not on the same host as authorization",
actorIRIStr,
)
return false, nil
- // Ensure the Approval actor is who we expect
+ // Ensure the auth actor is who we expect
// it to be, and not someone else trying to
- // do an Approval for an interaction with a
+ // do an auth for an interaction with a
// statusable they don't own.
case actorIRIStr != expectActorURIStr:
l.Errorf(
@@ -908,33 +911,32 @@ func isValidApprovable(
return false, nil
}
- // Extract the object IRI string from Approval.
- objectIRIs := ap.GetObjectIRIs(approvable)
+ // Extract the object IRI string from authorization.
+ objectIRIs := ap.GetInteractingObject(auth)
_, objectIRIStr := extractIRI(objectIRIs)
switch {
case objectIRIStr == "":
- l.Error("missing Approval object IRI")
+ l.Error("missing authorization interactingObject IRI")
return false, nil
- // Ensure the Approval Object is what we expect
+ // Ensure the authorization object is what we expect
// it to be, ie., it's approving the interaction
// we need it to approve, and not something else.
case objectIRIStr != expectObjectURIStr:
l.Errorf(
- "resolved Approval object IRI %s was not the same as expected object %s",
+ "resolved authorization interactingObject IRI %s was not the same as expected object %s",
objectIRIStr, expectObjectURIStr,
)
return false, nil
}
- // If there's a Target set then verify it's
- // what we expect it to be, ie., it should point
- // back to the post that's being interacted with.
- targetIRIs := ap.GetTargetIRIs(approvable)
+ // Ensure the authorization target is what we expect,
+ // ie., it should be the status being interacted with.
+ targetIRIs := ap.GetInteractionTarget(auth)
_, targetIRIStr := extractIRI(targetIRIs)
if targetIRIStr != "" && targetIRIStr != expectTargetURIStr {
l.Errorf(
- "resolved Approval target IRI %s was not the same as expected target %s",
+ "resolved authorization interactionTarget IRI %s was not the same as expected target %s",
targetIRIStr, expectTargetURIStr,
)
return false, nil
diff --git a/internal/federation/dereferencing/status_test.go b/internal/federation/dereferencing/status_test.go
index e44babbfc..62b38f188 100644
--- a/internal/federation/dereferencing/status_test.go
+++ b/internal/federation/dereferencing/status_test.go
@@ -136,7 +136,7 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithTag() {
// status values should be set
suite.Equal("https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7", status.URI)
suite.Equal("https://unknown-instance.com/users/@brand_new_person/01H641QSRS3TCXSVC10X4GPKW7", status.URL)
- suite.Equal("<p>Babe are you okay, you've hardly touched your <a href=\"https://unknown-instance.com/tags/piss\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>piss</span></a></p>", status.Content)
+ suite.Equal("<p><span class=\"h-card\"><a href=\"http://fossbros-anonymous.io/@foss_satan\" class=\"u-url mention\" rel=\"nofollow noreferrer noopener\" target=\"_blank\">@<span>foss_satan</span></a></span>Babe are you okay, you've hardly touched your <a href=\"https://unknown-instance.com/tags/piss\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>piss</span></a></p>", status.Content)
suite.Equal("https://unknown-instance.com/users/brand_new_person", status.AccountURI)
suite.False(*status.Local)
suite.Empty(status.ContentWarning)
diff --git a/internal/federation/federatingactor_test.go b/internal/federation/federatingactor_test.go
index 51ead5f31..6de4aa203 100644
--- a/internal/federation/federatingactor_test.go
+++ b/internal/federation/federatingactor_test.go
@@ -42,18 +42,14 @@ func (suite *FederatingActorTestSuite) TestSendNoRemoteFollowers() {
ctx := suite.T().Context()
testAccount := suite.testAccounts["local_account_1"]
testNote := testrig.NewAPNote(
- testrig.URLMustParse("http://localhost:8080/users/the_mighty_zork/statuses/01G1TR6BADACCZWQMNF9X21TV5"),
- testrig.URLMustParse("http://localhost:8080/@the_mighty_zork/statuses/01G1TR6BADACCZWQMNF9X21TV5"),
- time.Now(),
- "boobies",
- "",
- testrig.URLMustParse(testAccount.URI),
- []*url.URL{testrig.URLMustParse(testAccount.FollowersURI)},
- nil,
- false,
- nil,
- nil,
- nil,
+ &testrig.NewAPNoteParams{
+ ID: testrig.URLMustParse("http://localhost:8080/users/the_mighty_zork/statuses/01G1TR6BADACCZWQMNF9X21TV5"),
+ URL: testrig.URLMustParse("http://localhost:8080/@the_mighty_zork/statuses/01G1TR6BADACCZWQMNF9X21TV5"),
+ CreatedAt: time.Now(),
+ Content: "boobies",
+ AttributedTo: testrig.URLMustParse(testAccount.URI),
+ To: []*url.URL{testrig.URLMustParse(testAccount.FollowersURI)},
+ },
)
testActivity := testrig.WrapAPNoteInCreate(testrig.URLMustParse("http://localhost:8080/whatever_some_create"), testrig.URLMustParse(testAccount.URI), time.Now(), testNote)
@@ -98,18 +94,14 @@ func (suite *FederatingActorTestSuite) TestSendRemoteFollower() {
suite.NoError(err)
testNote := testrig.NewAPNote(
- testrig.URLMustParse("http://localhost:8080/users/the_mighty_zork/statuses/01G1TR6BADACCZWQMNF9X21TV5"),
- testrig.URLMustParse("http://localhost:8080/@the_mighty_zork/statuses/01G1TR6BADACCZWQMNF9X21TV5"),
- testrig.TimeMustParse("2022-06-02T12:22:21+02:00"),
- "boobies",
- "",
- testrig.URLMustParse(testAccount.URI),
- []*url.URL{testrig.URLMustParse(testAccount.FollowersURI)},
- nil,
- false,
- nil,
- nil,
- nil,
+ &testrig.NewAPNoteParams{
+ ID: testrig.URLMustParse("http://localhost:8080/users/the_mighty_zork/statuses/01G1TR6BADACCZWQMNF9X21TV5"),
+ URL: testrig.URLMustParse("http://localhost:8080/@the_mighty_zork/statuses/01G1TR6BADACCZWQMNF9X21TV5"),
+ CreatedAt: testrig.TimeMustParse("2022-06-02T12:22:21+02:00"),
+ Content: "boobies",
+ AttributedTo: testrig.URLMustParse(testAccount.URI),
+ To: []*url.URL{testrig.URLMustParse(testAccount.FollowersURI)},
+ },
)
testActivity := testrig.WrapAPNoteInCreate(testrig.URLMustParse("http://localhost:8080/whatever_some_create"), testrig.URLMustParse(testAccount.URI), testrig.TimeMustParse("2022-06-02T12:22:21+02:00"), testNote)
diff --git a/internal/federation/federatingdb/accept.go b/internal/federation/federatingdb/accept.go
index 2e4948a0e..d7606c4fa 100644
--- a/internal/federation/federatingdb/accept.go
+++ b/internal/federation/federatingdb/accept.go
@@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"net/url"
+ "time"
"code.superseriousbusiness.org/activity/streams/vocab"
"code.superseriousbusiness.org/gotosocial/internal/ap"
@@ -39,7 +40,7 @@ func (f *DB) GetAccept(
ctx context.Context,
acceptIRI *url.URL,
) (vocab.ActivityStreamsAccept, error) {
- approval, err := f.state.DB.GetInteractionRequestByURI(ctx, acceptIRI.String())
+ approval, err := f.state.DB.GetInteractionRequestByResponseURI(ctx, acceptIRI.String())
if err != nil {
return nil, err
}
@@ -63,9 +64,9 @@ func (f *DB) Accept(ctx context.Context, accept vocab.ActivityStreamsAccept) err
return nil
}
+ // Ensure an activity ID is given.
acceptID := ap.GetJSONLDId(accept)
if acceptID == nil {
- // We need an ID.
const text = "Accept had no id property"
return gtserror.NewErrorBadRequest(errors.New(text), text)
}
@@ -109,7 +110,7 @@ func (f *DB) Accept(ctx context.Context, accept vocab.ActivityStreamsAccept) err
case name == ap.ActivityLike:
objIRI := ap.GetJSONLDId(asType)
if objIRI == nil {
- log.Debugf(ctx, "could not retrieve id of inlined Accept object %s", name)
+ log.Warnf(ctx, "missing id for inlined object %s: %s", name, acceptID)
continue
}
@@ -131,7 +132,7 @@ func (f *DB) Accept(ctx context.Context, accept vocab.ActivityStreamsAccept) err
case name == ap.ActivityAnnounce || ap.IsStatusable(name):
objIRI := ap.GetJSONLDId(asType)
if objIRI == nil {
- log.Debugf(ctx, "could not retrieve id of inlined Accept object %s", name)
+ log.Warnf(ctx, "missing id for inlined object %s: %s", name, acceptID)
continue
}
@@ -146,9 +147,38 @@ func (f *DB) Accept(ctx context.Context, accept vocab.ActivityStreamsAccept) err
return err
}
+ // Todo: ACCEPT POLITE INLINED LIKE REQUEST.
+ //
+ // Implement this when we start
+ // sending out polite LikeRequests.
+
+ // ACCEPT POLITE INLINED REPLY REQUEST
+ case name == ap.ActivityReplyRequest:
+ replyReq, ok := asType.(vocab.GoToSocialReplyRequest)
+ if !ok {
+ const text = "malformed ReplyRequest as object of Accept"
+ return gtserror.NewErrorBadRequest(errors.New(text), text)
+ }
+
+ if err := f.acceptPoliteReplyRequest(
+ ctx,
+ acceptID,
+ accept,
+ replyReq,
+ receivingAcct,
+ requestingAcct,
+ ); err != nil {
+ return err
+ }
+
+ // Todo: ACCEPT POLITE INLINED ANNOUNCE REQUEST
+ //
+ // Implement this when we start
+ // sending out polite AnnounceRequests.
+
// UNHANDLED
default:
- log.Debugf(ctx, "unhandled object type: %s", name)
+ log.Debugf(ctx, "unhandled object type %s: %s", name, acceptID)
}
} else if object.IsIRI() {
@@ -445,8 +475,7 @@ func (f *DB) acceptStoredStatus(
// Mark the status as approved by this URI.
status.PendingApproval = util.Ptr(false)
status.ApprovedByURI = approvedByURI.String()
- if err := f.state.DB.UpdateStatus(
- ctx,
+ if err := f.state.DB.UpdateStatus(ctx,
status,
"pending_approval",
"approved_by_uri",
@@ -543,8 +572,7 @@ func (f *DB) acceptLikeIRI(
// Mark the fave as approved by this URI.
fave.PendingApproval = util.Ptr(false)
fave.ApprovedByURI = approvedByURI.String()
- if err := f.state.DB.UpdateStatusFave(
- ctx,
+ if err := f.state.DB.UpdateStatusFave(ctx,
fave,
"pending_approval",
"approved_by_uri",
@@ -566,6 +594,316 @@ func (f *DB) acceptLikeIRI(
return nil
}
+// partialAcceptInteractionRequest represents a
+// partially-parsed accept of an interaction request
+// returned from parseAcceptInteractionRequestable.
+type partialAcceptInteractionRequest struct {
+ intReqURI *url.URL
+ actorURI *url.URL
+ parentURI *url.URL
+ instrumentURI *url.URL
+ authURI *url.URL
+ intReq *gtsmodel.InteractionRequest // May be nil.
+}
+
+// parseAcceptInteractionRequestable does some initial parsing
+// and validation of the given Accept with inlined polite
+// interaction request (LikeRequest, ReplyRequest, AnnounceRequest).
+//
+// Will return nil, nil if there's no need for further processing.
+func (f *DB) parseAcceptInteractionRequestable(
+ ctx context.Context,
+ accept vocab.ActivityStreamsAccept,
+ intRequestable ap.InteractionRequestable,
+ receivingAcct *gtsmodel.Account,
+ requestingAcct *gtsmodel.Account,
+) (*partialAcceptInteractionRequest, error) {
+ intReqURI := ap.GetJSONLDId(intRequestable)
+ if intReqURI == nil {
+ const text = "no id set on embedded interaction request"
+ return nil, gtserror.NewErrorBadRequest(errors.New(text), text)
+ }
+
+ // Ensure we have actor IRI on
+ // the interaction requestable.
+ actors := ap.GetActorIRIs(intRequestable)
+ if len(actors) != 1 {
+ const text = "invalid or missing actor property on embedded interaction request"
+ return nil, gtserror.NewErrorBadRequest(errors.New(text), text)
+ }
+ actorURI := actors[0]
+
+ // Ensure we have an object URI, which
+ // should point to the statusable being
+ // interacted with, ie., the parent status.
+ objects := ap.GetObjectIRIs(intRequestable)
+ if len(objects) != 1 {
+ const text = "invalid or missing object property on embedded interaction request"
+ return nil, gtserror.NewErrorBadRequest(errors.New(text), text)
+ }
+ parentURI := objects[0]
+
+ // Ensure we have instrument, which should
+ // be or point to the activity/object that
+ // interacts with the parent status.
+ instruments := ap.ExtractInstruments(intRequestable)
+ if len(instruments) != 1 {
+ const text = "invalid or missing instrument property on embedded interaction request"
+ return nil, gtserror.NewErrorBadRequest(errors.New(text), text)
+ }
+ instrument := instruments[0]
+
+ // We just need the URI for the instrument,
+ // not the whole type, which we can either
+ // fetch from remote or get locally.
+ var instrumentURI *url.URL
+ if instrument.IsIRI() {
+ instrumentURI = instrument.GetIRI()
+ } else {
+ t := instrument.GetType()
+ if t == nil {
+ const text = "nil instrument type on embedded interaction request"
+ return nil, gtserror.NewErrorBadRequest(errors.New(text), text)
+ }
+ instrumentURI = ap.GetJSONLDId(t)
+ }
+
+ // Ensure we have result URI, which should
+ // point to an authorization for this interaction.
+ results := ap.GetResultIRIs(accept)
+ if len(results) != 1 {
+ const text = "invalid or missing result property on embedded interaction request"
+ return nil, gtserror.NewErrorBadRequest(errors.New(text), text)
+ }
+ authURI := results[0]
+
+ // Check if we have a gtsmodel interaction
+ // request already stored for this interaction.
+ intReq, err := f.state.DB.GetInteractionRequestByInteractionURI(ctx, instrumentURI.String())
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ // Real db error.
+ return nil, gtserror.Newf("db error getting interaction request: %w", err)
+ }
+
+ if intReq == nil {
+
+ // No request stored for this interaction.
+ // Means this is *probably* a remote interaction
+ // with a remote status. Double check this.
+ host := config.GetHost()
+ acctDomain := config.GetAccountDomain()
+ if instrumentURI.Host == host ||
+ instrumentURI.Host == acctDomain ||
+ intReqURI.Host == host ||
+ intReqURI.Host == acctDomain {
+ // Claims to be Accepting something of ours,
+ // but we don't have an interaction request
+ // stored. Most likely it's been deleted in
+ // the meantime, or this is a mistake. Bail.
+ return nil, nil
+ }
+
+ // This must be an Accept of a remote interaction
+ // request. Ensure relevance of this message by
+ // checking that receiver follows requester.
+ following, err := f.state.DB.IsFollowing(
+ ctx,
+ receivingAcct.ID,
+ requestingAcct.ID,
+ )
+ if err != nil {
+ err := gtserror.Newf("db error checking following: %w", err)
+ return nil, gtserror.NewErrorInternalError(err)
+ }
+
+ if !following {
+ // If we don't follow this person, and
+ // they're not Accepting something we
+ // created, then we don't care.
+ return nil, nil
+ }
+
+ } else {
+
+ // Request stored for this interaction URI.
+ //
+ // Note: this path is not actually possible until v0.21.0,
+ // because we don't send out polite requests yet in v0.20.0.
+
+ // If the request is already accepted,
+ // we don't need to do anything at all.
+ if intReq.IsAccepted() {
+ return nil, nil
+ }
+
+ // The person doing the Accept must be the
+ // same as the target of the interaction request.
+ if intReq.TargetAccountID != requestingAcct.ID {
+ const text = "cannot Accept interaction request on another actor's behalf"
+ return nil, gtserror.NewErrorForbidden(errors.New(text), text)
+ }
+
+ // The stored interaction request and the inlined
+ // interaction request must have the same target status.
+ if intReq.TargetStatus.URI != parentURI.String() {
+ const text = "Accept interaction request mismatched object URI"
+ return nil, gtserror.NewErrorForbidden(errors.New(text), text)
+ }
+
+ // The stored interaction request and the inlined
+ // interaction request must have the same URI.
+ if intReq.InteractionRequestURI != intReqURI.String() {
+ const text = "Accept interaction request mismatched id"
+ return nil, gtserror.NewErrorForbidden(errors.New(text), text)
+ }
+ }
+
+ // Return the things.
+ return &partialAcceptInteractionRequest{
+ intReqURI: intReqURI,
+ actorURI: actorURI,
+ parentURI: parentURI,
+ instrumentURI: instrumentURI,
+ authURI: authURI,
+ intReq: intReq, // May be nil.
+ }, nil
+}
+
+// acceptPoliteReplyRequest handles the Accept of a polite ReplyRequest,
+// ie., something that looks like this:
+//
+// {
+// "@context": [
+// "https://www.w3.org/ns/activitystreams",
+// "https://gotosocial.org/ns"
+// ],
+// "type": "Accept",
+// "to": "https://example.com/users/bob",
+// "id": "https://example.com/users/alice/activities/1234",
+// "actor": "https://example.com/users/alice",
+// "object": {
+// "type": "ReplyRequest",
+// "id": "https://example.com/users/bob/interaction_requests/12345",
+// "actor": "https://example.com/users/bob",
+// "object": "https://example.com/users/alice/statuses/1",
+// "instrument": "https://example.org/users/bob/statuses/12345"
+// },
+// "result": "https://example.com/users/alice/authorizations/1"
+// }
+func (f *DB) acceptPoliteReplyRequest(
+ ctx context.Context,
+ acceptID *url.URL,
+ accept vocab.ActivityStreamsAccept,
+ replyRequest vocab.GoToSocialReplyRequest,
+ receivingAcct *gtsmodel.Account,
+ requestingAcct *gtsmodel.Account,
+) error {
+ // Parse out the Accept and
+ // embedded interaction requestable.
+ partial, err := f.parseAcceptInteractionRequestable(
+ ctx,
+ accept,
+ replyRequest,
+ receivingAcct,
+ requestingAcct,
+ )
+ if err != nil {
+ return err
+ }
+
+ if partial == nil {
+ // Nothing to do!
+ return nil
+ }
+
+ if partial.intReq == nil {
+ // This is a remote accept of a remote reply.
+ //
+ // Process dereferencing etc asynchronously, leaving
+ // the interaction request as nil. We don't need to
+ // create an int req for remote accepts of remote
+ // replies, we can just validate + store the auth URI.
+ f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
+ APObjectType: ap.ActivityReplyRequest,
+ APActivityType: ap.ActivityAccept,
+ APIRI: partial.authURI,
+ APObject: partial.instrumentURI,
+ Receiving: receivingAcct,
+ Requesting: requestingAcct,
+ })
+
+ return nil
+ }
+
+ // We already have a request stored for this interaction.
+ //
+ // Note: this path is not actually possible until v0.21.0,
+ // because we don't send out polite requests yet in v0.20.0.
+
+ // Make sure the stored interaction request
+ // lines up with the Accept ReplyRequest.
+ if partial.intReq.InteractionType != gtsmodel.InteractionReply {
+ const text = "Accept ReplyRequest targets interaction request that isn't of type Reply"
+ return gtserror.NewErrorBadRequest(errors.New(text), text)
+ }
+
+ // The stored reply must be the same as
+ // the instrument of the ReplyRequest.
+ reply := partial.intReq.Reply
+ if reply.URI != partial.instrumentURI.String() {
+ const text = "Accept ReplyRequest mismatched instrument URI"
+ return gtserror.NewErrorForbidden(errors.New(text), text)
+ }
+
+ // The actor of the stored reply must be the
+ // same as the actor of the ReplyRequest.
+ if reply.AccountURI != partial.actorURI.String() {
+ const text = "Accept ReplyRequest mismatched actor URI"
+ return gtserror.NewErrorForbidden(errors.New(text), text)
+ }
+
+ // This all looks good, we can update the
+ // interaction request and stored reply.
+ unlock := f.state.FedLocks.Lock(partial.intReq.InteractionURI)
+ defer unlock()
+
+ authURIStr := partial.authURI.String()
+ partial.intReq.AcceptedAt = time.Now()
+ partial.intReq.AuthorizationURI = authURIStr
+ partial.intReq.ResponseURI = acceptID.String()
+ if err := f.state.DB.UpdateInteractionRequest(
+ ctx, partial.intReq,
+ "accepted_at",
+ "authorization_uri",
+ "response_uri",
+ ); err != nil {
+ return gtserror.Newf("db error updating interaction request: %w", err)
+ }
+
+ reply.ApprovedByURI = authURIStr
+ reply.PendingApproval = util.Ptr(false)
+ if err := f.state.DB.UpdateStatus(
+ ctx, reply,
+ "approved_by_uri",
+ "pending_approval",
+ ); err != nil {
+ return gtserror.Newf("db error updating status: %w", err)
+ }
+
+ // Handle any remaining side effects in the processor.
+ f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
+ APObjectType: ap.ActivityReplyRequest,
+ APActivityType: ap.ActivityAccept,
+ APIRI: partial.authURI,
+ APObject: partial.instrumentURI,
+ GTSModel: partial.intReq,
+ Receiving: receivingAcct,
+ Requesting: requestingAcct,
+ })
+
+ return nil
+}
+
// approvedByURI extracts the appropriate *url.URL
// to use as an interaction's approvedBy value by
// checking to see if the Accept has a result URL set.
@@ -577,11 +915,8 @@ func (f *DB) acceptLikeIRI(
// Error is only returned if the result URI is set
// but the host differs from the Accept ID host.
//
-// TODO: This function should be updated at some point
-// to check for inlined result type, and see if type is
-// a LikeApproval, ReplyApproval, or AnnounceApproval,
-// and check the attributedTo, object, and target of
-// the approval as well. But this'll do for now.
+// TODO: This function could be updated at some
+// point to check for inlined result type.
func approvedByURI(
acceptID *url.URL,
accept vocab.ActivityStreamsAccept,
@@ -623,11 +958,7 @@ func approvedByURI(
if resultIRI.Host != acceptID.Host {
// What the boobs is this?
- err := fmt.Errorf(
- "host of result %s differed from host of Accept %s",
- resultIRI, accept,
- )
- return nil, err
+ return nil, fmt.Errorf("host of result %s differed from host of Accept %s", resultIRI, accept)
}
// Use the result IRI we've been
diff --git a/internal/federation/federatingdb/accept_test.go b/internal/federation/federatingdb/accept_test.go
new file mode 100644
index 000000000..2651c6a5f
--- /dev/null
+++ b/internal/federation/federatingdb/accept_test.go
@@ -0,0 +1,120 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package federatingdb_test
+
+import (
+ "bytes"
+ "io"
+ "testing"
+
+ "code.superseriousbusiness.org/activity/streams/vocab"
+ "code.superseriousbusiness.org/gotosocial/internal/ap"
+ "code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
+ "code.superseriousbusiness.org/gotosocial/internal/messages"
+ "code.superseriousbusiness.org/gotosocial/testrig"
+ "github.com/stretchr/testify/suite"
+)
+
+const (
+ rMediaPath = "../../../testrig/media"
+ rTemplatePath = "../../../web/template"
+)
+
+type AcceptTestSuite struct {
+ FederatingDBTestSuite
+}
+
+func (suite *AcceptTestSuite) TestAcceptRemoteReplyRequest() {
+ // Accept of a reply by
+ // brand_new_person to foss_satan.
+ const acceptJSON = `{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://gotosocial.org/ns"
+ ],
+ "type": "Accept",
+ "to": "https://unknown-instance.com/users/brand_new_person",
+ "cc": "https://www.w3.org/ns/activitystreams#Public",
+ "id": "http://fossbros-anonymous.io/users/foss_satan/accepts/1234",
+ "actor": "http://fossbros-anonymous.io/users/foss_satan",
+ "object": {
+ "type": "ReplyRequest",
+ "id": "https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7/replyRequest",
+ "actor": "https://unknown-instance.com/users/brand_new_person",
+ "object": "http://fossbros-anonymous.io/users/foss_satan/statuses/01FVW7JHQFSFK166WWKR8CBA6M",
+ "instrument": "https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7"
+ },
+ "result": "http://fossbros-anonymous.io/users/foss_satan/authorizations/1234"
+}`
+
+ // The accept will be delivered by foss_satan to zork.
+ ctx := createTestContext(
+ suite.T(),
+ suite.testAccounts["local_account_1"],
+ suite.testAccounts["remote_account_1"],
+ )
+
+ // Have zork follow foss_satan for this test,
+ // else the message will be scattered unto the four winds.
+ follow := &gtsmodel.Follow{
+ ID: "01K4STEH5NWAXBZ4TFNGQQQ984",
+ CreatedAt: testrig.TimeMustParse("2022-05-14T13:21:09+02:00"),
+ UpdatedAt: testrig.TimeMustParse("2022-05-14T13:21:09+02:00"),
+ AccountID: "01F8MH1H7YV1Z7D2C8K2730QBF",
+ TargetAccountID: "01F8MH5ZK5VRH73AKHQM6Y9VNX",
+ URI: "http://localhost:8080/users/the_mighty_zork/follow/01G1TK3PQKFW1BQZ9WVYRTFECK",
+ }
+ if err := suite.state.DB.PutFollow(ctx, follow); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // Parse accept into vocab.Type.
+ t, err := ap.DecodeType(ctx, io.NopCloser(bytes.NewBufferString(acceptJSON)))
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+ accept := t.(vocab.ActivityStreamsAccept)
+
+ // Process the accept.
+ if err := suite.federatingDB.Accept(ctx, accept); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // There should be an accept msg
+ // heading to the processor now.
+ msg, ok := suite.state.Workers.Federator.Queue.PopCtx(ctx)
+ if !ok {
+ suite.FailNow("no message in queue")
+ }
+
+ suite.EqualValues(
+ &messages.FromFediAPI{
+ APObjectType: "ReplyRequest",
+ APActivityType: "Accept",
+ APIRI: testrig.URLMustParse("http://fossbros-anonymous.io/users/foss_satan/authorizations/1234"),
+ APObject: testrig.URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7"),
+ Requesting: suite.testAccounts["remote_account_1"],
+ Receiving: suite.testAccounts["local_account_1"],
+ },
+ msg,
+ )
+}
+
+func TestAcceptTestSuite(t *testing.T) {
+ suite.Run(t, new(AcceptTestSuite))
+}
diff --git a/internal/federation/federatingdb/block.go b/internal/federation/federatingdb/block.go
index 2950aef3b..e44081a56 100644
--- a/internal/federation/federatingdb/block.go
+++ b/internal/federation/federatingdb/block.go
@@ -41,7 +41,7 @@ func (f *DB) Block(ctx context.Context, blockable vocab.ActivityStreamsBlock) er
requesting := activityContext.requestingAcct
receiving := activityContext.receivingAcct
- if receiving.IsMoving() {
+ if requesting.IsMoving() {
// A Moving account
// can't do this.
return nil
diff --git a/internal/federation/federatingdb/create.go b/internal/federation/federatingdb/create.go
index 8de137d6c..d3ce2bfa5 100644
--- a/internal/federation/federatingdb/create.go
+++ b/internal/federation/federatingdb/create.go
@@ -281,43 +281,18 @@ func (f *DB) createStatusable(
statusable ap.Statusable,
forwarded bool,
) error {
- // Check whether this status is both
- // relevant, and doesn't look like spam.
- err := f.spamFilter.StatusableOK(ctx,
- receiver,
- requester,
- statusable,
- )
-
- switch {
- case err == nil:
- // No problem!
-
- case gtserror.IsNotRelevant(err):
- // This case is quite common if a remote (Mastodon)
- // instance forwards a message to us which is a reply
- // from someone else to a status we've also replied to.
- //
- // It does this to try to ensure thread completion, but
- // we have our own thread fetching mechanism anyway.
- log.Debugf(ctx, "status %s is not relevant to receiver (%v); dropping it",
- ap.GetJSONLDId(statusable), err,
- )
- return nil
+ // Check for spam / relevance.
+ ok, err := f.statusableOK(ctx, receiver, requester, statusable)
+ if err != nil {
+ // Error already
+ // wrapped.
+ return err
+ }
- case gtserror.IsSpam(err):
- // Log this at a higher level so admins can
- // gauge how much spam is being sent to them.
- //
- // TODO: add Prometheus metrics for this.
- log.Infof(ctx, "status %s looked like spam (%v); dropping it",
- ap.GetJSONLDId(statusable), err,
- )
+ if !ok {
+ // Not relevant / spam.
+ // Already logged.
return nil
-
- default:
- // A real error has occurred.
- return gtserror.Newf("error checking relevancy/spam: %w", err)
}
// If we do have a forward, we should ignore the content
diff --git a/internal/federation/federatingdb/interactionrequest.go b/internal/federation/federatingdb/interactionrequest.go
new file mode 100644
index 000000000..0026337d0
--- /dev/null
+++ b/internal/federation/federatingdb/interactionrequest.go
@@ -0,0 +1,572 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package federatingdb
+
+import (
+ "context"
+ "errors"
+ "net/http"
+
+ "code.superseriousbusiness.org/activity/streams/vocab"
+ "code.superseriousbusiness.org/gotosocial/internal/ap"
+ "code.superseriousbusiness.org/gotosocial/internal/db"
+ "code.superseriousbusiness.org/gotosocial/internal/gtserror"
+ "code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
+ "code.superseriousbusiness.org/gotosocial/internal/id"
+ "code.superseriousbusiness.org/gotosocial/internal/log"
+ "code.superseriousbusiness.org/gotosocial/internal/messages"
+ "code.superseriousbusiness.org/gotosocial/internal/util"
+)
+
+/*
+ The code in this file handles the three types of "polite"
+ interaction requests currently recognized by GoToSocial:
+ LikeRequest, ReplyRequest, and AnnounceRequest.
+
+ A request looks a bit like this, note the requested
+ interaction itself is nested in the "instrument" property:
+
+ {
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://gotosocial.org/ns"
+ ],
+ "type": "LikeRequest",
+ "id": "https://example.com/users/bob/interaction_requests/likes/12345",
+ "actor": "https://example.com/users/bob",
+ "object": "https://example.com/users/alice/statuses/1",
+ "to": "https://example.com/users/alice",
+ "instrument": {
+ "type": "Like",
+ "id": "https://example.com/users/bob/likes/12345",
+ "object": "https://example.com/users/alice/statuses/1",
+ "attributedTo": "https://example.com/users/bob",
+ "to": [
+ "https://www.w3.org/ns/activitystreams#Public",
+ "https://example.com/users/alice"
+ ]
+ }
+ }
+
+ Because each of the interaction types are a bit different,
+ they're unfortunately also parsed and stored differently:
+ LikeRequests have the Like checked first, here, against
+ the interaction policy of the target status, whereas
+ AnnounceRequests and ReplyRequests have the interaction
+ checked against the interaction policy of the target
+ status asynchronously, in the FromFediAPI processor.
+
+ It may be possible to dick about with the logic a bit and
+ shuffle the checks all here, or all in the processor, but
+ that's a job for future refactoring by future tobi/kimbe.
+*/
+
+// partialInteractionRequest represents a
+// partially-parsed interaction request
+// returned from the util function parseInteractionReq.
+type partialInteractionRequest struct {
+ intRequestURI string
+ requesting *gtsmodel.Account
+ receiving *gtsmodel.Account
+ object *gtsmodel.Status
+ instrument vocab.Type
+}
+
+// parseIntReq does some first-pass parsing
+// of the given InteractionRequestable (LikeRequest,
+// ReplyRequest, AnnounceRequest), checking stuff like:
+//
+// - interaction request has a single object
+// - interaction request object is a status
+// - object status belongs to receiving account
+// - interaction request has a single instrument
+//
+// It returns a partialInteractionRequest struct,
+// or an error if something goes wrong.
+func (f *DB) parseInteractionRequest(ctx context.Context, intRequest ap.InteractionRequestable) (*partialInteractionRequest, error) {
+
+ // Get and stringify the ID/URI of interaction request once,
+ // and mark this particular activity as handled in ID cache.
+ intRequestURI := ap.GetJSONLDId(intRequest).String()
+ f.activityIDs.Set(intRequestURI, struct{}{})
+
+ // Extract relevant values from passed ctx.
+ activityContext := getActivityContext(ctx)
+ if activityContext.internal {
+ // Already processed.
+ return nil, nil
+ }
+
+ requesting := activityContext.requestingAcct
+ receiving := activityContext.receivingAcct
+
+ if requesting.IsMoving() {
+ // A Moving account
+ // can't do this.
+ return nil, nil
+ }
+
+ if receiving.IsMoving() {
+ // Moving accounts can't
+ // do anything with interaction
+ // requests, so ignore it.
+ return nil, nil
+ }
+
+ // Make sure we have a single
+ // object of the interaction request.
+ objectIRIs := ap.GetObjectIRIs(intRequest)
+ if l := len(objectIRIs); l != 1 {
+ return nil, gtserror.NewfWithCode(
+ http.StatusBadRequest,
+ "invalid object len %d, wanted 1", l,
+ )
+ }
+
+ // Extract the status URI str.
+ statusIRI := objectIRIs[0]
+ statusIRIStr := statusIRI.String()
+
+ // Fetch status by given URI from the database.
+ status, err := f.state.DB.GetStatusByURI(ctx, statusIRIStr)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ return nil, gtserror.Newf("db error getting object status %s: %w", statusIRIStr, err)
+ }
+
+ // Ensure received by correct account.
+ if status.AccountID != receiving.ID {
+ return nil, gtserror.NewfWithCode(
+ http.StatusForbidden,
+ "receiver %s is not owner of interaction-requested status",
+ receiving.URI,
+ )
+ }
+
+ // Ensure we have the expected one instrument.
+ instruments := ap.ExtractInstruments(intRequest)
+ if l := len(instruments); l != 1 {
+ return nil, gtserror.NewfWithCode(
+ http.StatusBadRequest,
+ "invalid instrument len %d, wanted 1", l,
+ )
+ }
+
+ // Instrument should be a
+ // type and not just an IRI.
+ instrument := instruments[0].GetType()
+ if instrument == nil {
+ return nil, gtserror.NewWithCode(
+ http.StatusBadRequest,
+ "instrument was not vocab.Type",
+ )
+ }
+
+ // Check the instrument is an approveable type.
+ approvable, ok := instrument.(ap.WithApprovedBy)
+ if !ok {
+ return nil, gtserror.NewWithCode(
+ http.StatusBadRequest,
+ "instrument was not Approvable",
+ )
+ }
+
+ // Ensure that `approvedBy` isn't already set.
+ if u := ap.GetApprovedBy(approvable); u != nil {
+ return nil, gtserror.NewfWithCode(
+ http.StatusBadRequest,
+ "instrument claims to already be approvedBy %s",
+ u.String(),
+ )
+ }
+
+ return &partialInteractionRequest{
+ intRequestURI: intRequestURI,
+ requesting: requesting,
+ receiving: receiving,
+ object: status,
+ instrument: instrument,
+ }, nil
+}
+
+func (f *DB) LikeRequest(ctx context.Context, likeReq vocab.GoToSocialLikeRequest) error {
+ log.DebugKV(ctx, "LikeRequest", serialize{likeReq})
+
+ // Parse out base level interaction request information.
+ partial, err := f.parseInteractionRequest(ctx, likeReq)
+ if err != nil {
+ return err
+ }
+
+ // Ensure the instrument vocab.Type is Likeable.
+ likeable, ok := ap.ToLikeable(partial.instrument)
+ if !ok {
+ return gtserror.NewWithCode(
+ http.StatusBadRequest,
+ "could not parse instrument to Likeable",
+ )
+ }
+
+ // Convert received AS like type to internal fave model.
+ fave, err := f.converter.ASLikeToFave(ctx, likeable)
+ if err != nil {
+ err := gtserror.Newf("error converting from AS type: %w", err)
+ return gtserror.WrapWithCode(http.StatusBadRequest, err)
+ }
+
+ // Ensure fave enacted by correct account.
+ if fave.AccountID != partial.requesting.ID {
+ return gtserror.NewfWithCode(
+ http.StatusForbidden,
+ "requester %s is not expected actor %s",
+ partial.requesting.URI, fave.Account.URI,
+ )
+ }
+
+ // Ensure fave received by correct account.
+ if fave.TargetAccountID != partial.receiving.ID {
+ return gtserror.NewfWithCode(
+ http.StatusForbidden,
+ "receiver %s is not expected %s",
+ partial.receiving.URI, fave.TargetAccount.URI,
+ )
+ }
+
+ // Ensure this is a valid Like target for requester.
+ policyResult, err := f.intFilter.StatusLikeable(ctx,
+ partial.requesting,
+ fave.Status,
+ )
+ if err != nil {
+ return gtserror.Newf(
+ "error seeing if status %s is likeable: %w",
+ fave.Status.URI, err,
+ )
+ } else if policyResult.Forbidden() {
+ return gtserror.NewWithCode(
+ http.StatusForbidden,
+ "requester does not have permission to Like status",
+ )
+ }
+
+ // Policy result is either automatic or manual
+ // approval, so store the interaction request.
+ intReq := &gtsmodel.InteractionRequest{
+ ID: id.NewULID(),
+ TargetStatusID: fave.StatusID,
+ TargetStatus: fave.Status,
+ TargetAccountID: fave.TargetAccountID,
+ TargetAccount: fave.TargetAccount,
+ InteractingAccountID: fave.AccountID,
+ InteractingAccount: fave.Account,
+ InteractionRequestURI: partial.intRequestURI,
+ InteractionURI: fave.URI,
+ InteractionType: gtsmodel.InteractionLike,
+ Polite: util.Ptr(true),
+ Like: fave,
+ }
+ switch err := f.state.DB.PutInteractionRequest(ctx, intReq); {
+ case err == nil:
+ // No problem.
+
+ case errors.Is(err, db.ErrAlreadyExists):
+ // Already processed this, race condition? Just warn + return.
+ log.Warnf(ctx, "received duplicate interaction request: %s", partial.intRequestURI)
+ return nil
+
+ default:
+ // Proper DB error.
+ return gtserror.Newf(
+ "db error storing interaction request %s",
+ partial.intRequestURI,
+ )
+ }
+
+ // Int req is now stored.
+ //
+ // Set some fields on the
+ // pending fave and store it.
+ fave.ID = id.NewULID()
+ fave.PendingApproval = util.Ptr(true)
+ fave.PreApproved = policyResult.AutomaticApproval()
+ if err := f.state.DB.PutStatusFave(ctx, fave); err != nil {
+ if errors.Is(err, db.ErrAlreadyExists) {
+ // The fave already exists in the
+ // database, which means we've already
+ // handled side effects. We can just
+ // return nil here and be done with it.
+ return nil
+ }
+
+ return gtserror.Newf("error inserting %s into db: %w", fave.URI, err)
+ }
+
+ // Further processing will be carried out
+ // asynchronously, and our caller will return 202 Accepted.
+ f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
+ APActivityType: ap.ActivityCreate,
+ APObjectType: ap.ActivityLikeRequest,
+ GTSModel: intReq,
+ Receiving: partial.receiving,
+ Requesting: partial.requesting,
+ })
+
+ return nil
+}
+
+func (f *DB) ReplyRequest(ctx context.Context, replyReq vocab.GoToSocialReplyRequest) error {
+ log.DebugKV(ctx, "ReplyRequest", serialize{replyReq})
+
+ // Parse out base level interaction request information.
+ partial, err := f.parseInteractionRequest(ctx, replyReq)
+ if err != nil {
+ return err
+ }
+
+ // Ensure the instrument vocab.Type is Statusable.
+ statusable, ok := ap.ToStatusable(partial.instrument)
+ if !ok {
+ return gtserror.NewWithCode(
+ http.StatusBadRequest,
+ "could not parse instrument to Statusable",
+ )
+ }
+
+ // Check for spam / relevance.
+ ok, err = f.statusableOK(
+ ctx,
+ partial.receiving,
+ partial.requesting,
+ statusable,
+ )
+ if err != nil {
+ // Error already
+ // wrapped.
+ return err
+ }
+
+ if !ok {
+ // Not relevant / spam.
+ // Already logged.
+ return nil
+ }
+
+ // Statusable must reply to something.
+ inReplyToURIs := ap.GetInReplyTo(statusable)
+ if l := len(inReplyToURIs); l != 1 {
+ return gtserror.NewfWithCode(
+ http.StatusBadRequest,
+ "expected inReplyTo length 1, got %d", l,
+ )
+ }
+ inReplyToURI := inReplyToURIs[0]
+ inReplyToURIStr := inReplyToURI.String()
+
+ // Make sure we have the status this interaction reply encompasses.
+ inReplyTo, err := f.state.DB.GetStatusByURI(ctx, inReplyToURIStr)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ return gtserror.Newf("db error getting inReplyTo status %s: %w", inReplyToURIStr, err)
+ }
+
+ // Check status exists.
+ if inReplyTo == nil {
+ log.Warnf(ctx, "received ReplyRequest for non-existent status: %s", inReplyToURIStr)
+ return nil
+ }
+
+ // Make sure the parent status is owned by receiver.
+ if inReplyTo.AccountURI != partial.receiving.URI {
+ return gtserror.NewfWithCode(
+ http.StatusBadRequest,
+ "inReplyTo status %s not owned by receiving account %s",
+ inReplyToURIStr, partial.receiving.URI,
+ )
+ }
+
+ // Extract the attributed to (i.e. author) URI of status.
+ attributedToURI, err := ap.ExtractAttributedToURI(statusable)
+ if err != nil {
+ err := gtserror.Newf("invalid status attributedTo value: %w", err)
+ return gtserror.WrapWithCode(http.StatusBadRequest, err)
+ }
+
+ // Ensure status author is account of requester.
+ attributedToURIStr := attributedToURI.String()
+ if attributedToURIStr != partial.requesting.URI {
+ return gtserror.NewfWithCode(
+ http.StatusBadRequest,
+ "status attributedTo %s not requesting account %s",
+ inReplyToURIStr, partial.requesting.URI,
+ )
+ }
+
+ // Create a pending interaction request in the database.
+ // This request will be handled further by the processor.
+ intReq := &gtsmodel.InteractionRequest{
+ ID: id.NewULID(),
+ TargetStatusID: inReplyTo.ID,
+ TargetStatus: inReplyTo,
+ TargetAccountID: inReplyTo.AccountID,
+ TargetAccount: inReplyTo.Account,
+ InteractingAccountID: partial.requesting.ID,
+ InteractingAccount: partial.requesting,
+ InteractionRequestURI: partial.intRequestURI,
+ InteractionURI: ap.GetJSONLDId(statusable).String(),
+ InteractionType: gtsmodel.InteractionReply,
+ Polite: util.Ptr(true),
+ Reply: nil, // Not settable yet.
+ }
+ switch err := f.state.DB.PutInteractionRequest(ctx, intReq); {
+ case err == nil:
+ // No problem.
+
+ case errors.Is(err, db.ErrAlreadyExists):
+ // Already processed this, race condition? Just warn + return.
+ log.Warnf(ctx, "received duplicate interaction request: %s", partial.intRequestURI)
+ return nil
+
+ default:
+ // Proper DB error.
+ return gtserror.Newf(
+ "db error storing interaction request %s",
+ partial.intRequestURI,
+ )
+ }
+
+ // Further processing will be carried out
+ // asynchronously, return 202 Accepted.
+ f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
+ APActivityType: ap.ActivityCreate,
+ APObjectType: ap.ActivityReplyRequest,
+ GTSModel: intReq,
+ APObject: statusable,
+ Receiving: partial.receiving,
+ Requesting: partial.requesting,
+ })
+
+ return nil
+}
+
+func (f *DB) AnnounceRequest(ctx context.Context, announceReq vocab.GoToSocialAnnounceRequest) error {
+ log.DebugKV(ctx, "AnnounceRequest", serialize{announceReq})
+
+ // Parse out base level interaction request information.
+ partial, err := f.parseInteractionRequest(ctx, announceReq)
+ if err != nil {
+ return err
+ }
+
+ // Ensure the instrument vocab.Type is Announceable.
+ announceable, ok := ap.ToAnnounceable(partial.instrument)
+ if !ok {
+ return gtserror.NewWithCode(
+ http.StatusBadRequest,
+ "could not parse instrument to Announceable",
+ )
+ }
+
+ // Convert received AS Announce type to internal boost wrapper model.
+ boost, new, err := f.converter.ASAnnounceToStatus(ctx, announceable)
+ if err != nil {
+ err := gtserror.Newf("error converting from AS type: %w", err)
+ return gtserror.WrapWithCode(http.StatusBadRequest, err)
+ }
+
+ if !new {
+ // We already have this announce, just return.
+ log.Warnf(ctx, "received AnnounceRequest for existing announce: %s", boost.URI)
+ return nil
+ }
+
+ // Fetch origin status that this boost is targetting from database.
+ targetStatus, err := f.state.DB.GetStatusByURI(ctx, boost.BoostOfURI)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ return gtserror.Newf(
+ "db error getting announce object %s: %w",
+ boost.BoostOfURI, err,
+ )
+ }
+
+ if targetStatus == nil {
+ // Status doesn't seem to exist, just drop this AnnounceRequest.
+ log.Warnf(ctx, "received AnnounceRequest for non-existent status %s", boost.BoostOfURI)
+ return nil
+ }
+
+ // Ensure target status is owned by receiving account.
+ if targetStatus.AccountID != partial.receiving.ID {
+ return gtserror.NewfWithCode(
+ http.StatusBadRequest,
+ "announce object %s not owned by receiving account %s",
+ boost.BoostOfURI, partial.receiving.URI,
+ )
+ }
+
+ // Ensure announce enacted by correct account.
+ if boost.AccountID != partial.requesting.ID {
+ return gtserror.NewfWithCode(
+ http.StatusForbidden,
+ "requester %s is not expected actor %s",
+ partial.requesting.URI, boost.Account.URI,
+ )
+ }
+
+ // Create a pending interaction request in the database.
+ // This request will be handled further by the processor.
+ intReq := &gtsmodel.InteractionRequest{
+ ID: id.NewULID(),
+ TargetStatusID: targetStatus.ID,
+ TargetStatus: targetStatus,
+ TargetAccountID: targetStatus.AccountID,
+ TargetAccount: targetStatus.Account,
+ InteractingAccountID: boost.AccountID,
+ InteractingAccount: boost.Account,
+ InteractionRequestURI: partial.intRequestURI,
+ InteractionURI: boost.URI,
+ InteractionType: gtsmodel.InteractionAnnounce,
+ Polite: util.Ptr(true),
+ Announce: boost,
+ }
+ switch err := f.state.DB.PutInteractionRequest(ctx, intReq); {
+ case err == nil:
+ // No problem.
+
+ case errors.Is(err, db.ErrAlreadyExists):
+ // Already processed this, race condition? Just warn + return.
+ log.Warnf(ctx, "received duplicate interaction request: %s", partial.intRequestURI)
+ return nil
+
+ default:
+ // Proper DB error.
+ return gtserror.Newf(
+ "db error storing interaction request %s",
+ partial.intRequestURI,
+ )
+ }
+
+ // Further processing will be carried out
+ // asynchronously, return 202 Accepted.
+ f.state.Workers.Federator.Queue.Push(&messages.FromFediAPI{
+ APActivityType: ap.ActivityCreate,
+ APObjectType: ap.ActivityAnnounceRequest,
+ GTSModel: intReq,
+ Receiving: partial.receiving,
+ Requesting: partial.requesting,
+ })
+
+ return nil
+}
diff --git a/internal/federation/federatingdb/interactionrequest_test.go b/internal/federation/federatingdb/interactionrequest_test.go
new file mode 100644
index 000000000..81c0848ed
--- /dev/null
+++ b/internal/federation/federatingdb/interactionrequest_test.go
@@ -0,0 +1,289 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package federatingdb_test
+
+import (
+ "context"
+ "encoding/json"
+ "testing"
+ "time"
+
+ "code.superseriousbusiness.org/activity/streams"
+ "code.superseriousbusiness.org/activity/streams/vocab"
+ "code.superseriousbusiness.org/gotosocial/internal/ap"
+ "code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
+ "code.superseriousbusiness.org/gotosocial/testrig"
+ "github.com/stretchr/testify/suite"
+)
+
+type InteractionRequestTestSuite struct {
+ FederatingDBTestSuite
+}
+
+func (suite *InteractionRequestTestSuite) intReq(
+ receiving *gtsmodel.Account,
+ requesting *gtsmodel.Account,
+ jsonStr string,
+ dbF func(ctx context.Context, req vocab.Type) error,
+) error {
+ ctx := createTestContext(suite.T(), receiving, requesting)
+
+ raw := make(map[string]interface{})
+ if err := json.Unmarshal([]byte(jsonStr), &raw); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ t, err := streams.ToType(ctx, raw)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ return dbF(ctx, t)
+}
+
+func (suite *InteractionRequestTestSuite) TestReplyRequest() {
+ var (
+ ctx = suite.T().Context()
+ receiving = suite.testAccounts["admin_account"]
+ requesting = suite.testAccounts["remote_account_1"]
+ testStatus = suite.testStatuses["admin_account_status_1"]
+ intReqURI = "http://fossbros-anonymous.io/requests/87fb1478-ac46-406a-8463-96ce05645219"
+ intURI = "http://fossbros-anonymous.io/users/foss_satan/statuses/87fb1478-ac46-406a-8463-96ce05645219"
+ jsonStr = `{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://gotosocial.org/ns"
+ ],
+ "type": "ReplyRequest",
+ "id": "` + intReqURI + `",
+ "actor": "` + requesting.URI + `",
+ "object": "` + testStatus.URI + `",
+ "to": "` + receiving.URI + `",
+ "instrument": {
+ "attributedTo": "` + requesting.URI + `",
+ "cc": "` + requesting.FollowersURI + `",
+ "content": "\u003cp\u003ethis is a reply!\u003c/p\u003e",
+ "id": "` + intURI + `",
+ "inReplyTo": "` + testStatus.URI + `",
+ "tag": {
+ "href": "` + receiving.URI + `",
+ "name": "@` + receiving.Username + `@localhost:8080",
+ "type": "Mention"
+ },
+ "to": "https://www.w3.org/ns/activitystreams#Public",
+ "type": "Note"
+ }
+}`
+ )
+
+ suite.T().Logf("testing reply request:\n\n%s", jsonStr)
+
+ // Call the federatingDB function.
+ err := suite.intReq(
+ receiving,
+ requesting,
+ jsonStr,
+ func(ctx context.Context, req vocab.Type) error {
+ replyReq := req.(vocab.GoToSocialReplyRequest)
+ return suite.federatingDB.ReplyRequest(ctx, replyReq)
+ },
+ )
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // There should be an interaction request in the DB now.
+ var intReq *gtsmodel.InteractionRequest
+ if !testrig.WaitFor(func() bool {
+ intReq, err = suite.state.DB.GetInteractionRequestByInteractionURI(ctx, intURI)
+ return err == nil && intReq != nil
+ }) {
+ suite.FailNow("timed out waiting for int req to appear in the db")
+ }
+ suite.Equal(testStatus.ID, intReq.TargetStatusID)
+ suite.Equal(receiving.ID, intReq.TargetAccountID)
+ suite.Equal(requesting.ID, intReq.InteractingAccountID)
+ suite.Equal(intReqURI, intReq.InteractionRequestURI)
+ suite.Equal(intURI, intReq.InteractionURI)
+ suite.Equal(gtsmodel.InteractionReply, intReq.InteractionType)
+
+ // Should be a message heading to the processor.
+ msg, _ := suite.getFederatorMsg(5 * time.Second)
+ suite.Equal(ap.ActivityCreate, msg.APActivityType)
+ suite.Equal(ap.ActivityReplyRequest, msg.APObjectType)
+ suite.NotNil(msg.GTSModel)
+ suite.NotNil(msg.APObject)
+ suite.NotNil(msg.Receiving)
+ suite.NotNil(msg.Requesting)
+}
+
+func (suite *InteractionRequestTestSuite) TestLikeRequest() {
+ var (
+ ctx = suite.T().Context()
+ receiving = suite.testAccounts["admin_account"]
+ requesting = suite.testAccounts["remote_account_1"]
+ testStatus = suite.testStatuses["admin_account_status_1"]
+ intReqURI = "http://fossbros-anonymous.io/requests/87fb1478-ac46-406a-8463-96ce05645219"
+ intURI = "http://fossbros-anonymous.io/users/foss_satan/statuses/87fb1478-ac46-406a-8463-96ce05645219"
+ jsonStr = `{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://gotosocial.org/ns"
+ ],
+ "type": "LikeRequest",
+ "id": "` + intReqURI + `",
+ "actor": "` + requesting.URI + `",
+ "object": "` + testStatus.URI + `",
+ "to": "` + receiving.URI + `",
+ "instrument": {
+ "id": "` + intURI + `",
+ "object": "` + testStatus.URI + `",
+ "actor": "` + requesting.URI + `",
+ "to": "` + receiving.URI + `",
+ "type": "Like"
+ }
+}`
+ )
+
+ suite.T().Logf("testing like request:\n\n%s", jsonStr)
+
+ // Call the federatingDB function.
+ err := suite.intReq(
+ receiving,
+ requesting,
+ jsonStr,
+ func(ctx context.Context, req vocab.Type) error {
+ likeReq := req.(vocab.GoToSocialLikeRequest)
+ return suite.federatingDB.LikeRequest(ctx, likeReq)
+ },
+ )
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // There should be an interaction request in the DB now.
+ var intReq *gtsmodel.InteractionRequest
+ if !testrig.WaitFor(func() bool {
+ intReq, err = suite.state.DB.GetInteractionRequestByInteractionURI(ctx, intURI)
+ return err == nil && intReq != nil
+ }) {
+ suite.FailNow("timed out waiting for int req to appear in the db")
+ }
+ suite.Equal(testStatus.ID, intReq.TargetStatusID)
+ suite.Equal(receiving.ID, intReq.TargetAccountID)
+ suite.Equal(requesting.ID, intReq.InteractingAccountID)
+ suite.Equal(intReqURI, intReq.InteractionRequestURI)
+ suite.Equal(intURI, intReq.InteractionURI)
+ suite.Equal(gtsmodel.InteractionLike, intReq.InteractionType)
+
+ // The like should be in the DB now (unapproved).
+ var statusFave *gtsmodel.StatusFave
+ if !testrig.WaitFor(func() bool {
+ statusFave, err = suite.state.DB.GetStatusFaveByURI(ctx, intURI)
+ return err == nil && intReq != nil
+ }) {
+ suite.FailNow("timed out waiting for fave to appear in the db")
+ }
+ suite.Equal(requesting.ID, statusFave.AccountID)
+ suite.Equal(receiving.ID, statusFave.TargetAccountID)
+ suite.Equal(testStatus.ID, statusFave.StatusID)
+ suite.Equal(intURI, statusFave.URI)
+ suite.True(*statusFave.PendingApproval)
+ suite.Empty(statusFave.ApprovedByURI)
+
+ // Should be a message heading to the processor.
+ msg, _ := suite.getFederatorMsg(5 * time.Second)
+ suite.Equal(ap.ActivityCreate, msg.APActivityType)
+ suite.Equal(ap.ActivityLikeRequest, msg.APObjectType)
+ suite.NotNil(msg.GTSModel)
+ suite.NotNil(msg.Receiving)
+ suite.NotNil(msg.Requesting)
+}
+
+func (suite *InteractionRequestTestSuite) TestAnnounceRequest() {
+ var (
+ ctx = suite.T().Context()
+ receiving = suite.testAccounts["admin_account"]
+ requesting = suite.testAccounts["remote_account_1"]
+ testStatus = suite.testStatuses["admin_account_status_1"]
+ intReqURI = "http://fossbros-anonymous.io/requests/87fb1478-ac46-406a-8463-96ce05645219"
+ intURI = "http://fossbros-anonymous.io/users/foss_satan/statuses/87fb1478-ac46-406a-8463-96ce05645219"
+ jsonStr = `{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://gotosocial.org/ns"
+ ],
+ "type": "AnnounceRequest",
+ "id": "` + intReqURI + `",
+ "actor": "` + requesting.URI + `",
+ "object": "` + testStatus.URI + `",
+ "to": "` + receiving.URI + `",
+ "instrument": {
+ "id": "` + intURI + `",
+ "object": "` + testStatus.URI + `",
+ "actor": "` + requesting.URI + `",
+ "to": "` + requesting.FollowersURI + `",
+ "cc": "` + receiving.URI + `",
+ "type": "Announce"
+ }
+}`
+ )
+
+ suite.T().Logf("testing announce request:\n\n%s", jsonStr)
+
+ // Call the federatingDB function.
+ err := suite.intReq(
+ receiving,
+ requesting,
+ jsonStr,
+ func(ctx context.Context, req vocab.Type) error {
+ announceReq := req.(vocab.GoToSocialAnnounceRequest)
+ return suite.federatingDB.AnnounceRequest(ctx, announceReq)
+ },
+ )
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // There should be an interaction request in the DB now.
+ var intReq *gtsmodel.InteractionRequest
+ if !testrig.WaitFor(func() bool {
+ intReq, err = suite.state.DB.GetInteractionRequestByInteractionURI(ctx, intURI)
+ return err == nil && intReq != nil
+ }) {
+ suite.FailNow("timed out waiting for int req to appear in the db")
+ }
+ suite.Equal(testStatus.ID, intReq.TargetStatusID)
+ suite.Equal(receiving.ID, intReq.TargetAccountID)
+ suite.Equal(requesting.ID, intReq.InteractingAccountID)
+ suite.Equal(intReqURI, intReq.InteractionRequestURI)
+ suite.Equal(intURI, intReq.InteractionURI)
+ suite.Equal(gtsmodel.InteractionAnnounce, intReq.InteractionType)
+
+ // Should be a message heading to the processor.
+ msg, _ := suite.getFederatorMsg(5 * time.Second)
+ suite.Equal(ap.ActivityCreate, msg.APActivityType)
+ suite.Equal(ap.ActivityAnnounceRequest, msg.APObjectType)
+ suite.NotNil(msg.GTSModel)
+ suite.NotNil(msg.Receiving)
+ suite.NotNil(msg.Requesting)
+}
+
+func TestInteractionRequestTestSuite(t *testing.T) {
+ suite.Run(t, &InteractionRequestTestSuite{})
+}
diff --git a/internal/federation/federatingdb/like.go b/internal/federation/federatingdb/like.go
index debc343cf..ca26c0692 100644
--- a/internal/federation/federatingdb/like.go
+++ b/internal/federation/federatingdb/like.go
@@ -46,7 +46,7 @@ func (f *DB) Like(ctx context.Context, likeable vocab.ActivityStreamsLike) error
requesting := activityContext.requestingAcct
receiving := activityContext.receivingAcct
- if receiving.IsMoving() {
+ if requesting.IsMoving() {
// A Moving account
// can't do this.
return nil
diff --git a/internal/federation/federatingdb/reject.go b/internal/federation/federatingdb/reject.go
index 5ec3b1a27..88e5ca975 100644
--- a/internal/federation/federatingdb/reject.go
+++ b/internal/federation/federatingdb/reject.go
@@ -31,6 +31,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/log"
"code.superseriousbusiness.org/gotosocial/internal/messages"
"code.superseriousbusiness.org/gotosocial/internal/uris"
+ "code.superseriousbusiness.org/gotosocial/internal/util"
)
func (f *DB) Reject(ctx context.Context, reject vocab.ActivityStreamsReject) error {
@@ -305,21 +306,24 @@ func (f *DB) rejectStatusIRI(
InteractingAccountID: receivingAcct.ID,
InteractingAccount: receivingAcct,
InteractionURI: status.URI,
- URI: activityID,
+ Polite: util.Ptr(false),
+ ResponseURI: activityID,
RejectedAt: time.Now(),
}
if apObjectType == ap.ObjectNote {
// Reply.
+ req.InteractionRequestURI = gtsmodel.ForwardCompatibleInteractionRequestURI(status.URI, gtsmodel.ReplyRequestSuffix)
req.InteractionType = gtsmodel.InteractionReply
- req.StatusID = status.InReplyToID
- req.Status = status.InReplyTo
+ req.TargetStatusID = status.InReplyToID
+ req.TargetStatus = status.InReplyTo
req.Reply = status
} else {
// Announce.
+ req.InteractionRequestURI = gtsmodel.ForwardCompatibleInteractionRequestURI(status.URI, gtsmodel.AnnounceRequestSuffix)
req.InteractionType = gtsmodel.InteractionAnnounce
- req.StatusID = status.BoostOfID
- req.Status = status.BoostOf
+ req.TargetStatusID = status.BoostOfID
+ req.TargetStatus = status.BoostOf
req.Announce = status
}
@@ -331,8 +335,8 @@ func (f *DB) rejectStatusIRI(
case req.IsRejected():
// Interaction has already been rejected. Just
// update to this Reject URI and then return early.
- req.URI = activityID
- if err := f.state.DB.UpdateInteractionRequest(ctx, req, "uri"); err != nil {
+ req.ResponseURI = activityID
+ if err := f.state.DB.UpdateInteractionRequest(ctx, req, "response_uri"); err != nil {
err := gtserror.Newf("db error updating interaction request: %w", err)
return gtserror.NewErrorInternalError(err)
}
@@ -343,11 +347,11 @@ func (f *DB) rejectStatusIRI(
// Rejected, even if previously Accepted.
req.AcceptedAt = time.Time{}
req.RejectedAt = time.Now()
- req.URI = activityID
+ req.ResponseURI = activityID
if err := f.state.DB.UpdateInteractionRequest(ctx, req,
"accepted_at",
"rejected_at",
- "uri",
+ "response_uri",
); err != nil {
err := gtserror.Newf("db error updating interaction request: %w", err)
return gtserror.NewErrorInternalError(err)
@@ -430,16 +434,18 @@ func (f *DB) rejectLikeIRI(
// No interaction request existed yet for this
// fave, create a pre-rejected request now.
req = &gtsmodel.InteractionRequest{
- ID: id.NewULID(),
- TargetAccountID: requestingAcct.ID,
- TargetAccount: requestingAcct,
- InteractingAccountID: receivingAcct.ID,
- InteractingAccount: receivingAcct,
- InteractionURI: fave.URI,
- InteractionType: gtsmodel.InteractionLike,
- Like: fave,
- URI: activityID,
- RejectedAt: time.Now(),
+ ID: id.NewULID(),
+ TargetAccountID: requestingAcct.ID,
+ TargetAccount: requestingAcct,
+ InteractingAccountID: receivingAcct.ID,
+ InteractingAccount: receivingAcct,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(fave.URI, gtsmodel.LikeRequestSuffix),
+ InteractionURI: fave.URI,
+ InteractionType: gtsmodel.InteractionLike,
+ Polite: util.Ptr(false),
+ Like: fave,
+ ResponseURI: activityID,
+ RejectedAt: time.Now(),
}
if err := f.state.DB.PutInteractionRequest(ctx, req); err != nil {
@@ -450,8 +456,8 @@ func (f *DB) rejectLikeIRI(
case req.IsRejected():
// Interaction has already been rejected. Just
// update to this Reject URI and then return early.
- req.URI = activityID
- if err := f.state.DB.UpdateInteractionRequest(ctx, req, "uri"); err != nil {
+ req.ResponseURI = activityID
+ if err := f.state.DB.UpdateInteractionRequest(ctx, req, "response_uri"); err != nil {
err := gtserror.Newf("db error updating interaction request: %w", err)
return gtserror.NewErrorInternalError(err)
}
@@ -462,11 +468,11 @@ func (f *DB) rejectLikeIRI(
// Rejected, even if previously Accepted.
req.AcceptedAt = time.Time{}
req.RejectedAt = time.Now()
- req.URI = activityID
+ req.ResponseURI = activityID
if err := f.state.DB.UpdateInteractionRequest(ctx, req,
"accepted_at",
"rejected_at",
- "uri",
+ "response_uri",
); err != nil {
err := gtserror.Newf("db error updating interaction request: %w", err)
return gtserror.NewErrorInternalError(err)
diff --git a/internal/federation/federatingdb/util.go b/internal/federation/federatingdb/util.go
index 8124c8dc5..7e92707e7 100644
--- a/internal/federation/federatingdb/util.go
+++ b/internal/federation/federatingdb/util.go
@@ -28,6 +28,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/ap"
"code.superseriousbusiness.org/gotosocial/internal/config"
"code.superseriousbusiness.org/gotosocial/internal/gtscontext"
+ "code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/id"
"code.superseriousbusiness.org/gotosocial/internal/log"
@@ -110,11 +111,9 @@ func (f *DB) NewID(ctx context.Context, t vocab.Type) (idURL *url.URL, err error
// based on actor (i.e. followER not the followEE).
if uri := ap.GetActorIRIs(follow); len(uri) == 1 {
if actorAccount, err := f.state.DB.GetAccountByURI(ctx, uri[0].String()); err == nil {
- newID, err := id.NewRandomULID()
- if err != nil {
- return nil, err
- }
- return url.Parse(uris.GenerateURIForFollow(actorAccount.Username, newID))
+ newID := id.NewRandomULID()
+ uri := uris.GenerateURIForFollow(actorAccount.Username, newID)
+ return url.Parse(uri)
}
}
}
@@ -234,3 +233,53 @@ func (s serialize) String() string {
return byteutil.B2S(b)
}
+
+// statusableOK is a util function to check if
+// the given statusable is "ok" in terms of being
+// relevant to the receiver, and passing spam checks.
+func (f *DB) statusableOK(
+ ctx context.Context,
+ receiver *gtsmodel.Account,
+ requester *gtsmodel.Account,
+ statusable ap.Statusable,
+) (bool, error) {
+ // Check whether this status is both
+ // relevant, and doesn't look like spam.
+ err := f.spamFilter.StatusableOK(ctx,
+ receiver,
+ requester,
+ statusable,
+ )
+
+ switch {
+ case err == nil:
+ // No problem!
+ return true, nil
+
+ case gtserror.IsNotRelevant(err):
+ // This case is quite common if a remote (Mastodon)
+ // instance forwards a message to us which is a reply
+ // from someone else to a status we've also replied to.
+ //
+ // It does this to try to ensure thread completion, but
+ // we have our own thread fetching mechanism anyway.
+ log.Debugf(ctx, "status %s is not relevant to receiver (%v); dropping it",
+ ap.GetJSONLDId(statusable), err,
+ )
+ return false, nil
+
+ case gtserror.IsSpam(err):
+ // Log this at a higher level so admins can
+ // gauge how much spam is being sent to them.
+ //
+ // TODO: add Prometheus metrics for this.
+ log.Infof(ctx, "status %s looked like spam (%v); dropping it",
+ ap.GetJSONLDId(statusable), err,
+ )
+ return false, nil
+
+ default:
+ // A real error has occurred.
+ return false, gtserror.Newf("error checking relevancy/spam: %w", err)
+ }
+}
diff --git a/internal/federation/federator.go b/internal/federation/federator.go
index 5f8324da2..3f5c96002 100644
--- a/internal/federation/federator.go
+++ b/internal/federation/federator.go
@@ -99,6 +99,9 @@ func NewFederator(
federatingDB.Announce,
federatingDB.Move,
federatingDB.Flag,
+ federatingDB.LikeRequest,
+ federatingDB.ReplyRequest,
+ federatingDB.AnnounceRequest,
},
}
actor := newFederatingActor(f, f, federatingDB, clock)
diff --git a/internal/gtserror/error.go b/internal/gtserror/error.go
index bd83a8dc8..8eb3f1d65 100644
--- a/internal/gtserror/error.go
+++ b/internal/gtserror/error.go
@@ -71,11 +71,11 @@ func SetUnretrievable(err error) error {
return errors.WithValue(err, unrtrvableKey, struct{}{})
}
-// NotPermitted indicates that some call failed due to failed permission
+// IsNotPermitted indicates that some call failed due to failed permission
// or acceptibility checks. For example an attempt to dereference remote
// status in which the status author does not have permission to reply
// to the status it is intended to be replying to.
-func NotPermitted(err error) bool {
+func IsNotPermitted(err error) bool {
_, ok := errors.Value(err, notPermittedKey).(struct{})
return ok
}
diff --git a/internal/gtsmodel/interaction.go b/internal/gtsmodel/interaction.go
index 0b9ee693e..a517236e2 100644
--- a/internal/gtsmodel/interaction.go
+++ b/internal/gtsmodel/interaction.go
@@ -20,7 +20,7 @@ package gtsmodel
import "time"
// Like / Reply / Announce
-type InteractionType int
+type InteractionType enumType
const (
// WARNING: DO NOT CHANGE THE ORDER OF THESE,
@@ -29,11 +29,34 @@ const (
// If you need to add new interaction types,
// add them *to the end* of the list.
- InteractionLike InteractionType = iota
- InteractionReply
- InteractionAnnounce
+ InteractionLike InteractionType = 0
+ InteractionReply InteractionType = 1
+ InteractionAnnounce InteractionType = 2
)
+const (
+ // Suffix to append to the URI of
+ // impolite Likes to mock a LikeRequest.
+ LikeRequestSuffix = "#LikeRequest"
+
+ // Suffix to append to the URI of
+ // impolite replies to mock a ReplyRequest.
+ ReplyRequestSuffix = "#ReplyRequest"
+
+ // Suffix to append to the URI of impolite
+ // Announces to mock an AnnounceRequest.
+ AnnounceRequestSuffix = "#AnnounceRequest"
+)
+
+// A useless function that appends two strings, this exists largely
+// to indicate where a request URI is being generated as forward compatible
+// with our planned polite request flow fully introduced in v0.21.0.
+//
+// TODO: remove this in v0.21.0. everything the linter complains about after removing this, needs updating.
+func ForwardCompatibleInteractionRequestURI(interactionURI string, suffix string) string {
+ return interactionURI + suffix
+}
+
// Stringifies this InteractionType in a
// manner suitable for serving via the API.
func (i InteractionType) String() string {
@@ -52,30 +75,80 @@ func (i InteractionType) String() string {
}
}
-// InteractionRequest represents one interaction (like, reply, fave)
-// that is either accepted, rejected, or currently still awaiting
+// InteractionRequest represents one interaction request
+// that is either accepted, rejected, or awaiting
// acceptance or rejection by the target account.
type InteractionRequest struct {
- ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"` // id of this item in the database
- CreatedAt time.Time `bun:"type:timestamptz,nullzero,notnull,default:current_timestamp"` // when was item created
- StatusID string `bun:"type:CHAR(26),nullzero,notnull"` // ID of the interaction target status.
- Status *Status `bun:"-"` // Not stored in DB. Status being interacted with.
- TargetAccountID string `bun:"type:CHAR(26),nullzero,notnull"` // id of the account being interacted with
- TargetAccount *Account `bun:"-"` // Not stored in DB. Account being interacted with.
- InteractingAccountID string `bun:"type:CHAR(26),nullzero,notnull"` // id of the account requesting the interaction.
- InteractingAccount *Account `bun:"-"` // Not stored in DB. Account corresponding to targetAccountID
- InteractionURI string `bun:",nullzero,notnull,unique"` // URI of the interacting like, reply, or announce. Unique (only one interaction request allowed per interaction URI).
- InteractionType InteractionType `bun:",notnull"` // One of Like, Reply, or Announce.
- Like *StatusFave `bun:"-"` // Not stored in DB. Only set if InteractionType = InteractionLike.
- Reply *Status `bun:"-"` // Not stored in DB. Only set if InteractionType = InteractionReply.
- Announce *Status `bun:"-"` // Not stored in DB. Only set if InteractionType = InteractionAnnounce.
- AcceptedAt time.Time `bun:"type:timestamptz,nullzero"` // If interaction request was accepted, time at which this occurred.
- RejectedAt time.Time `bun:"type:timestamptz,nullzero"` // If interaction request was rejected, time at which this occurred.
-
- // ActivityPub URI of the Accept (if accepted) or Reject (if rejected).
+
+ // ID of this item in the database.
+ ID string `bun:"type:CHAR(26),pk,nullzero,notnull,unique"`
+
+ // ID of the status targeted by the interaction.
+ TargetStatusID string `bun:"type:CHAR(26),nullzero,notnull"`
+
+ // Local status corresponding to TargetStatusID.
+ // Column not stored in DB.
+ TargetStatus *Status `bun:"-"`
+
+ // ID of the account being interacted with.
+ TargetAccountID string `bun:"type:CHAR(26),nullzero,notnull"`
+
+ // Account corresponding to TargetAccountID.
+ // Column not stored in DB.
+ TargetAccount *Account `bun:"-"`
+
+ // ID of the account doing the interaction request.
+ InteractingAccountID string `bun:"type:CHAR(26),nullzero,notnull"`
+
+ // Account corresponding to InteractingAccountID.
+ // Column not stored in DB.
+ InteractingAccount *Account `bun:"-"`
+
+ // URI of the Request, if this InteractionRequest originated from
+ // a polite Request type (LikeRequest, ReplyRequest, AnnounceRequest, etc.).
+ //
+ // If the interaction request originated from an interaction
+ // (Like, Create (status), Announce, etc.) transmitted impolitely,
+ // this will be set to a mocked URI.
+ InteractionRequestURI string `bun:",nullzero,notnull,unique"`
+
+ // URI of the interaction itself.
+ InteractionURI string `bun:",nullzero,notnull,unique"`
+
+ // Type of interaction being requested.
+ InteractionType InteractionType `bun:",notnull"`
+
+ // True if this interaction request
+ // originated from a polite Request type.
+ Polite *bool `bun:",nullzero,notnull,default:false"`
+
+ // Set if InteractionType = InteractionLike.
+ // Column not stored in DB.
+ Like *StatusFave `bun:"-"`
+
+ // Set if InteractionType = InteractionReply.
+ // Column not stored in DB.
+ Reply *Status `bun:"-"`
+
+ // Set if InteractionType = InteractionAnnounce.
+ // Column not stored in DB.
+ Announce *Status `bun:"-"`
+
+ // If interaction request was accepted, time at which this occurred.
+ AcceptedAt time.Time `bun:"type:timestamptz,nullzero"`
+
+ // If interaction request was rejected, time at which this occurred.
+ RejectedAt time.Time `bun:"type:timestamptz,nullzero"`
+
+ // URI of the Accept (if accepted) or Reject (if rejected).
// Field may be empty if currently neither accepted not rejected, or if
// acceptance/rejection was implicit (ie., not resulting from an Activity).
- URI string `bun:",nullzero,unique"`
+ ResponseURI string `bun:",nullzero,unique"`
+
+ // URI of the Authorization object (if accepted).
+ //
+ // Field will only be set if the interaction has been accepted.
+ AuthorizationURI string `bun:",nullzero,unique"`
}
// IsHandled returns true if interaction
@@ -96,6 +169,39 @@ func (ir *InteractionRequest) IsRejected() bool {
return !ir.RejectedAt.IsZero()
}
+// IsPolite returns true if this interaction request was done
+// "politely" with a *Request type, or false if it was done
+// "impolitely" with direct send of a like, reply, or announce.
+//
+// The following information is not strictly needed but provides
+// useful context for why interaction requests are determined to
+// be either "polite" or "impolite".
+//
+// A "polite" interaction request flow indicates that it was
+// performed with the latest currently accepted manner of doing
+// things. This manner is different to that initially introduced
+// by us (GoToSocial) pre-v0.20.0, as it is the result of our
+// previous design going through many iterations with Mastodon
+// developers as part of designing their similar quote post flow.
+//
+// An "impolite" interaction request flow is that produced either
+// by an older interaction-policy-AWARE GoToSocial instance, or
+// by any interaction-policy-UNAWARE server instance.
+//
+// Regarding per-version GoToSocial behaviour (summarized by tobi):
+//
+// - from v0.19.0 and before, we know about and can respond only to
+// impolite interactions, and we send out impolite as well
+//
+// - from v0.20.0 onwards, we know about and can respond to both
+// polite / impolite interaction requests, but we still send out impolite
+//
+// - from v0.21.0 onwards, we know about and can respond to both
+// polite and impolite interaction requests, and we send out polite
+func (ir *InteractionRequest) IsPolite() bool {
+ return ir.Polite != nil && *ir.Polite
+}
+
// Interaction abstractly represents
// one interaction with a status, via
// liking, replying to, or boosting it.
diff --git a/internal/gtsmodel/status.go b/internal/gtsmodel/status.go
index b6bc303cd..78aa09dd9 100644
--- a/internal/gtsmodel/status.go
+++ b/internal/gtsmodel/status.go
@@ -76,7 +76,7 @@ type Status struct {
InteractionPolicy *InteractionPolicy `bun:""` // InteractionPolicy for this status. If null then the default InteractionPolicy should be assumed for this status's Visibility. Always null for boost wrappers.
PendingApproval *bool `bun:",nullzero,notnull,default:false"` // If true then status is a reply or boost wrapper that must be Approved by the reply-ee or boost-ee before being fully distributed.
PreApproved bool `bun:"-"` // If true, then status is a reply to or boost wrapper of a status on our instance, has permission to do the interaction, and an Accept should be sent out for it immediately. Field not stored in the DB.
- ApprovedByURI string `bun:",nullzero"` // URI of an Accept Activity that approves the Announce or Create Activity that this status was/will be attached to.
+ ApprovedByURI string `bun:",nullzero"` // URI of *either* an Accept Activity, or a ReplyAuthorization or AnnounceAuthorization, which approves the Announce, Create or interaction request Activity that this status was/will be attached to.
}
// GetID implements timeline.Timelineable{}.
diff --git a/internal/id/ulid.go b/internal/id/ulid.go
index 04afef8f0..f763a4772 100644
--- a/internal/id/ulid.go
+++ b/internal/id/ulid.go
@@ -22,6 +22,7 @@ import (
"math/big"
"time"
+ "code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/log"
"codeberg.org/gruf/go-kv/v2"
"github.com/oklog/ulid"
@@ -33,62 +34,71 @@ const (
randomRange = 631152381 // ~20 years in seconds
)
+// bigRandomRange contains randomRange as big.Int.
+var bigRandomRange = big.NewInt(randomRange)
+
// ULID represents a Universally Unique Lexicographically Sortable Identifier of 26 characters. See https://github.com/oklog/ulid
type ULID string
-// NewULID returns a new ULID string using the current time.
-func NewULID() string {
- ulid, err := ulid.New(
- ulid.Timestamp(time.Now()), rand.Reader,
- )
+// newAt returns a new ulid.ULID from timestamp,
+// else panics with caller's caller information.
+func newAt(ts uint64) string {
+ ulid, err := ulid.New(ts, rand.Reader)
if err != nil {
- panic(err)
+ panic(gtserror.NewfAt(4, "error generating ulid: %w", err))
}
return ulid.String()
}
+// NewULID returns a new ULID
+// string using the current time.
+func NewULID() string {
+ return newAt(ulid.Now())
+}
+
// NewULIDFromTime returns a new ULID string using
// given time, or from current time on any error.
func NewULIDFromTime(t time.Time) string {
ts := ulid.Timestamp(t)
if ts > ulid.MaxTime() {
log.WarnKVs(nil, kv.Fields{
- {K: "caller", V: log.Caller(2)},
+ {K: "caller", V: log.Caller(3)},
{K: "value", V: t},
{K: "msg", V: "invalid ulid time"},
}...)
ts = ulid.Now()
}
- return ulid.MustNew(ts, rand.Reader).String()
+ return newAt(ts)
}
-// NewRandomULID returns a new ULID string using a random time in an ~80 year range around the current datetime, or an error if something goes wrong.
-func NewRandomULID() (string, error) {
- b1, err := rand.Int(rand.Reader, big.NewInt(randomRange))
+// NewRandomULID returns a new ULID string using a random
+// time in an ~80 year range around the current datetime.
+func NewRandomULID() string {
+ n1, err := rand.Int(rand.Reader, bigRandomRange)
if err != nil {
- return "", err
+ panic(gtserror.NewfAt(3, "error reading rand: %w", err))
}
- r1 := time.Duration(int(b1.Int64()))
- b2, err := rand.Int(rand.Reader, big.NewInt(randomRange))
+ n2, err := rand.Int(rand.Reader, bigRandomRange)
if err != nil {
- return "", err
+ panic(gtserror.NewfAt(3, "error reading rand: %w", err))
}
- r2 := -time.Duration(int(b2.Int64()))
- arbitraryTime := time.Now().Add(r1 * time.Second).Add(r2 * time.Second)
- newUlid, err := ulid.New(ulid.Timestamp(arbitraryTime), rand.Reader)
- if err != nil {
- return "", err
- }
- return newUlid.String(), nil
+ // Random addition and decrement durations.
+ add := time.Duration(n1.Int64()) * time.Second
+ dec := -time.Duration(n2.Int64()) * time.Second
+
+ // Return new ULID string from now.
+ t := time.Now().Add(add).Add(dec)
+ return newAt(ulid.Timestamp(t))
}
+// TimeFromULID parses a ULID string and returns the
+// encoded time.Time{}, or error with caller prefix.
func TimeFromULID(id string) (time.Time, error) {
parsed, err := ulid.ParseStrict(id)
if err != nil {
- return time.Time{}, err
+ return time.Time{}, gtserror.NewfAt(3, "could not extract time (malformed ulid): %w", err)
}
-
return ulid.Time(parsed.Time()), nil
}
diff --git a/internal/processing/account/follow.go b/internal/processing/account/follow.go
index 26d552bbb..91955eaa7 100644
--- a/internal/processing/account/follow.go
+++ b/internal/processing/account/follow.go
@@ -82,10 +82,7 @@ func (p *Processor) FollowCreate(ctx context.Context, requestingAccount *gtsmode
// Neither follows nor follow requests, so
// create and store a new follow request.
- followID, err := id.NewRandomULID()
- if err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
+ followID := id.NewRandomULID()
followURI := uris.GenerateURIForFollow(requestingAccount.Username, followID)
fr := &gtsmodel.FollowRequest{
diff --git a/internal/processing/admin/rule.go b/internal/processing/admin/rule.go
index a665da9a1..de19cba0b 100644
--- a/internal/processing/admin/rule.go
+++ b/internal/processing/admin/rule.go
@@ -64,17 +64,12 @@ func (p *Processor) RuleGet(ctx context.Context, id string) (*apimodel.AdminInst
// RuleCreate adds a new rule to the instance.
func (p *Processor) RuleCreate(ctx context.Context, form *apimodel.InstanceRuleCreateRequest) (*apimodel.AdminInstanceRule, gtserror.WithCode) {
- ruleID, err := id.NewRandomULID()
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error creating id for new instance rule: %s", err), "error creating rule ID")
- }
-
rule := &gtsmodel.Rule{
- ID: ruleID,
+ ID: id.NewRandomULID(),
Text: form.Text,
}
- if err = p.state.DB.PutRule(ctx, rule); err != nil {
+ if err := p.state.DB.PutRule(ctx, rule); err != nil {
return nil, gtserror.NewErrorInternalError(err)
}
diff --git a/internal/processing/application/create.go b/internal/processing/application/create.go
index 7ee6fb6b9..d63b682d6 100644
--- a/internal/processing/application/create.go
+++ b/internal/processing/application/create.go
@@ -86,10 +86,7 @@ func (p *Processor) Create(
}
// Generate random client ID.
- clientID, err := id.NewRandomULID()
- if err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
+ clientID := id.NewRandomULID()
// Generate + store app
// to put in the database.
diff --git a/internal/processing/fedi/accept.go b/internal/processing/fedi/accept.go
index e63b460db..97e36fbb3 100644
--- a/internal/processing/fedi/accept.go
+++ b/internal/processing/fedi/accept.go
@@ -19,10 +19,8 @@ package fedi
import (
"context"
- "errors"
"code.superseriousbusiness.org/gotosocial/internal/ap"
- "code.superseriousbusiness.org/gotosocial/internal/db"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
)
@@ -34,44 +32,18 @@ import (
func (p *Processor) AcceptGet(
ctx context.Context,
requestedUser string,
- reqID string,
-) (interface{}, gtserror.WithCode) {
- // Authenticate incoming request, getting related accounts.
- auth, errWithCode := p.authenticate(ctx, requestedUser)
+ intReqID string,
+) (any, gtserror.WithCode) {
+ // Ensure valid request, intReq exists, etc.
+ intReq, errWithCode := p.validateIntReqRequest(ctx, requestedUser, intReqID)
if errWithCode != nil {
return nil, errWithCode
}
- if auth.handshakingURI != nil {
- // We're currently handshaking, which means
- // we don't know this account yet. This should
- // be a very rare race condition.
- err := gtserror.Newf("network race handshaking %s", auth.handshakingURI)
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- receivingAcct := auth.receivingAcct
-
- req, err := p.state.DB.GetInteractionRequestByID(ctx, reqID)
- if err != nil && !errors.Is(err, db.ErrNoEntries) {
- err := gtserror.Newf("db error getting interaction request %s: %w", reqID, err)
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- if req == nil || !req.IsAccepted() {
- // Request doesn't exist or hasn't been accepted.
- err := gtserror.Newf("interaction request %s not found", reqID)
- return nil, gtserror.NewErrorNotFound(err)
- }
-
- if req.TargetAccountID != receivingAcct.ID {
- const text = "interaction request does not belong to receiving account"
- return nil, gtserror.NewErrorNotFound(errors.New(text))
- }
-
- accept, err := p.converter.InteractionReqToASAccept(ctx, req)
+ // Convert + serialize the Accept.
+ accept, err := p.converter.InteractionReqToASAccept(ctx, intReq)
if err != nil {
- err := gtserror.Newf("error converting accept: %w", err)
+ err := gtserror.Newf("error converting to accept: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
diff --git a/internal/processing/fedi/authorization.go b/internal/processing/fedi/authorization.go
new file mode 100644
index 000000000..bbba6a2d8
--- /dev/null
+++ b/internal/processing/fedi/authorization.go
@@ -0,0 +1,57 @@
+// GoToSocial
+// Copyright (C) GoToSocial Authors admin@gotosocial.org
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package fedi
+
+import (
+ "context"
+
+ "code.superseriousbusiness.org/gotosocial/internal/ap"
+ "code.superseriousbusiness.org/gotosocial/internal/gtserror"
+)
+
+// AuthorizationGet handles the getting of a fedi/activitypub
+// representation of a local interaction authorization.
+//
+// It performs appropriate authentication before
+// returning a JSON serializable interface.
+func (p *Processor) AuthorizationGet(
+ ctx context.Context,
+ requestedUser string,
+ intReqID string,
+) (any, gtserror.WithCode) {
+ // Ensure valid request, intReq exists, etc.
+ intReq, errWithCode := p.validateIntReqRequest(ctx, requestedUser, intReqID)
+ if errWithCode != nil {
+ return nil, errWithCode
+ }
+
+ // Convert + serialize the Authorization.
+ authorization, err := p.converter.InteractionReqToASAuthorization(ctx, intReq)
+ if err != nil {
+ err := gtserror.Newf("error converting to authorization: %w", err)
+ return nil, gtserror.NewErrorInternalError(err)
+ }
+
+ data, err := ap.Serialize(authorization)
+ if err != nil {
+ err := gtserror.Newf("error serializing accept: %w", err)
+ return nil, gtserror.NewErrorInternalError(err)
+ }
+
+ return data, nil
+}
diff --git a/internal/processing/fedi/common.go b/internal/processing/fedi/common.go
index 9059aef39..fc783f93e 100644
--- a/internal/processing/fedi/common.go
+++ b/internal/processing/fedi/common.go
@@ -20,6 +20,7 @@ package fedi
import (
"context"
"errors"
+ "fmt"
"net/url"
"code.superseriousbusiness.org/gotosocial/internal/db"
@@ -81,3 +82,52 @@ func (p *Processor) authenticate(ctx context.Context, requestedUser string) (*co
receivingAcct: receiver,
}, nil
}
+
+// validateIntReqRequest is a shortcut function
+// for returning an accepted interaction request
+// targeting `requestedUser`.
+func (p *Processor) validateIntReqRequest(
+ ctx context.Context,
+ requestedUser string,
+ intReqID string,
+) (*gtsmodel.InteractionRequest, gtserror.WithCode) {
+ // Authenticate incoming request, getting related accounts.
+ auth, errWithCode := p.authenticate(ctx, requestedUser)
+ if errWithCode != nil {
+ return nil, errWithCode
+ }
+
+ if auth.handshakingURI != nil {
+ // We're currently handshaking, which means we don't know
+ // this account yet. This should be a very rare race condition.
+ err := gtserror.Newf("network race handshaking %s", auth.handshakingURI)
+ return nil, gtserror.NewErrorInternalError(err)
+ }
+
+ // Fetch interaction request with the given ID.
+ req, err := p.state.DB.GetInteractionRequestByID(ctx, intReqID)
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ err := gtserror.Newf("db error getting interaction request %s: %w", intReqID, err)
+ return nil, gtserror.NewErrorInternalError(err)
+ }
+
+ // Ensure that this is an existing
+ // and *accepted* interaction request.
+ if req == nil || !req.IsAccepted() {
+ const text = "interaction request not found"
+ return nil, gtserror.NewErrorNotFound(errors.New(text))
+ }
+
+ // Ensure interaction request was accepted
+ // by the account in the request path.
+ if req.TargetAccountID != auth.receivingAcct.ID {
+ text := fmt.Sprintf(
+ "account %s is not targeted by interaction request %s and therefore can't accept it",
+ requestedUser, intReqID,
+ )
+ return nil, gtserror.NewErrorNotFound(errors.New(text))
+ }
+
+ // All fine.
+ return req, nil
+}
diff --git a/internal/processing/interactionrequests/accept.go b/internal/processing/interactionrequests/accept.go
index ce682380b..7efd1f373 100644
--- a/internal/processing/interactionrequests/accept.go
+++ b/internal/processing/interactionrequests/accept.go
@@ -65,14 +65,16 @@ func (p *Processor) Accept(
defer unlock()
// Mark the request as accepted
- // and generate a URI for it.
+ // and generate URIs for it.
req.AcceptedAt = time.Now()
- req.URI = uris.GenerateURIForAccept(acct.Username, req.ID)
+ req.ResponseURI = uris.GenerateURIForAccept(acct.Username, req.ID)
+ req.AuthorizationURI = uris.GenerateURIForAuthorization(acct.Username, req.ID)
if err := p.state.DB.UpdateInteractionRequest(
ctx,
req,
"accepted_at",
- "uri",
+ "response_uri",
+ "authorization_uri",
); err != nil {
err := gtserror.Newf("db error updating interaction request: %w", err)
return nil, gtserror.NewErrorInternalError(err)
@@ -132,7 +134,7 @@ func (p *Processor) acceptLike(
// Update the Like.
req.Like.PendingApproval = util.Ptr(false)
req.Like.PreApproved = false
- req.Like.ApprovedByURI = req.URI
+ req.Like.ApprovedByURI = req.AuthorizationURI
if err := p.state.DB.UpdateStatusFave(
ctx,
req.Like,
@@ -173,7 +175,7 @@ func (p *Processor) acceptReply(
// Update the Reply.
req.Reply.PendingApproval = util.Ptr(false)
req.Reply.PreApproved = false
- req.Reply.ApprovedByURI = req.URI
+ req.Reply.ApprovedByURI = req.AuthorizationURI
if err := p.state.DB.UpdateStatus(
ctx,
req.Reply,
@@ -214,7 +216,7 @@ func (p *Processor) acceptAnnounce(
// Update the Announce.
req.Announce.PendingApproval = util.Ptr(false)
req.Announce.PreApproved = false
- req.Announce.ApprovedByURI = req.URI
+ req.Announce.ApprovedByURI = req.AuthorizationURI
if err := p.state.DB.UpdateStatus(
ctx,
req.Announce,
diff --git a/internal/processing/interactionrequests/accept_test.go b/internal/processing/interactionrequests/accept_test.go
index b48978f2c..cb4212c24 100644
--- a/internal/processing/interactionrequests/accept_test.go
+++ b/internal/processing/interactionrequests/accept_test.go
@@ -67,7 +67,7 @@ func (suite *AcceptTestSuite) TestAccept() {
suite.FailNow(err.Error())
}
suite.False(*dbStatus.PendingApproval)
- suite.Equal(dbReq.URI, dbStatus.ApprovedByURI)
+ suite.Equal(dbReq.AuthorizationURI, dbStatus.ApprovedByURI)
// Wait for a notification
// for interacting status.
diff --git a/internal/processing/interactionrequests/reject.go b/internal/processing/interactionrequests/reject.go
index 3ceaa47d9..4db52e260 100644
--- a/internal/processing/interactionrequests/reject.go
+++ b/internal/processing/interactionrequests/reject.go
@@ -66,12 +66,12 @@ func (p *Processor) Reject(
// Mark the request as rejected
// and generate a URI for it.
req.RejectedAt = time.Now()
- req.URI = uris.GenerateURIForReject(acct.Username, req.ID)
+ req.ResponseURI = uris.GenerateURIForReject(acct.Username, req.ID)
if err := p.state.DB.UpdateInteractionRequest(
ctx,
req,
"rejected_at",
- "uri",
+ "response_uri",
); err != nil {
err := gtserror.Newf("db error updating interaction request: %w", err)
return nil, gtserror.NewErrorInternalError(err)
diff --git a/internal/processing/search/get.go b/internal/processing/search/get.go
index 2e956b049..64aefd23c 100644
--- a/internal/processing/search/get.go
+++ b/internal/processing/search/get.go
@@ -524,7 +524,7 @@ func (p *Processor) byURI(
switch {
case gtserror.IsUnretrievable(err),
gtserror.IsWrongType(err),
- gtserror.NotPermitted(err):
+ gtserror.IsNotPermitted(err):
log.Debugf(ctx,
"semi-expected error type looking up %s as status: %v",
uri, err,
diff --git a/internal/processing/workers/federate.go b/internal/processing/workers/federate.go
index 3cc3d130c..7459f0114 100644
--- a/internal/processing/workers/federate.go
+++ b/internal/processing/workers/federate.go
@@ -115,7 +115,7 @@ func (f *federate) DeleteAccount(ctx context.Context, account *gtsmodel.Account)
// Address the delete CC public.
deleteCC := streams.NewActivityStreamsCcProperty()
- deleteCC.AppendIRI(ap.PublicURI())
+ deleteCC.AppendIRI(ap.PublicIRI())
delete.SetActivityStreamsCc(deleteCC)
// Send the Delete via the Actor's outbox.
@@ -491,12 +491,7 @@ func (f *federate) UndoAnnounce(ctx context.Context, boost *gtsmodel.Status) err
}
// Recreate the ActivityStreams Announce.
- asAnnounce, err := f.converter.BoostToAS(
- ctx,
- boost,
- boost.Account,
- boost.BoostOfAccount,
- )
+ asAnnounce, err := f.converter.BoostToAS(ctx, boost)
if err != nil {
return gtserror.Newf("error converting boost to AS: %w", err)
}
@@ -767,12 +762,7 @@ func (f *federate) Announce(ctx context.Context, boost *gtsmodel.Status) error {
}
// Create the ActivityStreams Announce.
- announce, err := f.converter.BoostToAS(
- ctx,
- boost,
- boost.Account,
- boost.BoostOfAccount,
- )
+ announce, err := f.converter.BoostToAS(ctx, boost)
if err != nil {
return gtserror.Newf("error converting boost to AS: %w", err)
}
@@ -1104,7 +1094,7 @@ func (f *federate) MoveAccount(ctx context.Context, account *gtsmodel.Account) e
ap.AppendTo(move, followersIRI)
// Address the move CC public.
- ap.AppendCc(move, ap.PublicURI())
+ ap.AppendCc(move, ap.PublicIRI())
// Send the Move via the Actor's outbox.
if _, err := f.FederatingActor().Send(
diff --git a/internal/processing/workers/fromclientapi.go b/internal/processing/workers/fromclientapi.go
index 22e7780f6..9cdbcc548 100644
--- a/internal/processing/workers/fromclientapi.go
+++ b/internal/processing/workers/fromclientapi.go
@@ -287,7 +287,7 @@ func (p *clientAPI) CreateStatus(ctx context.Context, cMsg *messages.FromClientA
// and/or notify the account that's being
// interacted with (if it's local): they can
// approve or deny the interaction later.
- if err := p.utils.requestReply(ctx, status); err != nil {
+ if err := p.utils.impoliteReplyRequest(ctx, status); err != nil {
return gtserror.Newf("error pending reply: %w", err)
}
@@ -310,19 +310,22 @@ func (p *clientAPI) CreateStatus(ctx context.Context, cMsg *messages.FromClientA
// URI attached.
// Store an already-accepted interaction request.
- id := id.NewULID()
+ requestID := id.NewULID()
approval := &gtsmodel.InteractionRequest{
- ID: id,
- StatusID: status.InReplyToID,
- TargetAccountID: status.InReplyToAccountID,
- TargetAccount: status.InReplyToAccount,
- InteractingAccountID: status.AccountID,
- InteractingAccount: status.Account,
- InteractionURI: status.URI,
- InteractionType: gtsmodel.InteractionReply,
- Reply: status,
- URI: uris.GenerateURIForAccept(status.InReplyToAccount.Username, id),
- AcceptedAt: time.Now(),
+ ID: requestID,
+ TargetStatusID: status.InReplyToID,
+ TargetAccountID: status.InReplyToAccountID,
+ TargetAccount: status.InReplyToAccount,
+ InteractingAccountID: status.AccountID,
+ InteractingAccount: status.Account,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(status.URI, gtsmodel.ReplyRequestSuffix),
+ InteractionURI: status.URI,
+ InteractionType: gtsmodel.InteractionReply,
+ Polite: util.Ptr(false), // TODO: Change this in v0.21.0 when we only send out polite requests.
+ Reply: status,
+ ResponseURI: uris.GenerateURIForAccept(status.InReplyToAccount.Username, requestID),
+ AuthorizationURI: uris.GenerateURIForAuthorization(status.InReplyToAccount.Username, requestID),
+ AcceptedAt: time.Now(),
}
if err := p.state.DB.PutInteractionRequest(ctx, approval); err != nil {
return gtserror.Newf("db error putting pre-approved interaction request: %w", err)
@@ -331,7 +334,7 @@ func (p *clientAPI) CreateStatus(ctx context.Context, cMsg *messages.FromClientA
// Mark the status as now approved.
status.PendingApproval = util.Ptr(false)
status.PreApproved = false
- status.ApprovedByURI = approval.URI
+ status.ApprovedByURI = approval.AuthorizationURI
if err := p.state.DB.UpdateStatus(
ctx,
status,
@@ -494,7 +497,7 @@ func (p *clientAPI) CreateLike(ctx context.Context, cMsg *messages.FromClientAPI
// and/or notify the account that's being
// interacted with (if it's local): they can
// approve or deny the interaction later.
- if err := p.utils.requestFave(ctx, fave); err != nil {
+ if err := p.utils.impoliteFaveRequest(ctx, fave); err != nil {
return gtserror.Newf("error pending fave: %w", err)
}
@@ -517,19 +520,22 @@ func (p *clientAPI) CreateLike(ctx context.Context, cMsg *messages.FromClientAPI
// URI attached.
// Store an already-accepted interaction request.
- id := id.NewULID()
+ requestID := id.NewULID()
approval := &gtsmodel.InteractionRequest{
- ID: id,
- StatusID: fave.StatusID,
- TargetAccountID: fave.TargetAccountID,
- TargetAccount: fave.TargetAccount,
- InteractingAccountID: fave.AccountID,
- InteractingAccount: fave.Account,
- InteractionURI: fave.URI,
- InteractionType: gtsmodel.InteractionLike,
- Like: fave,
- URI: uris.GenerateURIForAccept(fave.TargetAccount.Username, id),
- AcceptedAt: time.Now(),
+ ID: requestID,
+ TargetStatusID: fave.StatusID,
+ TargetAccountID: fave.TargetAccountID,
+ TargetAccount: fave.TargetAccount,
+ InteractingAccountID: fave.AccountID,
+ InteractingAccount: fave.Account,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(fave.URI, gtsmodel.LikeRequestSuffix),
+ InteractionURI: fave.URI,
+ InteractionType: gtsmodel.InteractionLike,
+ Polite: util.Ptr(false), // TODO: Change this in v0.21.0 when we only send out polite requests.
+ Like: fave,
+ ResponseURI: uris.GenerateURIForAccept(fave.TargetAccount.Username, requestID),
+ AuthorizationURI: uris.GenerateURIForAuthorization(fave.TargetAccount.Username, requestID),
+ AcceptedAt: time.Now(),
}
if err := p.state.DB.PutInteractionRequest(ctx, approval); err != nil {
return gtserror.Newf("db error putting pre-approved interaction request: %w", err)
@@ -538,7 +544,7 @@ func (p *clientAPI) CreateLike(ctx context.Context, cMsg *messages.FromClientAPI
// Mark the fave itself as now approved.
fave.PendingApproval = util.Ptr(false)
fave.PreApproved = false
- fave.ApprovedByURI = approval.URI
+ fave.ApprovedByURI = approval.AuthorizationURI
if err := p.state.DB.UpdateStatusFave(
ctx,
fave,
@@ -589,7 +595,7 @@ func (p *clientAPI) CreateAnnounce(ctx context.Context, cMsg *messages.FromClien
// and/or notify the account that's being
// interacted with (if it's local): they can
// approve or deny the interaction later.
- if err := p.utils.requestAnnounce(ctx, boost); err != nil {
+ if err := p.utils.impoliteAnnounceRequest(ctx, boost); err != nil {
return gtserror.Newf("error pending boost: %w", err)
}
@@ -612,19 +618,22 @@ func (p *clientAPI) CreateAnnounce(ctx context.Context, cMsg *messages.FromClien
// URI attached.
// Store an already-accepted interaction request.
- id := id.NewULID()
+ requestID := id.NewULID()
approval := &gtsmodel.InteractionRequest{
- ID: id,
- StatusID: boost.BoostOfID,
- TargetAccountID: boost.BoostOfAccountID,
- TargetAccount: boost.BoostOfAccount,
- InteractingAccountID: boost.AccountID,
- InteractingAccount: boost.Account,
- InteractionURI: boost.URI,
- InteractionType: gtsmodel.InteractionAnnounce,
- Announce: boost,
- URI: uris.GenerateURIForAccept(boost.BoostOfAccount.Username, id),
- AcceptedAt: time.Now(),
+ ID: requestID,
+ TargetStatusID: boost.BoostOfID,
+ TargetAccountID: boost.BoostOfAccountID,
+ TargetAccount: boost.BoostOfAccount,
+ InteractingAccountID: boost.AccountID,
+ InteractingAccount: boost.Account,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(boost.URI, gtsmodel.AnnounceRequestSuffix),
+ InteractionURI: boost.URI,
+ InteractionType: gtsmodel.InteractionAnnounce,
+ Polite: util.Ptr(false), // TODO: Change this in v0.21.0 when we only send out polite requests.
+ Announce: boost,
+ ResponseURI: uris.GenerateURIForAccept(boost.BoostOfAccount.Username, requestID),
+ AuthorizationURI: uris.GenerateURIForAuthorization(boost.BoostOfAccount.Username, requestID),
+ AcceptedAt: time.Now(),
}
if err := p.state.DB.PutInteractionRequest(ctx, approval); err != nil {
return gtserror.Newf("db error putting pre-approved interaction request: %w", err)
@@ -633,7 +642,7 @@ func (p *clientAPI) CreateAnnounce(ctx context.Context, cMsg *messages.FromClien
// Mark the boost itself as now approved.
boost.PendingApproval = util.Ptr(false)
boost.PreApproved = false
- boost.ApprovedByURI = approval.URI
+ boost.ApprovedByURI = approval.AuthorizationURI
if err := p.state.DB.UpdateStatus(
ctx,
boost,
diff --git a/internal/processing/workers/fromfediapi.go b/internal/processing/workers/fromfediapi.go
index 09c1df480..797a2d9c6 100644
--- a/internal/processing/workers/fromfediapi.go
+++ b/internal/processing/workers/fromfediapi.go
@@ -88,6 +88,10 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg *messages.FromF
case ap.ObjectNote:
return p.fediAPI.CreateStatus(ctx, fMsg)
+ // REQUEST TO REPLY TO A STATUS
+ case ap.ActivityReplyRequest:
+ return p.fediAPI.CreateReplyRequest(ctx, fMsg)
+
// CREATE FOLLOW (request)
case ap.ActivityFollow:
return p.fediAPI.CreateFollowReq(ctx, fMsg)
@@ -96,10 +100,18 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg *messages.FromF
case ap.ActivityLike:
return p.fediAPI.CreateLike(ctx, fMsg)
+ // REQUEST TO LIKE A STATUS
+ case ap.ActivityLikeRequest:
+ return p.fediAPI.CreateLikeRequest(ctx, fMsg)
+
// CREATE ANNOUNCE/BOOST
case ap.ActivityAnnounce:
return p.fediAPI.CreateAnnounce(ctx, fMsg)
+ // REQUEST TO BOOST A STATUS
+ case ap.ActivityAnnounceRequest:
+ return p.fediAPI.CreateAnnounceRequest(ctx, fMsg)
+
// CREATE BLOCK
case ap.ActivityBlock:
return p.fediAPI.CreateBlock(ctx, fMsg)
@@ -146,11 +158,15 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg *messages.FromF
case ap.ObjectNote:
return p.fediAPI.AcceptReply(ctx, fMsg)
+ // ACCEPT (pending) POLITE REPLY REQUEST
+ case ap.ActivityReplyRequest:
+ return p.fediAPI.AcceptPoliteReplyRequest(ctx, fMsg)
+
// ACCEPT (pending) ANNOUNCE
case ap.ActivityAnnounce:
return p.fediAPI.AcceptAnnounce(ctx, fMsg)
- // ACCEPT (remote) REPLY or ANNOUNCE
+ // ACCEPT (remote) IMPOLITE REPLY or ANNOUNCE
case ap.ObjectUnknown:
return p.fediAPI.AcceptRemoteStatus(ctx, fMsg)
}
@@ -219,6 +235,9 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg *messages.FromF
return gtserror.Newf("unhandled: %s %s", fMsg.APActivityType, fMsg.APObjectType)
}
+// CreateStatus handles the creation of a status/post sent as a Create message.
+// It is also capable of handling impolite reply requests to local + remote statuses,
+// ie., replies sent directly without doing the ReplyRequest process first.
func (p *fediAPI) CreateStatus(ctx context.Context, fMsg *messages.FromFediAPI) error {
var (
status *gtsmodel.Status
@@ -291,7 +310,7 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg *messages.FromFediAPI)
// preapproved, then just notify the account
// that's being interacted with: they can
// approve or deny the interaction later.
- if err := p.utils.requestReply(ctx, status); err != nil {
+ if err := p.utils.impoliteReplyRequest(ctx, status); err != nil {
return gtserror.Newf("error pending reply: %w", err)
}
@@ -306,20 +325,24 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg *messages.FromFediAPI)
// collection. Do the Accept immediately and
// then process everything else as normal.
- // Store an already-accepted interaction request.
- id := id.NewULID()
+ // Store an already-accepted
+ // impolite interaction request.
+ requestID := id.NewULID()
approval := &gtsmodel.InteractionRequest{
- ID: id,
- StatusID: status.InReplyToID,
- TargetAccountID: status.InReplyToAccountID,
- TargetAccount: status.InReplyToAccount,
- InteractingAccountID: status.AccountID,
- InteractingAccount: status.Account,
- InteractionURI: status.URI,
- InteractionType: gtsmodel.InteractionReply,
- Reply: status,
- URI: uris.GenerateURIForAccept(status.InReplyToAccount.Username, id),
- AcceptedAt: time.Now(),
+ ID: requestID,
+ TargetStatusID: status.InReplyToID,
+ TargetAccountID: status.InReplyToAccountID,
+ TargetAccount: status.InReplyToAccount,
+ InteractingAccountID: status.AccountID,
+ InteractingAccount: status.Account,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(status.URI, gtsmodel.ReplyRequestSuffix),
+ InteractionURI: status.URI,
+ InteractionType: gtsmodel.InteractionReply,
+ Polite: util.Ptr(false),
+ Reply: status,
+ ResponseURI: uris.GenerateURIForAccept(status.InReplyToAccount.Username, requestID),
+ AuthorizationURI: uris.GenerateURIForAuthorization(status.InReplyToAccount.Username, requestID),
+ AcceptedAt: time.Now(),
}
if err := p.state.DB.PutInteractionRequest(ctx, approval); err != nil {
return gtserror.Newf("db error putting pre-approved interaction request: %w", err)
@@ -328,7 +351,7 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg *messages.FromFediAPI)
// Mark the status as now approved.
status.PendingApproval = util.Ptr(false)
status.PreApproved = false
- status.ApprovedByURI = approval.URI
+ status.ApprovedByURI = approval.AuthorizationURI
if err := p.state.DB.UpdateStatus(
ctx,
status,
@@ -365,6 +388,118 @@ func (p *fediAPI) CreateStatus(ctx context.Context, fMsg *messages.FromFediAPI)
return nil
}
+// CreateReplyRequest handles a polite ReplyRequest.
+// This is distinct from CreateStatus, which is capable
+// of handling both "normal" top-level status creation,
+// in addition to *impolite* reply requests.
+func (p *fediAPI) CreateReplyRequest(ctx context.Context, fMsg *messages.FromFediAPI) error {
+ // Extract the ap model Statusable
+ // set by the federating db.
+ statusable, ok := fMsg.APObject.(ap.Statusable)
+ if !ok {
+ return gtserror.Newf("cannot cast %T -> ap.Statusable", fMsg.APObject)
+ }
+
+ // Call RefreshStatus to parse and process the
+ // statusable. This will also check permissions.
+ replyURI := ap.GetJSONLDId(statusable).String()
+ reply, _, err := p.federate.RefreshStatus(ctx,
+ fMsg.Receiving.Username,
+ &gtsmodel.Status{
+ URI: replyURI,
+ Local: util.Ptr(false),
+ },
+ statusable,
+ // Force refresh within 5min window.
+ dereferencing.Fresh,
+ )
+
+ switch {
+ case err == nil:
+ // All fine.
+
+ case gtserror.IsNotPermitted(err):
+ // Reply is straight up not permitted by
+ // the interaction policy of the status
+ // it's replying to. Nothing more to do.
+ log.Debugf(ctx,
+ "dropping unpermitted ReplyRequest with instrument %s",
+ replyURI,
+ )
+ return nil
+
+ default:
+ // There's some real error.
+ return gtserror.Newf(
+ "error processing ReplyRequest with instrument %s: %w",
+ replyURI, err,
+ )
+ }
+
+ // The reply is permitted. Check if we
+ // should send out an Accept immediately.
+ manualApproval := *reply.PendingApproval && !reply.PreApproved
+ if manualApproval {
+ // The reply requires manual approval.
+ //
+ // Just notify target account about
+ // the requested interaction.
+ if err := p.surface.notifyPendingReply(ctx, reply); err != nil {
+ return gtserror.Newf("error notifying pending reply: %w", err)
+ }
+
+ return nil
+ }
+
+ // The reply is automatically approved,
+ // handle side effects of this.
+ req, ok := fMsg.GTSModel.(*gtsmodel.InteractionRequest)
+ if !ok {
+ return gtserror.Newf("%T not parseable as *gtsmodel.InteractionRequest", fMsg.GTSModel)
+ }
+
+ // Mark the request as accepted.
+ req.AcceptedAt = time.Now()
+ req.ResponseURI = uris.GenerateURIForAccept(
+ req.TargetAccount.Username, req.ID,
+ )
+ req.AuthorizationURI = uris.GenerateURIForAuthorization(
+ req.TargetAccount.Username, req.ID,
+ )
+
+ // Update in the db.
+ if err := p.state.DB.UpdateInteractionRequest(
+ ctx,
+ req,
+ "accepted_at",
+ "response_uri",
+ "authorization_uri",
+ ); err != nil {
+ return gtserror.Newf("db error updating interaction request: %w", err)
+ }
+
+ // Send out the accept.
+ if err := p.federate.AcceptInteraction(ctx, req); err != nil {
+ log.Errorf(ctx, "error federating accept: %v", err)
+ }
+
+ // Update stats for the replying account.
+ if err := p.utils.incrementStatusesCount(ctx, fMsg.Requesting, reply); err != nil {
+ log.Errorf(ctx, "error updating account stats: %v", err)
+ }
+
+ // Timeline the reply + notify recipient(s).
+ if err := p.surface.timelineAndNotifyStatus(ctx, reply); err != nil {
+ log.Errorf(ctx, "error timelining and notifying status: %v", err)
+ }
+
+ // Interaction counts changed on the replied status;
+ // uncache the prepared version from all timelines.
+ p.surface.invalidateStatusFromTimelines(reply.InReplyToID)
+
+ return nil
+}
+
func (p *fediAPI) CreatePollVote(ctx context.Context, fMsg *messages.FromFediAPI) error {
// Cast poll vote type from the worker message.
vote, ok := fMsg.GTSModel.(*gtsmodel.PollVote)
@@ -430,18 +565,18 @@ func (p *fediAPI) UpdatePollVote(ctx context.Context, fMsg *messages.FromFediAPI
}
// Get the origin status.
- status := vote.Poll.Status
+ reply := vote.Poll.Status
- if *status.Local {
+ if *reply.Local {
// These were poll votes in a local status, we need to
// federate the updated status model with latest vote counts.
- if err := p.federate.UpdateStatus(ctx, status); err != nil {
+ if err := p.federate.UpdateStatus(ctx, reply); err != nil {
log.Errorf(ctx, "error federating status update: %v", err)
}
}
// Interaction counts changed, uncache from timelines.
- p.surface.invalidateStatusFromTimelines(status.ID)
+ p.surface.invalidateStatusFromTimelines(reply.ID)
return nil
}
@@ -503,6 +638,8 @@ func (p *fediAPI) CreateFollowReq(ctx context.Context, fMsg *messages.FromFediAP
return nil
}
+// CreateLike handles an impolite Like, ie., a Like sent directly.
+// This is different from the CreateLikeRequest function, which handles polite LikeRequests.
func (p *fediAPI) CreateLike(ctx context.Context, fMsg *messages.FromFediAPI) error {
fave, ok := fMsg.GTSModel.(*gtsmodel.StatusFave)
if !ok {
@@ -525,7 +662,7 @@ func (p *fediAPI) CreateLike(ctx context.Context, fMsg *messages.FromFediAPI) er
// preapproved, then just notify the account
// that's being interacted with: they can
// approve or deny the interaction later.
- if err := p.utils.requestFave(ctx, fave); err != nil {
+ if err := p.utils.impoliteFaveRequest(ctx, fave); err != nil {
return gtserror.Newf("error pending fave: %w", err)
}
@@ -540,20 +677,24 @@ func (p *fediAPI) CreateLike(ctx context.Context, fMsg *messages.FromFediAPI) er
// collection. Do the Accept immediately and
// then process everything else as normal.
- // Store an already-accepted interaction request.
- id := id.NewULID()
+ // Store an already-accepted
+ // impolite interaction request.
+ requestID := id.NewULID()
approval := &gtsmodel.InteractionRequest{
- ID: id,
- StatusID: fave.StatusID,
- TargetAccountID: fave.TargetAccountID,
- TargetAccount: fave.TargetAccount,
- InteractingAccountID: fave.AccountID,
- InteractingAccount: fave.Account,
- InteractionURI: fave.URI,
- InteractionType: gtsmodel.InteractionLike,
- Like: fave,
- URI: uris.GenerateURIForAccept(fave.TargetAccount.Username, id),
- AcceptedAt: time.Now(),
+ ID: requestID,
+ TargetStatusID: fave.StatusID,
+ TargetAccountID: fave.TargetAccountID,
+ TargetAccount: fave.TargetAccount,
+ InteractingAccountID: fave.AccountID,
+ InteractingAccount: fave.Account,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(fave.URI, gtsmodel.LikeRequestSuffix),
+ InteractionURI: fave.URI,
+ InteractionType: gtsmodel.InteractionLike,
+ Polite: util.Ptr(false),
+ Like: fave,
+ ResponseURI: uris.GenerateURIForAccept(fave.TargetAccount.Username, requestID),
+ AuthorizationURI: uris.GenerateURIForAuthorization(fave.TargetAccount.Username, requestID),
+ AcceptedAt: time.Now(),
}
if err := p.state.DB.PutInteractionRequest(ctx, approval); err != nil {
return gtserror.Newf("db error putting pre-approved interaction request: %w", err)
@@ -562,7 +703,7 @@ func (p *fediAPI) CreateLike(ctx context.Context, fMsg *messages.FromFediAPI) er
// Mark the fave itself as now approved.
fave.PendingApproval = util.Ptr(false)
fave.PreApproved = false
- fave.ApprovedByURI = approval.URI
+ fave.ApprovedByURI = approval.AuthorizationURI
if err := p.state.DB.UpdateStatusFave(
ctx,
fave,
@@ -591,6 +732,87 @@ func (p *fediAPI) CreateLike(ctx context.Context, fMsg *messages.FromFediAPI) er
return nil
}
+// CreateLikeRequest handles a polite LikeRequest, as
+// opposed to CreateLike, which handles *impolite* like
+// requests (ie., Likes sent directly).
+func (p *fediAPI) CreateLikeRequest(ctx context.Context, fMsg *messages.FromFediAPI) error {
+ req, ok := fMsg.GTSModel.(*gtsmodel.InteractionRequest)
+ if !ok {
+ return gtserror.Newf("%T not parseable as *gtsmodel.InteractionRequest", fMsg.GTSModel)
+ }
+
+ // At this point the not-yet-approved
+ // interaction request, and the pending
+ // fave, are both in the database.
+
+ if !req.Like.PreApproved {
+ // The fave is *not* pre-approved, and
+ // therefore requires manual approval.
+ //
+ // Just notify target account about
+ // the requested interaction.
+ if err := p.surface.notifyPendingFave(ctx, req.Like); err != nil {
+ return gtserror.Newf("error notifying pending like: %w", err)
+ }
+
+ return nil
+ }
+
+ // If it's pre-approved on the other hand
+ // we can handle everything immediately.
+
+ // Mark the request as accepted.
+ req.AcceptedAt = time.Now()
+ req.ResponseURI = uris.GenerateURIForAccept(
+ req.TargetAccount.Username, req.ID,
+ )
+ req.AuthorizationURI = uris.GenerateURIForAuthorization(
+ req.TargetAccount.Username, req.ID,
+ )
+
+ // Update in the db.
+ if err := p.state.DB.UpdateInteractionRequest(
+ ctx,
+ req,
+ "accepted_at",
+ "response_uri",
+ "authorization_uri",
+ ); err != nil {
+ return gtserror.Newf("db error updating interaction request: %w", err)
+ }
+
+ // Send out the accept.
+ if err := p.federate.AcceptInteraction(ctx, req); err != nil {
+ log.Errorf(ctx, "error federating accept: %v", err)
+ }
+
+ // Mark the fave as approved.
+ req.Like.PendingApproval = util.Ptr(false)
+ req.Like.ApprovedByURI = req.AuthorizationURI
+ req.Like.PreApproved = false
+
+ // Update in the db.
+ if err := p.state.DB.UpdateStatusFave(
+ ctx,
+ req.Like,
+ "pending_approval",
+ "approved_by_uri",
+ ); err != nil {
+ return gtserror.Newf("db error updating status fave: %w", err)
+ }
+
+ // Notify the faved account.
+ if err := p.surface.notifyFave(ctx, req.Like); err != nil {
+ log.Errorf(ctx, "error notifying fave: %v", err)
+ }
+
+ // Interaction counts changed on the faved status;
+ // uncache the prepared version from all timelines.
+ p.surface.invalidateStatusFromTimelines(req.Like.StatusID)
+
+ return nil
+}
+
func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg *messages.FromFediAPI) error {
boost, ok := fMsg.GTSModel.(*gtsmodel.Status)
if !ok {
@@ -610,7 +832,7 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg *messages.FromFediAPI
)
if err != nil {
if gtserror.IsUnretrievable(err) ||
- gtserror.NotPermitted(err) {
+ gtserror.IsNotPermitted(err) {
// Boosted status domain blocked, or
// otherwise not permitted, nothing to do.
log.Debugf(ctx, "skipping announce: %v", err)
@@ -632,7 +854,7 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg *messages.FromFediAPI
// preapproved, then just notify the account
// that's being interacted with: they can
// approve or deny the interaction later.
- if err := p.utils.requestAnnounce(ctx, boost); err != nil {
+ if err := p.utils.impoliteAnnounceRequest(ctx, boost); err != nil {
return gtserror.Newf("error pending boost: %w", err)
}
@@ -647,20 +869,24 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg *messages.FromFediAPI
// collection. Do the Accept immediately and
// then process everything else as normal.
- // Store an already-accepted interaction request.
- id := id.NewULID()
+ // Store an already-accepted
+ // impolite interaction request.
+ requestID := id.NewULID()
approval := &gtsmodel.InteractionRequest{
- ID: id,
- StatusID: boost.BoostOfID,
- TargetAccountID: boost.BoostOfAccountID,
- TargetAccount: boost.BoostOfAccount,
- InteractingAccountID: boost.AccountID,
- InteractingAccount: boost.Account,
- InteractionURI: boost.URI,
- InteractionType: gtsmodel.InteractionAnnounce,
- Announce: boost,
- URI: uris.GenerateURIForAccept(boost.BoostOfAccount.Username, id),
- AcceptedAt: time.Now(),
+ ID: requestID,
+ TargetStatusID: boost.BoostOfID,
+ TargetAccountID: boost.BoostOfAccountID,
+ TargetAccount: boost.BoostOfAccount,
+ InteractingAccountID: boost.AccountID,
+ InteractingAccount: boost.Account,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(boost.URI, gtsmodel.AnnounceRequestSuffix),
+ InteractionURI: boost.URI,
+ InteractionType: gtsmodel.InteractionAnnounce,
+ Polite: util.Ptr(false),
+ Announce: boost,
+ ResponseURI: uris.GenerateURIForAccept(boost.BoostOfAccount.Username, requestID),
+ AuthorizationURI: uris.GenerateURIForAuthorization(boost.BoostOfAccount.Username, requestID),
+ AcceptedAt: time.Now(),
}
if err := p.state.DB.PutInteractionRequest(ctx, approval); err != nil {
return gtserror.Newf("db error putting pre-approved interaction request: %w", err)
@@ -669,7 +895,7 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg *messages.FromFediAPI
// Mark the boost itself as now approved.
boost.PendingApproval = util.Ptr(false)
boost.PreApproved = false
- boost.ApprovedByURI = approval.URI
+ boost.ApprovedByURI = approval.AuthorizationURI
if err := p.state.DB.UpdateStatus(
ctx,
boost,
@@ -708,6 +934,103 @@ func (p *fediAPI) CreateAnnounce(ctx context.Context, fMsg *messages.FromFediAPI
return nil
}
+func (p *fediAPI) CreateAnnounceRequest(ctx context.Context, fMsg *messages.FromFediAPI) error {
+ req, ok := fMsg.GTSModel.(*gtsmodel.InteractionRequest)
+ if !ok {
+ return gtserror.Newf("%T not parseable as *gtsmodel.InteractionRequest", fMsg.GTSModel)
+ }
+
+ // At this point the not-yet-handled interaction req
+ // is in the database, but the announce isn't yet.
+ //
+ // We can check permissions for the announce *and*
+ // put it in the db (if acceptable) by doing Enrich.
+ boost, err := p.federate.EnrichAnnounce(
+ ctx,
+ req.Announce,
+ fMsg.Receiving.Username,
+ )
+
+ switch {
+ case err == nil:
+ // All fine.
+
+ case gtserror.IsNotPermitted(err):
+ // Announce is straight up not permitted
+ // by the interaction policy of the status
+ // it's targeting. Nothing more to do.
+ log.Debugf(ctx,
+ "dropping unpermitted AnnounceRequest with instrument %s",
+ req.Announce.URI,
+ )
+ return nil
+
+ default:
+ // There's some real error.
+ return gtserror.Newf(
+ "error processing AnnounceRequest with instrument %s: %w",
+ req.Announce.URI, err,
+ )
+ }
+
+ // The announce is permitted. Check if we
+ // should send out an Accept immediately.
+ manualApproval := *boost.PendingApproval && !boost.PreApproved
+ if manualApproval {
+ // The announce requires manual approval.
+ //
+ // Just notify target account about
+ // the requested interaction.
+ if err := p.surface.notifyPendingAnnounce(ctx, boost); err != nil {
+ return gtserror.Newf("error notifying pending announce: %w", err)
+ }
+
+ return nil
+ }
+
+ // The announce is automatically approved,
+ // mark the request as accepted.
+ req.AcceptedAt = time.Now()
+ req.ResponseURI = uris.GenerateURIForAccept(
+ req.TargetAccount.Username, req.ID,
+ )
+ req.AuthorizationURI = uris.GenerateURIForAuthorization(
+ req.TargetAccount.Username, req.ID,
+ )
+
+ // Update in the db.
+ if err := p.state.DB.UpdateInteractionRequest(
+ ctx,
+ req,
+ "accepted_at",
+ "response_uri",
+ "authorization_uri",
+ ); err != nil {
+ return gtserror.Newf("db error updating interaction request: %w", err)
+ }
+
+ // Send out the accept.
+ if err := p.federate.AcceptInteraction(ctx, req); err != nil {
+ log.Errorf(ctx, "error federating accept: %v", err)
+ }
+
+ // Update stats for the boosting account.
+ if err := p.utils.incrementStatusesCount(ctx, fMsg.Requesting, boost); err != nil {
+ log.Errorf(ctx, "error updating account stats: %v", err)
+ }
+
+ // Timeline the boost + notify recipient(s).
+ if err := p.surface.timelineAndNotifyStatus(ctx, boost); err != nil {
+ log.Errorf(ctx, "error timelining and notifying status: %v", err)
+ }
+
+ // Interaction counts changed on the boosted status;
+ // uncache the prepared version from all timelines.
+ p.surface.invalidateStatusFromTimelines(boost.BoostOfID)
+
+ return nil
+}
+
func (p *fediAPI) CreateBlock(ctx context.Context, fMsg *messages.FromFediAPI) error {
block, ok := fMsg.GTSModel.(*gtsmodel.Block)
if !ok {
@@ -842,29 +1165,29 @@ func (p *fediAPI) AcceptLike(ctx context.Context, fMsg *messages.FromFediAPI) er
}
func (p *fediAPI) AcceptReply(ctx context.Context, fMsg *messages.FromFediAPI) error {
- status, ok := fMsg.GTSModel.(*gtsmodel.Status)
+ reply, ok := fMsg.GTSModel.(*gtsmodel.Status)
if !ok {
return gtserror.Newf("%T not parseable as *gtsmodel.Status", fMsg.GTSModel)
}
// Update stats for the actor account.
- if err := p.utils.incrementStatusesCount(ctx, status.Account, status); err != nil {
+ if err := p.utils.incrementStatusesCount(ctx, reply.Account, reply); err != nil {
log.Errorf(ctx, "error updating account stats: %v", err)
}
// Timeline and notify the status.
- if err := p.surface.timelineAndNotifyStatus(ctx, status); err != nil {
+ if err := p.surface.timelineAndNotifyStatus(ctx, reply); err != nil {
log.Errorf(ctx, "error timelining and notifying status: %v", err)
}
// Send out the reply again, fully this time.
- if err := p.federate.CreateStatus(ctx, status); err != nil {
+ if err := p.federate.CreateStatus(ctx, reply); err != nil {
log.Errorf(ctx, "error federating announce: %v", err)
}
// Interaction counts changed on the replied-to status;
// uncache the prepared version from all timelines.
- p.surface.invalidateStatusFromTimelines(status.InReplyToID)
+ p.surface.invalidateStatusFromTimelines(reply.InReplyToID)
return nil
}
@@ -893,9 +1216,9 @@ func (p *fediAPI) AcceptRemoteStatus(ctx context.Context, fMsg *messages.FromFed
// barebones status and insert it into the database,
// if indeed it's actually a status URI we can fetch.
//
- // This will also check whether the given AcceptIRI
+ // This will also check whether the given approvedByURI
// actually grants permission for this status.
- status, _, err := p.federate.RefreshStatus(ctx,
+ reply, _, err := p.federate.RefreshStatus(ctx,
fMsg.Receiving.Username,
bareStatus,
nil, nil,
@@ -906,20 +1229,70 @@ func (p *fediAPI) AcceptRemoteStatus(ctx context.Context, fMsg *messages.FromFed
// No error means it was indeed a remote status, and the
// given approvedByURI permitted it. Timeline and notify it.
- if err := p.surface.timelineAndNotifyStatus(ctx, status); err != nil {
+ if err := p.surface.timelineAndNotifyStatus(ctx, reply); err != nil {
log.Errorf(ctx, "error timelining and notifying status: %v", err)
}
// Interaction counts changed on the interacted status;
// uncache the prepared version from all timelines.
- if status.InReplyToID != "" {
- p.surface.invalidateStatusFromTimelines(status.InReplyToID)
+ if reply.InReplyToID != "" {
+ p.surface.invalidateStatusFromTimelines(reply.InReplyToID)
+ }
+
+ if reply.BoostOfID != "" {
+ p.surface.invalidateStatusFromTimelines(reply.BoostOfID)
+ }
+
+ return nil
+}
+
+func (p *fediAPI) AcceptPoliteReplyRequest(ctx context.Context, fMsg *messages.FromFediAPI) error {
+ if util.IsNil(fMsg.GTSModel) {
+ // If the interaction request is nil, this
+ // must be an accept of a remote ReplyRequest
+ // not targeting one of our statuses.
+ //
+ // Just pass it to the AcceptRemoteStatus
+ // func to do dereferencing + side effects.
+ log.Debug(ctx, "accepting remote ReplyRequest for remote reply")
+ return p.AcceptRemoteStatus(ctx, fMsg)
+ }
+
+ // If the interaction request is not nil, this will
+ // be an accept of one of our replies to a remote.
+ //
+ // Since the int req + reply have already been updated
+ // in the federatingDB, we just need to do side effects.
+ intReq, ok := fMsg.GTSModel.(*gtsmodel.InteractionRequest)
+ if !ok {
+ return gtserror.Newf("%T not parseable as *gtsmodel.InteractionRequest", fMsg.GTSModel)
}
- if status.BoostOfID != "" {
- p.surface.invalidateStatusFromTimelines(status.BoostOfID)
+ // Ensure reply populated.
+ reply := intReq.Reply
+ if err := p.state.DB.PopulateStatus(ctx, reply); err != nil {
+ return gtserror.Newf("error populating status: %w", err)
}
+ // Update stats for the actor account.
+ if err := p.utils.incrementStatusesCount(ctx, reply.Account, reply); err != nil {
+ log.Errorf(ctx, "error updating account stats: %v", err)
+ }
+
+ // Timeline and notify the status.
+ if err := p.surface.timelineAndNotifyStatus(ctx, reply); err != nil {
+ log.Errorf(ctx, "error timelining and notifying status: %v", err)
+ }
+
+ // Send out the reply with approval attached.
+ if err := p.federate.CreateStatus(ctx, reply); err != nil {
+ log.Errorf(ctx, "error federating announce: %v", err)
+ }
+
+ // Interaction counts changed on the replied-to status;
+ // uncache the prepared version from all timelines.
+ p.surface.invalidateStatusFromTimelines(reply.InReplyToID)
+
return nil
}
@@ -1169,7 +1542,7 @@ func (p *fediAPI) RejectReply(ctx context.Context, fMsg *messages.FromFediAPI) e
// be in the database, we just need to do side effects.
// Get the rejected status.
- status, err := p.state.DB.GetStatusByURI(
+ reply, err := p.state.DB.GetStatusByURI(
gtscontext.SetBarebones(ctx),
req.InteractionURI,
)
@@ -1189,7 +1562,7 @@ func (p *fediAPI) RejectReply(ctx context.Context, fMsg *messages.FromFediAPI) e
// Perform the actual status deletion.
if err := p.utils.wipeStatus(
ctx,
- status,
+ reply,
deleteAttachments,
copyToSinBin,
); err != nil {
diff --git a/internal/processing/workers/fromfediapi_test.go b/internal/processing/workers/fromfediapi_test.go
index 7811e9f3d..790c78b70 100644
--- a/internal/processing/workers/fromfediapi_test.go
+++ b/internal/processing/workers/fromfediapi_test.go
@@ -18,6 +18,7 @@
package workers_test
import (
+ "bytes"
"context"
"encoding/json"
"errors"
@@ -26,11 +27,13 @@ import (
"testing"
"time"
+ "code.superseriousbusiness.org/activity/streams/vocab"
"code.superseriousbusiness.org/gotosocial/internal/ap"
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
"code.superseriousbusiness.org/gotosocial/internal/db"
"code.superseriousbusiness.org/gotosocial/internal/gtscontext"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
+ "code.superseriousbusiness.org/gotosocial/internal/id"
"code.superseriousbusiness.org/gotosocial/internal/messages"
"code.superseriousbusiness.org/gotosocial/internal/stream"
"code.superseriousbusiness.org/gotosocial/internal/util"
@@ -781,6 +784,123 @@ func (suite *FromFediAPITestSuite) TestUpdateNote() {
}
}
+func (suite *FromFediAPITestSuite) TestCreateReplyRequest() {
+ var (
+ ctx = suite.T().Context()
+ testStructs = testrig.SetupTestStructs(rMediaPath, rTemplatePath)
+ requesting = suite.testAccounts["remote_account_1"]
+ receiving = suite.testAccounts["admin_account"]
+ testStatus = suite.testStatuses["admin_account_status_1"]
+ intReqURI = "http://fossbros-anonymous.io/requests/87fb1478-ac46-406a-8463-96ce05645219"
+ intURI = "http://fossbros-anonymous.io/users/foss_satan/statuses/87fb1478-ac46-406a-8463-96ce05645219"
+ jsonStr = `{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://gotosocial.org/ns",
+ {
+ "sensitive": "as:sensitive"
+ }
+ ],
+ "type": "ReplyRequest",
+ "id": "` + intReqURI + `",
+ "actor": "` + requesting.URI + `",
+ "object": "` + testStatus.URI + `",
+ "to": "` + receiving.URI + `",
+ "instrument": {
+ "attributedTo": "` + requesting.URI + `",
+ "cc": "` + requesting.FollowersURI + `",
+ "content": "\u003cp\u003ethis is a reply!\u003c/p\u003e",
+ "id": "` + intURI + `",
+ "inReplyTo": "` + testStatus.URI + `",
+ "tag": {
+ "href": "` + receiving.URI + `",
+ "name": "@` + receiving.Username + `@localhost:8080",
+ "type": "Mention"
+ },
+ "to": "https://www.w3.org/ns/activitystreams#Public",
+ "type": "Note"
+ }
+}`
+ )
+ defer testrig.TearDownTestStructs(testStructs)
+
+ suite.T().Logf("testing reply request:\n\n%s", jsonStr)
+
+ // Decode the reply request + embedded statusable.
+ t, err := ap.DecodeType(ctx, io.NopCloser(bytes.NewBufferString(jsonStr)))
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+ replyReq := t.(vocab.GoToSocialReplyRequest)
+ statusable := replyReq.GetActivityStreamsInstrument().At(0).GetActivityStreamsNote().(ap.Statusable)
+
+ // Create a pending interaction request in the
+ // database, as though the reply req had already
+ // passed through the federatingdb function.
+ intReq := &gtsmodel.InteractionRequest{
+ ID: id.NewULID(),
+ TargetStatusID: testStatus.ID,
+ TargetStatus: testStatus,
+ TargetAccountID: receiving.ID,
+ TargetAccount: receiving,
+ InteractingAccountID: requesting.ID,
+ InteractingAccount: requesting,
+ InteractionRequestURI: intReqURI,
+ InteractionURI: ap.GetJSONLDId(statusable).String(),
+ InteractionType: gtsmodel.InteractionReply,
+ Polite: util.Ptr(true),
+ Reply: nil, // Not settable yet.
+ }
+ if err := testStructs.State.DB.PutInteractionRequest(ctx, intReq); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // Process the message.
+ if err = testStructs.Processor.Workers().ProcessFromFediAPI(
+ ctx,
+ &messages.FromFediAPI{
+ APObjectType: ap.ActivityReplyRequest,
+ APActivityType: ap.ActivityCreate,
+ GTSModel: intReq,
+ APObject: statusable,
+ Receiving: receiving,
+ Requesting: requesting,
+ },
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ // The interaction request should be accepted.
+ intReq, err = testStructs.State.DB.GetInteractionRequestByID(ctx, intReq.ID)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+ suite.WithinDuration(time.Now(), intReq.AcceptedAt, 1*time.Minute)
+ suite.NotEmpty(intReq.AuthorizationURI)
+ suite.NotEmpty(intReq.ResponseURI)
+
+ // Federator should send out an Accept that looks something like:
+ //
+ // {
+ // "@context": [
+ // "https://gotosocial.org/ns",
+ // "https://www.w3.org/ns/activitystreams"
+ // ],
+ // "actor": "http://localhost:8080/users/admin",
+ // "id": "http://localhost:8080/users/admin/accepts/01K2CV90660VRPZM39R35NMSG9",
+ // "object": {
+ // "actor": "http://fossbros-anonymous.io/users/foss_satan",
+ // "id": "http://fossbros-anonymous.io/requests/87fb1478-ac46-406a-8463-96ce05645219",
+ // "instrument": "http://fossbros-anonymous.io/users/foss_satan/statuses/87fb1478-ac46-406a-8463-96ce05645219",
+ // "object": "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R",
+ // "type": "ReplyRequest"
+ // },
+ // "result": "http://localhost:8080/users/admin/authorizations/01K2CV90660VRPZM39R35NMSG9",
+ // "to": "http://fossbros-anonymous.io/users/foss_satan",
+ // "type": "Accept"
+ // }
+}
+
func TestFromFederatorTestSuite(t *testing.T) {
suite.Run(t, &FromFediAPITestSuite{})
}
diff --git a/internal/processing/workers/util.go b/internal/processing/workers/util.go
index 3c17eaaf5..6382887eb 100644
--- a/internal/processing/workers/util.go
+++ b/internal/processing/workers/util.go
@@ -526,9 +526,13 @@ func (u *utils) decrementFollowRequestsCount(
return nil
}
-// requestFave stores an interaction request
+// impoliteFaveRequest stores an interaction request
// for the given fave, and notifies the interactee.
-func (u *utils) requestFave(
+//
+// It should be used only when an actor has sent a Like
+// directly in response to a post that requires approval
+// for it, instead of sending a LikeRequest.
+func (u *utils) impoliteFaveRequest(
ctx context.Context,
fave *gtsmodel.StatusFave,
) error {
@@ -555,8 +559,8 @@ func (u *utils) requestFave(
return nil
}
- // Create + store new interaction request.
- req = typeutils.StatusFaveToInteractionRequest(fave)
+ // Create + store new impolite interaction request.
+ req = typeutils.StatusFaveToImpoliteInteractionRequest(fave)
if err := u.state.DB.PutInteractionRequest(ctx, req); err != nil {
return gtserror.Newf("db error storing interaction request: %w", err)
}
@@ -569,9 +573,13 @@ func (u *utils) requestFave(
return nil
}
-// requestReply stores an interaction request
+// impoliteReplyRequest stores an interaction request
// for the given reply, and notifies the interactee.
-func (u *utils) requestReply(
+//
+// It should be used only when an actor has sent a reply
+// directly in response to a post that requires approval
+// for it, instead of sending a ReplyRequest.
+func (u *utils) impoliteReplyRequest(
ctx context.Context,
reply *gtsmodel.Status,
) error {
@@ -598,8 +606,8 @@ func (u *utils) requestReply(
return nil
}
- // Create + store interaction request.
- req = typeutils.StatusToInteractionRequest(reply)
+ // Create + store impolite interaction request.
+ req = typeutils.StatusToImpoliteInteractionRequest(reply)
if err := u.state.DB.PutInteractionRequest(ctx, req); err != nil {
return gtserror.Newf("db error storing interaction request: %w", err)
}
@@ -612,9 +620,13 @@ func (u *utils) requestReply(
return nil
}
-// requestAnnounce stores an interaction request
+// impoliteAnnounceRequest stores an interaction request
// for the given announce, and notifies the interactee.
-func (u *utils) requestAnnounce(
+//
+// It should be used only when an actor has sent an Announce
+// directly in response to a post that requires approval
+// for it, instead of sending an AnnounceRequest.
+func (u *utils) impoliteAnnounceRequest(
ctx context.Context,
boost *gtsmodel.Status,
) error {
@@ -641,8 +653,8 @@ func (u *utils) requestAnnounce(
return nil
}
- // Create + store interaction request.
- req = typeutils.StatusToInteractionRequest(boost)
+ // Create + store impolite interaction request.
+ req = typeutils.StatusToImpoliteInteractionRequest(boost)
if err := u.state.DB.PutInteractionRequest(ctx, req); err != nil {
return gtserror.Newf("db error storing interaction request: %w", err)
}
diff --git a/internal/transport/derefinstance.go b/internal/transport/derefinstance.go
index 4c21355d6..4d15daf3d 100644
--- a/internal/transport/derefinstance.go
+++ b/internal/transport/derefinstance.go
@@ -21,7 +21,6 @@ import (
"context"
"encoding/json"
"errors"
- "fmt"
"io"
"net/http"
"net/url"
@@ -77,13 +76,8 @@ func (t *transport) DereferenceInstance(ctx context.Context, iri *url.URL) (*gts
// we couldn't dereference the instance using any of the known methods, so just return a minimal representation
log.Debugf(ctx, "returning minimal representation of instance %s", iri.Host)
- id, err := id.NewRandomULID()
- if err != nil {
- return nil, fmt.Errorf("error creating new id for instance %s: %s", iri.Host, err)
- }
-
return &gtsmodel.Instance{
- ID: id,
+ ID: id.NewRandomULID(),
Domain: iri.Host,
URI: iri.String(),
}, nil
@@ -166,13 +160,8 @@ func (t *transport) dereferenceByAPIV1Instance(
contactUsername = apiResp.ContactAccount.Username
}
- ulid, err := id.NewRandomULID()
- if err != nil {
- return nil, err
- }
-
i := &gtsmodel.Instance{
- ID: ulid,
+ ID: id.NewRandomULID(),
Domain: iri.Host,
Title: apiResp.Title,
URI: iri.Scheme + "://" + iri.Host,
@@ -207,13 +196,8 @@ func (t *transport) dereferenceByNodeInfo(
//
// Start building out the bare minimum
// instance model, we'll add to it if we can.
- id, err := id.NewRandomULID()
- if err != nil {
- return nil, gtserror.Newf("error creating new id for instance %s: %w", iri.Host, err)
- }
-
i := &gtsmodel.Instance{
- ID: id,
+ ID: id.NewRandomULID(),
Domain: iri.Host,
URI: iri.String(),
}
diff --git a/internal/typeutils/astointernal.go b/internal/typeutils/astointernal.go
index ede2b3253..f352632b7 100644
--- a/internal/typeutils/astointernal.go
+++ b/internal/typeutils/astointernal.go
@@ -444,8 +444,8 @@ func (c *Converter) ASStatusToStatus(ctx context.Context, statusable ap.Statusab
// Set approvedByURI if present,
// for later dereferencing.
- if ipa, ok := statusable.(ap.InteractionPolicyAware); ok {
- approvedByURI := ap.GetApprovedBy(ipa)
+ if wab, ok := statusable.(ap.WithApprovedBy); ok {
+ approvedByURI := ap.GetApprovedBy(wab)
if approvedByURI != nil {
status.ApprovedByURI = approvedByURI.String()
}
diff --git a/internal/typeutils/internal.go b/internal/typeutils/internal.go
index 4504168ef..a18b7a287 100644
--- a/internal/typeutils/internal.go
+++ b/internal/typeutils/internal.go
@@ -104,17 +104,18 @@ func (c *Converter) StatusToBoost(
return boost, nil
}
-func StatusToInteractionRequest(status *gtsmodel.Status) *gtsmodel.InteractionRequest {
+func StatusToImpoliteInteractionRequest(status *gtsmodel.Status) *gtsmodel.InteractionRequest {
reqID := id.NewULIDFromTime(status.CreatedAt)
var (
- targetID string
- target *gtsmodel.Status
- targetAccountID string
- targetAccount *gtsmodel.Account
- interactionType gtsmodel.InteractionType
- reply *gtsmodel.Status
- announce *gtsmodel.Status
+ targetID string
+ target *gtsmodel.Status
+ targetAccountID string
+ targetAccount *gtsmodel.Account
+ interactionRequestURI string
+ interactionType gtsmodel.InteractionType
+ reply *gtsmodel.Status
+ announce *gtsmodel.Status
)
if status.InReplyToID != "" {
@@ -123,6 +124,7 @@ func StatusToInteractionRequest(status *gtsmodel.Status) *gtsmodel.InteractionRe
target = status.InReplyTo
targetAccountID = status.InReplyToAccountID
targetAccount = status.InReplyToAccount
+ interactionRequestURI = gtsmodel.ForwardCompatibleInteractionRequestURI(status.URI, gtsmodel.ReplyRequestSuffix)
interactionType = gtsmodel.InteractionReply
reply = status
} else {
@@ -131,41 +133,43 @@ func StatusToInteractionRequest(status *gtsmodel.Status) *gtsmodel.InteractionRe
target = status.BoostOf
targetAccountID = status.BoostOfAccountID
targetAccount = status.BoostOfAccount
+ interactionRequestURI = gtsmodel.ForwardCompatibleInteractionRequestURI(status.URI, gtsmodel.AnnounceRequestSuffix)
interactionType = gtsmodel.InteractionAnnounce
announce = status
}
return &gtsmodel.InteractionRequest{
- ID: reqID,
- CreatedAt: status.CreatedAt,
- StatusID: targetID,
- Status: target,
- TargetAccountID: targetAccountID,
- TargetAccount: targetAccount,
- InteractingAccountID: status.AccountID,
- InteractingAccount: status.Account,
- InteractionURI: status.URI,
- InteractionType: interactionType,
- Reply: reply,
- Announce: announce,
+ ID: reqID,
+ TargetStatusID: targetID,
+ TargetStatus: target,
+ TargetAccountID: targetAccountID,
+ TargetAccount: targetAccount,
+ InteractingAccountID: status.AccountID,
+ InteractingAccount: status.Account,
+ InteractionRequestURI: interactionRequestURI,
+ InteractionURI: status.URI,
+ InteractionType: interactionType,
+ Polite: util.Ptr(false),
+ Reply: reply,
+ Announce: announce,
}
}
-func StatusFaveToInteractionRequest(fave *gtsmodel.StatusFave) *gtsmodel.InteractionRequest {
+func StatusFaveToImpoliteInteractionRequest(fave *gtsmodel.StatusFave) *gtsmodel.InteractionRequest {
reqID := id.NewULIDFromTime(fave.CreatedAt)
-
return &gtsmodel.InteractionRequest{
- ID: reqID,
- CreatedAt: fave.CreatedAt,
- StatusID: fave.StatusID,
- Status: fave.Status,
- TargetAccountID: fave.TargetAccountID,
- TargetAccount: fave.TargetAccount,
- InteractingAccountID: fave.AccountID,
- InteractingAccount: fave.Account,
- InteractionURI: fave.URI,
- InteractionType: gtsmodel.InteractionLike,
- Like: fave,
+ ID: reqID,
+ TargetStatusID: fave.StatusID,
+ TargetStatus: fave.Status,
+ TargetAccountID: fave.TargetAccountID,
+ TargetAccount: fave.TargetAccount,
+ InteractingAccountID: fave.AccountID,
+ InteractingAccount: fave.Account,
+ InteractionRequestURI: gtsmodel.ForwardCompatibleInteractionRequestURI(fave.URI, gtsmodel.LikeRequestSuffix),
+ InteractionURI: fave.URI,
+ InteractionType: gtsmodel.InteractionLike,
+ Polite: util.Ptr(false),
+ Like: fave,
}
}
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
index 7cf736993..feb794e51 100644
--- a/internal/typeutils/internaltoas.go
+++ b/internal/typeutils/internaltoas.go
@@ -33,6 +33,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/ap"
"code.superseriousbusiness.org/gotosocial/internal/config"
"code.superseriousbusiness.org/gotosocial/internal/db"
+ "code.superseriousbusiness.org/gotosocial/internal/gtscontext"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/log"
@@ -489,8 +490,9 @@ func (c *Converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (ap.Stat
return nil, gtserror.Newf("error populating status: %w", err)
}
- var status ap.Statusable
-
+ // TODO: in future, allow longer
+ // posts to be federated as Articles.
+ var statusable ap.Statusable
if s.Poll != nil {
// If status has poll available, we convert
// it as an AS Question (similar to a Note).
@@ -502,80 +504,56 @@ func (c *Converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (ap.Stat
}
// Set poll as status.
- status = poll
+ statusable = poll
} else {
// Else we converter it as an AS Note.
- status = streams.NewActivityStreamsNote()
+ statusable = streams.NewActivityStreamsNote()
}
- // id
- statusURI, err := url.Parse(s.URI)
- if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", s.URI, err)
+ // `id` property.
+ if err := ap.SetJSONLDIdStr(statusable, s.URI); err != nil {
+ return nil, gtserror.Newf("error setting id: %w", err)
}
- statusIDProp := streams.NewJSONLDIdProperty()
- statusIDProp.SetIRI(statusURI)
- status.SetJSONLDId(statusIDProp)
- // type
- // will be set automatically by go-fed
+ // `summary` property.
+ ap.AppendSummary(statusable, s.ContentWarning)
- // summary aka cw
- statusSummaryProp := streams.NewActivityStreamsSummaryProperty()
- statusSummaryProp.AppendXMLSchemaString(s.ContentWarning)
- status.SetActivityStreamsSummary(statusSummaryProp)
-
- // inReplyTo
+ // `inReplyTo` property.
if s.InReplyToURI != "" {
rURI, err := url.Parse(s.InReplyToURI)
if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", s.InReplyToURI, err)
+ return nil, gtserror.Newf("error parsing inReplyTo: %w", err)
}
-
- inReplyToProp := streams.NewActivityStreamsInReplyToProperty()
- inReplyToProp.AppendIRI(rURI)
- status.SetActivityStreamsInReplyTo(inReplyToProp)
+ ap.AppendInReplyTo(statusable, rURI)
}
- // Set created / updated at properties.
- ap.SetPublished(status, s.CreatedAt)
+ // `published` and `updatedAt` properties.
+ ap.SetPublished(statusable, s.CreatedAt)
if at := s.EditedAt; !at.IsZero() {
- ap.SetUpdated(status, at)
+ ap.SetUpdated(statusable, at)
}
- // url
+ // Web-accessible `url` property.
if s.URL != "" {
sURL, err := url.Parse(s.URL)
if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", s.URL, err)
+ return nil, gtserror.Newf("error parsing url: %w", err)
}
-
- urlProp := streams.NewActivityStreamsUrlProperty()
- urlProp.AppendIRI(sURL)
- status.SetActivityStreamsUrl(urlProp)
+ ap.AppendURL(statusable, sURL)
}
- // attributedTo
- authorAccountURI, err := url.Parse(s.Account.URI)
+ // `attributedTo` property.
+ acctURI, err := url.Parse(s.Account.URI)
if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", s.Account.URI, err)
+ return nil, gtserror.Newf("error parsing account uri: %w", err)
}
- attributedToProp := streams.NewActivityStreamsAttributedToProperty()
- attributedToProp.AppendIRI(authorAccountURI)
- status.SetActivityStreamsAttributedTo(attributedToProp)
+ ap.AppendAttributedTo(statusable, acctURI)
- // tags
+ // Start building out `tag` property.
tagProp := streams.NewActivityStreamsTagProperty()
- // tag -- mentions
- mentions := s.Mentions
- if len(s.MentionIDs) != len(mentions) {
- mentions, err = c.state.DB.GetMentions(ctx, s.MentionIDs)
- if err != nil {
- return nil, gtserror.Newf("error getting mentions: %w", err)
- }
- }
- for _, m := range mentions {
+ // `tag`: mentions
+ for _, m := range s.Mentions {
asMention, err := c.MentionToAS(ctx, m)
if err != nil {
return nil, gtserror.Newf("error converting mention to AS mention: %w", err)
@@ -583,139 +561,109 @@ func (c *Converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (ap.Stat
tagProp.AppendActivityStreamsMention(asMention)
}
- // tag -- emojis
- emojis := s.Emojis
- if len(s.EmojiIDs) != len(emojis) {
- emojis, err = c.state.DB.GetEmojisByIDs(ctx, s.EmojiIDs)
- if err != nil {
- return nil, gtserror.Newf("error getting emojis from database: %w", err)
- }
- }
- for _, emoji := range emojis {
- asEmoji, err := c.EmojiToAS(ctx, emoji)
+ // `tag`: emojis
+ for _, e := range s.Emojis {
+ asEmoji, err := c.EmojiToAS(ctx, e)
if err != nil {
return nil, gtserror.Newf("error converting emoji to AS emoji: %w", err)
}
tagProp.AppendTootEmoji(asEmoji)
}
- // tag -- hashtags
- hashtags := s.Tags
- if len(s.TagIDs) != len(hashtags) {
- hashtags, err = c.state.DB.GetTags(ctx, s.TagIDs)
- if err != nil {
- return nil, gtserror.Newf("error getting tags: %w", err)
- }
- }
- for _, ht := range hashtags {
- asHashtag, err := c.TagToAS(ctx, ht)
+ // `tag`: hashtags
+ for _, t := range s.Tags {
+ asHashtag, err := c.TagToAS(ctx, t)
if err != nil {
return nil, gtserror.Newf("error converting tag to AS tag: %w", err)
}
tagProp.AppendTootHashtag(asHashtag)
}
- status.SetActivityStreamsTag(tagProp)
-
- // parse out some URIs we need here
- authorFollowersURI, err := url.Parse(s.Account.FollowersURI)
- if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", s.Account.FollowersURI, err)
- }
- publicURI, err := url.Parse(pub.PublicActivityPubIRI)
- if err != nil {
- return nil, gtserror.Newf("error parsing url %s: %w", pub.PublicActivityPubIRI, err)
- }
+ // Append built `tag` property.
+ statusable.SetActivityStreamsTag(tagProp)
- // to and cc
- toProp := streams.NewActivityStreamsToProperty()
- ccProp := streams.NewActivityStreamsCcProperty()
- switch s.Visibility {
- case gtsmodel.VisibilityDirect:
- // if DIRECT, then only mentioned users should be added to TO, and nothing to CC
- for _, m := range mentions {
+ // `to` and `cc` properties
+ // depend on visibility of post.
+ if s.Visibility == gtsmodel.VisibilityDirect {
+ // If DIRECT visibility, then only mentioned
+ // users should be added to TO, nothing in CC.
+ for _, m := range s.Mentions {
iri, err := url.Parse(m.TargetAccount.URI)
if err != nil {
- return nil, gtserror.Newf("error parsing uri %s: %w", m.TargetAccount.URI, err)
+ return nil, gtserror.Newf("error parsing mention target: %w", err)
}
- toProp.AppendIRI(iri)
+ ap.AppendTo(statusable, iri)
}
- case gtsmodel.VisibilityMutualsOnly:
- // TODO
- case gtsmodel.VisibilityFollowersOnly:
- // if FOLLOWERS ONLY then we want to add followers to TO, and mentions to CC
- toProp.AppendIRI(authorFollowersURI)
- for _, m := range mentions {
- iri, err := url.Parse(m.TargetAccount.URI)
- if err != nil {
- return nil, gtserror.Newf("error parsing uri %s: %w", m.TargetAccount.URI, err)
- }
- ccProp.AppendIRI(iri)
+
+ } else {
+ // For all other visibilities
+ // we need the followers URI.
+ followersURI, err := url.Parse(s.Account.FollowersURI)
+ if err != nil {
+ return nil, gtserror.Newf("error parsing followers url: %w", err)
}
- case gtsmodel.VisibilityUnlocked:
- // if UNLOCKED, we want to add followers to TO, and public and mentions to CC
- toProp.AppendIRI(authorFollowersURI)
- ccProp.AppendIRI(publicURI)
- for _, m := range mentions {
- iri, err := url.Parse(m.TargetAccount.URI)
- if err != nil {
- return nil, gtserror.Newf("error parsing uri %s: %w", m.TargetAccount.URI, err)
- }
- ccProp.AppendIRI(iri)
+
+ switch s.Visibility {
+ // If FOLLOWERS ONLY visibility, then
+ // we want to add followers to TO.
+ case gtsmodel.VisibilityFollowersOnly:
+ ap.AppendTo(statusable, followersURI)
+
+ // If UNLOCKED visibility, then
+ // we want to add followers to TO,
+ // with public in CC.
+ case gtsmodel.VisibilityUnlocked:
+ ap.AppendTo(statusable, followersURI)
+ ap.AppendCc(statusable, ap.PublicIRI())
+
+ // If PUBLIC visibility, then
+ // we want to add public to TO,
+ // with followers in CC.
+ case gtsmodel.VisibilityPublic:
+ ap.AppendTo(statusable, ap.PublicIRI())
+ ap.AppendCc(statusable, followersURI)
}
- case gtsmodel.VisibilityPublic:
- // if PUBLIC, we want to add public to TO, and followers and mentions to CC
- toProp.AppendIRI(publicURI)
- ccProp.AppendIRI(authorFollowersURI)
- for _, m := range mentions {
+
+ // In all non-direct cases,
+ // mentioned accounts go in Cc.
+ for _, m := range s.Mentions {
iri, err := url.Parse(m.TargetAccount.URI)
if err != nil {
return nil, gtserror.Newf("error parsing uri %s: %w", m.TargetAccount.URI, err)
}
- ccProp.AppendIRI(iri)
+ ap.AppendCc(statusable, iri)
}
}
- status.SetActivityStreamsTo(toProp)
- status.SetActivityStreamsCc(ccProp)
-
- // conversation
- // TODO
-
- // content -- the actual post
- // itself, plus the language
- contentProp := streams.NewActivityStreamsContentProperty()
- contentProp.AppendXMLSchemaString(s.Content)
+ // `content` and `contentMap` properties.
+ ap.AppendContent(statusable, s.Content)
if s.Language != "" {
- contentProp.AppendRDFLangString(map[string]string{
- s.Language: s.Content,
- })
+ ap.AppendContentMap(
+ statusable,
+ map[string]string{
+ s.Language: s.Content,
+ },
+ )
}
- status.SetActivityStreamsContent(contentProp)
-
- // attachments
- if err := c.attachAttachments(ctx, s, status); err != nil {
+ // `attachment` property.
+ if err := c.attachAttachments(ctx, s, statusable); err != nil {
return nil, gtserror.Newf("error attaching attachments: %w", err)
}
- // replies
- repliesCollection, err := c.StatusToASRepliesCollection(ctx, s, false)
+ // `replies` collection property.
+ // Todo: add `likes` and `shares` properties.
+ replies, err := c.StatusToASRepliesCollection(ctx, s, false)
if err != nil {
- return nil, fmt.Errorf("error creating repliesCollection: %w", err)
+ return nil, gtserror.Newf("error creating repliesCollection: %w", err)
}
+ ap.SetReplies(statusable, replies)
- repliesProp := streams.NewActivityStreamsRepliesProperty()
- repliesProp.SetActivityStreamsCollection(repliesCollection)
- status.SetActivityStreamsReplies(repliesProp)
+ // `sensitive` property.
+ ap.AppendSensitive(statusable, *s.Sensitive)
- // sensitive
- sensitiveProp := streams.NewActivityStreamsSensitiveProperty()
- sensitiveProp.AppendXMLSchemaBoolean(*s.Sensitive)
- status.SetActivityStreamsSensitive(sensitiveProp)
-
- // interactionPolicy
- if ipa, ok := status.(ap.InteractionPolicyAware); ok {
+ // `interactionPolicy` property.
+ if wip, ok := statusable.(ap.WithInteractionPolicy); ok {
var p *gtsmodel.InteractionPolicy
if s.InteractionPolicy != nil {
// Use InteractionPolicy
@@ -728,28 +676,29 @@ func (c *Converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (ap.Stat
}
policy, err := c.InteractionPolicyToASInteractionPolicy(ctx, p, s)
if err != nil {
- return nil, fmt.Errorf("error creating interactionPolicy: %w", err)
+ return nil, gtserror.Newf("error creating interactionPolicy: %w", err)
}
// Set interaction policy.
policyProp := streams.NewGoToSocialInteractionPolicyProperty()
policyProp.AppendGoToSocialInteractionPolicy(policy)
- ipa.SetGoToSocialInteractionPolicy(policyProp)
+ wip.SetGoToSocialInteractionPolicy(policyProp)
+ }
- // Parse + set approvedBy.
- if s.ApprovedByURI != "" {
- approvedBy, err := url.Parse(s.ApprovedByURI)
- if err != nil {
- return nil, fmt.Errorf("error parsing approvedBy: %w", err)
- }
+ // `approvedBy` and/or `replyAuthorization` property.
+ if s.ApprovedByURI != "" {
+ err := c.appendASInteractionAuthorization(
+ ctx,
+ s.ApprovedByURI,
+ statusable,
+ )
- approvedByProp := streams.NewGoToSocialApprovedByProperty()
- approvedByProp.Set(approvedBy)
- ipa.SetGoToSocialApprovedBy(approvedByProp)
+ if err != nil {
+ return nil, gtserror.Newf("error setting reply authorization field(s): %w", err)
}
}
- return status, nil
+ return statusable, nil
}
func (c *Converter) addPollToAS(poll *gtsmodel.Poll, dst ap.Pollable) error {
@@ -875,10 +824,7 @@ func (c *Converter) StatusToASDelete(ctx context.Context, s *gtsmodel.Status) (v
// At worst, a remote instance becomes aware of the
// URI for a status which is now deleted anyway.
if s.Visibility != gtsmodel.VisibilityDirect {
- publicURI, err := url.Parse(pub.PublicActivityPubIRI)
- if err != nil {
- return nil, fmt.Errorf("StatusToASDelete: error parsing url %s: %w", pub.PublicActivityPubIRI, err)
- }
+ publicURI := ap.PublicIRI()
toProp.AppendIRI(publicURI)
actorFollowersURI, err := url.Parse(s.Account.FollowersURI)
@@ -1227,180 +1173,137 @@ func (c *Converter) attachAttachments(
// FaveToAS converts a gts model status fave into an activityStreams LIKE, suitable for federation.
// We want to end up with something like this:
//
-// {
-// "@context": "https://www.w3.org/ns/activitystreams",
-// "actor": "https://ondergrond.org/users/dumpsterqueer",
-// "id": "https://ondergrond.org/users/dumpsterqueer#likes/44584",
-// "object": "https://testingtesting123.xyz/users/gotosocial_test_account/statuses/771aea80-a33d-4d6d-8dfd-57d4d2bfcbd4",
-// "type": "Like"
-// }
+// {
+// "@context": "https://www.w3.org/ns/activitystreams",
+// "actor": "https://ondergrond.org/users/dumpsterqueer",
+// "id": "https://ondergrond.org/users/dumpsterqueer#likes/44584",
+// "object": "https://testingtesting123.xyz/users/gotosocial_test_account/statuses/771aea80-a33d-4d6d-8dfd-57d4d2bfcbd4",
+// "type": "Like"
+// }
func (c *Converter) FaveToAS(ctx context.Context, f *gtsmodel.StatusFave) (vocab.ActivityStreamsLike, error) {
- // check if targetStatus is already pinned to this fave, and fetch it if not
- if f.Status == nil {
- s, err := c.state.DB.GetStatusByID(ctx, f.StatusID)
- if err != nil {
- return nil, fmt.Errorf("FaveToAS: error fetching target status from database: %s", err)
- }
- f.Status = s
- }
-
- // check if the targetAccount is already pinned to this fave, and fetch it if not
- if f.TargetAccount == nil {
- a, err := c.state.DB.GetAccountByID(ctx, f.TargetAccountID)
- if err != nil {
- return nil, fmt.Errorf("FaveToAS: error fetching target account from database: %s", err)
- }
- f.TargetAccount = a
- }
-
- // check if the faving account is already pinned to this fave, and fetch it if not
- if f.Account == nil {
- a, err := c.state.DB.GetAccountByID(ctx, f.AccountID)
- if err != nil {
- return nil, fmt.Errorf("FaveToAS: error fetching faving account from database: %s", err)
- }
- f.Account = a
+ // Ensure the status fave model is fully populated.
+ if err := c.state.DB.PopulateStatusFave(ctx, f); err != nil {
+ return nil, gtserror.Newf("error populating status fave: %w", err)
}
- // create the like
+ // Start building the Like.
like := streams.NewActivityStreamsLike()
- // set the actor property to the fave-ing account's URI
- actorProp := streams.NewActivityStreamsActorProperty()
- actorIRI, err := url.Parse(f.Account.URI)
- if err != nil {
- return nil, fmt.Errorf("FaveToAS: error parsing uri %s: %s", f.Account.URI, err)
+ // `id` property.
+ if err := ap.SetJSONLDIdStr(like, f.URI); err != nil {
+ return nil, gtserror.Newf("error setting id: %w", err)
}
- actorProp.AppendIRI(actorIRI)
- like.SetActivityStreamsActor(actorProp)
- // set the ID property to the fave's URI
- idProp := streams.NewJSONLDIdProperty()
- idIRI, err := url.Parse(f.URI)
+ // `actor` property is the faving account URI.
+ actorIRI, err := url.Parse(f.Account.URI)
if err != nil {
- return nil, fmt.Errorf("FaveToAS: error parsing uri %s: %s", f.URI, err)
+ return nil, gtserror.Newf("error parsing actor uri: %w", err)
}
- idProp.Set(idIRI)
- like.SetJSONLDId(idProp)
+ ap.AppendActorIRIs(like, actorIRI)
- // set the object property to the target status's URI
- objectProp := streams.NewActivityStreamsObjectProperty()
- statusIRI, err := url.Parse(f.Status.URI)
+ // `object` property is the target status URI.
+ targetStatusIRI, err := url.Parse(f.Status.URI)
if err != nil {
- return nil, fmt.Errorf("FaveToAS: error parsing uri %s: %s", f.Status.URI, err)
+ return nil, gtserror.Newf("error parsing status uri: %w", err)
}
- objectProp.AppendIRI(statusIRI)
- like.SetActivityStreamsObject(objectProp)
+ ap.AppendObjectIRIs(like, targetStatusIRI)
- // set the TO property to the target account's IRI
- toProp := streams.NewActivityStreamsToProperty()
+ // `to` is the owner of the target status.
toIRI, err := url.Parse(f.TargetAccount.URI)
if err != nil {
- return nil, fmt.Errorf("FaveToAS: error parsing uri %s: %s", f.TargetAccount.URI, err)
+ return nil, gtserror.Newf("error parsing account uri: %w", err)
}
- toProp.AppendIRI(toIRI)
- like.SetActivityStreamsTo(toProp)
+ ap.AppendTo(like, toIRI)
- // Parse + set approvedBy.
+ // Parse + set authorization.
if f.ApprovedByURI != "" {
- approvedBy, err := url.Parse(f.ApprovedByURI)
+ err := c.appendASInteractionAuthorization(
+ ctx,
+ f.ApprovedByURI,
+ like,
+ )
if err != nil {
- return nil, fmt.Errorf("error parsing approvedBy: %w", err)
+ return nil, gtserror.Newf("error setting like authorization field(s): %w", err)
}
-
- approvedByProp := streams.NewGoToSocialApprovedByProperty()
- approvedByProp.Set(approvedBy)
- like.SetGoToSocialApprovedBy(approvedByProp)
}
return like, nil
}
-// BoostToAS converts a gts model boost into an activityStreams ANNOUNCE, suitable for federation
-func (c *Converter) BoostToAS(ctx context.Context, boostWrapperStatus *gtsmodel.Status, boostingAccount *gtsmodel.Account, boostedAccount *gtsmodel.Account) (vocab.ActivityStreamsAnnounce, error) {
- // the boosted status is probably pinned to the boostWrapperStatus but double check to make sure
- if boostWrapperStatus.BoostOf == nil {
- b, err := c.state.DB.GetStatusByID(ctx, boostWrapperStatus.BoostOfID)
- if err != nil {
- return nil, fmt.Errorf("BoostToAS: error getting status with ID %s from the db: %s", boostWrapperStatus.BoostOfID, err)
- }
- boostWrapperStatus.BoostOf = b
+// BoostToAS converts a *gtsmodel.Status boost wrapper into
+// an ActivityStreams Announce activity, suitable for federation.
+//
+// Result will look something like:
+//
+// {
+// "@context": "https://www.w3.org/ns/activitystreams",
+// "actor": "http://localhost:8080/users/the_mighty_zork",
+// "cc": "http://localhost:8080/users/the_mighty_zork",
+// "id": "http://localhost:8080/users/the_mighty_zork/statuses/01G74JJ1KS331G2JXHRMZCE0ER",
+// "object": "http://localhost:8080/users/the_mighty_zork/statuses/01FCTA44PW9H1TB328S9AQXKDS",
+// "published": "2022-06-09T13:12:00Z",
+// "to": "http://localhost:8080/users/the_mighty_zork/followers",
+// "type": "Announce"
+// }
+func (c *Converter) BoostToAS(ctx context.Context, bw *gtsmodel.Status) (vocab.ActivityStreamsAnnounce, error) {
+ // Ensure the status model is fully populated.
+ if err := c.state.DB.PopulateStatus(ctx, bw); err != nil {
+ return nil, gtserror.Newf("error populating boost wrapper status: %w", err)
}
- // create the announce
+ // Start building the Announce.
announce := streams.NewActivityStreamsAnnounce()
- // set the actor
- boosterURI, err := url.Parse(boostingAccount.URI)
- if err != nil {
- return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", boostingAccount.URI, err)
+ // `id` property.
+ if err := ap.SetJSONLDIdStr(announce, bw.URI); err != nil {
+ return nil, gtserror.Newf("error setting id: %w", err)
}
- actorProp := streams.NewActivityStreamsActorProperty()
- actorProp.AppendIRI(boosterURI)
- announce.SetActivityStreamsActor(actorProp)
- // set the ID
- boostIDURI, err := url.Parse(boostWrapperStatus.URI)
+ // `actor` property.
+ actorURI, err := url.Parse(bw.AccountURI)
if err != nil {
- return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", boostWrapperStatus.URI, err)
+ return nil, fmt.Errorf("error parsing actor uri: %s", err)
}
- idProp := streams.NewJSONLDIdProperty()
- idProp.SetIRI(boostIDURI)
- announce.SetJSONLDId(idProp)
+ ap.AppendActorIRIs(announce, actorURI)
- // set the object
- boostedStatusURI, err := url.Parse(boostWrapperStatus.BoostOf.URI)
+ // `object` property is the target status URI.
+ boostTargetURI, err := url.Parse(bw.BoostOf.URI)
if err != nil {
- return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", boostWrapperStatus.BoostOf.URI, err)
+ return nil, fmt.Errorf("error parsing target status uri: %s", err)
}
- objectProp := streams.NewActivityStreamsObjectProperty()
- objectProp.AppendIRI(boostedStatusURI)
- announce.SetActivityStreamsObject(objectProp)
+ ap.AppendObjectIRIs(announce, boostTargetURI)
- // set the published time
- publishedProp := streams.NewActivityStreamsPublishedProperty()
- publishedProp.Set(boostWrapperStatus.CreatedAt)
- announce.SetActivityStreamsPublished(publishedProp)
+ // `published` property is the time of the boost.
+ ap.SetPublished(announce, bw.CreatedAt)
- // set the to
- followersURI, err := url.Parse(boostingAccount.FollowersURI)
+ // `to` property.
+ followersURI, err := url.Parse(bw.Account.FollowersURI)
if err != nil {
- return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", boostingAccount.FollowersURI, err)
+ return nil, fmt.Errorf("error parsing followers URI: %s", err)
}
- toProp := streams.NewActivityStreamsToProperty()
- toProp.AppendIRI(followersURI)
- announce.SetActivityStreamsTo(toProp)
+ ap.AppendTo(announce, followersURI)
- // set the cc
- ccProp := streams.NewActivityStreamsCcProperty()
- boostedAccountURI, err := url.Parse(boostedAccount.URI)
+ // `cc` property.
+ boostedAccountURI, err := url.Parse(bw.BoostOfAccount.URI)
if err != nil {
- return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", boostedAccount.URI, err)
+ return nil, fmt.Errorf("error parsing target account URI: %s", err)
}
- ccProp.AppendIRI(boostedAccountURI)
+ ap.AppendCc(announce, boostedAccountURI)
- // maybe CC it to public depending on the boosted status visibility
- switch boostWrapperStatus.BoostOf.Visibility {
+ // `cc` should include public if
+ // this is a public or unlocked boost.
+ switch bw.BoostOf.Visibility {
case gtsmodel.VisibilityPublic, gtsmodel.VisibilityUnlocked:
- publicURI, err := url.Parse(pub.PublicActivityPubIRI)
- if err != nil {
- return nil, fmt.Errorf("BoostToAS: error parsing uri %s: %s", pub.PublicActivityPubIRI, err)
- }
- ccProp.AppendIRI(publicURI)
+ ap.AppendCc(announce, ap.PublicIRI())
}
- announce.SetActivityStreamsCc(ccProp)
-
- // Parse + set approvedBy.
- if boostWrapperStatus.ApprovedByURI != "" {
- approvedBy, err := url.Parse(boostWrapperStatus.ApprovedByURI)
+ // Parse + set authorization.
+ if bw.ApprovedByURI != "" {
+ approvedBy, err := url.Parse(bw.ApprovedByURI)
if err != nil {
return nil, fmt.Errorf("error parsing approvedBy: %w", err)
}
-
- approvedByProp := streams.NewGoToSocialApprovedByProperty()
- approvedByProp.Set(approvedBy)
- announce.SetGoToSocialApprovedBy(approvedByProp)
+ ap.SetApprovedBy(announce, approvedBy)
}
return announce, nil
@@ -2172,7 +2075,7 @@ func (c *Converter) InteractionReqToASAccept(
) (vocab.ActivityStreamsAccept, error) {
accept := streams.NewActivityStreamsAccept()
- acceptID, err := url.Parse(req.URI)
+ acceptID, err := url.Parse(req.ResponseURI)
if err != nil {
return nil, gtserror.Newf("invalid accept uri: %w", err)
}
@@ -2187,14 +2090,14 @@ func (c *Converter) InteractionReqToASAccept(
return nil, gtserror.Newf("invalid object uri: %w", err)
}
- if req.Status == nil {
- req.Status, err = c.state.DB.GetStatusByID(ctx, req.StatusID)
+ if req.TargetStatus == nil {
+ req.TargetStatus, err = c.state.DB.GetStatusByID(ctx, req.TargetStatusID)
if err != nil {
return nil, gtserror.Newf("db error getting interaction req target status: %w", err)
}
}
- targetIRI, err := url.Parse(req.Status.URI)
+ targetIRI, err := url.Parse(req.TargetStatus.URI)
if err != nil {
return nil, gtserror.Newf("invalid interaction req target status uri: %w", err)
}
@@ -2204,35 +2107,99 @@ func (c *Converter) InteractionReqToASAccept(
return nil, gtserror.Newf("invalid interacting account uri: %w", err)
}
- // Set id to the URI of
- // interaction request.
+ // Set id.
ap.SetJSONLDId(accept, acceptID)
- // Actor is the account that
- // owns the approval / accept.
+ // Actor is the account
+ // Accepting the interaction.
ap.AppendActorIRIs(accept, actorIRI)
- // Object is the interaction URI.
- ap.AppendObjectIRIs(accept, objectIRI)
+ polite := req.IsPolite()
+ if polite {
+ // If accepting a polite request, put
+ // a barebones version of the *Request
+ // in the `object` property.
+ var (
+ objProp = streams.NewActivityStreamsObjectProperty()
+ ir ap.InteractionRequestable
+ )
+ switch req.InteractionType {
+ case gtsmodel.InteractionLike:
+ v := streams.NewGoToSocialLikeRequest()
+ objProp.AppendGoToSocialLikeRequest(v)
+ ir = v
+ case gtsmodel.InteractionReply:
+ v := streams.NewGoToSocialReplyRequest()
+ objProp.AppendGoToSocialReplyRequest(v)
+ ir = v
+ case gtsmodel.InteractionAnnounce:
+ v := streams.NewGoToSocialAnnounceRequest()
+ objProp.AppendGoToSocialAnnounceRequest(v)
+ ir = v
+ }
+
+ // URI of the interaction request.
+ if err := ap.SetJSONLDIdStr(ir, req.InteractionRequestURI); err != nil {
+ return nil, err
+ }
- // Target is the URI of the
- // status being interacted with.
- ap.AppendTargetIRIs(accept, targetIRI)
+ // URI of the interacting actor.
+ ap.AppendActorIRIs(ir, toIRI)
+
+ // URI of the status.
+ ap.AppendObjectIRIs(ir, targetIRI)
+
+ // URI of the interaction.
+ ap.AppendInstrumentIRIs(ir, objectIRI)
+
+ // Set the thing.
+ accept.SetActivityStreamsObject(objProp)
+
+ // If polite, also include the "result" URI
+ // of the interaction Authorization object.
+ resultIRI, err := url.Parse(req.AuthorizationURI)
+ if err != nil {
+ return nil, gtserror.Newf("invalid authorization uri: %w", err)
+ }
+ ap.AppendResultIRIs(accept, resultIRI)
+
+ } else {
+ // If accepting an impolite request, just set
+ // interaction URI as object and target status
+ // IRI as target. Don't give authorization in
+ // result field, as this will confuse pre v0.20.0
+ // instances who don't understand Auth types yet.
+ //
+ // TODO: remove this path in v0.21.0 and send an
+ // accept of a Request for impolite requests too.
+ ap.AppendObjectIRIs(accept, objectIRI)
+ ap.AppendTargetIRIs(accept, targetIRI)
+ }
// Address to the owner
// of interaction URI.
ap.AppendTo(accept, toIRI)
- // Whether or not we cc this Accept to
- // followers and public depends on the
- // type of interaction it Accepts.
+ // If the request is polite, send
+ // the Accept only to the requester,
+ // no need to cc anything.
+ if polite {
+ return accept, nil
+ }
+
+ // If the request was impolite, it's
+ // helpful for federation to distribute
+ // the Accept to our followers as well,
+ // depending on the type of interaction.
var cc bool
switch req.InteractionType {
case gtsmodel.InteractionLike:
// Accept of Like doesn't get cc'd
- // because it's not that important.
+ // because it's not that important,
+ // as Likes are usually only ever
+ // sent to the post author.
case gtsmodel.InteractionReply:
// Accept of reply gets cc'd.
@@ -2244,10 +2211,7 @@ func (c *Converter) InteractionReqToASAccept(
}
if cc {
- publicIRI, err := url.Parse(pub.PublicActivityPubIRI)
- if err != nil {
- return nil, gtserror.Newf("invalid public uri: %w", err)
- }
+ publicIRI := ap.PublicIRI()
followersIRI, err := url.Parse(req.TargetAccount.FollowersURI)
if err != nil {
@@ -2268,7 +2232,7 @@ func (c *Converter) InteractionReqToASReject(
) (vocab.ActivityStreamsReject, error) {
reject := streams.NewActivityStreamsReject()
- rejectID, err := url.Parse(req.URI)
+ rejectID, err := url.Parse(req.ResponseURI)
if err != nil {
return nil, gtserror.Newf("invalid reject uri: %w", err)
}
@@ -2283,14 +2247,14 @@ func (c *Converter) InteractionReqToASReject(
return nil, gtserror.Newf("invalid object uri: %w", err)
}
- if req.Status == nil {
- req.Status, err = c.state.DB.GetStatusByID(ctx, req.StatusID)
+ if req.TargetStatus == nil {
+ req.TargetStatus, err = c.state.DB.GetStatusByID(ctx, req.TargetStatusID)
if err != nil {
return nil, gtserror.Newf("db error getting interaction req target status: %w", err)
}
}
- targetIRI, err := url.Parse(req.Status.URI)
+ targetIRI, err := url.Parse(req.TargetStatus.URI)
if err != nil {
return nil, gtserror.Newf("invalid interaction req target status uri: %w", err)
}
@@ -2300,28 +2264,80 @@ func (c *Converter) InteractionReqToASReject(
return nil, gtserror.Newf("invalid interacting account uri: %w", err)
}
- // Set id to the URI of
- // interaction request.
+ // Set id.
ap.SetJSONLDId(reject, rejectID)
- // Actor is the account that
- // owns the approval / reject.
+ // Actor is the account
+ // Rejecting the interaction.
ap.AppendActorIRIs(reject, actorIRI)
- // Object is the interaction URI.
- ap.AppendObjectIRIs(reject, objectIRI)
+ polite := req.IsPolite()
+ if polite {
+ // If rejecting a polite request, put
+ // a barebones version of the *Request
+ // in the `object` property.
+ var (
+ objProp = streams.NewActivityStreamsObjectProperty()
+ ir ap.InteractionRequestable
+ )
+ switch req.InteractionType {
+ case gtsmodel.InteractionLike:
+ v := streams.NewGoToSocialLikeRequest()
+ objProp.AppendGoToSocialLikeRequest(v)
+ ir = v
+ case gtsmodel.InteractionReply:
+ v := streams.NewGoToSocialReplyRequest()
+ objProp.AppendGoToSocialReplyRequest(v)
+ ir = v
+ case gtsmodel.InteractionAnnounce:
+ v := streams.NewGoToSocialAnnounceRequest()
+ objProp.AppendGoToSocialAnnounceRequest(v)
+ ir = v
+ }
+
+ // URI of the interaction request.
+ if err := ap.SetJSONLDIdStr(ir, req.InteractionRequestURI); err != nil {
+ return nil, err
+ }
+
+ // URI of the interacting actor.
+ ap.AppendActorIRIs(ir, toIRI)
+
+ // URI of the status.
+ ap.AppendObjectIRIs(ir, targetIRI)
+
+ // URI of the interaction.
+ ap.AppendInstrumentIRIs(ir, objectIRI)
- // Target is the URI of the
- // status being interacted with.
- ap.AppendTargetIRIs(reject, targetIRI)
+ // Set the thing.
+ reject.SetActivityStreamsObject(objProp)
+
+ } else {
+ // If rejecting an impolite request, just set
+ // interaction URI as object and target status
+ // IRI as target.
+ //
+ // TODO: remove this path in v0.21.0 and send a
+ // Reject of a Request for impolite requests too.
+ ap.AppendObjectIRIs(reject, objectIRI)
+ ap.AppendTargetIRIs(reject, targetIRI)
+ }
// Address to the owner
// of interaction URI.
ap.AppendTo(reject, toIRI)
- // Whether or not we cc this Reject to
- // followers and public depends on the
- // type of interaction it Rejects.
+ // If the request is polite, send
+ // the Reject only to the requester,
+ // no need to cc anything.
+ if polite {
+ return reject, nil
+ }
+
+ // If the request was impolite, it's
+ // helpful for federation to distribute
+ // the Reject to our followers as well,
+ // depending on the type of interaction.
var cc bool
switch req.InteractionType {
@@ -2340,10 +2356,7 @@ func (c *Converter) InteractionReqToASReject(
}
if cc {
- publicIRI, err := url.Parse(pub.PublicActivityPubIRI)
- if err != nil {
- return nil, gtserror.Newf("invalid public uri: %w", err)
- }
+ publicIRI := ap.PublicIRI()
followersIRI, err := url.Parse(req.TargetAccount.FollowersURI)
if err != nil {
@@ -2355,3 +2368,136 @@ func (c *Converter) InteractionReqToASReject(
return reject, nil
}
+
+// InteractionReqToASAuthorization converts an approved *gtsmodel.InteractionRequest
+// to a LikeAuthorization, ReplyAuthorization, or AnnounceAuthorization object.
+//
+// End result will look something like this:
+//
+// {
+// "@context": [
+// "https://gotosocial.org/ns",
+// "https://www.w3.org/ns/activitystreams"
+// ],
+// "attributedTo": "http://localhost:8080/users/the_mighty_zork",
+// "id": "http://localhost:8080/users/the_mighty_zork/authorizations/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+// "interactingObject": "https://fossbros-anonymous.io/users/foss_satan/likes/01J1AKRRHQ6MDDQHV0TP716T2K",
+// "interactionTarget": "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3",
+// "type": "LikeAuthorization"
+// }
+func (c *Converter) InteractionReqToASAuthorization(
+ ctx context.Context,
+ req *gtsmodel.InteractionRequest,
+) (ap.Authorizationable, error) {
+ if !req.IsAccepted() {
+ const text = "cannot convert not-accepted interaction request to Authorization type"
+ return nil, gtserror.New(text)
+ }
+
+ if err := c.state.DB.PopulateInteractionRequest(ctx, req); err != nil {
+ return nil, gtserror.Newf("error populating interaction request: %w", err)
+ }
+
+ var auth ap.Authorizationable
+ switch req.InteractionType {
+ case gtsmodel.InteractionLike:
+ auth = streams.NewGoToSocialLikeAuthorization()
+ case gtsmodel.InteractionReply:
+ auth = streams.NewGoToSocialReplyAuthorization()
+ case gtsmodel.InteractionAnnounce:
+ auth = streams.NewGoToSocialAnnounceAuthorization()
+ }
+
+ // Set the ID.
+ if err := ap.SetJSONLDIdStr(auth, req.AuthorizationURI); err != nil {
+ return nil, err
+ }
+
+ // Set attributed to actor URI.
+ attributedToURI, err := url.Parse(req.TargetAccount.URI)
+ if err != nil {
+ return nil, gtserror.Newf("invalid target account URI: %w", err)
+ }
+ ap.AppendAttributedTo(auth, attributedToURI)
+
+ // Set interaction URI (eg., uri of the fave, reply, or announce).
+ intObjURI, err := url.Parse(req.InteractionURI)
+ if err != nil {
+ return nil, gtserror.Newf("invalid interaction URI: %w", err)
+ }
+ ap.AppendInteractingObject(auth, intObjURI)
+
+ // Set interaction target URI (ie., uri of the status interacted with).
+ intTargetURI, err := url.Parse(req.TargetStatus.URI)
+ if err != nil {
+ return nil, gtserror.Newf("invalid interaction target URI: %w", err)
+ }
+ ap.AppendInteractionTarget(auth, intTargetURI)
+
+ return auth, nil
+}
+
+// appendASInteractionAuthorization is a utility function
+// that sets `approvedBy`, and `likeAuthorization`,
+// `replyAuthorization`, or `announceAuthorization`.
+func (c *Converter) appendASInteractionAuthorization(
+ ctx context.Context,
+ approvedByURIStr string,
+ t vocab.Type,
+) error {
+ // ApprovedByURI is the URI of an
+ // Authorization for this interaction.
+ approvedByURI, err := url.Parse(approvedByURIStr)
+ if err != nil {
+ return gtserror.Newf("error parsing approvedByURIStr: %w", err)
+ }
+
+ // Fetch relevant approved interaction
+ // request for this approvedByURIStr.
+ intReq, err := c.state.DB.GetInteractionRequestByAuthorizationURI(
+ gtscontext.SetBarebones(ctx),
+ approvedByURIStr,
+ )
+ if err != nil {
+ return gtserror.Newf("db error checking for int req: %w", err)
+ }
+
+ // Make sure it's actually accepted.
+ if !intReq.IsAccepted() {
+ return gtserror.Newf(
+ "approvedByURIStr %s corresponded to not-accepted interaction request %s",
+ approvedByURIStr, intReq.ID,
+ )
+ }
+
+ // Deprecated: Set `approvedBy`
+ // property to URI of the Accept.
+ //
+ // Todo: Remove this in v0.21.0.
+ if wap, ok := t.(ap.WithApprovedBy); ok {
+ responseURI, err := url.Parse(intReq.ResponseURI)
+ if err != nil {
+ return gtserror.Newf("error parsing responseURI: %w", err)
+ }
+ ap.SetApprovedBy(wap, responseURI)
+ }
+
+ // Set the appropriate authorization
+ // property depending on type.
+ switch intReq.InteractionType {
+ case gtsmodel.InteractionLike:
+ if wla, ok := t.(ap.WithLikeAuthorization); ok {
+ ap.SetLikeAuthorization(wla, approvedByURI)
+ }
+ case gtsmodel.InteractionReply:
+ if wra, ok := t.(ap.WithReplyAuthorization); ok {
+ ap.SetReplyAuthorization(wra, approvedByURI)
+ }
+ case gtsmodel.InteractionAnnounce:
+ if waa, ok := t.(ap.WithAnnounceAuthorization); ok {
+ ap.SetAnnounceAuthorization(waa, approvedByURI)
+ }
+ }
+
+ return nil
+}
diff --git a/internal/typeutils/internaltoas_test.go b/internal/typeutils/internaltoas_test.go
index 5c3e52ddb..970e16cfa 100644
--- a/internal/typeutils/internaltoas_test.go
+++ b/internal/typeutils/internaltoas_test.go
@@ -25,6 +25,8 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/ap"
"code.superseriousbusiness.org/gotosocial/internal/db"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
+ "code.superseriousbusiness.org/gotosocial/internal/uris"
+ "code.superseriousbusiness.org/gotosocial/internal/util"
"code.superseriousbusiness.org/gotosocial/testrig"
"github.com/stretchr/testify/suite"
)
@@ -947,6 +949,264 @@ func (suite *InternalToASTestSuite) TestStatusToASWithMentions() {
}`, string(bytes))
}
+func (suite *InternalToASTestSuite) TestStatusToASPoliteApproved() {
+ ctx := suite.T().Context()
+
+ // Take a status from admin that replies to turtle.
+ testStatus := new(gtsmodel.Status)
+ *testStatus = *suite.testStatuses["admin_account_status_5"]
+
+ // Take corresponding interaction request.
+ intReq := new(gtsmodel.InteractionRequest)
+ *intReq = *suite.testInteractionRequests["admin_account_reply_turtle"]
+
+ // Mark the status as approved by updating the
+ // status + corresponding interaction request.
+ username := suite.testAccounts["local_account_2"].Username
+ intReq.ResponseURI = uris.GenerateURIForAccept(
+ username,
+ intReq.ID,
+ )
+ intReq.AuthorizationURI = uris.GenerateURIForAuthorization(
+ username,
+ intReq.ID,
+ )
+ intReq.AcceptedAt = testrig.TimeMustParse("2024-11-01T11:00:00+02:00")
+
+ // Mark it as polite too.
+ intReq.Polite = util.Ptr(true)
+
+ if err := suite.state.DB.UpdateInteractionRequest(
+ ctx,
+ intReq,
+ "response_uri",
+ "authorization_uri",
+ "accepted_at",
+ "polite",
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ testStatus.ApprovedByURI = intReq.AuthorizationURI
+ if err := suite.state.DB.UpdateStatus(
+ ctx,
+ testStatus,
+ "approved_by_uri",
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ asStatus, err := suite.typeconverter.StatusToAS(ctx, testStatus)
+ suite.NoError(err)
+
+ ser, err := ap.Serialize(asStatus)
+ suite.NoError(err)
+
+ bytes, err := json.MarshalIndent(ser, "", " ")
+ suite.NoError(err)
+
+ suite.Equal(`{
+ "@context": [
+ "https://gotosocial.org/ns",
+ "https://www.w3.org/ns/activitystreams",
+ {
+ "sensitive": "as:sensitive"
+ }
+ ],
+ "approvedBy": "http://localhost:8080/users/1happyturtle/accepts/01J5QVXCCEATJYSXM9H6MZT4JR",
+ "attachment": [],
+ "attributedTo": "http://localhost:8080/users/admin",
+ "cc": [
+ "http://localhost:8080/users/admin/followers",
+ "http://localhost:8080/users/1happyturtle"
+ ],
+ "content": "\u003cp\u003eHi \u003cspan class=\"h-card\"\u003e\u003ca href=\"http://localhost:8080/@1happyturtle\" class=\"u-url mention\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003e@\u003cspan\u003e1happyturtle\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e, can I reply?\u003c/p\u003e",
+ "id": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ",
+ "inReplyTo": "http://localhost:8080/users/1happyturtle/statuses/01F8MHC8VWDRBQR0N1BATDDEM5",
+ "interactionPolicy": {
+ "canAnnounce": {
+ "always": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "approvalRequired": [],
+ "automaticApproval": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "manualApproval": []
+ },
+ "canLike": {
+ "always": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "approvalRequired": [],
+ "automaticApproval": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "manualApproval": []
+ },
+ "canReply": {
+ "always": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "approvalRequired": [],
+ "automaticApproval": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "manualApproval": []
+ }
+ },
+ "published": "2024-02-20T12:41:37+02:00",
+ "replies": {
+ "first": {
+ "id": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ/replies?page=true",
+ "next": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ/replies?page=true\u0026only_other_accounts=false",
+ "partOf": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ/replies",
+ "type": "CollectionPage"
+ },
+ "id": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ/replies",
+ "type": "Collection"
+ },
+ "replyAuthorization": "http://localhost:8080/users/1happyturtle/authorizations/01J5QVXCCEATJYSXM9H6MZT4JR",
+ "sensitive": false,
+ "summary": "",
+ "tag": {
+ "href": "http://localhost:8080/users/1happyturtle",
+ "name": "@1happyturtle@localhost:8080",
+ "type": "Mention"
+ },
+ "to": "https://www.w3.org/ns/activitystreams#Public",
+ "type": "Note",
+ "url": "http://localhost:8080/@admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ"
+}`, string(bytes))
+}
+
+func (suite *InternalToASTestSuite) TestStatusToASPImpoliteApproved() {
+ ctx := suite.T().Context()
+
+ // Take a status from admin that replies to turtle.
+ testStatus := new(gtsmodel.Status)
+ *testStatus = *suite.testStatuses["admin_account_status_5"]
+
+ // Take corresponding interaction request.
+ intReq := new(gtsmodel.InteractionRequest)
+ *intReq = *suite.testInteractionRequests["admin_account_reply_turtle"]
+
+ // Mark the status as approved by updating the
+ // status + corresponding interaction request.
+ username := suite.testAccounts["local_account_2"].Username
+ intReq.ResponseURI = uris.GenerateURIForAccept(
+ username,
+ intReq.ID,
+ )
+ intReq.AuthorizationURI = uris.GenerateURIForAuthorization(
+ username,
+ intReq.ID,
+ )
+ intReq.AcceptedAt = testrig.TimeMustParse("2024-11-01T11:00:00+02:00")
+
+ if err := suite.state.DB.UpdateInteractionRequest(
+ ctx,
+ intReq,
+ "response_uri",
+ "authorization_uri",
+ "accepted_at",
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ testStatus.ApprovedByURI = intReq.AuthorizationURI
+ if err := suite.state.DB.UpdateStatus(
+ ctx,
+ testStatus,
+ "approved_by_uri",
+ ); err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ asStatus, err := suite.typeconverter.StatusToAS(ctx, testStatus)
+ suite.NoError(err)
+
+ ser, err := ap.Serialize(asStatus)
+ suite.NoError(err)
+
+ bytes, err := json.MarshalIndent(ser, "", " ")
+ suite.NoError(err)
+
+ suite.Equal(`{
+ "@context": [
+ "https://gotosocial.org/ns",
+ "https://www.w3.org/ns/activitystreams",
+ {
+ "sensitive": "as:sensitive"
+ }
+ ],
+ "approvedBy": "http://localhost:8080/users/1happyturtle/accepts/01J5QVXCCEATJYSXM9H6MZT4JR",
+ "attachment": [],
+ "attributedTo": "http://localhost:8080/users/admin",
+ "cc": [
+ "http://localhost:8080/users/admin/followers",
+ "http://localhost:8080/users/1happyturtle"
+ ],
+ "content": "\u003cp\u003eHi \u003cspan class=\"h-card\"\u003e\u003ca href=\"http://localhost:8080/@1happyturtle\" class=\"u-url mention\" rel=\"nofollow noreferrer noopener\" target=\"_blank\"\u003e@\u003cspan\u003e1happyturtle\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e, can I reply?\u003c/p\u003e",
+ "id": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ",
+ "inReplyTo": "http://localhost:8080/users/1happyturtle/statuses/01F8MHC8VWDRBQR0N1BATDDEM5",
+ "interactionPolicy": {
+ "canAnnounce": {
+ "always": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "approvalRequired": [],
+ "automaticApproval": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "manualApproval": []
+ },
+ "canLike": {
+ "always": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "approvalRequired": [],
+ "automaticApproval": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "manualApproval": []
+ },
+ "canReply": {
+ "always": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "approvalRequired": [],
+ "automaticApproval": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "manualApproval": []
+ }
+ },
+ "published": "2024-02-20T12:41:37+02:00",
+ "replies": {
+ "first": {
+ "id": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ/replies?page=true",
+ "next": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ/replies?page=true\u0026only_other_accounts=false",
+ "partOf": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ/replies",
+ "type": "CollectionPage"
+ },
+ "id": "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ/replies",
+ "type": "Collection"
+ },
+ "replyAuthorization": "http://localhost:8080/users/1happyturtle/authorizations/01J5QVXCCEATJYSXM9H6MZT4JR",
+ "sensitive": false,
+ "summary": "",
+ "tag": {
+ "href": "http://localhost:8080/users/1happyturtle",
+ "name": "@1happyturtle@localhost:8080",
+ "type": "Mention"
+ },
+ "to": "https://www.w3.org/ns/activitystreams#Public",
+ "type": "Note",
+ "url": "http://localhost:8080/@admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ"
+}`, string(bytes))
+}
+
func (suite *InternalToASTestSuite) TestStatusToASDeletePublicReply() {
testStatus := suite.testStatuses["admin_account_status_3"]
ctx := suite.T().Context()
@@ -1119,7 +1379,7 @@ func (suite *InternalToASTestSuite) TestSelfBoostFollowersOnlyToAS() {
boostWrapperStatus.URI = "http://localhost:8080/users/the_mighty_zork/statuses/01G74JJ1KS331G2JXHRMZCE0ER"
boostWrapperStatus.CreatedAt = testrig.TimeMustParse("2022-06-09T13:12:00Z")
- asBoost, err := suite.typeconverter.BoostToAS(ctx, boostWrapperStatus, testAccount, testAccount)
+ asBoost, err := suite.typeconverter.BoostToAS(ctx, boostWrapperStatus)
suite.NoError(err)
ser, err := ap.Serialize(asBoost)
@@ -1320,23 +1580,24 @@ func (suite *InternalToASTestSuite) TestPollVoteToASCreate() {
}`, string(bytes1))
}
-func (suite *InternalToASTestSuite) TestInteractionReqToASAcceptAnnounce() {
+func (suite *InternalToASTestSuite) TestImpoliteInteractionReqToASAcceptAnnounce() {
acceptingAccount := suite.testAccounts["local_account_1"]
interactingAccount := suite.testAccounts["remote_account_1"]
req := &gtsmodel.InteractionRequest{
- ID: "01J1AKMZ8JE5NW0ZSFTRC1JJNE",
- CreatedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
- StatusID: "01JJYCVKCXB9JTQD1XW2KB8MT3",
- Status: &gtsmodel.Status{URI: "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3"},
- TargetAccountID: acceptingAccount.ID,
- TargetAccount: acceptingAccount,
- InteractingAccountID: interactingAccount.ID,
- InteractingAccount: interactingAccount,
- InteractionURI: "https://fossbros-anonymous.io/users/foss_satan/statuses/01J1AKRRHQ6MDDQHV0TP716T2K",
- InteractionType: gtsmodel.InteractionAnnounce,
- URI: "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
- AcceptedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
+ ID: "01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ TargetStatusID: "01JJYCVKCXB9JTQD1XW2KB8MT3",
+ TargetStatus: &gtsmodel.Status{URI: "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3"},
+ TargetAccountID: acceptingAccount.ID,
+ TargetAccount: acceptingAccount,
+ InteractingAccountID: interactingAccount.ID,
+ InteractingAccount: interactingAccount,
+ InteractionRequestURI: "https://fossbros-anonymous.io/users/foss_satan/statuses/01J1AKRRHQ6MDDQHV0TP716T2K" + gtsmodel.AnnounceRequestSuffix,
+ InteractionURI: "https://fossbros-anonymous.io/users/foss_satan/statuses/01J1AKRRHQ6MDDQHV0TP716T2K",
+ InteractionType: gtsmodel.InteractionAnnounce,
+ Polite: util.Ptr(false),
+ ResponseURI: "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ AcceptedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
}
accept, err := suite.typeconverter.InteractionReqToASAccept(
@@ -1372,23 +1633,24 @@ func (suite *InternalToASTestSuite) TestInteractionReqToASAcceptAnnounce() {
}`, string(b))
}
-func (suite *InternalToASTestSuite) TestInteractionReqToASAcceptLike() {
+func (suite *InternalToASTestSuite) TestImpoliteInteractionReqToASAcceptLike() {
acceptingAccount := suite.testAccounts["local_account_1"]
interactingAccount := suite.testAccounts["remote_account_1"]
req := &gtsmodel.InteractionRequest{
- ID: "01J1AKMZ8JE5NW0ZSFTRC1JJNE",
- CreatedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
- StatusID: "01JJYCVKCXB9JTQD1XW2KB8MT3",
- Status: &gtsmodel.Status{URI: "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3"},
- TargetAccountID: acceptingAccount.ID,
- TargetAccount: acceptingAccount,
- InteractingAccountID: interactingAccount.ID,
- InteractingAccount: interactingAccount,
- InteractionURI: "https://fossbros-anonymous.io/users/foss_satan/statuses/01J1AKRRHQ6MDDQHV0TP716T2K",
- InteractionType: gtsmodel.InteractionLike,
- URI: "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
- AcceptedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
+ ID: "01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ TargetStatusID: "01JJYCVKCXB9JTQD1XW2KB8MT3",
+ TargetStatus: &gtsmodel.Status{URI: "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3"},
+ TargetAccountID: acceptingAccount.ID,
+ TargetAccount: acceptingAccount,
+ InteractingAccountID: interactingAccount.ID,
+ InteractingAccount: interactingAccount,
+ InteractionRequestURI: "https://fossbros-anonymous.io/users/foss_satan/likes/01J1AKRRHQ6MDDQHV0TP716T2K" + gtsmodel.LikeRequestSuffix,
+ InteractionURI: "https://fossbros-anonymous.io/users/foss_satan/likes/01J1AKRRHQ6MDDQHV0TP716T2K",
+ InteractionType: gtsmodel.InteractionLike,
+ Polite: util.Ptr(false),
+ ResponseURI: "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ AcceptedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
}
accept, err := suite.typeconverter.InteractionReqToASAccept(
@@ -1413,13 +1675,124 @@ func (suite *InternalToASTestSuite) TestInteractionReqToASAcceptLike() {
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "http://localhost:8080/users/the_mighty_zork",
"id": "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
- "object": "https://fossbros-anonymous.io/users/foss_satan/statuses/01J1AKRRHQ6MDDQHV0TP716T2K",
+ "object": "https://fossbros-anonymous.io/users/foss_satan/likes/01J1AKRRHQ6MDDQHV0TP716T2K",
"target": "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3",
"to": "http://fossbros-anonymous.io/users/foss_satan",
"type": "Accept"
}`, string(b))
}
+func (suite *InternalToASTestSuite) TestInteractionReqToASAcceptLikePolite() {
+ acceptingAccount := suite.testAccounts["local_account_1"]
+ interactingAccount := suite.testAccounts["remote_account_1"]
+
+ req := &gtsmodel.InteractionRequest{
+ ID: "01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ TargetStatusID: "01JJYCVKCXB9JTQD1XW2KB8MT3",
+ TargetStatus: &gtsmodel.Status{URI: "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3"},
+ TargetAccountID: acceptingAccount.ID,
+ TargetAccount: acceptingAccount,
+ InteractingAccountID: interactingAccount.ID,
+ InteractingAccount: interactingAccount,
+ InteractionRequestURI: "https://fossbros-anonymous.io/users/foss_satan/interaction_requests/01J1AKRRHQ6MDDQHV0TP716T2K",
+ InteractionURI: "https://fossbros-anonymous.io/users/foss_satan/likes/01J1AKRRHQ6MDDQHV0TP716T2K",
+ InteractionType: gtsmodel.InteractionLike,
+ Polite: util.Ptr(true),
+ ResponseURI: "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ AuthorizationURI: "http://localhost:8080/users/the_mighty_zork/authorizations/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ AcceptedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
+ }
+
+ accept, err := suite.typeconverter.InteractionReqToASAccept(
+ suite.T().Context(),
+ req,
+ )
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ i, err := ap.Serialize(accept)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ b, err := json.MarshalIndent(i, "", " ")
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ suite.Equal(`{
+ "@context": [
+ "https://gotosocial.org/ns",
+ "https://www.w3.org/ns/activitystreams"
+ ],
+ "actor": "http://localhost:8080/users/the_mighty_zork",
+ "id": "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ "object": {
+ "actor": "http://fossbros-anonymous.io/users/foss_satan",
+ "id": "https://fossbros-anonymous.io/users/foss_satan/interaction_requests/01J1AKRRHQ6MDDQHV0TP716T2K",
+ "instrument": "https://fossbros-anonymous.io/users/foss_satan/likes/01J1AKRRHQ6MDDQHV0TP716T2K",
+ "object": "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3",
+ "type": "LikeRequest"
+ },
+ "result": "http://localhost:8080/users/the_mighty_zork/authorizations/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ "to": "http://fossbros-anonymous.io/users/foss_satan",
+ "type": "Accept"
+}`, string(b))
+}
+
+func (suite *InternalToASTestSuite) TestPoliteInteractionReqToASAuthorization() {
+ acceptingAccount := suite.testAccounts["local_account_1"]
+ interactingAccount := suite.testAccounts["remote_account_1"]
+
+ req := &gtsmodel.InteractionRequest{
+ ID: "01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ TargetStatusID: "01JJYCVKCXB9JTQD1XW2KB8MT3",
+ TargetStatus: &gtsmodel.Status{URI: "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3"},
+ TargetAccountID: acceptingAccount.ID,
+ TargetAccount: acceptingAccount,
+ InteractingAccountID: interactingAccount.ID,
+ InteractingAccount: interactingAccount,
+ InteractionURI: "https://fossbros-anonymous.io/users/foss_satan/likes/01J1AKRRHQ6MDDQHV0TP716T2K",
+ InteractionType: gtsmodel.InteractionLike,
+ Polite: util.Ptr(true),
+ InteractionRequestURI: "https://fossbros-anonymous.io/users/foss_satan/interaction_requests/01J1AKRRHQ6MDDQHV0TP716T2K",
+ ResponseURI: "http://localhost:8080/users/the_mighty_zork/accepts/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ AuthorizationURI: "http://localhost:8080/users/the_mighty_zork/authorizations/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ AcceptedAt: testrig.TimeMustParse("2022-06-09T13:12:00Z"),
+ }
+
+ auth, err := suite.typeconverter.InteractionReqToASAuthorization(
+ suite.T().Context(),
+ req,
+ )
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ i, err := ap.Serialize(auth)
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ b, err := json.MarshalIndent(i, "", " ")
+ if err != nil {
+ suite.FailNow(err.Error())
+ }
+
+ suite.Equal(`{
+ "@context": [
+ "https://gotosocial.org/ns",
+ "https://www.w3.org/ns/activitystreams"
+ ],
+ "attributedTo": "http://localhost:8080/users/the_mighty_zork",
+ "id": "http://localhost:8080/users/the_mighty_zork/authorizations/01J1AKMZ8JE5NW0ZSFTRC1JJNE",
+ "interactingObject": "https://fossbros-anonymous.io/users/foss_satan/likes/01J1AKRRHQ6MDDQHV0TP716T2K",
+ "interactionTarget": "http://localhost:8080/users/the_mighty_zork/statuses/01JJYCVKCXB9JTQD1XW2KB8MT3",
+ "type": "LikeAuthorization"
+}`, string(b))
+}
+
func TestInternalToASTestSuite(t *testing.T) {
suite.Run(t, new(InternalToASTestSuite))
}
diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go
index b2a4652d3..961e99206 100644
--- a/internal/typeutils/internaltofrontend.go
+++ b/internal/typeutils/internaltofrontend.go
@@ -2883,7 +2883,7 @@ func (c *Converter) InteractionReqToAPIInteractionReq(
interactedStatus, err := c.StatusToAPIStatus(
ctx,
- req.Status,
+ req.TargetStatus,
requestingAcct,
)
if err != nil {
@@ -2921,16 +2921,21 @@ func (c *Converter) InteractionReqToAPIInteractionReq(
rejectedAt = util.FormatISO8601(req.RejectedAt)
}
+ createdAt, err := id.TimeFromULID(req.ID)
+ if err != nil {
+ err := gtserror.Newf("error converting id to time: %w", err)
+ return nil, err
+ }
+
return &apimodel.InteractionRequest{
ID: req.ID,
Type: req.InteractionType.String(),
- CreatedAt: util.FormatISO8601(req.CreatedAt),
+ CreatedAt: util.FormatISO8601(createdAt),
Account: interactingAcct,
Status: interactedStatus,
Reply: reply,
AcceptedAt: acceptedAt,
RejectedAt: rejectedAt,
- URI: req.URI,
}, nil
}
diff --git a/internal/typeutils/internaltofrontend_test.go b/internal/typeutils/internaltofrontend_test.go
index 47ad284e6..5d066f410 100644
--- a/internal/typeutils/internaltofrontend_test.go
+++ b/internal/typeutils/internaltofrontend_test.go
@@ -3054,7 +3054,7 @@ func (suite *InternalToFrontendTestSuite) TestIntReqToAPI() {
suite.Equal(`{
"id": "01J5QVXCCEATJYSXM9H6MZT4JR",
"type": "reply",
- "created_at": "2024-02-20T10:41:37.000Z",
+ "created_at": "2024-08-20T12:24:13.966Z",
"account": {
"id": "01F8MH17FWEB39HZJ76B6VXSKF",
"username": "admin",
diff --git a/internal/typeutils/wrap.go b/internal/typeutils/wrap.go
index 59c7e2264..ae83ea4c7 100644
--- a/internal/typeutils/wrap.go
+++ b/internal/typeutils/wrap.go
@@ -53,7 +53,7 @@ func (c *Converter) WrapAccountableInUpdate(accountable ap.Accountable) (vocab.A
update.SetActivityStreamsObject(objectProp)
// to should be public.
- ap.AppendTo(update, ap.PublicURI())
+ ap.AppendTo(update, ap.PublicIRI())
// bcc should be followers.
ap.AppendBcc(update, ap.GetFollowers(accountable))
diff --git a/internal/uris/uri.go b/internal/uris/uri.go
index d7ae9fe75..1a5ed7fbf 100644
--- a/internal/uris/uri.go
+++ b/internal/uris/uri.go
@@ -27,27 +27,28 @@ import (
)
const (
- UsersPath = "users" // UsersPath is for serving users info
- StatusesPath = "statuses" // StatusesPath is for serving statuses
- InboxPath = "inbox" // InboxPath represents the activitypub inbox location
- OutboxPath = "outbox" // OutboxPath represents the activitypub outbox location
- FollowersPath = "followers" // FollowersPath represents the activitypub followers location
- FollowingPath = "following" // FollowingPath represents the activitypub following location
- LikedPath = "liked" // LikedPath represents the activitypub liked location
- CollectionsPath = "collections" // CollectionsPath represents the activitypub collections location
- FeaturedPath = "featured" // FeaturedPath represents the activitypub featured location
- PublicKeyPath = "main-key" // PublicKeyPath is for serving an account's public key
- FollowPath = "follow" // FollowPath used to generate the URI for an individual follow or follow request
- UpdatePath = "updates" // UpdatePath is used to generate the URI for an account update
- BlocksPath = "blocks" // BlocksPath is used to generate the URI for a block
- MovesPath = "moves" // MovesPath is used to generate the URI for a move
- ReportsPath = "reports" // ReportsPath is used to generate the URI for a report/flag
- ConfirmEmailPath = "confirm_email" // ConfirmEmailPath is used to generate the URI for an email confirmation link
- FileserverPath = "fileserver" // FileserverPath is a path component for serving attachments + media
- EmojiPath = "emoji" // EmojiPath represents the activitypub emoji location
- TagsPath = "tags" // TagsPath represents the activitypub tags location
- AcceptsPath = "accepts" // AcceptsPath represents the activitypub Accept's location
- RejectsPath = "rejects" // RejectsPath represents the activitypub Reject's location
+ UsersPath = "users" // UsersPath is for serving users info
+ StatusesPath = "statuses" // StatusesPath is for serving statuses
+ InboxPath = "inbox" // InboxPath represents the activitypub inbox location
+ OutboxPath = "outbox" // OutboxPath represents the activitypub outbox location
+ FollowersPath = "followers" // FollowersPath represents the activitypub followers location
+ FollowingPath = "following" // FollowingPath represents the activitypub following location
+ LikedPath = "liked" // LikedPath represents the activitypub liked location
+ CollectionsPath = "collections" // CollectionsPath represents the activitypub collections location
+ FeaturedPath = "featured" // FeaturedPath represents the activitypub featured location
+ PublicKeyPath = "main-key" // PublicKeyPath is for serving an account's public key
+ FollowPath = "follow" // FollowPath used to generate the URI for an individual follow or follow request
+ UpdatePath = "updates" // UpdatePath is used to generate the URI for an account update
+ BlocksPath = "blocks" // BlocksPath is used to generate the URI for a block
+ MovesPath = "moves" // MovesPath is used to generate the URI for a move
+ ReportsPath = "reports" // ReportsPath is used to generate the URI for a report/flag
+ ConfirmEmailPath = "confirm_email" // ConfirmEmailPath is used to generate the URI for an email confirmation link
+ FileserverPath = "fileserver" // FileserverPath is a path component for serving attachments + media
+ EmojiPath = "emoji" // EmojiPath represents the activitypub emoji location
+ TagsPath = "tags" // TagsPath represents the activitypub tags location
+ AcceptsPath = "accepts" // AcceptsPath represents the activitypub Accept's location
+ AuthorizationsPath = "authorizations" // AuthorizationsPath represents the location of an Authorization type such as LikeAuthorization, ReplyAuthorization, etc.
+ RejectsPath = "rejects" // RejectsPath represents the activitypub Reject's location
)
// UserURIs contains a bunch of UserURIs
@@ -210,6 +211,21 @@ func GenerateURIForAccept(username string, thisAcceptID string) string {
)
}
+// GenerateURIForAuthorization returns the AP URI for a new Authorization object,
+// ie., LikeAuthorization, ReplyAuthorization, or AnnounceAuthorization.
+// Eg., https://example.org/users/whatever_user/authorizations/01F7XTH1QGBAPMGF49WJZ91XGC
+func GenerateURIForAuthorization(username string, id string) string {
+ proto := config.GetProtocol()
+ host := config.GetHost()
+ return buildURL4(proto,
+ host,
+ UsersPath,
+ username,
+ AuthorizationsPath,
+ id,
+ )
+}
+
// GenerateURIForReject returns the AP URI for a new Reject activity -- something like:
// https://example.org/users/whatever_user/rejects/01F7XTH1QGBAPMGF49WJZ91XGC
func GenerateURIForReject(username string, thisRejectID string) string {
diff --git a/testrig/testmodels.go b/testrig/testmodels.go
index b7d527010..256107b80 100644
--- a/testrig/testmodels.go
+++ b/testrig/testmodels.go
@@ -3360,21 +3360,20 @@ type ActivityWithSignature struct {
// their requesting signatures.
func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]ActivityWithSignature {
dmForZork := NewAPNote(
- URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/5424b153-4553-4f30-9358-7b92f7cd42f6"),
- URLMustParse("http://fossbros-anonymous.io/@foss_satan/5424b153-4553-4f30-9358-7b92f7cd42f6"),
- TimeMustParse("2022-07-13T12:13:12+02:00"),
- "@the_mighty_zork@localhost:8080 hey zork here's a new private note for you",
- "new note for zork",
- URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
- []*url.URL{URLMustParse("http://localhost:8080/users/the_mighty_zork")},
- nil,
- true,
- []vocab.ActivityStreamsMention{newAPMention(
- URLMustParse("http://localhost:8080/users/the_mighty_zork"),
- "@the_mighty_zork@localhost:8080",
- )},
- []vocab.TootHashtag{},
- nil,
+ &NewAPNoteParams{
+ ID: URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/5424b153-4553-4f30-9358-7b92f7cd42f6"),
+ URL: URLMustParse("http://fossbros-anonymous.io/@foss_satan/5424b153-4553-4f30-9358-7b92f7cd42f6"),
+ CreatedAt: TimeMustParse("2022-07-13T12:13:12+02:00"),
+ Content: "@the_mighty_zork@localhost:8080 hey zork here's a new private note for you",
+ Summary: "new note for zork",
+ AttributedTo: URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
+ To: []*url.URL{URLMustParse("http://localhost:8080/users/the_mighty_zork")},
+ Sensitive: true,
+ Mentions: []vocab.ActivityStreamsMention{newAPMention(
+ URLMustParse("http://localhost:8080/users/the_mighty_zork"),
+ "@the_mighty_zork@localhost:8080",
+ )},
+ },
)
createDmForZork := WrapAPNoteInCreate(
URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/5424b153-4553-4f30-9358-7b92f7cd42f6/activity"),
@@ -3384,21 +3383,19 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
createDmForZorkSig, createDmForZorkDigest, creatDmForZorkDate := GetSignatureForActivity(createDmForZork, accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_1"].InboxURI))
replyToTurtle := NewAPNote(
- URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/2f1195a6-5cb0-4475-adf5-92ab9a0147fe"),
- URLMustParse("http://fossbros-anonymous.io/@foss_satan/2f1195a6-5cb0-4475-adf5-92ab9a0147fe"),
- TimeMustParse("2022-07-13T12:13:12+02:00"),
- "@1happyturtle@localhost:8080 u suck lol",
- "",
- URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
- []*url.URL{URLMustParse("http://fossbros-anonymous.io/users/foss_satan/followers")},
- []*url.URL{URLMustParse("http://localhost:8080/users/1happyturtle")},
- false,
- []vocab.ActivityStreamsMention{newAPMention(
- URLMustParse("http://localhost:8080/users/1happyturtle"),
- "@1happyturtle@localhost:8080",
- )},
- []vocab.TootHashtag{},
- nil,
+ &NewAPNoteParams{
+ ID: URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/2f1195a6-5cb0-4475-adf5-92ab9a0147fe"),
+ URL: URLMustParse("http://fossbros-anonymous.io/@foss_satan/2f1195a6-5cb0-4475-adf5-92ab9a0147fe"),
+ CreatedAt: TimeMustParse("2022-07-13T12:13:12+02:00"),
+ Content: "@1happyturtle@localhost:8080 u suck lol",
+ AttributedTo: URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
+ To: []*url.URL{URLMustParse("http://fossbros-anonymous.io/users/foss_satan/followers")},
+ CC: []*url.URL{URLMustParse("http://localhost:8080/users/1happyturtle")},
+ Mentions: []vocab.ActivityStreamsMention{newAPMention(
+ URLMustParse("http://localhost:8080/users/1happyturtle"),
+ "@1happyturtle@localhost:8080",
+ )},
+ },
)
createReplyToTurtle := WrapAPNoteInCreate(
URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/2f1195a6-5cb0-4475-adf5-92ab9a0147fe"),
@@ -3409,23 +3406,20 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
createReplyToTurtleForTurtleSig, createReplyToTurtleForTurtleDigest, createReplyToTurtleForTurtleDate := GetSignatureForActivity(createReplyToTurtle, accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_2"].InboxURI))
forwardedMessage := NewAPNote(
- URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1"),
- URLMustParse("http://example.org/@Some_User/afaba698-5740-4e32-a702-af61aa543bc1"),
- TimeMustParse("2022-07-13T12:13:12+02:00"),
- "this is a public status, please forward it!",
- "",
- URLMustParse("http://example.org/users/Some_User"),
- []*url.URL{ap.PublicURI()},
- nil,
- false,
- []vocab.ActivityStreamsMention{},
- []vocab.TootHashtag{},
- []vocab.ActivityStreamsImage{
- newAPImage(
- URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1/attachment1.jpg"),
- "image/jpeg",
- "trent reznor looking handsome as balls",
- "LEDara58O=t5EMSOENEN9]}?aK%0"),
+ &NewAPNoteParams{
+ ID: URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1"),
+ URL: URLMustParse("http://example.org/@Some_User/afaba698-5740-4e32-a702-af61aa543bc1"),
+ CreatedAt: TimeMustParse("2022-07-13T12:13:12+02:00"),
+ Content: "this is a public status, please forward it!",
+ AttributedTo: URLMustParse("http://example.org/users/Some_User"),
+ To: []*url.URL{ap.PublicIRI()},
+ Attachments: []vocab.ActivityStreamsImage{
+ newAPImage(
+ URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1/attachment1.jpg"),
+ "image/jpeg",
+ "trent reznor looking handsome as balls",
+ "LEDara58O=t5EMSOENEN9]}?aK%0"),
+ },
},
)
createForwardedMessage := WrapAPNoteInCreate(
@@ -3473,33 +3467,33 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
deleteForRemoteAccount3Sig, deleteForRemoteAccount3Digest, deleteForRemoteAccount3Date := GetSignatureForActivity(deleteForRemoteAccount3, "https://somewhere.mysterious/users/rest_in_piss#main-key", keyToSignDelete, URLMustParse(accounts["local_account_1"].InboxURI))
remoteAccount2Status1Updated := NewAPNote(
- URLMustParse("http://example.org/users/Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5"),
- URLMustParse("http://example.org/@Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5"),
- TimeMustParse("2023-11-02T12:44:25+02:00"),
- `<p>hi <span class="h-card"><a href="http://localhost:8080/@admin" class="u-url mention" rel="nofollow noreferrer noopener" target="_blank">@<span>admin</span></a></span> here's some media for ya, <span class="h-card"><a href="http://localhost:8080/@the_mighty_zork" class="u-url mention" rel="nofollow noreferrer noopener" target="_blank">@<span>the_mighty_zork</span></a></span> you might like this too</p>`,
- "<p>some unknown media included</p>",
- URLMustParse("http://example.org/users/Some_User"),
- []*url.URL{
- ap.PublicURI(),
- },
- []*url.URL{
- URLMustParse("http://example.org/users/Some_User/followers"),
- URLMustParse("http://localhost:8080/users/admin"),
- URLMustParse("http://localhost:8080/users/the_mighty_zork"),
- },
- true,
- []vocab.ActivityStreamsMention{
- newAPMention(
+ &NewAPNoteParams{
+ ID: URLMustParse("http://example.org/users/Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5"),
+ URL: URLMustParse("http://example.org/@Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5"),
+ CreatedAt: TimeMustParse("2023-11-02T12:44:25+02:00"),
+ Content: `<p>hi <span class="h-card"><a href="http://localhost:8080/@admin" class="u-url mention" rel="nofollow noreferrer noopener" target="_blank">@<span>admin</span></a></span> here's some media for ya, <span class="h-card"><a href="http://localhost:8080/@the_mighty_zork" class="u-url mention" rel="nofollow noreferrer noopener" target="_blank">@<span>the_mighty_zork</span></a></span> you might like this too</p>`,
+ Summary: "<p>some unknown media included</p>",
+ AttributedTo: URLMustParse("http://example.org/users/Some_User"),
+ To: []*url.URL{
+ ap.PublicIRI(),
+ },
+ CC: []*url.URL{
+ URLMustParse("http://example.org/users/Some_User/followers"),
URLMustParse("http://localhost:8080/users/admin"),
- "@admin@localhost:8080",
- ),
- newAPMention(
URLMustParse("http://localhost:8080/users/the_mighty_zork"),
- "@the_mighty_zork@localhost:8080",
- ),
+ },
+ Sensitive: true,
+ Mentions: []vocab.ActivityStreamsMention{
+ newAPMention(
+ URLMustParse("http://localhost:8080/users/admin"),
+ "@admin@localhost:8080",
+ ),
+ newAPMention(
+ URLMustParse("http://localhost:8080/users/the_mighty_zork"),
+ "@the_mighty_zork@localhost:8080",
+ ),
+ },
},
- nil,
- nil,
)
update := WrapAPNoteInUpdate(
URLMustParse("http://example.org/users/Some_User/statuses/01HE7XJ1CG84TBKH5V9XKBVGF5/update1"),
@@ -3849,126 +3843,114 @@ func NewTestFediAttachments(relativePath string) map[string]RemoteAttachmentFile
func NewTestFediStatuses() map[string]vocab.ActivityStreamsNote {
return map[string]vocab.ActivityStreamsNote{
"http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1": NewAPNote(
- URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1"),
- URLMustParse("http://example.org/@Some_User/afaba698-5740-4e32-a702-af61aa543bc1"),
- TimeMustParse("2022-07-13T12:13:12+02:00"),
- "this is a public status, please forward it!",
- "",
- URLMustParse("http://example.org/users/Some_User"),
- []*url.URL{ap.PublicURI()},
- nil,
- false,
- []vocab.ActivityStreamsMention{},
- []vocab.TootHashtag{},
- []vocab.ActivityStreamsImage{
- newAPImage(
- URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1/attachment1.jpg"),
- "image/jpeg",
- "trent reznor looking handsome as balls",
- "LEDara58O=t5EMSOENEN9]}?aK%0"),
+ &NewAPNoteParams{
+ ID: URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1"),
+ URL: URLMustParse("http://example.org/@Some_User/afaba698-5740-4e32-a702-af61aa543bc1"),
+ CreatedAt: TimeMustParse("2022-07-13T12:13:12+02:00"),
+ Content: "this is a public status, please forward it!",
+ AttributedTo: URLMustParse("http://example.org/users/Some_User"),
+ To: []*url.URL{ap.PublicIRI()},
+ Attachments: []vocab.ActivityStreamsImage{
+ newAPImage(
+ URLMustParse("http://example.org/users/Some_User/statuses/afaba698-5740-4e32-a702-af61aa543bc1/attachment1.jpg"),
+ "image/jpeg",
+ "trent reznor looking handsome as balls",
+ "LEDara58O=t5EMSOENEN9]}?aK%0"),
+ },
},
),
"https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839": NewAPNote(
- URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839"),
- URLMustParse("https://unknown-instance.com/users/@brand_new_person/01FE4NTHKWW7THT67EF10EB839"),
- TimeMustParse("2022-07-13T12:13:12+02:00"),
- "Hello world!",
- "",
- URLMustParse("https://unknown-instance.com/users/brand_new_person"),
- []*url.URL{
- ap.PublicURI(),
+ &NewAPNoteParams{
+ ID: URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839"),
+ URL: URLMustParse("https://unknown-instance.com/users/@brand_new_person/01FE4NTHKWW7THT67EF10EB839"),
+ CreatedAt: TimeMustParse("2022-07-13T12:13:12+02:00"),
+ Content: "Hello world!",
+ AttributedTo: URLMustParse("https://unknown-instance.com/users/brand_new_person"),
+ To: []*url.URL{
+ ap.PublicIRI(),
+ },
},
- []*url.URL{},
- false,
- nil,
- []vocab.TootHashtag{},
- nil,
),
"https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV": NewAPNote(
- URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV"),
- URLMustParse("https://unknown-instance.com/users/@brand_new_person/01FE5Y30E3W4P7TRE0R98KAYQV"),
- TimeMustParse("2022-07-13T12:13:12+02:00"),
- "Hey @the_mighty_zork@localhost:8080 how's it going?",
- "",
- URLMustParse("https://unknown-instance.com/users/brand_new_person"),
- []*url.URL{
- ap.PublicURI(),
- },
- []*url.URL{},
- false,
- []vocab.ActivityStreamsMention{
- newAPMention(
- URLMustParse("http://localhost:8080/users/the_mighty_zork"),
- "@the_mighty_zork@localhost:8080",
- ),
+ &NewAPNoteParams{
+ ID: URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV"),
+ URL: URLMustParse("https://unknown-instance.com/users/@brand_new_person/01FE5Y30E3W4P7TRE0R98KAYQV"),
+ CreatedAt: TimeMustParse("2022-07-13T12:13:12+02:00"),
+ Content: "Hey @the_mighty_zork@localhost:8080 how's it going?",
+ AttributedTo: URLMustParse("https://unknown-instance.com/users/brand_new_person"),
+ To: []*url.URL{
+ ap.PublicIRI(),
+ },
+ Mentions: []vocab.ActivityStreamsMention{
+ newAPMention(
+ URLMustParse("http://localhost:8080/users/the_mighty_zork"),
+ "@the_mighty_zork@localhost:8080",
+ ),
+ },
},
- []vocab.TootHashtag{},
- nil,
),
"https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7": NewAPNote(
- URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7"),
- URLMustParse("https://unknown-instance.com/users/@brand_new_person/01H641QSRS3TCXSVC10X4GPKW7"),
- TimeMustParse("2023-04-12T12:13:12+02:00"),
- "<p>Babe are you okay, you've hardly touched your <a href=\"https://unknown-instance.com/tags/piss\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>piss</span></a></p>",
- "",
- URLMustParse("https://unknown-instance.com/users/brand_new_person"),
- []*url.URL{
- ap.PublicURI(),
- },
- []*url.URL{},
- false,
- []vocab.ActivityStreamsMention{},
- []vocab.TootHashtag{
- newAPHashtag(
- URLMustParse("https://unknown-instance.com/tags/piss"),
- "#piss",
- ),
+ &NewAPNoteParams{
+ ID: URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01H641QSRS3TCXSVC10X4GPKW7"),
+ URL: URLMustParse("https://unknown-instance.com/users/@brand_new_person/01H641QSRS3TCXSVC10X4GPKW7"),
+ CreatedAt: TimeMustParse("2023-04-12T12:13:12+02:00"),
+ Content: `<p><span class="h-card"><a href="http://fossbros-anonymous.io/@foss_satan" class="u-url mention">@<span>foss_satan</span></a></span>Babe are you okay, you've hardly touched your <a href="https://unknown-instance.com/tags/piss" class="mention hashtag" rel="tag nofollow noreferrer noopener" target="_blank">#<span>piss</span></a></p>`,
+ AttributedTo: URLMustParse("https://unknown-instance.com/users/brand_new_person"),
+ To: []*url.URL{
+ ap.PublicIRI(),
+ URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
+ },
+ Mentions: []vocab.ActivityStreamsMention{
+ newAPMention(
+ URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
+ "@foss_satan@fossbros-anonymous.io",
+ ),
+ },
+ Tags: []vocab.TootHashtag{
+ newAPHashtag(
+ URLMustParse("https://unknown-instance.com/tags/piss"),
+ "#piss",
+ ),
+ },
+ InReplyTo: URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/01FVW7JHQFSFK166WWKR8CBA6M"),
},
- nil,
),
"https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042": NewAPNote(
- URLMustParse("https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042"),
- URLMustParse("https://turnip.farm/@turniplover6969/70c53e54-3146-42d5-a630-83c8b6c7c042"),
- TimeMustParse("2022-07-13T12:13:12+02:00"),
- "",
- "",
- URLMustParse("https://turnip.farm/users/turniplover6969"),
- []*url.URL{
- ap.PublicURI(),
- },
- []*url.URL{},
- false,
- nil,
- []vocab.TootHashtag{},
- []vocab.ActivityStreamsImage{
- newAPImage(
- URLMustParse("https://turnip.farm/attachments/f17843c7-015e-4251-9b5a-91389c49ee57.jpg"),
- "image/jpeg",
- "",
- "",
- ),
+ &NewAPNoteParams{
+ ID: URLMustParse("https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042"),
+ URL: URLMustParse("https://turnip.farm/@turniplover6969/70c53e54-3146-42d5-a630-83c8b6c7c042"),
+ CreatedAt: TimeMustParse("2022-07-13T12:13:12+02:00"),
+ AttributedTo: URLMustParse("https://turnip.farm/users/turniplover6969"),
+ To: []*url.URL{
+ ap.PublicIRI(),
+ },
+ Attachments: []vocab.ActivityStreamsImage{
+ newAPImage(
+ URLMustParse("https://turnip.farm/attachments/f17843c7-015e-4251-9b5a-91389c49ee57.jpg"),
+ "image/jpeg",
+ "",
+ "",
+ ),
+ },
},
),
"http://fossbros-anonymous.io/users/foss_satan/statuses/106221634728637552": NewAPNote(
- URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/106221634728637552"),
- URLMustParse("http://fossbros-anonymous.io/@foss_satan/106221634728637552"),
- TimeMustParse("2022-07-13T12:13:12+02:00"),
- `<p><span class="h-card"><a href="http://localhost:8080/@the_mighty_zork" class="u-url mention">@<span>the_mighty_zork</span></a></span> nice there it is:</p><p><a href="http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/activity" rel="nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="ellipsis">social.pixie.town/users/f0x/st</span><span class="invisible">atuses/106221628567855262/activity</span></a></p>`,
- "",
- URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
- []*url.URL{
- ap.PublicURI(),
- },
- []*url.URL{},
- false,
- []vocab.ActivityStreamsMention{
- newAPMention(
- URLMustParse("http://localhost:8080/users/the_mighty_zork"),
- "@the_mighty_zork@localhost:8080",
- ),
+ &NewAPNoteParams{
+ ID: URLMustParse("http://fossbros-anonymous.io/users/foss_satan/statuses/106221634728637552"),
+ URL: URLMustParse("http://fossbros-anonymous.io/@foss_satan/106221634728637552"),
+ CreatedAt: TimeMustParse("2022-07-13T12:13:12+02:00"),
+ Content: `<p><span class="h-card"><a href="http://localhost:8080/@the_mighty_zork" class="u-url mention">@<span>the_mighty_zork</span></a></span> nice there it is:</p><p><a href="http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/activity" rel="nofollow noopener noreferrer" target="_blank"><span class="invisible">https://</span><span class="ellipsis">social.pixie.town/users/f0x/st</span><span class="invisible">atuses/106221628567855262/activity</span></a></p>`,
+ AttributedTo: URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
+ To: []*url.URL{
+ ap.PublicIRI(),
+ },
+ Mentions: []vocab.ActivityStreamsMention{
+ newAPMention(
+ URLMustParse("http://localhost:8080/users/the_mighty_zork"),
+ "@the_mighty_zork@localhost:8080",
+ ),
+ },
},
- []vocab.TootHashtag{},
- nil,
),
}
}
@@ -4235,14 +4217,21 @@ func NewTestWebPushSubscriptions() map[string]*gtsmodel.WebPushSubscription {
func NewTestInteractionRequests() map[string]*gtsmodel.InteractionRequest {
return map[string]*gtsmodel.InteractionRequest{
+ // Impolite reply request.
+ //
+ // TODO: in v0.21.0 change this to a polite
+ // reply request, as this is a local interaction
+ // request, and polite is the only kind we'll
+ // be sending out *ourselves* from then on.
"admin_account_reply_turtle": {
- ID: "01J5QVXCCEATJYSXM9H6MZT4JR",
- CreatedAt: TimeMustParse("2024-02-20T12:41:37+02:00"),
- StatusID: "01F8MHC8VWDRBQR0N1BATDDEM5",
- TargetAccountID: "01F8MH5NBDF2MV7CTC4Q5128HF",
- InteractingAccountID: "01F8MH17FWEB39HZJ76B6VXSKF",
- InteractionURI: "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ",
- InteractionType: gtsmodel.InteractionReply,
+ ID: "01J5QVXCCEATJYSXM9H6MZT4JR",
+ TargetStatusID: "01F8MHC8VWDRBQR0N1BATDDEM5",
+ TargetAccountID: "01F8MH5NBDF2MV7CTC4Q5128HF",
+ InteractingAccountID: "01F8MH17FWEB39HZJ76B6VXSKF",
+ InteractionURI: "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ",
+ InteractionRequestURI: "http://localhost:8080/users/admin/statuses/01J5QVB9VC76NPPRQ207GG4DRZ#ReplyRequest",
+ InteractionType: gtsmodel.InteractionReply,
+ Polite: util.Ptr(false),
},
}
}
@@ -5080,99 +5069,103 @@ func newAPEmoji(id *url.URL, name string, updated time.Time, image vocab.Activit
return emoji
}
-// NewAPNote returns a new activity streams note for the given parameters
-func NewAPNote(
- noteID *url.URL,
- noteURL *url.URL,
- noteCreatedAt time.Time,
- noteContent string,
- noteSummary string,
- noteAttributedTo *url.URL,
- noteTo []*url.URL,
- noteCC []*url.URL,
- noteSensitive bool,
- noteMentions []vocab.ActivityStreamsMention,
- noteTags []vocab.TootHashtag,
- noteAttachments []vocab.ActivityStreamsImage,
-) vocab.ActivityStreamsNote {
- // create the note itself
+type NewAPNoteParams struct {
+ ID *url.URL
+ URL *url.URL
+ CreatedAt time.Time
+ Content string
+ Summary string
+ AttributedTo *url.URL
+ To []*url.URL
+ CC []*url.URL
+ Sensitive bool
+ Mentions []vocab.ActivityStreamsMention
+ Tags []vocab.TootHashtag
+ Attachments []vocab.ActivityStreamsImage
+ InReplyTo *url.URL
+ ApprovedBy *url.URL
+ ReplyAuthorization *url.URL
+}
+
+// NewAPNote is a utility function that returns a new
+// activity streams note using the given parameters.
+func NewAPNote(p *NewAPNoteParams) vocab.ActivityStreamsNote {
+ // Instantiate the note itself.
note := streams.NewActivityStreamsNote()
- // set id
- if noteID != nil {
- id := streams.NewJSONLDIdProperty()
- id.Set(noteID)
- note.SetJSONLDId(id)
+ // Set id.
+ if p.ID != nil {
+ ap.SetJSONLDId(note, p.ID)
}
- // set noteURL
- if noteURL != nil {
- url := streams.NewActivityStreamsUrlProperty()
- url.AppendIRI(noteURL)
- note.SetActivityStreamsUrl(url)
+ // Set noteURL.
+ if p.URL != nil {
+ ap.AppendURL(note, p.URL)
}
- published := streams.NewActivityStreamsPublishedProperty()
- published.Set(noteCreatedAt)
- note.SetActivityStreamsPublished(published)
-
- // set noteContent
- if noteContent != "" {
- content := streams.NewActivityStreamsContentProperty()
- content.AppendXMLSchemaString(noteContent)
- note.SetActivityStreamsContent(content)
+ // Set published.
+ ap.SetPublished(note, p.CreatedAt)
+
+ // Set content.
+ if p.Content != "" {
+ ap.AppendContent(note, p.Content)
}
- // set noteSummary (aka content warning)
- if noteSummary != "" {
- summary := streams.NewActivityStreamsSummaryProperty()
- summary.AppendXMLSchemaString(noteSummary)
- note.SetActivityStreamsSummary(summary)
+ // Set summary (aka content warning).
+ if p.Summary != "" {
+ ap.AppendSummary(note, p.Summary)
}
- // set noteAttributedTo (the url of the author of the note)
- if noteAttributedTo != nil {
- attributedTo := streams.NewActivityStreamsAttributedToProperty()
- attributedTo.AppendIRI(noteAttributedTo)
- note.SetActivityStreamsAttributedTo(attributedTo)
+ // Set attributedTo (ie., the
+ // uri of the author of the note).
+ if p.AttributedTo != nil {
+ ap.AppendAttributedTo(note, p.AttributedTo)
}
- // set noteTO
- if noteTo != nil {
- to := streams.NewActivityStreamsToProperty()
- for _, r := range noteTo {
- to.AppendIRI(r)
- }
- note.SetActivityStreamsTo(to)
+ // Set `to`.
+ if p.To != nil {
+ ap.AppendTo(note, p.To...)
}
- // set noteCC
- if noteCC != nil {
- cc := streams.NewActivityStreamsCcProperty()
- for _, r := range noteCC {
- cc.AppendIRI(r)
- }
- note.SetActivityStreamsCc(cc)
+ // Set `cc`.
+ if p.CC != nil {
+ ap.AppendCc(note, p.CC...)
+ }
+
+ // Set `inReplyTo`.
+ if p.InReplyTo != nil {
+ ap.AppendInReplyTo(note, p.InReplyTo)
+ }
+
+ // Set `approvedBy`.
+ if p.ApprovedBy != nil {
+ ap.SetApprovedBy(note, p.ApprovedBy)
+ }
+
+ // Set `replyAuthorization`.
+ if p.ReplyAuthorization != nil {
+ ap.SetReplyAuthorization(note, p.ReplyAuthorization)
}
// Tag entries
tag := streams.NewActivityStreamsTagProperty()
- // mentions
- for _, m := range noteMentions {
+ // Set mentions.
+ for _, m := range p.Mentions {
tag.AppendActivityStreamsMention(m)
}
note.SetActivityStreamsTag(tag)
- // hashtags
- for _, t := range noteTags {
+ // Set hashtags.
+ for _, t := range p.Tags {
tag.AppendTootHashtag(t)
}
- // append any attachments as ActivityStreamsImage
- if noteAttachments != nil {
+ // Append any attachments
+ // as ActivityStreamsImage
+ if p.Attachments != nil {
attachmentProperty := streams.NewActivityStreamsAttachmentProperty()
- for _, a := range noteAttachments {
+ for _, a := range p.Attachments {
attachmentProperty.AppendActivityStreamsImage(a)
}
note.SetActivityStreamsAttachment(attachmentProperty)
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/gen_consts.go b/vendor/code.superseriousbusiness.org/activity/streams/gen_consts.go
index 0eb116f40..6caf143f8 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/gen_consts.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/gen_consts.go
@@ -254,6 +254,9 @@ var ActivityStreamsAltitudePropertyName string = "altitude"
// GoToSocialAlwaysPropertyName is the string literal of the name for the always property in the GoToSocial vocabulary.
var GoToSocialAlwaysPropertyName string = "always"
+// GoToSocialAnnounceAuthorizationPropertyName is the string literal of the name for the announceAuthorization property in the GoToSocial vocabulary.
+var GoToSocialAnnounceAuthorizationPropertyName string = "announceAuthorization"
+
// ActivityStreamsAnyOfPropertyName is the string literal of the name for the anyOf property in the ActivityStreams vocabulary.
var ActivityStreamsAnyOfPropertyName string = "anyOf"
@@ -404,6 +407,9 @@ var ActivityStreamsLastPropertyName string = "last"
// ActivityStreamsLatitudePropertyName is the string literal of the name for the latitude property in the ActivityStreams vocabulary.
var ActivityStreamsLatitudePropertyName string = "latitude"
+// GoToSocialLikeAuthorizationPropertyName is the string literal of the name for the likeAuthorization property in the GoToSocial vocabulary.
+var GoToSocialLikeAuthorizationPropertyName string = "likeAuthorization"
+
// ActivityStreamsLikedPropertyName is the string literal of the name for the liked property in the ActivityStreams vocabulary.
var ActivityStreamsLikedPropertyName string = "liked"
@@ -491,6 +497,9 @@ var ActivityStreamsRelationshipPropertyName string = "relationship"
// ActivityStreamsRepliesPropertyName is the string literal of the name for the replies property in the ActivityStreams vocabulary.
var ActivityStreamsRepliesPropertyName string = "replies"
+// GoToSocialReplyAuthorizationPropertyName is the string literal of the name for the replyAuthorization property in the GoToSocial vocabulary.
+var GoToSocialReplyAuthorizationPropertyName string = "replyAuthorization"
+
// ActivityStreamsResultPropertyName is the string literal of the name for the result property in the ActivityStreams vocabulary.
var ActivityStreamsResultPropertyName string = "result"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/gen_init.go b/vendor/code.superseriousbusiness.org/activity/streams/gen_init.go
index e837355d9..b34f706b7 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/gen_init.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/gen_init.go
@@ -140,6 +140,7 @@ import (
typelibrary "code.superseriousbusiness.org/activity/streams/impl/funkwhale/type_library"
typetrack "code.superseriousbusiness.org/activity/streams/impl/funkwhale/type_track"
propertyalways "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_always"
+ propertyannounceauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization"
propertyapprovalrequired "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_approvalrequired"
propertyapprovedby "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_approvedby"
propertyautomaticapproval "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_automaticapproval"
@@ -152,7 +153,9 @@ import (
propertyinteractingobject "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactingobject"
propertyinteractionpolicy "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactionpolicy"
propertyinteractiontarget "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactiontarget"
+ propertylikeauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization"
propertymanualapproval "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_manualapproval"
+ propertyreplyauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization"
typeannounceapproval "code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announceapproval"
typeannounceauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announceauthorization"
typeannouncerequest "code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announcerequest"
@@ -337,6 +340,7 @@ func init() {
typelibrary.SetManager(mgr)
typetrack.SetManager(mgr)
propertyalways.SetManager(mgr)
+ propertyannounceauthorization.SetManager(mgr)
propertyapprovalrequired.SetManager(mgr)
propertyapprovedby.SetManager(mgr)
propertyautomaticapproval.SetManager(mgr)
@@ -349,7 +353,9 @@ func init() {
propertyinteractingobject.SetManager(mgr)
propertyinteractionpolicy.SetManager(mgr)
propertyinteractiontarget.SetManager(mgr)
+ propertylikeauthorization.SetManager(mgr)
propertymanualapproval.SetManager(mgr)
+ propertyreplyauthorization.SetManager(mgr)
typeannounceapproval.SetManager(mgr)
typeannounceauthorization.SetManager(mgr)
typeannouncerequest.SetManager(mgr)
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/gen_manager.go b/vendor/code.superseriousbusiness.org/activity/streams/gen_manager.go
index 90a6b33c7..b181e858c 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/gen_manager.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/gen_manager.go
@@ -140,6 +140,7 @@ import (
typelibrary "code.superseriousbusiness.org/activity/streams/impl/funkwhale/type_library"
typetrack "code.superseriousbusiness.org/activity/streams/impl/funkwhale/type_track"
propertyalways "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_always"
+ propertyannounceauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization"
propertyapprovalrequired "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_approvalrequired"
propertyapprovedby "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_approvedby"
propertyautomaticapproval "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_automaticapproval"
@@ -152,7 +153,9 @@ import (
propertyinteractingobject "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactingobject"
propertyinteractionpolicy "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactionpolicy"
propertyinteractiontarget "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactiontarget"
+ propertylikeauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization"
propertymanualapproval "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_manualapproval"
+ propertyreplyauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization"
typeannounceapproval "code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announceapproval"
typeannounceauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announceauthorization"
typeannouncerequest "code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announcerequest"
@@ -351,6 +354,19 @@ func (this Manager) DeserializeAnnounceAuthorizationGoToSocial() func(map[string
}
}
+// DeserializeAnnounceAuthorizationPropertyGoToSocial returns the deserialization
+// method for the "GoToSocialAnnounceAuthorizationProperty" non-functional
+// property in the vocabulary "GoToSocial"
+func (this Manager) DeserializeAnnounceAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialAnnounceAuthorizationProperty, error) {
+ return func(m map[string]interface{}, aliasMap map[string]string) (vocab.GoToSocialAnnounceAuthorizationProperty, error) {
+ i, err := propertyannounceauthorization.DeserializeAnnounceAuthorizationProperty(m, aliasMap)
+ if i == nil {
+ return nil, err
+ }
+ return i, err
+ }
+}
+
// DeserializeAnnounceRequestGoToSocial returns the deserialization method for the
// "GoToSocialAnnounceRequest" non-functional property in the vocabulary
// "GoToSocial"
@@ -1469,6 +1485,19 @@ func (this Manager) DeserializeLikeAuthorizationGoToSocial() func(map[string]int
}
}
+// DeserializeLikeAuthorizationPropertyGoToSocial returns the deserialization
+// method for the "GoToSocialLikeAuthorizationProperty" non-functional
+// property in the vocabulary "GoToSocial"
+func (this Manager) DeserializeLikeAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialLikeAuthorizationProperty, error) {
+ return func(m map[string]interface{}, aliasMap map[string]string) (vocab.GoToSocialLikeAuthorizationProperty, error) {
+ i, err := propertylikeauthorization.DeserializeLikeAuthorizationProperty(m, aliasMap)
+ if i == nil {
+ return nil, err
+ }
+ return i, err
+ }
+}
+
// DeserializeLikeRequestGoToSocial returns the deserialization method for the
// "GoToSocialLikeRequest" non-functional property in the vocabulary
// "GoToSocial"
@@ -2132,6 +2161,19 @@ func (this Manager) DeserializeReplyAuthorizationGoToSocial() func(map[string]in
}
}
+// DeserializeReplyAuthorizationPropertyGoToSocial returns the deserialization
+// method for the "GoToSocialReplyAuthorizationProperty" non-functional
+// property in the vocabulary "GoToSocial"
+func (this Manager) DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error) {
+ return func(m map[string]interface{}, aliasMap map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error) {
+ i, err := propertyreplyauthorization.DeserializeReplyAuthorizationProperty(m, aliasMap)
+ if i == nil {
+ return nil, err
+ }
+ return i, err
+ }
+}
+
// DeserializeReplyRequestGoToSocial returns the deserialization method for the
// "GoToSocialReplyRequest" non-functional property in the vocabulary
// "GoToSocial"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/gen_pkg_gotosocial_property_constructors.go b/vendor/code.superseriousbusiness.org/activity/streams/gen_pkg_gotosocial_property_constructors.go
index c4cd38bba..af56d3bb9 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/gen_pkg_gotosocial_property_constructors.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/gen_pkg_gotosocial_property_constructors.go
@@ -4,6 +4,7 @@ package streams
import (
propertyalways "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_always"
+ propertyannounceauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization"
propertyapprovalrequired "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_approvalrequired"
propertyapprovedby "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_approvedby"
propertyautomaticapproval "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_automaticapproval"
@@ -16,7 +17,9 @@ import (
propertyinteractingobject "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactingobject"
propertyinteractionpolicy "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactionpolicy"
propertyinteractiontarget "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactiontarget"
+ propertylikeauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization"
propertymanualapproval "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_manualapproval"
+ propertyreplyauthorization "code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization"
vocab "code.superseriousbusiness.org/activity/streams/vocab"
)
@@ -25,6 +28,12 @@ func NewGoToSocialAlwaysProperty() vocab.GoToSocialAlwaysProperty {
return propertyalways.NewGoToSocialAlwaysProperty()
}
+// NewGoToSocialGoToSocialAnnounceAuthorizationProperty creates a new
+// GoToSocialAnnounceAuthorizationProperty
+func NewGoToSocialAnnounceAuthorizationProperty() vocab.GoToSocialAnnounceAuthorizationProperty {
+ return propertyannounceauthorization.NewGoToSocialAnnounceAuthorizationProperty()
+}
+
// NewGoToSocialGoToSocialApprovalRequiredProperty creates a new
// GoToSocialApprovalRequiredProperty
func NewGoToSocialApprovalRequiredProperty() vocab.GoToSocialApprovalRequiredProperty {
@@ -94,8 +103,20 @@ func NewGoToSocialInteractionTargetProperty() vocab.GoToSocialInteractionTargetP
return propertyinteractiontarget.NewGoToSocialInteractionTargetProperty()
}
+// NewGoToSocialGoToSocialLikeAuthorizationProperty creates a new
+// GoToSocialLikeAuthorizationProperty
+func NewGoToSocialLikeAuthorizationProperty() vocab.GoToSocialLikeAuthorizationProperty {
+ return propertylikeauthorization.NewGoToSocialLikeAuthorizationProperty()
+}
+
// NewGoToSocialGoToSocialManualApprovalProperty creates a new
// GoToSocialManualApprovalProperty
func NewGoToSocialManualApprovalProperty() vocab.GoToSocialManualApprovalProperty {
return propertymanualapproval.NewGoToSocialManualApprovalProperty()
}
+
+// NewGoToSocialGoToSocialReplyAuthorizationProperty creates a new
+// GoToSocialReplyAuthorizationProperty
+func NewGoToSocialReplyAuthorizationProperty() vocab.GoToSocialReplyAuthorizationProperty {
+ return propertyreplyauthorization.NewGoToSocialReplyAuthorizationProperty()
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_pkg.go
index 7ecd4121b..924cec939 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_pkg.go
@@ -19,6 +19,11 @@ type privateManager interface {
// method for the "ActivityStreamsAltitudeProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeAltitudePropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsAltitudeProperty, error)
+ // DeserializeAnnounceAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialAnnounceAuthorizationProperty" non-functional property
+ // in the vocabulary "GoToSocial"
+ DeserializeAnnounceAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialAnnounceAuthorizationProperty, error)
// DeserializeApprovedByPropertyGoToSocial returns the deserialization
// method for the "GoToSocialApprovedByProperty" non-functional
// property in the vocabulary "GoToSocial"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_type_activitystreams_announce.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_type_activitystreams_announce.go
index 0851dfa94..9906fdd49 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_type_activitystreams_announce.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_announce/gen_type_activitystreams_announce.go
@@ -31,48 +31,49 @@ import (
// "type": "Announce"
// }
type ActivityStreamsAnnounce struct {
- ActivityStreamsActor vocab.ActivityStreamsActorProperty
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- ActivityStreamsInstrument vocab.ActivityStreamsInstrumentProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsOrigin vocab.ActivityStreamsOriginProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsResult vocab.ActivityStreamsResultProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTarget vocab.ActivityStreamsTargetProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsActor vocab.ActivityStreamsActorProperty
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialAnnounceAuthorization vocab.GoToSocialAnnounceAuthorizationProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ ActivityStreamsInstrument vocab.ActivityStreamsInstrumentProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsOrigin vocab.ActivityStreamsOriginProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ ActivityStreamsResult vocab.ActivityStreamsResultProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTarget vocab.ActivityStreamsTargetProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsAnnounceExtends returns true if the Announce type extends from
@@ -154,6 +155,11 @@ func DeserializeAnnounce(m map[string]interface{}, aliasMap map[string]string) (
} else if p != nil {
this.ActivityStreamsAltitude = p
}
+ if p, err := mgr.DeserializeAnnounceAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialAnnounceAuthorization = p
+ }
if p, err := mgr.DeserializeApprovedByPropertyGoToSocial()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -353,6 +359,8 @@ func DeserializeAnnounce(m map[string]interface{}, aliasMap map[string]string) (
continue
} else if k == "altitude" {
continue
+ } else if k == "announceAuthorization" {
+ continue
} else if k == "approvedBy" {
continue
} else if k == "attachment" {
@@ -684,6 +692,12 @@ func (this ActivityStreamsAnnounce) GetActivityStreamsUrl() vocab.ActivityStream
return this.ActivityStreamsUrl
}
+// GetGoToSocialAnnounceAuthorization returns the "announceAuthorization" property
+// if it exists, and nil otherwise.
+func (this ActivityStreamsAnnounce) GetGoToSocialAnnounceAuthorization() vocab.GoToSocialAnnounceAuthorizationProperty {
+ return this.GoToSocialAnnounceAuthorization
+}
+
// GetGoToSocialApprovedBy returns the "approvedBy" property if it exists, and nil
// otherwise.
func (this ActivityStreamsAnnounce) GetGoToSocialApprovedBy() vocab.GoToSocialApprovedByProperty {
@@ -727,6 +741,7 @@ func (this ActivityStreamsAnnounce) JSONLDContext() map[string]string {
m := map[string]string{"https://www.w3.org/ns/activitystreams": this.alias}
m = this.helperJSONLDContext(this.ActivityStreamsActor, m)
m = this.helperJSONLDContext(this.ActivityStreamsAltitude, m)
+ m = this.helperJSONLDContext(this.GoToSocialAnnounceAuthorization, m)
m = this.helperJSONLDContext(this.GoToSocialApprovedBy, m)
m = this.helperJSONLDContext(this.ActivityStreamsAttachment, m)
m = this.helperJSONLDContext(this.ActivityStreamsAttributedTo, m)
@@ -801,6 +816,20 @@ func (this ActivityStreamsAnnounce) LessThan(o vocab.ActivityStreamsAnnounce) bo
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "announceAuthorization"
+ if lhs, rhs := this.GoToSocialAnnounceAuthorization, o.GetGoToSocialAnnounceAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "approvedBy"
if lhs, rhs := this.GoToSocialApprovedBy, o.GetGoToSocialApprovedBy(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1372,6 +1401,14 @@ func (this ActivityStreamsAnnounce) Serialize() (map[string]interface{}, error)
m[this.ActivityStreamsAltitude.Name()] = i
}
}
+ // Maybe serialize property "announceAuthorization"
+ if this.GoToSocialAnnounceAuthorization != nil {
+ if i, err := this.GoToSocialAnnounceAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialAnnounceAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "approvedBy"
if this.GoToSocialApprovedBy != nil {
if i, err := this.GoToSocialApprovedBy.Serialize(); err != nil {
@@ -1875,6 +1912,11 @@ func (this *ActivityStreamsAnnounce) SetActivityStreamsUrl(i vocab.ActivityStrea
this.ActivityStreamsUrl = i
}
+// SetGoToSocialAnnounceAuthorization sets the "announceAuthorization" property.
+func (this *ActivityStreamsAnnounce) SetGoToSocialAnnounceAuthorization(i vocab.GoToSocialAnnounceAuthorizationProperty) {
+ this.GoToSocialAnnounceAuthorization = i
+}
+
// SetGoToSocialApprovedBy sets the "approvedBy" property.
func (this *ActivityStreamsAnnounce) SetGoToSocialApprovedBy(i vocab.GoToSocialApprovedByProperty) {
this.GoToSocialApprovedBy = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_pkg.go
index e3ebfdb94..bba914f0a 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_pkg.go
@@ -117,6 +117,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_type_activitystreams_article.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_type_activitystreams_article.go
index 8a0229af7..3de164802 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_type_activitystreams_article.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_article/gen_type_activitystreams_article.go
@@ -22,44 +22,45 @@ import (
// "type": "Article"
// }
type ActivityStreamsArticle struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsArticleExtends returns true if the Article type extends from the
@@ -261,6 +262,11 @@ func DeserializeArticle(m map[string]interface{}, aliasMap map[string]string) (*
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -372,6 +378,8 @@ func DeserializeArticle(m map[string]interface{}, aliasMap map[string]string) (*
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -625,6 +633,12 @@ func (this ActivityStreamsArticle) GetGoToSocialInteractionPolicy() vocab.GoToSo
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsArticle) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsArticle) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -686,6 +700,7 @@ func (this ActivityStreamsArticle) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1068,6 +1083,20 @@ func (this ActivityStreamsArticle) LessThan(o vocab.ActivityStreamsArticle) bool
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1439,6 +1468,14 @@ func (this ActivityStreamsArticle) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1703,6 +1740,11 @@ func (this *ActivityStreamsArticle) SetGoToSocialInteractionPolicy(i vocab.GoToS
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsArticle) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsArticle) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_pkg.go
index 729435fbd..aaaa194c7 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_pkg.go
@@ -125,6 +125,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_type_activitystreams_audio.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_type_activitystreams_audio.go
index bb6664c2c..5b633801f 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_type_activitystreams_audio.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_audio/gen_type_activitystreams_audio.go
@@ -22,46 +22,47 @@ import (
// }
// }
type ActivityStreamsAudio struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- TootBlurhash vocab.TootBlurhashProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- TootFocalPoint vocab.TootFocalPointProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ TootBlurhash vocab.TootBlurhashProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ TootFocalPoint vocab.TootFocalPointProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsAudioExtends returns true if the Audio type extends from the
@@ -273,6 +274,11 @@ func DeserializeAudio(m map[string]interface{}, aliasMap map[string]string) (*Ac
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -388,6 +394,8 @@ func DeserializeAudio(m map[string]interface{}, aliasMap map[string]string) (*Ac
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -641,6 +649,12 @@ func (this ActivityStreamsAudio) GetGoToSocialInteractionPolicy() vocab.GoToSoci
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsAudio) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsAudio) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -715,6 +729,7 @@ func (this ActivityStreamsAudio) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1125,6 +1140,20 @@ func (this ActivityStreamsAudio) LessThan(o vocab.ActivityStreamsAudio) bool {
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1512,6 +1541,14 @@ func (this ActivityStreamsAudio) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1776,6 +1813,11 @@ func (this *ActivityStreamsAudio) SetGoToSocialInteractionPolicy(i vocab.GoToSoc
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsAudio) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsAudio) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_pkg.go
index 98036d6d1..c3e4665df 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_pkg.go
@@ -125,6 +125,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_type_activitystreams_document.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_type_activitystreams_document.go
index 0d2d06780..f7d823984 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_type_activitystreams_document.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_document/gen_type_activitystreams_document.go
@@ -18,46 +18,47 @@ import (
// "url": "http://example.org/4q-sales-forecast.pdf"
// }
type ActivityStreamsDocument struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- TootBlurhash vocab.TootBlurhashProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- TootFocalPoint vocab.TootFocalPointProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ TootBlurhash vocab.TootBlurhashProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ TootFocalPoint vocab.TootFocalPointProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsDocumentExtends returns true if the Document type extends from
@@ -249,6 +250,11 @@ func DeserializeDocument(m map[string]interface{}, aliasMap map[string]string) (
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -364,6 +370,8 @@ func DeserializeDocument(m map[string]interface{}, aliasMap map[string]string) (
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -642,6 +650,12 @@ func (this ActivityStreamsDocument) GetGoToSocialInteractionPolicy() vocab.GoToS
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsDocument) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsDocument) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -716,6 +730,7 @@ func (this ActivityStreamsDocument) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1126,6 +1141,20 @@ func (this ActivityStreamsDocument) LessThan(o vocab.ActivityStreamsDocument) bo
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1513,6 +1542,14 @@ func (this ActivityStreamsDocument) Serialize() (map[string]interface{}, error)
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1777,6 +1814,11 @@ func (this *ActivityStreamsDocument) SetGoToSocialInteractionPolicy(i vocab.GoTo
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsDocument) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsDocument) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_pkg.go
index 6ec762ae5..c6760f1a6 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_pkg.go
@@ -117,6 +117,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_type_activitystreams_event.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_type_activitystreams_event.go
index 1ce5e55ba..e7de9773b 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_type_activitystreams_event.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_event/gen_type_activitystreams_event.go
@@ -19,44 +19,45 @@ import (
// "type": "Event"
// }
type ActivityStreamsEvent struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsEventExtends returns true if the Event type extends from the
@@ -238,6 +239,11 @@ func DeserializeEvent(m map[string]interface{}, aliasMap map[string]string) (*Ac
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -349,6 +355,8 @@ func DeserializeEvent(m map[string]interface{}, aliasMap map[string]string) (*Ac
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -622,6 +630,12 @@ func (this ActivityStreamsEvent) GetGoToSocialInteractionPolicy() vocab.GoToSoci
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsEvent) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsEvent) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -683,6 +697,7 @@ func (this ActivityStreamsEvent) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1065,6 +1080,20 @@ func (this ActivityStreamsEvent) LessThan(o vocab.ActivityStreamsEvent) bool {
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1436,6 +1465,14 @@ func (this ActivityStreamsEvent) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1700,6 +1737,11 @@ func (this *ActivityStreamsEvent) SetGoToSocialInteractionPolicy(i vocab.GoToSoc
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsEvent) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsEvent) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_pkg.go
index 4ab62e8ae..b3bcc10c6 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_pkg.go
@@ -129,6 +129,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_type_activitystreams_image.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_type_activitystreams_image.go
index 23274172e..b5f446d62 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_type_activitystreams_image.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_image/gen_type_activitystreams_image.go
@@ -29,48 +29,49 @@ import (
// ]
// }
type ActivityStreamsImage struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- TootBlurhash vocab.TootBlurhashProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- TootFocalPoint vocab.TootFocalPointProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsHeight vocab.ActivityStreamsHeightProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- ActivityStreamsWidth vocab.ActivityStreamsWidthProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ TootBlurhash vocab.TootBlurhashProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ TootFocalPoint vocab.TootFocalPointProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsHeight vocab.ActivityStreamsHeightProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ ActivityStreamsWidth vocab.ActivityStreamsWidthProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsImageExtends returns true if the Image type extends from the
@@ -267,6 +268,11 @@ func DeserializeImage(m map[string]interface{}, aliasMap map[string]string) (*Ac
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -389,6 +395,8 @@ func DeserializeImage(m map[string]interface{}, aliasMap map[string]string) (*Ac
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -676,6 +684,12 @@ func (this ActivityStreamsImage) GetGoToSocialInteractionPolicy() vocab.GoToSoci
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsImage) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsImage) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -751,6 +765,7 @@ func (this ActivityStreamsImage) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1176,6 +1191,20 @@ func (this ActivityStreamsImage) LessThan(o vocab.ActivityStreamsImage) bool {
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1585,6 +1614,14 @@ func (this ActivityStreamsImage) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1867,6 +1904,11 @@ func (this *ActivityStreamsImage) SetGoToSocialInteractionPolicy(i vocab.GoToSoc
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsImage) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsImage) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_pkg.go
index 2c681db43..f27026614 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_pkg.go
@@ -88,6 +88,11 @@ type privateManager interface {
// deserialization method for the "ActivityStreamsInstrumentProperty"
// non-functional property in the vocabulary "ActivityStreams"
DeserializeInstrumentPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsInstrumentProperty, error)
+ // DeserializeLikeAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialLikeAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeLikeAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialLikeAuthorizationProperty, error)
// DeserializeLikesPropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsLikesProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_type_activitystreams_like.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_type_activitystreams_like.go
index f1f0ac6a7..d2aed32e3 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_type_activitystreams_like.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_like/gen_type_activitystreams_like.go
@@ -42,6 +42,7 @@ type ActivityStreamsLike struct {
ActivityStreamsImage vocab.ActivityStreamsImageProperty
ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
ActivityStreamsInstrument vocab.ActivityStreamsInstrumentProperty
+ GoToSocialLikeAuthorization vocab.GoToSocialLikeAuthorizationProperty
ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
@@ -211,6 +212,11 @@ func DeserializeLike(m map[string]interface{}, aliasMap map[string]string) (*Act
} else if p != nil {
this.ActivityStreamsInstrument = p
}
+ if p, err := mgr.DeserializeLikeAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialLikeAuthorization = p
+ }
if p, err := mgr.DeserializeLikesPropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -361,6 +367,8 @@ func DeserializeLike(m map[string]interface{}, aliasMap map[string]string) (*Act
continue
} else if k == "instrument" {
continue
+ } else if k == "likeAuthorization" {
+ continue
} else if k == "likes" {
continue
} else if k == "location" {
@@ -682,6 +690,12 @@ func (this ActivityStreamsLike) GetGoToSocialApprovedBy() vocab.GoToSocialApprov
return this.GoToSocialApprovedBy
}
+// GetGoToSocialLikeAuthorization returns the "likeAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsLike) GetGoToSocialLikeAuthorization() vocab.GoToSocialLikeAuthorizationProperty {
+ return this.GoToSocialLikeAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsLike) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -736,6 +750,7 @@ func (this ActivityStreamsLike) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsImage, m)
m = this.helperJSONLDContext(this.ActivityStreamsInReplyTo, m)
m = this.helperJSONLDContext(this.ActivityStreamsInstrument, m)
+ m = this.helperJSONLDContext(this.GoToSocialLikeAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsLikes, m)
m = this.helperJSONLDContext(this.ActivityStreamsLocation, m)
m = this.helperJSONLDContext(this.ActivityStreamsMediaType, m)
@@ -1031,6 +1046,20 @@ func (this ActivityStreamsLike) LessThan(o vocab.ActivityStreamsLike) bool {
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "likeAuthorization"
+ if lhs, rhs := this.GoToSocialLikeAuthorization, o.GetGoToSocialLikeAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "likes"
if lhs, rhs := this.ActivityStreamsLikes, o.GetActivityStreamsLikes(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1500,6 +1529,14 @@ func (this ActivityStreamsLike) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsInstrument.Name()] = i
}
}
+ // Maybe serialize property "likeAuthorization"
+ if this.GoToSocialLikeAuthorization != nil {
+ if i, err := this.GoToSocialLikeAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialLikeAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "likes"
if this.ActivityStreamsLikes != nil {
if i, err := this.ActivityStreamsLikes.Serialize(); err != nil {
@@ -1872,6 +1909,11 @@ func (this *ActivityStreamsLike) SetGoToSocialApprovedBy(i vocab.GoToSocialAppro
this.GoToSocialApprovedBy = i
}
+// SetGoToSocialLikeAuthorization sets the "likeAuthorization" property.
+func (this *ActivityStreamsLike) SetGoToSocialLikeAuthorization(i vocab.GoToSocialLikeAuthorizationProperty) {
+ this.GoToSocialLikeAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsLike) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_pkg.go
index 31280fdfd..b340c14b4 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_pkg.go
@@ -117,6 +117,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_type_activitystreams_note.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_type_activitystreams_note.go
index 15989dd87..dcb24a081 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_type_activitystreams_note.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_note/gen_type_activitystreams_note.go
@@ -19,44 +19,45 @@ import (
// "type": "Note"
// }
type ActivityStreamsNote struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsNoteExtends returns true if the Note type extends from the other
@@ -238,6 +239,11 @@ func DeserializeNote(m map[string]interface{}, aliasMap map[string]string) (*Act
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -349,6 +355,8 @@ func DeserializeNote(m map[string]interface{}, aliasMap map[string]string) (*Act
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -622,6 +630,12 @@ func (this ActivityStreamsNote) GetGoToSocialInteractionPolicy() vocab.GoToSocia
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsNote) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsNote) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -683,6 +697,7 @@ func (this ActivityStreamsNote) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1065,6 +1080,20 @@ func (this ActivityStreamsNote) LessThan(o vocab.ActivityStreamsNote) bool {
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1436,6 +1465,14 @@ func (this ActivityStreamsNote) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1700,6 +1737,11 @@ func (this *ActivityStreamsNote) SetGoToSocialInteractionPolicy(i vocab.GoToSoci
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsNote) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsNote) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_pkg.go
index 6ea71e27e..2e1119eb0 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_pkg.go
@@ -125,6 +125,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_type_activitystreams_page.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_type_activitystreams_page.go
index 2ba55241d..13f6b40d0 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_type_activitystreams_page.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_page/gen_type_activitystreams_page.go
@@ -18,46 +18,47 @@ import (
// "url": "http://example.org/weather-in-omaha.html"
// }
type ActivityStreamsPage struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- TootBlurhash vocab.TootBlurhashProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- TootFocalPoint vocab.TootFocalPointProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ TootBlurhash vocab.TootBlurhashProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ TootFocalPoint vocab.TootFocalPointProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsPageExtends returns true if the Page type extends from the other
@@ -249,6 +250,11 @@ func DeserializePage(m map[string]interface{}, aliasMap map[string]string) (*Act
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -364,6 +370,8 @@ func DeserializePage(m map[string]interface{}, aliasMap map[string]string) (*Act
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -637,6 +645,12 @@ func (this ActivityStreamsPage) GetGoToSocialInteractionPolicy() vocab.GoToSocia
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsPage) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsPage) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -711,6 +725,7 @@ func (this ActivityStreamsPage) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1121,6 +1136,20 @@ func (this ActivityStreamsPage) LessThan(o vocab.ActivityStreamsPage) bool {
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1508,6 +1537,14 @@ func (this ActivityStreamsPage) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1772,6 +1809,11 @@ func (this *ActivityStreamsPage) SetGoToSocialInteractionPolicy(i vocab.GoToSoci
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsPage) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsPage) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_pkg.go
index e87a1ca33..2821f74c5 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_pkg.go
@@ -133,6 +133,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_type_activitystreams_place.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_type_activitystreams_place.go
index 2c7f96e8d..34d0c90f9 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_type_activitystreams_place.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_place/gen_type_activitystreams_place.go
@@ -29,49 +29,50 @@ import (
// "units": "miles"
// }
type ActivityStreamsPlace struct {
- ActivityStreamsAccuracy vocab.ActivityStreamsAccuracyProperty
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLatitude vocab.ActivityStreamsLatitudeProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsLongitude vocab.ActivityStreamsLongitudeProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsRadius vocab.ActivityStreamsRadiusProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUnits vocab.ActivityStreamsUnitsProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAccuracy vocab.ActivityStreamsAccuracyProperty
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLatitude vocab.ActivityStreamsLatitudeProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsLongitude vocab.ActivityStreamsLongitudeProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsRadius vocab.ActivityStreamsRadiusProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUnits vocab.ActivityStreamsUnitsProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsPlaceExtends returns true if the Place type extends from the
@@ -273,6 +274,11 @@ func DeserializePlace(m map[string]interface{}, aliasMap map[string]string) (*Ac
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -397,6 +403,8 @@ func DeserializePlace(m map[string]interface{}, aliasMap map[string]string) (*Ac
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -702,6 +710,12 @@ func (this ActivityStreamsPlace) GetGoToSocialInteractionPolicy() vocab.GoToSoci
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsPlace) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsPlace) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -767,6 +781,7 @@ func (this ActivityStreamsPlace) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsRadius, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1206,6 +1221,20 @@ func (this ActivityStreamsPlace) LessThan(o vocab.ActivityStreamsPlace) bool {
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1623,6 +1652,14 @@ func (this ActivityStreamsPlace) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1920,6 +1957,11 @@ func (this *ActivityStreamsPlace) SetGoToSocialInteractionPolicy(i vocab.GoToSoc
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsPlace) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsPlace) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_pkg.go
index dbd20143d..4f01c913a 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_pkg.go
@@ -121,6 +121,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_type_activitystreams_profile.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_type_activitystreams_profile.go
index 7eed51390..6881acc18 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_type_activitystreams_profile.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_profile/gen_type_activitystreams_profile.go
@@ -23,45 +23,46 @@ import (
// "type": "Profile"
// }
type ActivityStreamsProfile struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDescribes vocab.ActivityStreamsDescribesProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDescribes vocab.ActivityStreamsDescribesProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsProfileExtends returns true if the Profile type extends from the
@@ -248,6 +249,11 @@ func DeserializeProfile(m map[string]interface{}, aliasMap map[string]string) (*
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -361,6 +367,8 @@ func DeserializeProfile(m map[string]interface{}, aliasMap map[string]string) (*
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -640,6 +648,12 @@ func (this ActivityStreamsProfile) GetGoToSocialInteractionPolicy() vocab.GoToSo
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsProfile) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsProfile) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -702,6 +716,7 @@ func (this ActivityStreamsProfile) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1098,6 +1113,20 @@ func (this ActivityStreamsProfile) LessThan(o vocab.ActivityStreamsProfile) bool
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1477,6 +1506,14 @@ func (this ActivityStreamsProfile) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1746,6 +1783,11 @@ func (this *ActivityStreamsProfile) SetGoToSocialInteractionPolicy(i vocab.GoToS
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsProfile) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsProfile) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_pkg.go
index f2ce80982..76fb4bc0c 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_pkg.go
@@ -137,6 +137,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeResultPropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsResultProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_type_activitystreams_question.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_type_activitystreams_question.go
index f2ef016f1..61fc6ab5f 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_type_activitystreams_question.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_question/gen_type_activitystreams_question.go
@@ -40,52 +40,53 @@ import (
// "type": "Question"
// }
type ActivityStreamsQuestion struct {
- ActivityStreamsActor vocab.ActivityStreamsActorProperty
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- ActivityStreamsAnyOf vocab.ActivityStreamsAnyOfProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsClosed vocab.ActivityStreamsClosedProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- ActivityStreamsInstrument vocab.ActivityStreamsInstrumentProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsOneOf vocab.ActivityStreamsOneOfProperty
- ActivityStreamsOrigin vocab.ActivityStreamsOriginProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsResult vocab.ActivityStreamsResultProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTarget vocab.ActivityStreamsTargetProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- TootVotersCount vocab.TootVotersCountProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsActor vocab.ActivityStreamsActorProperty
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ ActivityStreamsAnyOf vocab.ActivityStreamsAnyOfProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsClosed vocab.ActivityStreamsClosedProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ ActivityStreamsInstrument vocab.ActivityStreamsInstrumentProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsOneOf vocab.ActivityStreamsOneOfProperty
+ ActivityStreamsOrigin vocab.ActivityStreamsOriginProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsResult vocab.ActivityStreamsResultProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTarget vocab.ActivityStreamsTargetProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ TootVotersCount vocab.TootVotersCountProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsQuestionExtends returns true if the Question type extends from
@@ -292,6 +293,11 @@ func DeserializeQuestion(m map[string]interface{}, aliasMap map[string]string) (
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeResultPropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -428,6 +434,8 @@ func DeserializeQuestion(m map[string]interface{}, aliasMap map[string]string) (
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "result" {
continue
} else if k == "sensitive" {
@@ -749,6 +757,12 @@ func (this ActivityStreamsQuestion) GetGoToSocialInteractionPolicy() vocab.GoToS
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsQuestion) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsQuestion) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -821,6 +835,7 @@ func (this ActivityStreamsQuestion) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsResult, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
@@ -1276,6 +1291,20 @@ func (this ActivityStreamsQuestion) LessThan(o vocab.ActivityStreamsQuestion) bo
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "result"
if lhs, rhs := this.ActivityStreamsResult, o.GetActivityStreamsResult(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1729,6 +1758,14 @@ func (this ActivityStreamsQuestion) Serialize() (map[string]interface{}, error)
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "result"
if this.ActivityStreamsResult != nil {
if i, err := this.ActivityStreamsResult.Serialize(); err != nil {
@@ -2052,6 +2089,11 @@ func (this *ActivityStreamsQuestion) SetGoToSocialInteractionPolicy(i vocab.GoTo
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsQuestion) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsQuestion) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_pkg.go
index b03980b2a..91317d98c 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_pkg.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_pkg.go
@@ -125,6 +125,11 @@ type privateManager interface {
// method for the "ActivityStreamsRepliesProperty" non-functional
// property in the vocabulary "ActivityStreams"
DeserializeRepliesPropertyActivityStreams() func(map[string]interface{}, map[string]string) (vocab.ActivityStreamsRepliesProperty, error)
+ // DeserializeReplyAuthorizationPropertyGoToSocial returns the
+ // deserialization method for the
+ // "GoToSocialReplyAuthorizationProperty" non-functional property in
+ // the vocabulary "GoToSocial"
+ DeserializeReplyAuthorizationPropertyGoToSocial() func(map[string]interface{}, map[string]string) (vocab.GoToSocialReplyAuthorizationProperty, error)
// DeserializeSensitivePropertyActivityStreams returns the deserialization
// method for the "ActivityStreamsSensitiveProperty" non-functional
// property in the vocabulary "ActivityStreams"
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_type_activitystreams_video.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_type_activitystreams_video.go
index c8a93e70f..d27f1652d 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_type_activitystreams_video.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/activitystreams/type_video/gen_type_activitystreams_video.go
@@ -19,46 +19,47 @@ import (
// "url": "http://example.org/video.mkv"
// }
type ActivityStreamsVideo struct {
- ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
- GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
- ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
- ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
- ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
- ActivityStreamsBcc vocab.ActivityStreamsBccProperty
- TootBlurhash vocab.TootBlurhashProperty
- ActivityStreamsBto vocab.ActivityStreamsBtoProperty
- ActivityStreamsCc vocab.ActivityStreamsCcProperty
- ActivityStreamsContent vocab.ActivityStreamsContentProperty
- ActivityStreamsContext vocab.ActivityStreamsContextProperty
- ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
- ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
- TootFocalPoint vocab.TootFocalPointProperty
- ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
- ActivityStreamsIcon vocab.ActivityStreamsIconProperty
- JSONLDId vocab.JSONLDIdProperty
- ActivityStreamsImage vocab.ActivityStreamsImageProperty
- ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
- GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
- ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
- ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
- ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
- ActivityStreamsName vocab.ActivityStreamsNameProperty
- ActivityStreamsObject vocab.ActivityStreamsObjectProperty
- ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
- ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
- ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
- ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
- ActivityStreamsShares vocab.ActivityStreamsSharesProperty
- ActivityStreamsSource vocab.ActivityStreamsSourceProperty
- ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
- ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
- ActivityStreamsTag vocab.ActivityStreamsTagProperty
- ActivityStreamsTo vocab.ActivityStreamsToProperty
- JSONLDType vocab.JSONLDTypeProperty
- ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
- ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
- alias string
- unknown map[string]interface{}
+ ActivityStreamsAltitude vocab.ActivityStreamsAltitudeProperty
+ GoToSocialApprovedBy vocab.GoToSocialApprovedByProperty
+ ActivityStreamsAttachment vocab.ActivityStreamsAttachmentProperty
+ ActivityStreamsAttributedTo vocab.ActivityStreamsAttributedToProperty
+ ActivityStreamsAudience vocab.ActivityStreamsAudienceProperty
+ ActivityStreamsBcc vocab.ActivityStreamsBccProperty
+ TootBlurhash vocab.TootBlurhashProperty
+ ActivityStreamsBto vocab.ActivityStreamsBtoProperty
+ ActivityStreamsCc vocab.ActivityStreamsCcProperty
+ ActivityStreamsContent vocab.ActivityStreamsContentProperty
+ ActivityStreamsContext vocab.ActivityStreamsContextProperty
+ ActivityStreamsDuration vocab.ActivityStreamsDurationProperty
+ ActivityStreamsEndTime vocab.ActivityStreamsEndTimeProperty
+ TootFocalPoint vocab.TootFocalPointProperty
+ ActivityStreamsGenerator vocab.ActivityStreamsGeneratorProperty
+ ActivityStreamsIcon vocab.ActivityStreamsIconProperty
+ JSONLDId vocab.JSONLDIdProperty
+ ActivityStreamsImage vocab.ActivityStreamsImageProperty
+ ActivityStreamsInReplyTo vocab.ActivityStreamsInReplyToProperty
+ GoToSocialInteractionPolicy vocab.GoToSocialInteractionPolicyProperty
+ ActivityStreamsLikes vocab.ActivityStreamsLikesProperty
+ ActivityStreamsLocation vocab.ActivityStreamsLocationProperty
+ ActivityStreamsMediaType vocab.ActivityStreamsMediaTypeProperty
+ ActivityStreamsName vocab.ActivityStreamsNameProperty
+ ActivityStreamsObject vocab.ActivityStreamsObjectProperty
+ ActivityStreamsPreview vocab.ActivityStreamsPreviewProperty
+ ActivityStreamsPublished vocab.ActivityStreamsPublishedProperty
+ ActivityStreamsReplies vocab.ActivityStreamsRepliesProperty
+ GoToSocialReplyAuthorization vocab.GoToSocialReplyAuthorizationProperty
+ ActivityStreamsSensitive vocab.ActivityStreamsSensitiveProperty
+ ActivityStreamsShares vocab.ActivityStreamsSharesProperty
+ ActivityStreamsSource vocab.ActivityStreamsSourceProperty
+ ActivityStreamsStartTime vocab.ActivityStreamsStartTimeProperty
+ ActivityStreamsSummary vocab.ActivityStreamsSummaryProperty
+ ActivityStreamsTag vocab.ActivityStreamsTagProperty
+ ActivityStreamsTo vocab.ActivityStreamsToProperty
+ JSONLDType vocab.JSONLDTypeProperty
+ ActivityStreamsUpdated vocab.ActivityStreamsUpdatedProperty
+ ActivityStreamsUrl vocab.ActivityStreamsUrlProperty
+ alias string
+ unknown map[string]interface{}
}
// ActivityStreamsVideoExtends returns true if the Video type extends from the
@@ -250,6 +251,11 @@ func DeserializeVideo(m map[string]interface{}, aliasMap map[string]string) (*Ac
} else if p != nil {
this.ActivityStreamsReplies = p
}
+ if p, err := mgr.DeserializeReplyAuthorizationPropertyGoToSocial()(m, aliasMap); err != nil {
+ return nil, err
+ } else if p != nil {
+ this.GoToSocialReplyAuthorization = p
+ }
if p, err := mgr.DeserializeSensitivePropertyActivityStreams()(m, aliasMap); err != nil {
return nil, err
} else if p != nil {
@@ -365,6 +371,8 @@ func DeserializeVideo(m map[string]interface{}, aliasMap map[string]string) (*Ac
continue
} else if k == "replies" {
continue
+ } else if k == "replyAuthorization" {
+ continue
} else if k == "sensitive" {
continue
} else if k == "shares" {
@@ -638,6 +646,12 @@ func (this ActivityStreamsVideo) GetGoToSocialInteractionPolicy() vocab.GoToSoci
return this.GoToSocialInteractionPolicy
}
+// GetGoToSocialReplyAuthorization returns the "replyAuthorization" property if it
+// exists, and nil otherwise.
+func (this ActivityStreamsVideo) GetGoToSocialReplyAuthorization() vocab.GoToSocialReplyAuthorizationProperty {
+ return this.GoToSocialReplyAuthorization
+}
+
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
func (this ActivityStreamsVideo) GetJSONLDId() vocab.JSONLDIdProperty {
return this.JSONLDId
@@ -712,6 +726,7 @@ func (this ActivityStreamsVideo) JSONLDContext() map[string]string {
m = this.helperJSONLDContext(this.ActivityStreamsPreview, m)
m = this.helperJSONLDContext(this.ActivityStreamsPublished, m)
m = this.helperJSONLDContext(this.ActivityStreamsReplies, m)
+ m = this.helperJSONLDContext(this.GoToSocialReplyAuthorization, m)
m = this.helperJSONLDContext(this.ActivityStreamsSensitive, m)
m = this.helperJSONLDContext(this.ActivityStreamsShares, m)
m = this.helperJSONLDContext(this.ActivityStreamsSource, m)
@@ -1122,6 +1137,20 @@ func (this ActivityStreamsVideo) LessThan(o vocab.ActivityStreamsVideo) bool {
// Anything else is greater than nil
return false
} // Else: Both are nil
+ // Compare property "replyAuthorization"
+ if lhs, rhs := this.GoToSocialReplyAuthorization, o.GetGoToSocialReplyAuthorization(); lhs != nil && rhs != nil {
+ if lhs.LessThan(rhs) {
+ return true
+ } else if rhs.LessThan(lhs) {
+ return false
+ }
+ } else if lhs == nil && rhs != nil {
+ // Nil is less than anything else
+ return true
+ } else if rhs != nil && rhs == nil {
+ // Anything else is greater than nil
+ return false
+ } // Else: Both are nil
// Compare property "sensitive"
if lhs, rhs := this.ActivityStreamsSensitive, o.GetActivityStreamsSensitive(); lhs != nil && rhs != nil {
if lhs.LessThan(rhs) {
@@ -1509,6 +1538,14 @@ func (this ActivityStreamsVideo) Serialize() (map[string]interface{}, error) {
m[this.ActivityStreamsReplies.Name()] = i
}
}
+ // Maybe serialize property "replyAuthorization"
+ if this.GoToSocialReplyAuthorization != nil {
+ if i, err := this.GoToSocialReplyAuthorization.Serialize(); err != nil {
+ return nil, err
+ } else if i != nil {
+ m[this.GoToSocialReplyAuthorization.Name()] = i
+ }
+ }
// Maybe serialize property "sensitive"
if this.ActivityStreamsSensitive != nil {
if i, err := this.ActivityStreamsSensitive.Serialize(); err != nil {
@@ -1773,6 +1810,11 @@ func (this *ActivityStreamsVideo) SetGoToSocialInteractionPolicy(i vocab.GoToSoc
this.GoToSocialInteractionPolicy = i
}
+// SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+func (this *ActivityStreamsVideo) SetGoToSocialReplyAuthorization(i vocab.GoToSocialReplyAuthorizationProperty) {
+ this.GoToSocialReplyAuthorization = i
+}
+
// SetJSONLDId sets the "id" property.
func (this *ActivityStreamsVideo) SetJSONLDId(i vocab.JSONLDIdProperty) {
this.JSONLDId = i
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_doc.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_doc.go
new file mode 100644
index 000000000..ace6a9aaa
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_doc.go
@@ -0,0 +1,17 @@
+// Code generated by astool. DO NOT EDIT.
+
+// Package propertyannounceauthorization contains the implementation for the
+// announceAuthorization property. All applications are strongly encouraged to
+// use the interface instead of this concrete definition. The interfaces allow
+// applications to consume only the types and properties needed and be
+// independent of the go-fed implementation if another alternative
+// implementation is created. This package is code-generated and subject to
+// the same license as the go-fed tool used to generate it.
+//
+// This package is independent of other types' and properties' implementations
+// by having a Manager injected into it to act as a factory for the concrete
+// implementations. The implementations have been generated into their own
+// separate subpackages for each vocabulary.
+//
+// Strongly consider using the interfaces instead of this package.
+package propertyannounceauthorization
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_pkg.go
new file mode 100644
index 000000000..2271a5813
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_pkg.go
@@ -0,0 +1,15 @@
+// Code generated by astool. DO NOT EDIT.
+
+package propertyannounceauthorization
+
+var mgr privateManager
+
+// privateManager abstracts the code-generated manager that provides access to
+// concrete implementations.
+type privateManager interface{}
+
+// SetManager sets the manager package-global variable. For internal use only, do
+// not use as part of Application behavior. Must be called at golang init time.
+func SetManager(m privateManager) {
+ mgr = m
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_property_gotosocial_announceAuthorization.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_property_gotosocial_announceAuthorization.go
new file mode 100644
index 000000000..dcd897abd
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization/gen_property_gotosocial_announceAuthorization.go
@@ -0,0 +1,183 @@
+// Code generated by astool. DO NOT EDIT.
+
+package propertyannounceauthorization
+
+import (
+ anyuri "code.superseriousbusiness.org/activity/streams/values/anyURI"
+ vocab "code.superseriousbusiness.org/activity/streams/vocab"
+ "fmt"
+ "net/url"
+)
+
+// GoToSocialAnnounceAuthorizationProperty is the functional property
+// "announceAuthorization". It is permitted to be a single nilable value type.
+type GoToSocialAnnounceAuthorizationProperty struct {
+ xmlschemaAnyURIMember *url.URL
+ unknown interface{}
+ alias string
+}
+
+// DeserializeAnnounceAuthorizationProperty creates a "announceAuthorization"
+// property from an interface representation that has been unmarshalled from a
+// text or binary format.
+func DeserializeAnnounceAuthorizationProperty(m map[string]interface{}, aliasMap map[string]string) (*GoToSocialAnnounceAuthorizationProperty, error) {
+ alias := ""
+ if a, ok := aliasMap["https://gotosocial.org/ns"]; ok {
+ alias = a
+ }
+ propName := "announceAuthorization"
+ if len(alias) > 0 {
+ // Use alias both to find the property, and set within the property.
+ propName = fmt.Sprintf("%s:%s", alias, "announceAuthorization")
+ }
+ i, ok := m[propName]
+
+ if ok {
+ if v, err := anyuri.DeserializeAnyURI(i); err == nil {
+ this := &GoToSocialAnnounceAuthorizationProperty{
+ alias: alias,
+ xmlschemaAnyURIMember: v,
+ }
+ return this, nil
+ }
+ this := &GoToSocialAnnounceAuthorizationProperty{
+ alias: alias,
+ unknown: i,
+ }
+ return this, nil
+ }
+ return nil, nil
+}
+
+// NewGoToSocialAnnounceAuthorizationProperty creates a new announceAuthorization
+// property.
+func NewGoToSocialAnnounceAuthorizationProperty() *GoToSocialAnnounceAuthorizationProperty {
+ return &GoToSocialAnnounceAuthorizationProperty{alias: ""}
+}
+
+// Clear ensures no value of this property is set. Calling IsXMLSchemaAnyURI
+// afterwards will return false.
+func (this *GoToSocialAnnounceAuthorizationProperty) Clear() {
+ this.unknown = nil
+ this.xmlschemaAnyURIMember = nil
+}
+
+// Get returns the value of this property. When IsXMLSchemaAnyURI returns false,
+// Get will return any arbitrary value.
+func (this GoToSocialAnnounceAuthorizationProperty) Get() *url.URL {
+ return this.xmlschemaAnyURIMember
+}
+
+// GetIRI returns the IRI of this property. When IsIRI returns false, GetIRI will
+// return any arbitrary value.
+func (this GoToSocialAnnounceAuthorizationProperty) GetIRI() *url.URL {
+ return this.xmlschemaAnyURIMember
+}
+
+// HasAny returns true if the value or IRI is set.
+func (this GoToSocialAnnounceAuthorizationProperty) HasAny() bool {
+ return this.IsXMLSchemaAnyURI()
+}
+
+// IsIRI returns true if this property is an IRI.
+func (this GoToSocialAnnounceAuthorizationProperty) IsIRI() bool {
+ return this.xmlschemaAnyURIMember != nil
+}
+
+// IsXMLSchemaAnyURI returns true if this property is set and not an IRI.
+func (this GoToSocialAnnounceAuthorizationProperty) IsXMLSchemaAnyURI() bool {
+ return this.xmlschemaAnyURIMember != nil
+}
+
+// JSONLDContext returns the JSONLD URIs required in the context string for this
+// property and the specific values that are set. The value in the map is the
+// alias used to import the property's value or values.
+func (this GoToSocialAnnounceAuthorizationProperty) JSONLDContext() map[string]string {
+ m := map[string]string{"https://gotosocial.org/ns": this.alias}
+ var child map[string]string
+
+ /*
+ Since the literal maps in this function are determined at
+ code-generation time, this loop should not overwrite an existing key with a
+ new value.
+ */
+ for k, v := range child {
+ m[k] = v
+ }
+ return m
+}
+
+// KindIndex computes an arbitrary value for indexing this kind of value. This is
+// a leaky API detail only for folks looking to replace the go-fed
+// implementation. Applications should not use this method.
+func (this GoToSocialAnnounceAuthorizationProperty) KindIndex() int {
+ if this.IsXMLSchemaAnyURI() {
+ return 0
+ }
+ if this.IsIRI() {
+ return -2
+ }
+ return -1
+}
+
+// LessThan compares two instances of this property with an arbitrary but stable
+// comparison. Applications should not use this because it is only meant to
+// help alternative implementations to go-fed to be able to normalize
+// nonfunctional properties.
+func (this GoToSocialAnnounceAuthorizationProperty) LessThan(o vocab.GoToSocialAnnounceAuthorizationProperty) bool {
+ if this.IsIRI() {
+ // IRIs are always less than other values, none, or unknowns
+ return true
+ } else if o.IsIRI() {
+ // This other, none, or unknown value is always greater than IRIs
+ return false
+ }
+ // LessThan comparison for the single value or unknown value.
+ if !this.IsXMLSchemaAnyURI() && !o.IsXMLSchemaAnyURI() {
+ // Both are unknowns.
+ return false
+ } else if this.IsXMLSchemaAnyURI() && !o.IsXMLSchemaAnyURI() {
+ // Values are always greater than unknown values.
+ return false
+ } else if !this.IsXMLSchemaAnyURI() && o.IsXMLSchemaAnyURI() {
+ // Unknowns are always less than known values.
+ return true
+ } else {
+ // Actual comparison.
+ return anyuri.LessAnyURI(this.Get(), o.Get())
+ }
+}
+
+// Name returns the name of this property: "announceAuthorization".
+func (this GoToSocialAnnounceAuthorizationProperty) Name() string {
+ if len(this.alias) > 0 {
+ return this.alias + ":" + "announceAuthorization"
+ } else {
+ return "announceAuthorization"
+ }
+}
+
+// Serialize converts this into an interface representation suitable for
+// marshalling into a text or binary format. Applications should not need this
+// function as most typical use cases serialize types instead of individual
+// properties. It is exposed for alternatives to go-fed implementations to use.
+func (this GoToSocialAnnounceAuthorizationProperty) Serialize() (interface{}, error) {
+ if this.IsXMLSchemaAnyURI() {
+ return anyuri.SerializeAnyURI(this.Get())
+ }
+ return this.unknown, nil
+}
+
+// Set sets the value of this property. Calling IsXMLSchemaAnyURI afterwards will
+// return true.
+func (this *GoToSocialAnnounceAuthorizationProperty) Set(v *url.URL) {
+ this.Clear()
+ this.xmlschemaAnyURIMember = v
+}
+
+// SetIRI sets the value of this property. Calling IsIRI afterwards will return
+// true.
+func (this *GoToSocialAnnounceAuthorizationProperty) SetIRI(v *url.URL) {
+ this.Clear()
+ this.Set(v)
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_doc.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_doc.go
new file mode 100644
index 000000000..bbb41f098
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_doc.go
@@ -0,0 +1,17 @@
+// Code generated by astool. DO NOT EDIT.
+
+// Package propertylikeauthorization contains the implementation for the
+// likeAuthorization property. All applications are strongly encouraged to use
+// the interface instead of this concrete definition. The interfaces allow
+// applications to consume only the types and properties needed and be
+// independent of the go-fed implementation if another alternative
+// implementation is created. This package is code-generated and subject to
+// the same license as the go-fed tool used to generate it.
+//
+// This package is independent of other types' and properties' implementations
+// by having a Manager injected into it to act as a factory for the concrete
+// implementations. The implementations have been generated into their own
+// separate subpackages for each vocabulary.
+//
+// Strongly consider using the interfaces instead of this package.
+package propertylikeauthorization
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_pkg.go
new file mode 100644
index 000000000..c2540aed5
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_pkg.go
@@ -0,0 +1,15 @@
+// Code generated by astool. DO NOT EDIT.
+
+package propertylikeauthorization
+
+var mgr privateManager
+
+// privateManager abstracts the code-generated manager that provides access to
+// concrete implementations.
+type privateManager interface{}
+
+// SetManager sets the manager package-global variable. For internal use only, do
+// not use as part of Application behavior. Must be called at golang init time.
+func SetManager(m privateManager) {
+ mgr = m
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_property_gotosocial_likeAuthorization.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_property_gotosocial_likeAuthorization.go
new file mode 100644
index 000000000..d98c3d96f
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization/gen_property_gotosocial_likeAuthorization.go
@@ -0,0 +1,182 @@
+// Code generated by astool. DO NOT EDIT.
+
+package propertylikeauthorization
+
+import (
+ anyuri "code.superseriousbusiness.org/activity/streams/values/anyURI"
+ vocab "code.superseriousbusiness.org/activity/streams/vocab"
+ "fmt"
+ "net/url"
+)
+
+// GoToSocialLikeAuthorizationProperty is the functional property
+// "likeAuthorization". It is permitted to be a single nilable value type.
+type GoToSocialLikeAuthorizationProperty struct {
+ xmlschemaAnyURIMember *url.URL
+ unknown interface{}
+ alias string
+}
+
+// DeserializeLikeAuthorizationProperty creates a "likeAuthorization" property
+// from an interface representation that has been unmarshalled from a text or
+// binary format.
+func DeserializeLikeAuthorizationProperty(m map[string]interface{}, aliasMap map[string]string) (*GoToSocialLikeAuthorizationProperty, error) {
+ alias := ""
+ if a, ok := aliasMap["https://gotosocial.org/ns"]; ok {
+ alias = a
+ }
+ propName := "likeAuthorization"
+ if len(alias) > 0 {
+ // Use alias both to find the property, and set within the property.
+ propName = fmt.Sprintf("%s:%s", alias, "likeAuthorization")
+ }
+ i, ok := m[propName]
+
+ if ok {
+ if v, err := anyuri.DeserializeAnyURI(i); err == nil {
+ this := &GoToSocialLikeAuthorizationProperty{
+ alias: alias,
+ xmlschemaAnyURIMember: v,
+ }
+ return this, nil
+ }
+ this := &GoToSocialLikeAuthorizationProperty{
+ alias: alias,
+ unknown: i,
+ }
+ return this, nil
+ }
+ return nil, nil
+}
+
+// NewGoToSocialLikeAuthorizationProperty creates a new likeAuthorization property.
+func NewGoToSocialLikeAuthorizationProperty() *GoToSocialLikeAuthorizationProperty {
+ return &GoToSocialLikeAuthorizationProperty{alias: ""}
+}
+
+// Clear ensures no value of this property is set. Calling IsXMLSchemaAnyURI
+// afterwards will return false.
+func (this *GoToSocialLikeAuthorizationProperty) Clear() {
+ this.unknown = nil
+ this.xmlschemaAnyURIMember = nil
+}
+
+// Get returns the value of this property. When IsXMLSchemaAnyURI returns false,
+// Get will return any arbitrary value.
+func (this GoToSocialLikeAuthorizationProperty) Get() *url.URL {
+ return this.xmlschemaAnyURIMember
+}
+
+// GetIRI returns the IRI of this property. When IsIRI returns false, GetIRI will
+// return any arbitrary value.
+func (this GoToSocialLikeAuthorizationProperty) GetIRI() *url.URL {
+ return this.xmlschemaAnyURIMember
+}
+
+// HasAny returns true if the value or IRI is set.
+func (this GoToSocialLikeAuthorizationProperty) HasAny() bool {
+ return this.IsXMLSchemaAnyURI()
+}
+
+// IsIRI returns true if this property is an IRI.
+func (this GoToSocialLikeAuthorizationProperty) IsIRI() bool {
+ return this.xmlschemaAnyURIMember != nil
+}
+
+// IsXMLSchemaAnyURI returns true if this property is set and not an IRI.
+func (this GoToSocialLikeAuthorizationProperty) IsXMLSchemaAnyURI() bool {
+ return this.xmlschemaAnyURIMember != nil
+}
+
+// JSONLDContext returns the JSONLD URIs required in the context string for this
+// property and the specific values that are set. The value in the map is the
+// alias used to import the property's value or values.
+func (this GoToSocialLikeAuthorizationProperty) JSONLDContext() map[string]string {
+ m := map[string]string{"https://gotosocial.org/ns": this.alias}
+ var child map[string]string
+
+ /*
+ Since the literal maps in this function are determined at
+ code-generation time, this loop should not overwrite an existing key with a
+ new value.
+ */
+ for k, v := range child {
+ m[k] = v
+ }
+ return m
+}
+
+// KindIndex computes an arbitrary value for indexing this kind of value. This is
+// a leaky API detail only for folks looking to replace the go-fed
+// implementation. Applications should not use this method.
+func (this GoToSocialLikeAuthorizationProperty) KindIndex() int {
+ if this.IsXMLSchemaAnyURI() {
+ return 0
+ }
+ if this.IsIRI() {
+ return -2
+ }
+ return -1
+}
+
+// LessThan compares two instances of this property with an arbitrary but stable
+// comparison. Applications should not use this because it is only meant to
+// help alternative implementations to go-fed to be able to normalize
+// nonfunctional properties.
+func (this GoToSocialLikeAuthorizationProperty) LessThan(o vocab.GoToSocialLikeAuthorizationProperty) bool {
+ if this.IsIRI() {
+ // IRIs are always less than other values, none, or unknowns
+ return true
+ } else if o.IsIRI() {
+ // This other, none, or unknown value is always greater than IRIs
+ return false
+ }
+ // LessThan comparison for the single value or unknown value.
+ if !this.IsXMLSchemaAnyURI() && !o.IsXMLSchemaAnyURI() {
+ // Both are unknowns.
+ return false
+ } else if this.IsXMLSchemaAnyURI() && !o.IsXMLSchemaAnyURI() {
+ // Values are always greater than unknown values.
+ return false
+ } else if !this.IsXMLSchemaAnyURI() && o.IsXMLSchemaAnyURI() {
+ // Unknowns are always less than known values.
+ return true
+ } else {
+ // Actual comparison.
+ return anyuri.LessAnyURI(this.Get(), o.Get())
+ }
+}
+
+// Name returns the name of this property: "likeAuthorization".
+func (this GoToSocialLikeAuthorizationProperty) Name() string {
+ if len(this.alias) > 0 {
+ return this.alias + ":" + "likeAuthorization"
+ } else {
+ return "likeAuthorization"
+ }
+}
+
+// Serialize converts this into an interface representation suitable for
+// marshalling into a text or binary format. Applications should not need this
+// function as most typical use cases serialize types instead of individual
+// properties. It is exposed for alternatives to go-fed implementations to use.
+func (this GoToSocialLikeAuthorizationProperty) Serialize() (interface{}, error) {
+ if this.IsXMLSchemaAnyURI() {
+ return anyuri.SerializeAnyURI(this.Get())
+ }
+ return this.unknown, nil
+}
+
+// Set sets the value of this property. Calling IsXMLSchemaAnyURI afterwards will
+// return true.
+func (this *GoToSocialLikeAuthorizationProperty) Set(v *url.URL) {
+ this.Clear()
+ this.xmlschemaAnyURIMember = v
+}
+
+// SetIRI sets the value of this property. Calling IsIRI afterwards will return
+// true.
+func (this *GoToSocialLikeAuthorizationProperty) SetIRI(v *url.URL) {
+ this.Clear()
+ this.Set(v)
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_doc.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_doc.go
new file mode 100644
index 000000000..5ff0ca45d
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_doc.go
@@ -0,0 +1,17 @@
+// Code generated by astool. DO NOT EDIT.
+
+// Package propertyreplyauthorization contains the implementation for the
+// replyAuthorization property. All applications are strongly encouraged to
+// use the interface instead of this concrete definition. The interfaces allow
+// applications to consume only the types and properties needed and be
+// independent of the go-fed implementation if another alternative
+// implementation is created. This package is code-generated and subject to
+// the same license as the go-fed tool used to generate it.
+//
+// This package is independent of other types' and properties' implementations
+// by having a Manager injected into it to act as a factory for the concrete
+// implementations. The implementations have been generated into their own
+// separate subpackages for each vocabulary.
+//
+// Strongly consider using the interfaces instead of this package.
+package propertyreplyauthorization
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_pkg.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_pkg.go
new file mode 100644
index 000000000..a23c898d2
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_pkg.go
@@ -0,0 +1,15 @@
+// Code generated by astool. DO NOT EDIT.
+
+package propertyreplyauthorization
+
+var mgr privateManager
+
+// privateManager abstracts the code-generated manager that provides access to
+// concrete implementations.
+type privateManager interface{}
+
+// SetManager sets the manager package-global variable. For internal use only, do
+// not use as part of Application behavior. Must be called at golang init time.
+func SetManager(m privateManager) {
+ mgr = m
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_property_gotosocial_replyAuthorization.go b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_property_gotosocial_replyAuthorization.go
new file mode 100644
index 000000000..235d86b97
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization/gen_property_gotosocial_replyAuthorization.go
@@ -0,0 +1,183 @@
+// Code generated by astool. DO NOT EDIT.
+
+package propertyreplyauthorization
+
+import (
+ anyuri "code.superseriousbusiness.org/activity/streams/values/anyURI"
+ vocab "code.superseriousbusiness.org/activity/streams/vocab"
+ "fmt"
+ "net/url"
+)
+
+// GoToSocialReplyAuthorizationProperty is the functional property
+// "replyAuthorization". It is permitted to be a single nilable value type.
+type GoToSocialReplyAuthorizationProperty struct {
+ xmlschemaAnyURIMember *url.URL
+ unknown interface{}
+ alias string
+}
+
+// DeserializeReplyAuthorizationProperty creates a "replyAuthorization" property
+// from an interface representation that has been unmarshalled from a text or
+// binary format.
+func DeserializeReplyAuthorizationProperty(m map[string]interface{}, aliasMap map[string]string) (*GoToSocialReplyAuthorizationProperty, error) {
+ alias := ""
+ if a, ok := aliasMap["https://gotosocial.org/ns"]; ok {
+ alias = a
+ }
+ propName := "replyAuthorization"
+ if len(alias) > 0 {
+ // Use alias both to find the property, and set within the property.
+ propName = fmt.Sprintf("%s:%s", alias, "replyAuthorization")
+ }
+ i, ok := m[propName]
+
+ if ok {
+ if v, err := anyuri.DeserializeAnyURI(i); err == nil {
+ this := &GoToSocialReplyAuthorizationProperty{
+ alias: alias,
+ xmlschemaAnyURIMember: v,
+ }
+ return this, nil
+ }
+ this := &GoToSocialReplyAuthorizationProperty{
+ alias: alias,
+ unknown: i,
+ }
+ return this, nil
+ }
+ return nil, nil
+}
+
+// NewGoToSocialReplyAuthorizationProperty creates a new replyAuthorization
+// property.
+func NewGoToSocialReplyAuthorizationProperty() *GoToSocialReplyAuthorizationProperty {
+ return &GoToSocialReplyAuthorizationProperty{alias: ""}
+}
+
+// Clear ensures no value of this property is set. Calling IsXMLSchemaAnyURI
+// afterwards will return false.
+func (this *GoToSocialReplyAuthorizationProperty) Clear() {
+ this.unknown = nil
+ this.xmlschemaAnyURIMember = nil
+}
+
+// Get returns the value of this property. When IsXMLSchemaAnyURI returns false,
+// Get will return any arbitrary value.
+func (this GoToSocialReplyAuthorizationProperty) Get() *url.URL {
+ return this.xmlschemaAnyURIMember
+}
+
+// GetIRI returns the IRI of this property. When IsIRI returns false, GetIRI will
+// return any arbitrary value.
+func (this GoToSocialReplyAuthorizationProperty) GetIRI() *url.URL {
+ return this.xmlschemaAnyURIMember
+}
+
+// HasAny returns true if the value or IRI is set.
+func (this GoToSocialReplyAuthorizationProperty) HasAny() bool {
+ return this.IsXMLSchemaAnyURI()
+}
+
+// IsIRI returns true if this property is an IRI.
+func (this GoToSocialReplyAuthorizationProperty) IsIRI() bool {
+ return this.xmlschemaAnyURIMember != nil
+}
+
+// IsXMLSchemaAnyURI returns true if this property is set and not an IRI.
+func (this GoToSocialReplyAuthorizationProperty) IsXMLSchemaAnyURI() bool {
+ return this.xmlschemaAnyURIMember != nil
+}
+
+// JSONLDContext returns the JSONLD URIs required in the context string for this
+// property and the specific values that are set. The value in the map is the
+// alias used to import the property's value or values.
+func (this GoToSocialReplyAuthorizationProperty) JSONLDContext() map[string]string {
+ m := map[string]string{"https://gotosocial.org/ns": this.alias}
+ var child map[string]string
+
+ /*
+ Since the literal maps in this function are determined at
+ code-generation time, this loop should not overwrite an existing key with a
+ new value.
+ */
+ for k, v := range child {
+ m[k] = v
+ }
+ return m
+}
+
+// KindIndex computes an arbitrary value for indexing this kind of value. This is
+// a leaky API detail only for folks looking to replace the go-fed
+// implementation. Applications should not use this method.
+func (this GoToSocialReplyAuthorizationProperty) KindIndex() int {
+ if this.IsXMLSchemaAnyURI() {
+ return 0
+ }
+ if this.IsIRI() {
+ return -2
+ }
+ return -1
+}
+
+// LessThan compares two instances of this property with an arbitrary but stable
+// comparison. Applications should not use this because it is only meant to
+// help alternative implementations to go-fed to be able to normalize
+// nonfunctional properties.
+func (this GoToSocialReplyAuthorizationProperty) LessThan(o vocab.GoToSocialReplyAuthorizationProperty) bool {
+ if this.IsIRI() {
+ // IRIs are always less than other values, none, or unknowns
+ return true
+ } else if o.IsIRI() {
+ // This other, none, or unknown value is always greater than IRIs
+ return false
+ }
+ // LessThan comparison for the single value or unknown value.
+ if !this.IsXMLSchemaAnyURI() && !o.IsXMLSchemaAnyURI() {
+ // Both are unknowns.
+ return false
+ } else if this.IsXMLSchemaAnyURI() && !o.IsXMLSchemaAnyURI() {
+ // Values are always greater than unknown values.
+ return false
+ } else if !this.IsXMLSchemaAnyURI() && o.IsXMLSchemaAnyURI() {
+ // Unknowns are always less than known values.
+ return true
+ } else {
+ // Actual comparison.
+ return anyuri.LessAnyURI(this.Get(), o.Get())
+ }
+}
+
+// Name returns the name of this property: "replyAuthorization".
+func (this GoToSocialReplyAuthorizationProperty) Name() string {
+ if len(this.alias) > 0 {
+ return this.alias + ":" + "replyAuthorization"
+ } else {
+ return "replyAuthorization"
+ }
+}
+
+// Serialize converts this into an interface representation suitable for
+// marshalling into a text or binary format. Applications should not need this
+// function as most typical use cases serialize types instead of individual
+// properties. It is exposed for alternatives to go-fed implementations to use.
+func (this GoToSocialReplyAuthorizationProperty) Serialize() (interface{}, error) {
+ if this.IsXMLSchemaAnyURI() {
+ return anyuri.SerializeAnyURI(this.Get())
+ }
+ return this.unknown, nil
+}
+
+// Set sets the value of this property. Calling IsXMLSchemaAnyURI afterwards will
+// return true.
+func (this *GoToSocialReplyAuthorizationProperty) Set(v *url.URL) {
+ this.Clear()
+ this.xmlschemaAnyURIMember = v
+}
+
+// SetIRI sets the value of this property. Calling IsIRI afterwards will return
+// true.
+func (this *GoToSocialReplyAuthorizationProperty) SetIRI(v *url.URL) {
+ this.Clear()
+ this.Set(v)
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_announceAuthorization_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_announceAuthorization_interface.go
new file mode 100644
index 000000000..f9542d827
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_announceAuthorization_interface.go
@@ -0,0 +1,53 @@
+// Code generated by astool. DO NOT EDIT.
+
+package vocab
+
+import "net/url"
+
+// URI/ID of an AnnounceAuthorization permitting the Announce this property is
+// attached to.
+type GoToSocialAnnounceAuthorizationProperty interface {
+ // Clear ensures no value of this property is set. Calling
+ // IsXMLSchemaAnyURI afterwards will return false.
+ Clear()
+ // Get returns the value of this property. When IsXMLSchemaAnyURI returns
+ // false, Get will return any arbitrary value.
+ Get() *url.URL
+ // GetIRI returns the IRI of this property. When IsIRI returns false,
+ // GetIRI will return any arbitrary value.
+ GetIRI() *url.URL
+ // HasAny returns true if the value or IRI is set.
+ HasAny() bool
+ // IsIRI returns true if this property is an IRI.
+ IsIRI() bool
+ // IsXMLSchemaAnyURI returns true if this property is set and not an IRI.
+ IsXMLSchemaAnyURI() bool
+ // JSONLDContext returns the JSONLD URIs required in the context string
+ // for this property and the specific values that are set. The value
+ // in the map is the alias used to import the property's value or
+ // values.
+ JSONLDContext() map[string]string
+ // KindIndex computes an arbitrary value for indexing this kind of value.
+ // This is a leaky API detail only for folks looking to replace the
+ // go-fed implementation. Applications should not use this method.
+ KindIndex() int
+ // LessThan compares two instances of this property with an arbitrary but
+ // stable comparison. Applications should not use this because it is
+ // only meant to help alternative implementations to go-fed to be able
+ // to normalize nonfunctional properties.
+ LessThan(o GoToSocialAnnounceAuthorizationProperty) bool
+ // Name returns the name of this property: "announceAuthorization".
+ Name() string
+ // Serialize converts this into an interface representation suitable for
+ // marshalling into a text or binary format. Applications should not
+ // need this function as most typical use cases serialize types
+ // instead of individual properties. It is exposed for alternatives to
+ // go-fed implementations to use.
+ Serialize() (interface{}, error)
+ // Set sets the value of this property. Calling IsXMLSchemaAnyURI
+ // afterwards will return true.
+ Set(v *url.URL)
+ // SetIRI sets the value of this property. Calling IsIRI afterwards will
+ // return true.
+ SetIRI(v *url.URL)
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_approvedBy_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_approvedBy_interface.go
index c99467246..86a98f638 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_approvedBy_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_approvedBy_interface.go
@@ -4,11 +4,12 @@ package vocab
import "net/url"
-// URI/ID of an Accept Activity or approval, which itself points towards the ID of
-// the Activity or Object to which this property is attached. The presence of
-// this property on an Activity or Object indicates that an interaction has
-// been Approve'd by the Actor whose Object this Activity or Object interacts
-// with.
+// DEPRECATED: Use `likeAuthorization`, `replyAuthorization`, or
+// `announceAuthorization` instead. URI/ID of an Accept Activity or approval,
+// which itself points towards the ID of the Activity or Object to which this
+// property is attached. The presence of this property on an Activity or
+// Object indicates that an interaction has been Approve'd by the Actor whose
+// Object this Activity or Object interacts with.
type GoToSocialApprovedByProperty interface {
// Clear ensures no value of this property is set. Calling
// IsXMLSchemaAnyURI afterwards will return false.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesCcPublicFromUnauthedWeb_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesCcPublicFromUnauthedWeb_interface.go
index a84a2a366..8019bd142 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesCcPublicFromUnauthedWeb_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesCcPublicFromUnauthedWeb_interface.go
@@ -8,8 +8,7 @@ import "net/url"
// (Notes, Articles, etc) from unauthenticated (ie., logged-out) access via
// web pages, web apps, web APIs, etc. This setting has no bearing on
// dereferences via HTTP GET to ActivityPub endpoints (application/ld+json;
-// profile="https://www.w3.org/ns/activitystreams"), for which GoToSocial
-// always requires HTTP signatures.
+// profile="https://www.w3.org/ns/activitystreams").
type GoToSocialHidesCcPublicFromUnauthedWebProperty interface {
// Clear ensures no value of this property is set. Calling
// IsXMLSchemaBoolean afterwards will return false.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesToPublicFromUnauthedWeb_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesToPublicFromUnauthedWeb_interface.go
index f876e6eb2..e5ed0067e 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesToPublicFromUnauthedWeb_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_hidesToPublicFromUnauthedWeb_interface.go
@@ -8,8 +8,7 @@ import "net/url"
// (Notes, Articles, etc) from unauthenticated (ie., logged-out) access via
// web pages, web apps, web APIs, etc. This setting has no bearing on
// dereferences via HTTP GET to ActivityPub endpoints (application/ld+json;
-// profile="https://www.w3.org/ns/activitystreams"), for which GoToSocial
-// always requires HTTP signatures.
+// profile="https://www.w3.org/ns/activitystreams").
type GoToSocialHidesToPublicFromUnauthedWebProperty interface {
// Clear ensures no value of this property is set. Calling
// IsXMLSchemaBoolean afterwards will return false.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_likeAuthorization_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_likeAuthorization_interface.go
new file mode 100644
index 000000000..8c3ca0915
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_likeAuthorization_interface.go
@@ -0,0 +1,52 @@
+// Code generated by astool. DO NOT EDIT.
+
+package vocab
+
+import "net/url"
+
+// URI/ID of a LikeAuthorization permitting the Like this property is attached to.
+type GoToSocialLikeAuthorizationProperty interface {
+ // Clear ensures no value of this property is set. Calling
+ // IsXMLSchemaAnyURI afterwards will return false.
+ Clear()
+ // Get returns the value of this property. When IsXMLSchemaAnyURI returns
+ // false, Get will return any arbitrary value.
+ Get() *url.URL
+ // GetIRI returns the IRI of this property. When IsIRI returns false,
+ // GetIRI will return any arbitrary value.
+ GetIRI() *url.URL
+ // HasAny returns true if the value or IRI is set.
+ HasAny() bool
+ // IsIRI returns true if this property is an IRI.
+ IsIRI() bool
+ // IsXMLSchemaAnyURI returns true if this property is set and not an IRI.
+ IsXMLSchemaAnyURI() bool
+ // JSONLDContext returns the JSONLD URIs required in the context string
+ // for this property and the specific values that are set. The value
+ // in the map is the alias used to import the property's value or
+ // values.
+ JSONLDContext() map[string]string
+ // KindIndex computes an arbitrary value for indexing this kind of value.
+ // This is a leaky API detail only for folks looking to replace the
+ // go-fed implementation. Applications should not use this method.
+ KindIndex() int
+ // LessThan compares two instances of this property with an arbitrary but
+ // stable comparison. Applications should not use this because it is
+ // only meant to help alternative implementations to go-fed to be able
+ // to normalize nonfunctional properties.
+ LessThan(o GoToSocialLikeAuthorizationProperty) bool
+ // Name returns the name of this property: "likeAuthorization".
+ Name() string
+ // Serialize converts this into an interface representation suitable for
+ // marshalling into a text or binary format. Applications should not
+ // need this function as most typical use cases serialize types
+ // instead of individual properties. It is exposed for alternatives to
+ // go-fed implementations to use.
+ Serialize() (interface{}, error)
+ // Set sets the value of this property. Calling IsXMLSchemaAnyURI
+ // afterwards will return true.
+ Set(v *url.URL)
+ // SetIRI sets the value of this property. Calling IsIRI afterwards will
+ // return true.
+ SetIRI(v *url.URL)
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_replyAuthorization_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_replyAuthorization_interface.go
new file mode 100644
index 000000000..078e5e3d0
--- /dev/null
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_property_gotosocial_replyAuthorization_interface.go
@@ -0,0 +1,53 @@
+// Code generated by astool. DO NOT EDIT.
+
+package vocab
+
+import "net/url"
+
+// URI/ID of a ReplyAuthorization permitting the Object this property is attached
+// to.
+type GoToSocialReplyAuthorizationProperty interface {
+ // Clear ensures no value of this property is set. Calling
+ // IsXMLSchemaAnyURI afterwards will return false.
+ Clear()
+ // Get returns the value of this property. When IsXMLSchemaAnyURI returns
+ // false, Get will return any arbitrary value.
+ Get() *url.URL
+ // GetIRI returns the IRI of this property. When IsIRI returns false,
+ // GetIRI will return any arbitrary value.
+ GetIRI() *url.URL
+ // HasAny returns true if the value or IRI is set.
+ HasAny() bool
+ // IsIRI returns true if this property is an IRI.
+ IsIRI() bool
+ // IsXMLSchemaAnyURI returns true if this property is set and not an IRI.
+ IsXMLSchemaAnyURI() bool
+ // JSONLDContext returns the JSONLD URIs required in the context string
+ // for this property and the specific values that are set. The value
+ // in the map is the alias used to import the property's value or
+ // values.
+ JSONLDContext() map[string]string
+ // KindIndex computes an arbitrary value for indexing this kind of value.
+ // This is a leaky API detail only for folks looking to replace the
+ // go-fed implementation. Applications should not use this method.
+ KindIndex() int
+ // LessThan compares two instances of this property with an arbitrary but
+ // stable comparison. Applications should not use this because it is
+ // only meant to help alternative implementations to go-fed to be able
+ // to normalize nonfunctional properties.
+ LessThan(o GoToSocialReplyAuthorizationProperty) bool
+ // Name returns the name of this property: "replyAuthorization".
+ Name() string
+ // Serialize converts this into an interface representation suitable for
+ // marshalling into a text or binary format. Applications should not
+ // need this function as most typical use cases serialize types
+ // instead of individual properties. It is exposed for alternatives to
+ // go-fed implementations to use.
+ Serialize() (interface{}, error)
+ // Set sets the value of this property. Calling IsXMLSchemaAnyURI
+ // afterwards will return true.
+ Set(v *url.URL)
+ // SetIRI sets the value of this property. Calling IsIRI afterwards will
+ // return true.
+ SetIRI(v *url.URL)
+}
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_announce_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_announce_interface.go
index 0b5aef0f1..5f8cf0eef 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_announce_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_announce_interface.go
@@ -136,6 +136,9 @@ type ActivityStreamsAnnounce interface {
// GetActivityStreamsUrl returns the "url" property if it exists, and nil
// otherwise.
GetActivityStreamsUrl() ActivityStreamsUrlProperty
+ // GetGoToSocialAnnounceAuthorization returns the "announceAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialAnnounceAuthorization() GoToSocialAnnounceAuthorizationProperty
// GetGoToSocialApprovedBy returns the "approvedBy" property if it exists,
// and nil otherwise.
GetGoToSocialApprovedBy() GoToSocialApprovedByProperty
@@ -241,6 +244,9 @@ type ActivityStreamsAnnounce interface {
SetActivityStreamsUpdated(i ActivityStreamsUpdatedProperty)
// SetActivityStreamsUrl sets the "url" property.
SetActivityStreamsUrl(i ActivityStreamsUrlProperty)
+ // SetGoToSocialAnnounceAuthorization sets the "announceAuthorization"
+ // property.
+ SetGoToSocialAnnounceAuthorization(i GoToSocialAnnounceAuthorizationProperty)
// SetGoToSocialApprovedBy sets the "approvedBy" property.
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetJSONLDId sets the "id" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_article_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_article_interface.go
index 149fdb6a9..1dd2a5b51 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_article_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_article_interface.go
@@ -118,6 +118,9 @@ type ActivityStreamsArticle interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -214,6 +217,8 @@ type ActivityStreamsArticle interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_audio_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_audio_interface.go
index 70ad5d20a..032fd5473 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_audio_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_audio_interface.go
@@ -118,6 +118,9 @@ type ActivityStreamsAudio interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -219,6 +222,8 @@ type ActivityStreamsAudio interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_document_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_document_interface.go
index f417c9452..0a654bfe7 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_document_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_document_interface.go
@@ -114,6 +114,9 @@ type ActivityStreamsDocument interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -216,6 +219,8 @@ type ActivityStreamsDocument interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_event_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_event_interface.go
index 9edbb7b36..3a9e6546e 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_event_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_event_interface.go
@@ -115,6 +115,9 @@ type ActivityStreamsEvent interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -210,6 +213,8 @@ type ActivityStreamsEvent interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_image_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_image_interface.go
index 5073d044a..c7fb3b69d 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_image_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_image_interface.go
@@ -131,6 +131,9 @@ type ActivityStreamsImage interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -236,6 +239,8 @@ type ActivityStreamsImage interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_like_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_like_interface.go
index 1dcbdd914..f4501c23e 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_like_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_like_interface.go
@@ -131,6 +131,9 @@ type ActivityStreamsLike interface {
// GetGoToSocialApprovedBy returns the "approvedBy" property if it exists,
// and nil otherwise.
GetGoToSocialApprovedBy() GoToSocialApprovedByProperty
+ // GetGoToSocialLikeAuthorization returns the "likeAuthorization" property
+ // if it exists, and nil otherwise.
+ GetGoToSocialLikeAuthorization() GoToSocialLikeAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -234,6 +237,8 @@ type ActivityStreamsLike interface {
SetActivityStreamsUrl(i ActivityStreamsUrlProperty)
// SetGoToSocialApprovedBy sets the "approvedBy" property.
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
+ // SetGoToSocialLikeAuthorization sets the "likeAuthorization" property.
+ SetGoToSocialLikeAuthorization(i GoToSocialLikeAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_note_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_note_interface.go
index d78560050..4b1ecd095 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_note_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_note_interface.go
@@ -115,6 +115,9 @@ type ActivityStreamsNote interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -210,6 +213,8 @@ type ActivityStreamsNote interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_page_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_page_interface.go
index 635dab3b2..935069f03 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_page_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_page_interface.go
@@ -114,6 +114,9 @@ type ActivityStreamsPage interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -215,6 +218,8 @@ type ActivityStreamsPage interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_place_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_place_interface.go
index 0c983542e..bdd429a42 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_place_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_place_interface.go
@@ -140,6 +140,9 @@ type ActivityStreamsPlace interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -245,6 +248,8 @@ type ActivityStreamsPlace interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_profile_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_profile_interface.go
index b4b8a7697..65725835b 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_profile_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_profile_interface.go
@@ -122,6 +122,9 @@ type ActivityStreamsProfile interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -220,6 +223,8 @@ type ActivityStreamsProfile interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_question_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_question_interface.go
index c249bfc33..44cc24d71 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_question_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_question_interface.go
@@ -157,6 +157,9 @@ type ActivityStreamsQuestion interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -270,6 +273,8 @@ type ActivityStreamsQuestion interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_video_interface.go b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_video_interface.go
index c42dd635a..85c788605 100644
--- a/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_video_interface.go
+++ b/vendor/code.superseriousbusiness.org/activity/streams/vocab/gen_type_activitystreams_video_interface.go
@@ -115,6 +115,9 @@ type ActivityStreamsVideo interface {
// GetGoToSocialInteractionPolicy returns the "interactionPolicy" property
// if it exists, and nil otherwise.
GetGoToSocialInteractionPolicy() GoToSocialInteractionPolicyProperty
+ // GetGoToSocialReplyAuthorization returns the "replyAuthorization"
+ // property if it exists, and nil otherwise.
+ GetGoToSocialReplyAuthorization() GoToSocialReplyAuthorizationProperty
// GetJSONLDId returns the "id" property if it exists, and nil otherwise.
GetJSONLDId() JSONLDIdProperty
// GetJSONLDType returns the "type" property if it exists, and nil
@@ -216,6 +219,8 @@ type ActivityStreamsVideo interface {
SetGoToSocialApprovedBy(i GoToSocialApprovedByProperty)
// SetGoToSocialInteractionPolicy sets the "interactionPolicy" property.
SetGoToSocialInteractionPolicy(i GoToSocialInteractionPolicyProperty)
+ // SetGoToSocialReplyAuthorization sets the "replyAuthorization" property.
+ SetGoToSocialReplyAuthorization(i GoToSocialReplyAuthorizationProperty)
// SetJSONLDId sets the "id" property.
SetJSONLDId(i JSONLDIdProperty)
// SetJSONLDType sets the "type" property.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9034d1476..e2faccc3c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,4 +1,4 @@
-# code.superseriousbusiness.org/activity v1.16.0
+# code.superseriousbusiness.org/activity v1.17.0
## explicit; go 1.23
code.superseriousbusiness.org/activity/pub
code.superseriousbusiness.org/activity/streams
@@ -139,6 +139,7 @@ code.superseriousbusiness.org/activity/streams/impl/funkwhale/type_artist
code.superseriousbusiness.org/activity/streams/impl/funkwhale/type_library
code.superseriousbusiness.org/activity/streams/impl/funkwhale/type_track
code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_always
+code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_announceauthorization
code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_approvalrequired
code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_approvedby
code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_automaticapproval
@@ -151,7 +152,9 @@ code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_hidestop
code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactingobject
code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactionpolicy
code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_interactiontarget
+code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_likeauthorization
code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_manualapproval
+code.superseriousbusiness.org/activity/streams/impl/gotosocial/property_replyauthorization
code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announceapproval
code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announceauthorization
code.superseriousbusiness.org/activity/streams/impl/gotosocial/type_announcerequest