diff options
Diffstat (limited to 'testrig/testmodels.go')
-rw-r--r-- | testrig/testmodels.go | 558 |
1 files changed, 505 insertions, 53 deletions
diff --git a/testrig/testmodels.go b/testrig/testmodels.go index 0d95ef21d..e550c66f7 100644 --- a/testrig/testmodels.go +++ b/testrig/testmodels.go @@ -19,13 +19,26 @@ package testrig import ( + "bytes" + "context" + "crypto" "crypto/rand" "crypto/rsa" + "crypto/x509" + "encoding/json" + "encoding/pem" + "io/ioutil" "net" + "net/http" + "net/url" "time" - "github.com/superseriousbusiness/gotosocial/internal/db/gtsmodel" + "github.com/go-fed/activity/pub" + "github.com/go-fed/activity/streams" + "github.com/go-fed/activity/streams/vocab" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/oauth" + "github.com/superseriousbusiness/gotosocial/internal/typeutils" ) // NewTestTokens returns a map of tokens keyed according to which account the token belongs to. @@ -274,15 +287,16 @@ func NewTestAccounts() map[string]*gtsmodel.Account { URI: "http://localhost:8080/users/weed_lord420", URL: "http://localhost:8080/@weed_lord420", LastWebfingeredAt: time.Time{}, - InboxURL: "http://localhost:8080/users/weed_lord420/inbox", - OutboxURL: "http://localhost:8080/users/weed_lord420/outbox", - SharedInboxURL: "", - FollowersURL: "http://localhost:8080/users/weed_lord420/followers", - FeaturedCollectionURL: "http://localhost:8080/users/weed_lord420/collections/featured", + InboxURI: "http://localhost:8080/users/weed_lord420/inbox", + OutboxURI: "http://localhost:8080/users/weed_lord420/outbox", + FollowersURI: "http://localhost:8080/users/weed_lord420/followers", + FollowingURI: "http://localhost:8080/users/weed_lord420/following", + FeaturedCollectionURI: "http://localhost:8080/users/weed_lord420/collections/featured", ActorType: gtsmodel.ActivityStreamsPerson, AlsoKnownAs: "", PrivateKey: &rsa.PrivateKey{}, PublicKey: &rsa.PublicKey{}, + PublicKeyURI: "http://localhost:8080/users/weed_lord420#main-key", SensitizedAt: time.Time{}, SilencedAt: time.Time{}, SuspendedAt: time.Time{}, @@ -310,12 +324,13 @@ func NewTestAccounts() map[string]*gtsmodel.Account { Language: "en", URI: "http://localhost:8080/users/admin", URL: "http://localhost:8080/@admin", + PublicKeyURI: "http://localhost:8080/users/admin#main-key", LastWebfingeredAt: time.Time{}, - InboxURL: "http://localhost:8080/users/admin/inbox", - OutboxURL: "http://localhost:8080/users/admin/outbox", - SharedInboxURL: "", - FollowersURL: "http://localhost:8080/users/admin/followers", - FeaturedCollectionURL: "http://localhost:8080/users/admin/collections/featured", + InboxURI: "http://localhost:8080/users/admin/inbox", + OutboxURI: "http://localhost:8080/users/admin/outbox", + FollowersURI: "http://localhost:8080/users/admin/followers", + FollowingURI: "http://localhost:8080/users/admin/following", + FeaturedCollectionURI: "http://localhost:8080/users/admin/collections/featured", ActorType: gtsmodel.ActivityStreamsPerson, AlsoKnownAs: "", PrivateKey: &rsa.PrivateKey{}, @@ -348,15 +363,16 @@ func NewTestAccounts() map[string]*gtsmodel.Account { URI: "http://localhost:8080/users/the_mighty_zork", URL: "http://localhost:8080/@the_mighty_zork", LastWebfingeredAt: time.Time{}, - InboxURL: "http://localhost:8080/users/the_mighty_zork/inbox", - OutboxURL: "http://localhost:8080/users/the_mighty_zork/outbox", - SharedInboxURL: "", - FollowersURL: "http://localhost:8080/users/the_mighty_zork/followers", - FeaturedCollectionURL: "http://localhost:8080/users/the_mighty_zork/collections/featured", + InboxURI: "http://localhost:8080/users/the_mighty_zork/inbox", + OutboxURI: "http://localhost:8080/users/the_mighty_zork/outbox", + FollowersURI: "http://localhost:8080/users/the_mighty_zork/followers", + FollowingURI: "http://localhost:8080/users/the_mighty_zork/following", + FeaturedCollectionURI: "http://localhost:8080/users/the_mighty_zork/collections/featured", ActorType: gtsmodel.ActivityStreamsPerson, AlsoKnownAs: "", PrivateKey: &rsa.PrivateKey{}, PublicKey: &rsa.PublicKey{}, + PublicKeyURI: "http://localhost:8080/users/the_mighty_zork#main-key", SensitizedAt: time.Time{}, SilencedAt: time.Time{}, SuspendedAt: time.Time{}, @@ -385,15 +401,16 @@ func NewTestAccounts() map[string]*gtsmodel.Account { URI: "http://localhost:8080/users/1happyturtle", URL: "http://localhost:8080/@1happyturtle", LastWebfingeredAt: time.Time{}, - InboxURL: "http://localhost:8080/users/1happyturtle/inbox", - OutboxURL: "http://localhost:8080/users/1happyturtle/outbox", - SharedInboxURL: "", - FollowersURL: "http://localhost:8080/users/1happyturtle/followers", - FeaturedCollectionURL: "http://localhost:8080/users/1happyturtle/collections/featured", + InboxURI: "http://localhost:8080/users/1happyturtle/inbox", + OutboxURI: "http://localhost:8080/users/1happyturtle/outbox", + FollowersURI: "http://localhost:8080/users/1happyturtle/followers", + FollowingURI: "http://localhost:8080/users/1happyturtle/following", + FeaturedCollectionURI: "http://localhost:8080/users/1happyturtle/collections/featured", ActorType: gtsmodel.ActivityStreamsPerson, AlsoKnownAs: "", PrivateKey: &rsa.PrivateKey{}, PublicKey: &rsa.PublicKey{}, + PublicKeyURI: "http://localhost:8080/users/1happyturtle#main-key", SensitizedAt: time.Time{}, SilencedAt: time.Time{}, SuspendedAt: time.Time{}, @@ -426,18 +443,19 @@ func NewTestAccounts() map[string]*gtsmodel.Account { Discoverable: true, Sensitive: false, Language: "en", - URI: "https://fossbros-anonymous.io/users/foss_satan", - URL: "https://fossbros-anonymous.io/@foss_satan", + URI: "http://fossbros-anonymous.io/users/foss_satan", + URL: "http://fossbros-anonymous.io/@foss_satan", LastWebfingeredAt: time.Time{}, - InboxURL: "https://fossbros-anonymous.io/users/foss_satan/inbox", - OutboxURL: "https://fossbros-anonymous.io/users/foss_satan/outbox", - SharedInboxURL: "", - FollowersURL: "https://fossbros-anonymous.io/users/foss_satan/followers", - FeaturedCollectionURL: "https://fossbros-anonymous.io/users/foss_satan/collections/featured", + InboxURI: "http://fossbros-anonymous.io/users/foss_satan/inbox", + OutboxURI: "http://fossbros-anonymous.io/users/foss_satan/outbox", + FollowersURI: "http://fossbros-anonymous.io/users/foss_satan/followers", + FollowingURI: "http://fossbros-anonymous.io/users/foss_satan/following", + FeaturedCollectionURI: "http://fossbros-anonymous.io/users/foss_satan/collections/featured", ActorType: gtsmodel.ActivityStreamsPerson, AlsoKnownAs: "", - PrivateKey: &rsa.PrivateKey{}, - PublicKey: nil, + PrivateKey: nil, + PublicKey: &rsa.PublicKey{}, + PublicKeyURI: "http://fossbros-anonymous.io/users/foss_satan#main-key", SensitizedAt: time.Time{}, SilencedAt: time.Time{}, SuspendedAt: time.Time{}, @@ -468,10 +486,10 @@ func NewTestAccounts() map[string]*gtsmodel.Account { } pub := &priv.PublicKey - // only local accounts get a private key - if v.Domain == "" { - v.PrivateKey = priv - } + // normally only local accounts get a private key (obviously) + // but for testing purposes and signing requests, we'll give + // remote accounts a private key as well + v.PrivateKey = priv v.PublicKey = pub } return accounts @@ -676,25 +694,26 @@ func NewTestAttachments() map[string]*gtsmodel.MediaAttachment { func NewTestEmojis() map[string]*gtsmodel.Emoji { return map[string]*gtsmodel.Emoji{ "rainbow": { - ID: "a96ec4f3-1cae-47e4-a508-f9d66a6b221b", - Shortcode: "rainbow", - Domain: "", - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - ImageRemoteURL: "", - ImageStaticRemoteURL: "", - ImageURL: "http://localhost:8080/fileserver/39b745a3-774d-4b65-8bb2-b63d9e20a343/emoji/original/a96ec4f3-1cae-47e4-a508-f9d66a6b221b.png", - ImagePath: "/tmp/gotosocial/39b745a3-774d-4b65-8bb2-b63d9e20a343/emoji/original/a96ec4f3-1cae-47e4-a508-f9d66a6b221b.png", - ImageStaticURL: "http://localhost:8080/fileserver/39b745a3-774d-4b65-8bb2-b63d9e20a343/emoji/static/a96ec4f3-1cae-47e4-a508-f9d66a6b221b.png", - ImageStaticPath: "/tmp/gotosocial/39b745a3-774d-4b65-8bb2-b63d9e20a343/emoji/static/a96ec4f3-1cae-47e4-a508-f9d66a6b221b.png", - ImageContentType: "image/png", - ImageFileSize: 36702, - ImageStaticFileSize: 10413, - ImageUpdatedAt: time.Now(), - Disabled: false, - URI: "http://localhost:8080/emoji/a96ec4f3-1cae-47e4-a508-f9d66a6b221b", - VisibleInPicker: true, - CategoryID: "", + ID: "a96ec4f3-1cae-47e4-a508-f9d66a6b221b", + Shortcode: "rainbow", + Domain: "", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + ImageRemoteURL: "", + ImageStaticRemoteURL: "", + ImageURL: "http://localhost:8080/fileserver/39b745a3-774d-4b65-8bb2-b63d9e20a343/emoji/original/a96ec4f3-1cae-47e4-a508-f9d66a6b221b.png", + ImagePath: "/tmp/gotosocial/39b745a3-774d-4b65-8bb2-b63d9e20a343/emoji/original/a96ec4f3-1cae-47e4-a508-f9d66a6b221b.png", + ImageStaticURL: "http://localhost:8080/fileserver/39b745a3-774d-4b65-8bb2-b63d9e20a343/emoji/static/a96ec4f3-1cae-47e4-a508-f9d66a6b221b.png", + ImageStaticPath: "/tmp/gotosocial/39b745a3-774d-4b65-8bb2-b63d9e20a343/emoji/static/a96ec4f3-1cae-47e4-a508-f9d66a6b221b.png", + ImageContentType: "image/png", + ImageStaticContentType: "image/png", + ImageFileSize: 36702, + ImageStaticFileSize: 10413, + ImageUpdatedAt: time.Now(), + Disabled: false, + URI: "http://localhost:8080/emoji/a96ec4f3-1cae-47e4-a508-f9d66a6b221b", + VisibleInPicker: true, + CategoryID: "", }, } } @@ -993,3 +1012,436 @@ func NewTestFaves() map[string]*gtsmodel.StatusFave { }, } } + +type ActivityWithSignature struct { + Activity pub.Activity + SignatureHeader string + DigestHeader string + DateHeader string +} + +// NewTestActivities returns a bunch of pub.Activity types for use in testing the federation protocols. +// A struct of accounts needs to be passed in because the activities will also be bundled along with +// their requesting signatures. +func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]ActivityWithSignature { + dmForZork := newNote( + URLMustParse("https://fossbros-anonymous.io/users/foss_satan/statuses/5424b153-4553-4f30-9358-7b92f7cd42f6"), + URLMustParse("https://fossbros-anonymous.io/@foss_satan/5424b153-4553-4f30-9358-7b92f7cd42f6"), + "hey zork here's a new private note for you", + "new note for zork", + URLMustParse("https://fossbros-anonymous.io/users/foss_satan"), + []*url.URL{URLMustParse("http://localhost:8080/users/the_mighty_zork")}, + nil, + true) + createDmForZork := wrapNoteInCreate( + URLMustParse("https://fossbros-anonymous.io/users/foss_satan/statuses/5424b153-4553-4f30-9358-7b92f7cd42f6/activity"), + URLMustParse("https://fossbros-anonymous.io/users/foss_satan"), + time.Now(), + dmForZork) + sig, digest, date := getSignatureForActivity(createDmForZork, accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_1"].InboxURI)) + + return map[string]ActivityWithSignature{ + "dm_for_zork": { + Activity: createDmForZork, + SignatureHeader: sig, + DigestHeader: digest, + DateHeader: date, + }, + } +} + +// NewTestFediPeople returns a bunch of activity pub Person representations for testing converters and so on. +func NewTestFediPeople() map[string]typeutils.Accountable { + new_person_1priv, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + panic(err) + } + new_person_1pub := &new_person_1priv.PublicKey + + return map[string]typeutils.Accountable{ + "new_person_1": newPerson( + URLMustParse("https://unknown-instance.com/users/brand_new_person"), + URLMustParse("https://unknown-instance.com/users/brand_new_person/following"), + URLMustParse("https://unknown-instance.com/users/brand_new_person/followers"), + URLMustParse("https://unknown-instance.com/users/brand_new_person/inbox"), + URLMustParse("https://unknown-instance.com/users/brand_new_person/outbox"), + URLMustParse("https://unknown-instance.com/users/brand_new_person/collections/featured"), + "brand_new_person", + "Geoff Brando New Personson", + "hey I'm a new person, your instance hasn't seen me yet uwu", + URLMustParse("https://unknown-instance.com/@brand_new_person"), + true, + URLMustParse("https://unknown-instance.com/users/brand_new_person#main-key"), + new_person_1pub, + URLMustParse("https://unknown-instance.com/media/some_avatar_filename.jpeg"), + "image/jpeg", + URLMustParse("https://unknown-instance.com/media/some_header_filename.jpeg"), + "image/png", + ), + } +} + +func NewTestDereferenceRequests(accounts map[string]*gtsmodel.Account) map[string]ActivityWithSignature { + sig, digest, date := getSignatureForDereference(accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_1"].URI)) + return map[string]ActivityWithSignature{ + "foss_satan_dereference_zork": { + SignatureHeader: sig, + DigestHeader: digest, + DateHeader: date, + }, + } +} + +// getSignatureForActivity does some sneaky sneaky work with a mock http client and a test transport controller, in order to derive +// the HTTP Signature for the given activity, public key ID, private key, and destination. +func getSignatureForActivity(activity pub.Activity, pubKeyID string, privkey crypto.PrivateKey, destination *url.URL) (signatureHeader string, digestHeader string, dateHeader string) { + // create a client that basically just pulls the signature out of the request and sets it + client := &mockHTTPClient{ + do: func(req *http.Request) (*http.Response, error) { + signatureHeader = req.Header.Get("Signature") + digestHeader = req.Header.Get("Digest") + dateHeader = req.Header.Get("Date") + r := ioutil.NopCloser(bytes.NewReader([]byte{})) // we only need this so the 'close' func doesn't nil out + return &http.Response{ + StatusCode: 200, + Body: r, + }, nil + }, + } + + // use the client to create a new transport + c := NewTestTransportController(client) + tp, err := c.NewTransport(pubKeyID, privkey) + if err != nil { + panic(err) + } + + // convert the activity into json bytes + m, err := activity.Serialize() + if err != nil { + panic(err) + } + bytes, err := json.Marshal(m) + if err != nil { + panic(err) + } + + // trigger the delivery function, which will trigger the 'do' function of the recorder above + if err := tp.Deliver(context.Background(), bytes, destination); err != nil { + panic(err) + } + + // headers should now be populated + return +} + +// getSignatureForDereference does some sneaky sneaky work with a mock http client and a test transport controller, in order to derive +// the HTTP Signature for the given derefence GET request using public key ID, private key, and destination. +func getSignatureForDereference(pubKeyID string, privkey crypto.PrivateKey, destination *url.URL) (signatureHeader string, digestHeader string, dateHeader string) { + // create a client that basically just pulls the signature out of the request and sets it + client := &mockHTTPClient{ + do: func(req *http.Request) (*http.Response, error) { + signatureHeader = req.Header.Get("Signature") + digestHeader = req.Header.Get("Digest") + dateHeader = req.Header.Get("Date") + r := ioutil.NopCloser(bytes.NewReader([]byte{})) // we only need this so the 'close' func doesn't nil out + return &http.Response{ + StatusCode: 200, + Body: r, + }, nil + }, + } + + // use the client to create a new transport + c := NewTestTransportController(client) + tp, err := c.NewTransport(pubKeyID, privkey) + if err != nil { + panic(err) + } + + // trigger the delivery function, which will trigger the 'do' function of the recorder above + if _, err := tp.Dereference(context.Background(), destination); err != nil { + panic(err) + } + + // headers should now be populated + return +} + +func newPerson( + profileIDURI *url.URL, + followingURI *url.URL, + followersURI *url.URL, + inboxURI *url.URL, + outboxURI *url.URL, + featuredURI *url.URL, + username string, + displayName string, + note string, + profileURL *url.URL, + discoverable bool, + publicKeyURI *url.URL, + pkey *rsa.PublicKey, + avatarURL *url.URL, + avatarContentType string, + headerURL *url.URL, + headerContentType string) typeutils.Accountable { + person := streams.NewActivityStreamsPerson() + + // id should be the activitypub URI of this user + // something like https://example.org/users/example_user + idProp := streams.NewJSONLDIdProperty() + idProp.SetIRI(profileIDURI) + person.SetJSONLDId(idProp) + + // following + // The URI for retrieving a list of accounts this user is following + followingProp := streams.NewActivityStreamsFollowingProperty() + followingProp.SetIRI(followingURI) + person.SetActivityStreamsFollowing(followingProp) + + // followers + // The URI for retrieving a list of this user's followers + followersProp := streams.NewActivityStreamsFollowersProperty() + followersProp.SetIRI(followersURI) + person.SetActivityStreamsFollowers(followersProp) + + // inbox + // the activitypub inbox of this user for accepting messages + inboxProp := streams.NewActivityStreamsInboxProperty() + inboxProp.SetIRI(inboxURI) + person.SetActivityStreamsInbox(inboxProp) + + // outbox + // the activitypub outbox of this user for serving messages + outboxProp := streams.NewActivityStreamsOutboxProperty() + outboxProp.SetIRI(outboxURI) + person.SetActivityStreamsOutbox(outboxProp) + + // featured posts + // Pinned posts. + featuredProp := streams.NewTootFeaturedProperty() + featuredProp.SetIRI(featuredURI) + person.SetTootFeatured(featuredProp) + + // featuredTags + // NOT IMPLEMENTED + + // preferredUsername + // Used for Webfinger lookup. Must be unique on the domain, and must correspond to a Webfinger acct: URI. + preferredUsernameProp := streams.NewActivityStreamsPreferredUsernameProperty() + preferredUsernameProp.SetXMLSchemaString(username) + person.SetActivityStreamsPreferredUsername(preferredUsernameProp) + + // name + // Used as profile display name. + nameProp := streams.NewActivityStreamsNameProperty() + if displayName != "" { + nameProp.AppendXMLSchemaString(displayName) + } else { + nameProp.AppendXMLSchemaString(username) + } + person.SetActivityStreamsName(nameProp) + + // summary + // Used as profile bio. + if note != "" { + summaryProp := streams.NewActivityStreamsSummaryProperty() + summaryProp.AppendXMLSchemaString(note) + person.SetActivityStreamsSummary(summaryProp) + } + + // url + // Used as profile link. + urlProp := streams.NewActivityStreamsUrlProperty() + urlProp.AppendIRI(profileURL) + person.SetActivityStreamsUrl(urlProp) + + // manuallyApprovesFollowers + // Will be shown as a locked account. + // TODO: NOT IMPLEMENTED **YET** -- this needs to be added as an activitypub extension to https://github.com/go-fed/activity, see https://github.com/go-fed/activity/tree/master/astool + + // discoverable + // Will be shown in the profile directory. + discoverableProp := streams.NewTootDiscoverableProperty() + discoverableProp.Set(discoverable) + person.SetTootDiscoverable(discoverableProp) + + // devices + // NOT IMPLEMENTED, probably won't implement + + // alsoKnownAs + // Required for Move activity. + // TODO: NOT IMPLEMENTED **YET** -- this needs to be added as an activitypub extension to https://github.com/go-fed/activity, see https://github.com/go-fed/activity/tree/master/astool + + // publicKey + // Required for signatures. + publicKeyProp := streams.NewW3IDSecurityV1PublicKeyProperty() + + // create the public key + publicKey := streams.NewW3IDSecurityV1PublicKey() + + // set ID for the public key + publicKeyIDProp := streams.NewJSONLDIdProperty() + publicKeyIDProp.SetIRI(publicKeyURI) + publicKey.SetJSONLDId(publicKeyIDProp) + + // set owner for the public key + publicKeyOwnerProp := streams.NewW3IDSecurityV1OwnerProperty() + publicKeyOwnerProp.SetIRI(profileIDURI) + publicKey.SetW3IDSecurityV1Owner(publicKeyOwnerProp) + + // set the pem key itself + encodedPublicKey, err := x509.MarshalPKIXPublicKey(pkey) + if err != nil { + panic(err) + } + publicKeyBytes := pem.EncodeToMemory(&pem.Block{ + Type: "PUBLIC KEY", + Bytes: encodedPublicKey, + }) + publicKeyPEMProp := streams.NewW3IDSecurityV1PublicKeyPemProperty() + publicKeyPEMProp.Set(string(publicKeyBytes)) + publicKey.SetW3IDSecurityV1PublicKeyPem(publicKeyPEMProp) + + // append the public key to the public key property + publicKeyProp.AppendW3IDSecurityV1PublicKey(publicKey) + + // set the public key property on the Person + person.SetW3IDSecurityV1PublicKey(publicKeyProp) + + // tag + // TODO: Any tags used in the summary of this profile + + // attachment + // Used for profile fields. + // TODO: The PropertyValue type has to be added: https://schema.org/PropertyValue + + // endpoints + // NOT IMPLEMENTED -- this is for shared inbox which we don't use + + // icon + // Used as profile avatar. + iconProperty := streams.NewActivityStreamsIconProperty() + iconImage := streams.NewActivityStreamsImage() + mediaType := streams.NewActivityStreamsMediaTypeProperty() + mediaType.Set(avatarContentType) + iconImage.SetActivityStreamsMediaType(mediaType) + avatarURLProperty := streams.NewActivityStreamsUrlProperty() + avatarURLProperty.AppendIRI(avatarURL) + iconImage.SetActivityStreamsUrl(avatarURLProperty) + iconProperty.AppendActivityStreamsImage(iconImage) + person.SetActivityStreamsIcon(iconProperty) + + // image + // Used as profile header. + headerProperty := streams.NewActivityStreamsImageProperty() + headerImage := streams.NewActivityStreamsImage() + headerMediaType := streams.NewActivityStreamsMediaTypeProperty() + mediaType.Set(headerContentType) + headerImage.SetActivityStreamsMediaType(headerMediaType) + headerURLProperty := streams.NewActivityStreamsUrlProperty() + headerURLProperty.AppendIRI(headerURL) + headerImage.SetActivityStreamsUrl(headerURLProperty) + headerProperty.AppendActivityStreamsImage(headerImage) + + return person +} + +// newNote returns a new activity streams note for the given parameters +func newNote( + noteID *url.URL, + noteURL *url.URL, + noteContent string, + noteSummary string, + noteAttributedTo *url.URL, + noteTo []*url.URL, + noteCC []*url.URL, + noteSensitive bool) vocab.ActivityStreamsNote { + + // create the note itself + note := streams.NewActivityStreamsNote() + + // set id + if noteID != nil { + id := streams.NewJSONLDIdProperty() + id.Set(noteID) + note.SetJSONLDId(id) + } + + // set noteURL + if noteURL != nil { + url := streams.NewActivityStreamsUrlProperty() + url.AppendIRI(noteURL) + note.SetActivityStreamsUrl(url) + } + + // set noteContent + if noteContent != "" { + content := streams.NewActivityStreamsContentProperty() + content.AppendXMLSchemaString(noteContent) + note.SetActivityStreamsContent(content) + } + + // set noteSummary (aka content warning) + if noteSummary != "" { + summary := streams.NewActivityStreamsSummaryProperty() + summary.AppendXMLSchemaString(noteSummary) + note.SetActivityStreamsSummary(summary) + } + + // set noteAttributedTo (the url of the author of the note) + if noteAttributedTo != nil { + attributedTo := streams.NewActivityStreamsAttributedToProperty() + attributedTo.AppendIRI(noteAttributedTo) + note.SetActivityStreamsAttributedTo(attributedTo) + } + + return note +} + +// wrapNoteInCreate wraps the given activity streams note in a Create activity streams action +func wrapNoteInCreate(createID *url.URL, createActor *url.URL, createPublished time.Time, createNote vocab.ActivityStreamsNote) vocab.ActivityStreamsCreate { + // create the.... create + create := streams.NewActivityStreamsCreate() + + // set createID + if createID != nil { + id := streams.NewJSONLDIdProperty() + id.Set(createID) + create.SetJSONLDId(id) + } + + // set createActor + if createActor != nil { + actor := streams.NewActivityStreamsActorProperty() + actor.AppendIRI(createActor) + create.SetActivityStreamsActor(actor) + } + + // set createPublished (time) + if !createPublished.IsZero() { + published := streams.NewActivityStreamsPublishedProperty() + published.Set(createPublished) + create.SetActivityStreamsPublished(published) + } + + // setCreateTo + if createNote.GetActivityStreamsTo() != nil { + create.SetActivityStreamsTo(createNote.GetActivityStreamsTo()) + } + + // setCreateCC + if createNote.GetActivityStreamsCc() != nil { + create.SetActivityStreamsCc(createNote.GetActivityStreamsCc()) + } + + // set createNote + if createNote != nil { + note := streams.NewActivityStreamsObjectProperty() + note.AppendActivityStreamsNote(createNote) + create.SetActivityStreamsObject(note) + } + + return create +} |