2023-03-12 16:00:57 +01:00
// 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/>.
2021-05-08 14:25:55 +02:00
package typeutils
import (
2021-08-25 15:34:33 +02:00
"context"
2021-08-10 13:32:39 +02:00
"net/url"
2022-09-04 14:41:42 +02:00
"sync"
2021-08-10 13:32:39 +02:00
2022-10-08 14:00:39 +02:00
"github.com/gorilla/feeds"
2021-11-13 17:29:43 +01:00
"github.com/superseriousbusiness/activity/streams/vocab"
2021-08-10 13:32:39 +02:00
"github.com/superseriousbusiness/gotosocial/internal/ap"
2023-01-02 13:10:50 +01:00
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
2021-05-08 14:25:55 +02:00
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)
// TypeConverter is an interface for the common action of converting between apimodule (frontend, serializable) models,
// internal gts models used in the database, and activitypub models used in federation.
//
// It requires access to the database because many of the conversions require pulling out database entries and counting them etc.
// That said, it *absolutely should not* manipulate database entries in any way, only examine them.
type TypeConverter interface {
/ *
2021-10-04 15:24:19 +02:00
INTERNAL ( gts ) MODEL TO FRONTEND ( api ) MODEL
2021-05-08 14:25:55 +02:00
* /
2021-10-04 15:24:19 +02:00
// AccountToAPIAccountSensitive takes a db model account as a param, and returns a populated apitype account, or an error
2021-05-08 14:25:55 +02:00
// if something goes wrong. The returned account should be ready to serialize on an API level, and may have sensitive fields,
// so serve it only to an authorized user who should have permission to see it.
2023-01-02 13:10:50 +01:00
AccountToAPIAccountSensitive ( ctx context . Context , account * gtsmodel . Account ) ( * apimodel . Account , error )
2021-10-04 15:24:19 +02:00
// AccountToAPIAccountPublic takes a db model account as a param, and returns a populated apitype account, or an error
2021-05-08 14:25:55 +02:00
// if something goes wrong. The returned account should be ready to serialize on an API level, and may NOT have sensitive fields.
// In other words, this is the public record that the server has of an account.
2023-01-02 13:10:50 +01:00
AccountToAPIAccountPublic ( ctx context . Context , account * gtsmodel . Account ) ( * apimodel . Account , error )
2021-10-04 15:24:19 +02:00
// AccountToAPIAccountBlocked takes a db model account as a param, and returns a apitype account, or an error if
2021-07-11 16:22:21 +02:00
// something goes wrong. The returned account will be a bare minimum representation of the account. This function should be used
// when someone wants to view an account they've blocked.
2023-01-02 13:10:50 +01:00
AccountToAPIAccountBlocked ( ctx context . Context , account * gtsmodel . Account ) ( * apimodel . Account , error )
2021-10-04 15:24:19 +02:00
// AppToAPIAppSensitive takes a db model application as a param, and returns a populated apitype application, or an error
2021-05-08 14:25:55 +02:00
// if something goes wrong. The returned application should be ready to serialize on an API level, and may have sensitive fields
// (such as client id and client secret), so serve it only to an authorized user who should have permission to see it.
2023-01-02 13:10:50 +01:00
AppToAPIAppSensitive ( ctx context . Context , application * gtsmodel . Application ) ( * apimodel . Application , error )
2021-10-04 15:24:19 +02:00
// AppToAPIAppPublic takes a db model application as a param, and returns a populated apitype application, or an error
2021-05-08 14:25:55 +02:00
// if something goes wrong. The returned application should be ready to serialize on an API level, and has sensitive
// fields sanitized so that it can be served to non-authorized accounts without revealing any private information.
2023-01-02 13:10:50 +01:00
AppToAPIAppPublic ( ctx context . Context , application * gtsmodel . Application ) ( * apimodel . Application , error )
2021-10-04 15:24:19 +02:00
// AttachmentToAPIAttachment converts a gts model media attacahment into its api representation for serialization on the API.
2023-01-02 13:10:50 +01:00
AttachmentToAPIAttachment ( ctx context . Context , attachment * gtsmodel . MediaAttachment ) ( apimodel . Attachment , error )
2021-10-04 15:24:19 +02:00
// MentionToAPIMention converts a gts model mention into its api (frontend) representation for serialization on the API.
2023-01-02 13:10:50 +01:00
MentionToAPIMention ( ctx context . Context , m * gtsmodel . Mention ) ( apimodel . Mention , error )
2021-10-04 15:24:19 +02:00
// EmojiToAPIEmoji converts a gts model emoji into its api (frontend) representation for serialization on the API.
2023-01-02 13:10:50 +01:00
EmojiToAPIEmoji ( ctx context . Context , e * gtsmodel . Emoji ) ( apimodel . Emoji , error )
2022-10-12 15:01:42 +02:00
// EmojiToAdminAPIEmoji converts a gts model emoji into an API representation with extra admin information.
2023-01-02 13:10:50 +01:00
EmojiToAdminAPIEmoji ( ctx context . Context , e * gtsmodel . Emoji ) ( * apimodel . AdminEmoji , error )
2022-11-14 23:47:27 +01:00
// EmojiCategoryToAPIEmojiCategory converts a gts model emoji category into its api (frontend) representation.
2023-01-02 13:10:50 +01:00
EmojiCategoryToAPIEmojiCategory ( ctx context . Context , category * gtsmodel . EmojiCategory ) ( * apimodel . EmojiCategory , error )
2021-10-04 15:24:19 +02:00
// TagToAPITag converts a gts model tag into its api (frontend) representation for serialization on the API.
2023-07-31 15:47:35 +02:00
// If stubHistory is set to 'true', then the 'history' field of the tag will be populated with a pointer to an empty slice, for API compatibility reasons.
TagToAPITag ( ctx context . Context , t * gtsmodel . Tag , stubHistory bool ) ( apimodel . Tag , error )
2021-10-04 15:24:19 +02:00
// StatusToAPIStatus converts a gts model status into its api (frontend) representation for serialization on the API.
2021-06-17 18:02:33 +02:00
//
// Requesting account can be nil.
2023-01-02 13:10:50 +01:00
StatusToAPIStatus ( ctx context . Context , s * gtsmodel . Status , requestingAccount * gtsmodel . Account ) ( * apimodel . Status , error )
2021-10-04 15:24:19 +02:00
// VisToAPIVis converts a gts visibility into its api equivalent
2023-01-02 13:10:50 +01:00
VisToAPIVis ( ctx context . Context , m gtsmodel . Visibility ) apimodel . Visibility
2023-02-02 14:08:13 +01:00
// InstanceToAPIV1Instance converts a gts instance into its api equivalent for serving at /api/v1/instance
InstanceToAPIV1Instance ( ctx context . Context , i * gtsmodel . Instance ) ( * apimodel . InstanceV1 , error )
// InstanceToAPIV2Instance converts a gts instance into its api equivalent for serving at /api/v2/instance
InstanceToAPIV2Instance ( ctx context . Context , i * gtsmodel . Instance ) ( * apimodel . InstanceV2 , error )
2021-10-04 15:24:19 +02:00
// RelationshipToAPIRelationship converts a gts relationship into its api equivalent for serving in various places
2023-01-02 13:10:50 +01:00
RelationshipToAPIRelationship ( ctx context . Context , r * gtsmodel . Relationship ) ( * apimodel . Relationship , error )
2021-10-04 15:24:19 +02:00
// NotificationToAPINotification converts a gts notification into a api notification
2023-01-02 13:10:50 +01:00
NotificationToAPINotification ( ctx context . Context , n * gtsmodel . Notification ) ( * apimodel . Notification , error )
2021-10-04 15:24:19 +02:00
// DomainBlockToAPIDomainBlock converts a gts model domin block into a api domain block, for serving at /api/v1/admin/domain_blocks
2023-01-02 13:10:50 +01:00
DomainBlockToAPIDomainBlock ( ctx context . Context , b * gtsmodel . DomainBlock , export bool ) ( * apimodel . DomainBlock , error )
2023-01-23 13:14:21 +01:00
// ReportToAPIReport converts a gts model report into an api model report, for serving at /api/v1/reports
ReportToAPIReport ( ctx context . Context , r * gtsmodel . Report ) ( * apimodel . Report , error )
2023-01-25 11:12:17 +01:00
// ReportToAdminAPIReport converts a gts model report into an admin view report, for serving at /api/v1/admin/reports
ReportToAdminAPIReport ( ctx context . Context , r * gtsmodel . Report , requestingAccount * gtsmodel . Account ) ( * apimodel . AdminReport , error )
2023-05-25 10:37:38 +02:00
// ListToAPIList converts one gts model list into an api model list, for serving at /api/v1/lists/{id}
ListToAPIList ( ctx context . Context , l * gtsmodel . List ) ( * apimodel . List , error )
2023-07-29 12:49:14 +02:00
// MarkersToAPIMarker converts several gts model markers into an api marker, for serving at /api/v1/markers
MarkersToAPIMarker ( ctx context . Context , markers [ ] * gtsmodel . Marker ) ( * apimodel . Marker , error )
2021-05-21 15:48:26 +02:00
2022-10-08 14:00:39 +02:00
/ *
INTERNAL ( gts ) MODEL TO FRONTEND ( rss ) MODEL
* /
StatusToRSSItem ( ctx context . Context , s * gtsmodel . Status ) ( * feeds . Item , error )
2021-05-08 14:25:55 +02:00
/ *
ACTIVITYSTREAMS MODEL TO INTERNAL ( gts ) MODEL
* /
2023-02-03 21:03:05 +01:00
// ASRepresentationToAccount converts a remote account/person/application representation into a gts model account.
2021-05-23 18:07:04 +02:00
//
2023-02-03 21:03:05 +01:00
// If accountDomain is provided then this value will be used as the account's Domain, else the AP ID host.
ASRepresentationToAccount ( ctx context . Context , accountable ap . Accountable , accountDomain string ) ( * gtsmodel . Account , error )
2021-05-15 11:58:11 +02:00
// ASStatus converts a remote activitystreams 'status' representation into a gts model status.
2021-08-25 15:34:33 +02:00
ASStatusToStatus ( ctx context . Context , statusable ap . Statusable ) ( * gtsmodel . Status , error )
2021-05-15 11:58:11 +02:00
// ASFollowToFollowRequest converts a remote activitystreams `follow` representation into gts model follow request.
2021-08-25 15:34:33 +02:00
ASFollowToFollowRequest ( ctx context . Context , followable ap . Followable ) ( * gtsmodel . FollowRequest , error )
2021-05-21 15:48:26 +02:00
// ASFollowToFollowRequest converts a remote activitystreams `follow` representation into gts model follow.
2021-08-25 15:34:33 +02:00
ASFollowToFollow ( ctx context . Context , followable ap . Followable ) ( * gtsmodel . Follow , error )
2021-05-27 16:06:24 +02:00
// ASLikeToFave converts a remote activitystreams 'like' representation into a gts model status fave.
2021-08-25 15:34:33 +02:00
ASLikeToFave ( ctx context . Context , likeable ap . Likeable ) ( * gtsmodel . StatusFave , error )
2021-07-11 16:22:21 +02:00
// ASBlockToBlock converts a remote activity streams 'block' representation into a gts model block.
2021-08-25 15:34:33 +02:00
ASBlockToBlock ( ctx context . Context , blockable ap . Blockable ) ( * gtsmodel . Block , error )
2021-05-28 19:57:04 +02:00
// ASAnnounceToStatus converts an activitystreams 'announce' into a status.
//
// The returned bool indicates whether this status is new (true) or not new (false).
//
// In other words, if the status is already in the database with the ID set on the announceable, then that will be returned,
// the returned bool will be false, and no further processing is necessary. If the returned bool is true, indicating
// that this is a new announce, then further processing will be necessary, because the returned status will be bareboned and
// require further dereferencing.
//
// This is useful when multiple users on an instance might receive the same boost, and we only want to process the boost once.
//
// NOTE -- this is different from one status being boosted multiple times! In this case, new boosts should indeed be created.
2021-08-25 15:34:33 +02:00
ASAnnounceToStatus ( ctx context . Context , announceable ap . Announceable ) ( status * gtsmodel . Status , new bool , err error )
2023-01-25 11:12:27 +01:00
// ASFlagToReport converts a remote activitystreams 'flag' representation into a gts model report.
ASFlagToReport ( ctx context . Context , flaggable ap . Flaggable ) ( report * gtsmodel . Report , err error )
2021-05-08 14:25:55 +02:00
/ *
INTERNAL ( gts ) MODEL TO ACTIVITYSTREAMS MODEL
* /
// AccountToAS converts a gts model account into an activity streams person, suitable for federation
2021-08-25 15:34:33 +02:00
AccountToAS ( ctx context . Context , a * gtsmodel . Account ) ( vocab . ActivityStreamsPerson , error )
2021-07-11 16:22:21 +02:00
// AccountToASMinimal converts a gts model account into an activity streams person, suitable for federation.
//
// The returned account will just have the Type, Username, PublicKey, and ID properties set. This is
// suitable for serving to requesters to whom we want to give as little information as possible because
// we don't trust them (yet).
2021-08-25 15:34:33 +02:00
AccountToASMinimal ( ctx context . Context , a * gtsmodel . Account ) ( vocab . ActivityStreamsPerson , error )
2021-05-08 14:25:55 +02:00
// StatusToAS converts a gts model status into an activity streams note, suitable for federation
2021-08-25 15:34:33 +02:00
StatusToAS ( ctx context . Context , s * gtsmodel . Status ) ( vocab . ActivityStreamsNote , error )
2023-03-03 20:56:34 +01:00
// StatusToASDelete converts a gts model status into a Delete of that status, using just the
// URI of the status as object, and addressing the Delete appropriately.
StatusToASDelete ( ctx context . Context , status * gtsmodel . Status ) ( vocab . ActivityStreamsDelete , error )
2021-05-21 15:48:26 +02:00
// FollowToASFollow converts a gts model Follow into an activity streams Follow, suitable for federation
2021-08-25 15:34:33 +02:00
FollowToAS ( ctx context . Context , f * gtsmodel . Follow , originAccount * gtsmodel . Account , targetAccount * gtsmodel . Account ) ( vocab . ActivityStreamsFollow , error )
2021-05-21 15:48:26 +02:00
// MentionToAS converts a gts model mention into an activity streams Mention, suitable for federation
2021-08-25 15:34:33 +02:00
MentionToAS ( ctx context . Context , m * gtsmodel . Mention ) ( vocab . ActivityStreamsMention , error )
2022-09-02 12:11:43 +02:00
// EmojiToAS converts a gts emoji into a mastodon ns Emoji, suitable for federation
EmojiToAS ( ctx context . Context , e * gtsmodel . Emoji ) ( vocab . TootEmoji , error )
2023-07-31 15:47:35 +02:00
// TagToAS converts a gts model tag into a toot Hashtag, suitable for federation.
TagToAS ( ctx context . Context , t * gtsmodel . Tag ) ( vocab . TootHashtag , error )
2021-05-21 15:48:26 +02:00
// AttachmentToAS converts a gts model media attachment into an activity streams Attachment, suitable for federation
2021-08-25 15:34:33 +02:00
AttachmentToAS ( ctx context . Context , a * gtsmodel . MediaAttachment ) ( vocab . ActivityStreamsDocument , error )
2021-05-24 18:49:48 +02:00
// FaveToAS converts a gts model status fave into an activityStreams LIKE, suitable for federation.
2021-08-25 15:34:33 +02:00
FaveToAS ( ctx context . Context , f * gtsmodel . StatusFave ) ( vocab . ActivityStreamsLike , error )
2021-05-28 19:57:04 +02:00
// BoostToAS converts a gts model boost into an activityStreams ANNOUNCE, suitable for federation
2021-08-25 15:34:33 +02:00
BoostToAS ( ctx context . Context , boostWrapperStatus * gtsmodel . Status , boostingAccount * gtsmodel . Account , boostedAccount * gtsmodel . Account ) ( vocab . ActivityStreamsAnnounce , error )
2021-07-11 16:22:21 +02:00
// BlockToAS converts a gts model block into an activityStreams BLOCK, suitable for federation.
2021-08-25 15:34:33 +02:00
BlockToAS ( ctx context . Context , block * gtsmodel . Block ) ( vocab . ActivityStreamsBlock , error )
2021-08-10 13:32:39 +02:00
// StatusToASRepliesCollection converts a gts model status into an activityStreams REPLIES collection.
2021-08-25 15:34:33 +02:00
StatusToASRepliesCollection ( ctx context . Context , status * gtsmodel . Status , onlyOtherAccounts bool ) ( vocab . ActivityStreamsCollection , error )
2021-08-10 13:32:39 +02:00
// StatusURIsToASRepliesPage returns a collection page with appropriate next/part of pagination.
2021-08-25 15:34:33 +02:00
StatusURIsToASRepliesPage ( ctx context . Context , status * gtsmodel . Status , onlyOtherAccounts bool , minID string , replies map [ string ] * url . URL ) ( vocab . ActivityStreamsCollectionPage , error )
2021-10-24 11:57:39 +02:00
// OutboxToASCollection returns an ordered collection with appropriate id, next, and last fields.
// The returned collection won't have any actual entries; just links to where entries can be obtained.
OutboxToASCollection ( ctx context . Context , outboxID string ) ( vocab . ActivityStreamsOrderedCollection , error )
// StatusesToASOutboxPage returns an ordered collection page using the given statuses and parameters as contents.
//
// The maxID and minID should be the parameters that were passed to the database to obtain the given statuses.
// These will be used to create the 'id' field of the collection.
//
// OutboxID is used to create the 'partOf' field in the collection.
//
// Appropriate 'next' and 'prev' fields will be created based on the highest and lowest IDs present in the statuses slice.
StatusesToASOutboxPage ( ctx context . Context , outboxID string , maxID string , minID string , statuses [ ] * gtsmodel . Status ) ( vocab . ActivityStreamsOrderedCollectionPage , error )
2023-03-01 18:52:44 +01:00
// StatusesToASFeaturedCollection converts a slice of statuses into an ordered collection
// of URIs, suitable for serializing and serving via the activitypub API.
StatusesToASFeaturedCollection ( ctx context . Context , featuredCollectionID string , statuses [ ] * gtsmodel . Status ) ( vocab . ActivityStreamsOrderedCollection , error )
2023-01-27 14:48:11 +01:00
// ReportToASFlag converts a gts model report into an activitystreams FLAG, suitable for federation.
ReportToASFlag ( ctx context . Context , r * gtsmodel . Report ) ( vocab . ActivityStreamsFlag , error )
2021-10-24 11:57:39 +02:00
2021-05-27 16:06:24 +02:00
/ *
INTERNAL ( gts ) MODEL TO INTERNAL MODEL
* /
// FollowRequestToFollow just converts a follow request into a follow, that's it! No bells and whistles.
2021-08-25 15:34:33 +02:00
FollowRequestToFollow ( ctx context . Context , f * gtsmodel . FollowRequest ) * gtsmodel . Follow
2021-05-27 16:06:24 +02:00
// StatusToBoost wraps the given status into a boosting status.
2021-08-25 15:34:33 +02:00
StatusToBoost ( ctx context . Context , s * gtsmodel . Status , boostingAccount * gtsmodel . Account ) ( * gtsmodel . Status , error )
2021-05-28 22:47:18 +02:00
/ *
WRAPPER CONVENIENCE FUNCTIONS
* /
2021-05-29 19:39:43 +02:00
2021-05-28 22:47:18 +02:00
// WrapPersonInUpdate
WrapPersonInUpdate ( person vocab . ActivityStreamsPerson , originAccount * gtsmodel . Account ) ( vocab . ActivityStreamsUpdate , error )
2021-10-24 11:57:39 +02:00
// WrapNoteInCreate wraps a Note with a Create activity.
//
// If objectIRIOnly is set to true, then the function won't put the *entire* note in the Object field of the Create,
// but just the AP URI of the note. This is useful in cases where you want to give a remote server something to dereference,
// and still have control over whether or not they're allowed to actually see the contents.
WrapNoteInCreate ( note vocab . ActivityStreamsNote , objectIRIOnly bool ) ( vocab . ActivityStreamsCreate , error )
2021-05-08 14:25:55 +02:00
}
type converter struct {
2022-09-04 14:41:42 +02:00
db db . DB
defaultAvatars [ ] string
randAvatars sync . Map
2021-05-08 14:25:55 +02:00
}
// NewConverter returns a new Converter
2021-12-07 13:31:39 +01:00
func NewConverter ( db db . DB ) TypeConverter {
2022-09-04 14:41:42 +02:00
return & converter {
db : db ,
defaultAvatars : populateDefaultAvatars ( ) ,
}
2021-05-08 14:25:55 +02:00
}