summaryrefslogtreecommitdiff
path: root/internal/typeutils/internaltoas.go
diff options
context:
space:
mode:
authorLibravatar Tobi Smethurst <31960611+tsmethurst@users.noreply.github.com>2021-05-08 14:25:55 +0200
committerLibravatar GitHub <noreply@github.com>2021-05-08 14:25:55 +0200
commit6f5c045284d34ba580d3007f70b97e05d6760527 (patch)
tree7614da22fba906361a918fb3527465b39272ac93 /internal/typeutils/internaltoas.go
parentRevert "make boosts work woo (#12)" (#15) (diff)
downloadgotosocial-6f5c045284d34ba580d3007f70b97e05d6760527.tar.xz
Ap (#14)
Big restructuring and initial work on activitypub
Diffstat (limited to 'internal/typeutils/internaltoas.go')
-rw-r--r--internal/typeutils/internaltoas.go260
1 files changed, 260 insertions, 0 deletions
diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go
new file mode 100644
index 000000000..73c121155
--- /dev/null
+++ b/internal/typeutils/internaltoas.go
@@ -0,0 +1,260 @@
+/*
+ GoToSocial
+ Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
+
+ 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 typeutils
+
+import (
+ "crypto/x509"
+ "encoding/pem"
+ "net/url"
+
+ "github.com/go-fed/activity/streams"
+ "github.com/go-fed/activity/streams/vocab"
+ "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+)
+
+// Converts a gts model account into an Activity Streams person type, following
+// the spec laid out for mastodon here: https://docs.joinmastodon.org/spec/activitypub/
+func (c *converter) AccountToAS(a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) {
+ person := streams.NewActivityStreamsPerson()
+
+ // id should be the activitypub URI of this user
+ // something like https://example.org/users/example_user
+ profileIDURI, err := url.Parse(a.URI)
+ if err != nil {
+ return nil, err
+ }
+ idProp := streams.NewJSONLDIdProperty()
+ idProp.SetIRI(profileIDURI)
+ person.SetJSONLDId(idProp)
+
+ // following
+ // The URI for retrieving a list of accounts this user is following
+ followingURI, err := url.Parse(a.FollowingURI)
+ if err != nil {
+ return nil, err
+ }
+ followingProp := streams.NewActivityStreamsFollowingProperty()
+ followingProp.SetIRI(followingURI)
+ person.SetActivityStreamsFollowing(followingProp)
+
+ // followers
+ // The URI for retrieving a list of this user's followers
+ followersURI, err := url.Parse(a.FollowersURI)
+ if err != nil {
+ return nil, err
+ }
+ followersProp := streams.NewActivityStreamsFollowersProperty()
+ followersProp.SetIRI(followersURI)
+ person.SetActivityStreamsFollowers(followersProp)
+
+ // inbox
+ // the activitypub inbox of this user for accepting messages
+ inboxURI, err := url.Parse(a.InboxURI)
+ if err != nil {
+ return nil, err
+ }
+ inboxProp := streams.NewActivityStreamsInboxProperty()
+ inboxProp.SetIRI(inboxURI)
+ person.SetActivityStreamsInbox(inboxProp)
+
+ // outbox
+ // the activitypub outbox of this user for serving messages
+ outboxURI, err := url.Parse(a.OutboxURI)
+ if err != nil {
+ return nil, err
+ }
+ outboxProp := streams.NewActivityStreamsOutboxProperty()
+ outboxProp.SetIRI(outboxURI)
+ person.SetActivityStreamsOutbox(outboxProp)
+
+ // featured posts
+ // Pinned posts.
+ featuredURI, err := url.Parse(a.FeaturedCollectionURI)
+ if err != nil {
+ return nil, err
+ }
+ 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(a.Username)
+ person.SetActivityStreamsPreferredUsername(preferredUsernameProp)
+
+ // name
+ // Used as profile display name.
+ nameProp := streams.NewActivityStreamsNameProperty()
+ if a.Username != "" {
+ nameProp.AppendXMLSchemaString(a.DisplayName)
+ } else {
+ nameProp.AppendXMLSchemaString(a.Username)
+ }
+ person.SetActivityStreamsName(nameProp)
+
+ // summary
+ // Used as profile bio.
+ if a.Note != "" {
+ summaryProp := streams.NewActivityStreamsSummaryProperty()
+ summaryProp.AppendXMLSchemaString(a.Note)
+ person.SetActivityStreamsSummary(summaryProp)
+ }
+
+ // url
+ // Used as profile link.
+ profileURL, err := url.Parse(a.URL)
+ if err != nil {
+ return nil, err
+ }
+ 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(a.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()
+ publicKeyURI, err := url.Parse(a.PublicKeyURI)
+ if err != nil {
+ return nil, err
+ }
+ 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(a.PublicKey)
+ if err != nil {
+ return nil, 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.
+ if a.AvatarMediaAttachmentID != "" {
+ iconProperty := streams.NewActivityStreamsIconProperty()
+
+ iconImage := streams.NewActivityStreamsImage()
+
+ avatar := &gtsmodel.MediaAttachment{}
+ if err := c.db.GetByID(a.AvatarMediaAttachmentID, avatar); err != nil {
+ return nil, err
+ }
+
+ mediaType := streams.NewActivityStreamsMediaTypeProperty()
+ mediaType.Set(avatar.File.ContentType)
+ iconImage.SetActivityStreamsMediaType(mediaType)
+
+ avatarURLProperty := streams.NewActivityStreamsUrlProperty()
+ avatarURL, err := url.Parse(avatar.URL)
+ if err != nil {
+ return nil, err
+ }
+ avatarURLProperty.AppendIRI(avatarURL)
+ iconImage.SetActivityStreamsUrl(avatarURLProperty)
+
+ iconProperty.AppendActivityStreamsImage(iconImage)
+ person.SetActivityStreamsIcon(iconProperty)
+ }
+
+ // image
+ // Used as profile header.
+ if a.HeaderMediaAttachmentID != "" {
+ headerProperty := streams.NewActivityStreamsImageProperty()
+
+ headerImage := streams.NewActivityStreamsImage()
+
+ header := &gtsmodel.MediaAttachment{}
+ if err := c.db.GetByID(a.HeaderMediaAttachmentID, header); err != nil {
+ return nil, err
+ }
+
+ mediaType := streams.NewActivityStreamsMediaTypeProperty()
+ mediaType.Set(header.File.ContentType)
+ headerImage.SetActivityStreamsMediaType(mediaType)
+
+ headerURLProperty := streams.NewActivityStreamsUrlProperty()
+ headerURL, err := url.Parse(header.URL)
+ if err != nil {
+ return nil, err
+ }
+ headerURLProperty.AppendIRI(headerURL)
+ headerImage.SetActivityStreamsUrl(headerURLProperty)
+
+ headerProperty.AppendActivityStreamsImage(headerImage)
+ }
+
+ return person, nil
+}
+
+func (c *converter) StatusToAS(s *gtsmodel.Status) (vocab.ActivityStreamsNote, error) {
+ return nil, nil
+}