diff options
Diffstat (limited to 'internal')
112 files changed, 599 insertions, 706 deletions
diff --git a/internal/api/activitypub/emoji/emojiget_test.go b/internal/api/activitypub/emoji/emojiget_test.go index ad4e070b2..ea9bbc752 100644 --- a/internal/api/activitypub/emoji/emojiget_test.go +++ b/internal/api/activitypub/emoji/emojiget_test.go @@ -43,7 +43,7 @@ import (  type EmojiGetTestSuite struct {  	suite.Suite  	db           db.DB -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	federator    federation.Federator  	emailSender  email.Sender @@ -75,7 +75,7 @@ func (suite *EmojiGetTestSuite) SetupTest() {  	suite.state.DB = suite.db  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/activitypub/users/user_test.go b/internal/api/activitypub/users/user_test.go index d0487777b..0689e7de8 100644 --- a/internal/api/activitypub/users/user_test.go +++ b/internal/api/activitypub/users/user_test.go @@ -39,7 +39,7 @@ type UserStandardTestSuite struct {  	// standard suite interfaces  	suite.Suite  	db           db.DB -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	federator    federation.Federator  	emailSender  email.Sender @@ -85,7 +85,7 @@ func (suite *UserStandardTestSuite) SetupTest() {  	suite.db = testrig.NewTestDB(&suite.state)  	suite.state.DB = suite.db -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/client/accounts/account_test.go b/internal/api/client/accounts/account_test.go index 7d8a78bff..6984f2563 100644 --- a/internal/api/client/accounts/account_test.go +++ b/internal/api/client/accounts/account_test.go @@ -36,6 +36,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -90,7 +91,7 @@ func (suite *AccountStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/api/client/admin/admin_test.go b/internal/api/client/admin/admin_test.go index cca8ffa66..bb403c2d6 100644 --- a/internal/api/client/admin/admin_test.go +++ b/internal/api/client/admin/admin_test.go @@ -36,6 +36,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -96,7 +97,7 @@ func (suite *AdminStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/api/client/bookmarks/bookmarks_test.go b/internal/api/client/bookmarks/bookmarks_test.go index e0b85c483..6a6fc6108 100644 --- a/internal/api/client/bookmarks/bookmarks_test.go +++ b/internal/api/client/bookmarks/bookmarks_test.go @@ -50,7 +50,7 @@ type BookmarkTestSuite struct {  	// standard suite interfaces  	suite.Suite  	db           db.DB -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	federator    federation.Federator  	emailSender  email.Sender @@ -98,7 +98,7 @@ func (suite *BookmarkTestSuite) SetupTest() {  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/client/favourites/favourites_test.go b/internal/api/client/favourites/favourites_test.go index 8e14a4e99..7033a8d39 100644 --- a/internal/api/client/favourites/favourites_test.go +++ b/internal/api/client/favourites/favourites_test.go @@ -37,7 +37,7 @@ type FavouritesStandardTestSuite struct {  	// standard suite interfaces  	suite.Suite  	db           db.DB -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	federator    federation.Federator  	emailSender  email.Sender @@ -82,7 +82,7 @@ func (suite *FavouritesStandardTestSuite) SetupTest() {  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/client/followrequests/followrequest_test.go b/internal/api/client/followrequests/followrequest_test.go index 51b8223bd..113950049 100644 --- a/internal/api/client/followrequests/followrequest_test.go +++ b/internal/api/client/followrequests/followrequest_test.go @@ -35,6 +35,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -87,7 +88,7 @@ func (suite *FollowRequestStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/api/client/instance/instance_test.go b/internal/api/client/instance/instance_test.go index 1ba3d72a9..116f4d4b4 100644 --- a/internal/api/client/instance/instance_test.go +++ b/internal/api/client/instance/instance_test.go @@ -35,6 +35,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -89,7 +90,7 @@ func (suite *InstanceStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/api/client/lists/lists_test.go b/internal/api/client/lists/lists_test.go index ebaf6998e..353306e1e 100644 --- a/internal/api/client/lists/lists_test.go +++ b/internal/api/client/lists/lists_test.go @@ -28,6 +28,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -88,7 +89,7 @@ func (suite *ListsStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/api/client/media/mediacreate_test.go b/internal/api/client/media/mediacreate_test.go index 2ffa8b8a1..23445607e 100644 --- a/internal/api/client/media/mediacreate_test.go +++ b/internal/api/client/media/mediacreate_test.go @@ -56,7 +56,7 @@ type MediaCreateTestSuite struct {  	storage      *storage.Driver  	mediaManager *media.Manager  	federator    federation.Federator -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	oauthServer  oauth.Server  	emailSender  email.Sender  	processor    *processing.Processor @@ -91,7 +91,7 @@ func (suite *MediaCreateTestSuite) SetupSuite() {  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/client/media/mediaupdate_test.go b/internal/api/client/media/mediaupdate_test.go index 8140f1acc..eb8266082 100644 --- a/internal/api/client/media/mediaupdate_test.go +++ b/internal/api/client/media/mediaupdate_test.go @@ -52,7 +52,7 @@ type MediaUpdateTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	federator    federation.Federator -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	oauthServer  oauth.Server  	emailSender  email.Sender @@ -87,7 +87,7 @@ func (suite *MediaUpdateTestSuite) SetupSuite() {  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/client/reports/reports_test.go b/internal/api/client/reports/reports_test.go index cf5167816..c1986cf1f 100644 --- a/internal/api/client/reports/reports_test.go +++ b/internal/api/client/reports/reports_test.go @@ -28,6 +28,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -81,7 +82,7 @@ func (suite *ReportsStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/api/client/search/search_test.go b/internal/api/client/search/search_test.go index fd98a0a64..b8d0dab6c 100644 --- a/internal/api/client/search/search_test.go +++ b/internal/api/client/search/search_test.go @@ -35,6 +35,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/processing"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -85,7 +86,7 @@ func (suite *SearchStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/api/client/statuses/status_test.go b/internal/api/client/statuses/status_test.go index 857e04dfe..4946bb9d3 100644 --- a/internal/api/client/statuses/status_test.go +++ b/internal/api/client/statuses/status_test.go @@ -37,7 +37,7 @@ type StatusStandardTestSuite struct {  	// standard suite interfaces  	suite.Suite  	db           db.DB -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	federator    federation.Federator  	emailSender  email.Sender @@ -82,7 +82,7 @@ func (suite *StatusStandardTestSuite) SetupTest() {  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/client/streaming/streaming_test.go b/internal/api/client/streaming/streaming_test.go index c8296ef2f..87c07d8f1 100644 --- a/internal/api/client/streaming/streaming_test.go +++ b/internal/api/client/streaming/streaming_test.go @@ -49,7 +49,7 @@ type StreamingTestSuite struct {  	// standard suite interfaces  	suite.Suite  	db           db.DB -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	federator    federation.Federator  	emailSender  email.Sender @@ -94,7 +94,7 @@ func (suite *StreamingTestSuite) SetupTest() {  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/client/user/user_test.go b/internal/api/client/user/user_test.go index ded004920..db7adfd6d 100644 --- a/internal/api/client/user/user_test.go +++ b/internal/api/client/user/user_test.go @@ -36,7 +36,7 @@ import (  type UserStandardTestSuite struct {  	suite.Suite  	db           db.DB -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	federator    federation.Federator  	emailSender  email.Sender @@ -73,7 +73,7 @@ func (suite *UserStandardTestSuite) SetupTest() {  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/fileserver/fileserver_test.go b/internal/api/fileserver/fileserver_test.go index e57b86082..6f46fbe74 100644 --- a/internal/api/fileserver/fileserver_test.go +++ b/internal/api/fileserver/fileserver_test.go @@ -42,7 +42,7 @@ type FileserverTestSuite struct {  	storage      *storage.Driver  	state        state.State  	federator    federation.Federator -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	processor    *processing.Processor  	mediaManager *media.Manager  	oauthServer  oauth.Server @@ -79,7 +79,7 @@ func (suite *FileserverTestSuite) SetupSuite() {  	suite.federator = testrig.NewTestFederator(&suite.state, testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../testrig/media")), suite.mediaManager)  	suite.processor = testrig.NewTestProcessor(&suite.state, suite.federator, suite.emailSender, suite.mediaManager) -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/api/wellknown/webfinger/webfinger_test.go b/internal/api/wellknown/webfinger/webfinger_test.go index cee87d9c0..3cec7fcde 100644 --- a/internal/api/wellknown/webfinger/webfinger_test.go +++ b/internal/api/wellknown/webfinger/webfinger_test.go @@ -39,7 +39,7 @@ type WebfingerStandardTestSuite struct {  	suite.Suite  	db           db.DB  	state        state.State -	tc           typeutils.TypeConverter +	tc           *typeutils.Converter  	mediaManager *media.Manager  	federator    federation.Federator  	emailSender  email.Sender @@ -79,7 +79,7 @@ func (suite *WebfingerStandardTestSuite) SetupTest() {  	suite.db = testrig.NewTestDB(&suite.state)  	suite.state.DB = suite.db -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/cleaner/media_test.go b/internal/cleaner/media_test.go index 824df2ca5..20a643ea8 100644 --- a/internal/cleaner/media_test.go +++ b/internal/cleaner/media_test.go @@ -34,6 +34,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage"  	"github.com/superseriousbusiness/gotosocial/internal/transport" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -74,7 +75,7 @@ func (suite *MediaTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.testAttachments = testrig.NewTestAttachments() diff --git a/internal/db/bundb/bundb_test.go b/internal/db/bundb/bundb_test.go index f3640cf59..2ab539147 100644 --- a/internal/db/bundb/bundb_test.go +++ b/internal/db/bundb/bundb_test.go @@ -22,6 +22,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/state" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -81,7 +82,8 @@ func (suite *BunDBStandardTestSuite) SetupTest() {  	testrig.InitTestLog()  	suite.state.Caches.Init()  	suite.db = testrig.NewTestDB(&suite.state) -	testrig.StartTimelines(&suite.state, visibility.NewFilter(&suite.state), testrig.NewTestTypeConverter(suite.db)) +	converter := typeutils.NewConverter(&suite.state) +	testrig.StartTimelines(&suite.state, visibility.NewFilter(&suite.state), converter)  	testrig.StandardDBSetup(suite.db, suite.testAccounts)  } diff --git a/internal/federation/dereferencing/account.go b/internal/federation/dereferencing/account.go index ec8d274a4..04efc464f 100644 --- a/internal/federation/dereferencing/account.go +++ b/internal/federation/dereferencing/account.go @@ -372,7 +372,7 @@ func (d *deref) enrichAccount(ctx context.Context, requestUser string, uri *url.  	}  	// Convert the dereferenced AP account object to our GTS model. -	latestAcc, err := d.typeConverter.ASRepresentationToAccount(ctx, +	latestAcc, err := d.converter.ASRepresentationToAccount(ctx,  		apubAcc,  		account.Domain,  	) diff --git a/internal/federation/dereferencing/dereferencer.go b/internal/federation/dereferencing/dereferencer.go index 8beba9947..6248aa2c1 100644 --- a/internal/federation/dereferencing/dereferencer.go +++ b/internal/federation/dereferencing/dereferencer.go @@ -85,7 +85,7 @@ type Dereferencer interface {  type deref struct {  	state               *state.State -	typeConverter       typeutils.TypeConverter +	converter           *typeutils.Converter  	transportController transport.Controller  	mediaManager        *media.Manager  	derefAvatars        map[string]*media.ProcessingMedia @@ -99,10 +99,10 @@ type deref struct {  }  // NewDereferencer returns a Dereferencer initialized with the given parameters. -func NewDereferencer(state *state.State, typeConverter typeutils.TypeConverter, transportController transport.Controller, mediaManager *media.Manager) Dereferencer { +func NewDereferencer(state *state.State, converter *typeutils.Converter, transportController transport.Controller, mediaManager *media.Manager) Dereferencer {  	return &deref{  		state:               state, -		typeConverter:       typeConverter, +		converter:           converter,  		transportController: transportController,  		mediaManager:        mediaManager,  		derefAvatars:        make(map[string]*media.ProcessingMedia), diff --git a/internal/federation/dereferencing/dereferencer_test.go b/internal/federation/dereferencing/dereferencer_test.go index 6e9aa729c..1fefc1db9 100644 --- a/internal/federation/dereferencing/dereferencer_test.go +++ b/internal/federation/dereferencing/dereferencer_test.go @@ -25,6 +25,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -63,17 +64,19 @@ func (suite *DereferencerStandardTestSuite) SetupTest() {  	suite.db = testrig.NewTestDB(&suite.state) +	converter := typeutils.NewConverter(&suite.state) +  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		converter,  	)  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.DB = suite.db  	suite.state.Storage = suite.storage  	media := testrig.NewTestMediaManager(&suite.state) -	suite.dereferencer = dereferencing.NewDereferencer(&suite.state, testrig.NewTestTypeConverter(suite.db), testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../testrig/media")), media) +	suite.dereferencer = dereferencing.NewDereferencer(&suite.state, converter, testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../testrig/media")), media)  	testrig.StandardDBSetup(suite.db, nil)  } diff --git a/internal/federation/dereferencing/status.go b/internal/federation/dereferencing/status.go index 8586884eb..5ec04175e 100644 --- a/internal/federation/dereferencing/status.go +++ b/internal/federation/dereferencing/status.go @@ -263,7 +263,7 @@ func (d *deref) enrichStatus(  	// ActivityPub model was recently dereferenced, so assume that passed status  	// may contain out-of-date information, convert AP model to our GTS model. -	latestStatus, err := d.typeConverter.ASStatusToStatus(ctx, apubStatus) +	latestStatus, err := d.converter.ASStatusToStatus(ctx, apubStatus)  	if err != nil {  		return nil, nil, gtserror.Newf("error converting statusable to gts model for status %s: %w", uri, err)  	} diff --git a/internal/federation/federatingdb/accept.go b/internal/federation/federatingdb/accept.go index 27dcec612..1c514d035 100644 --- a/internal/federation/federatingdb/accept.go +++ b/internal/federation/federatingdb/accept.go @@ -94,7 +94,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA  				return errors.New("ACCEPT: couldn't parse follow into vocab.ActivityStreamsFollow")  			}  			// convert the follow to something we can understand -			gtsFollow, err := f.typeConverter.ASFollowToFollow(ctx, asFollow) +			gtsFollow, err := f.converter.ASFollowToFollow(ctx, asFollow)  			if err != nil {  				return fmt.Errorf("ACCEPT: error converting asfollow to gtsfollow: %s", err)  			} diff --git a/internal/federation/federatingdb/announce.go b/internal/federation/federatingdb/announce.go index 334c46ba5..5a5b80bc1 100644 --- a/internal/federation/federatingdb/announce.go +++ b/internal/federation/federatingdb/announce.go @@ -44,7 +44,7 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre  		return nil // Already processed.  	} -	boost, isNew, err := f.typeConverter.ASAnnounceToStatus(ctx, announce) +	boost, isNew, err := f.converter.ASAnnounceToStatus(ctx, announce)  	if err != nil {  		return gtserror.Newf("error converting announce to boost: %w", err)  	} diff --git a/internal/federation/federatingdb/create.go b/internal/federation/federatingdb/create.go index 3c9eaf9a5..12e324166 100644 --- a/internal/federation/federatingdb/create.go +++ b/internal/federation/federatingdb/create.go @@ -94,7 +94,7 @@ func (f *federatingDB) activityBlock(ctx context.Context, asType vocab.Type, rec  		return errors.New("activityBlock: could not convert type to block")  	} -	block, err := f.typeConverter.ASBlockToBlock(ctx, blockable) +	block, err := f.converter.ASBlockToBlock(ctx, blockable)  	if err != nil {  		return fmt.Errorf("activityBlock: could not convert Block to gts model block")  	} @@ -246,7 +246,7 @@ func (f *federatingDB) createStatusable(  	// This is a non-forwarded status we can trust the requester on,  	// convert this provided statusable data to a useable gtsmodel status. -	status, err = f.typeConverter.ASStatusToStatus(ctx, statusable) +	status, err = f.converter.ASStatusToStatus(ctx, statusable)  	if err != nil {  		return gtserror.Newf("error converting statusable to status: %w", err)  	} @@ -333,7 +333,7 @@ func (f *federatingDB) activityFollow(ctx context.Context, asType vocab.Type, re  		return errors.New("activityFollow: could not convert type to follow")  	} -	followRequest, err := f.typeConverter.ASFollowToFollowRequest(ctx, follow) +	followRequest, err := f.converter.ASFollowToFollowRequest(ctx, follow)  	if err != nil {  		return fmt.Errorf("activityFollow: could not convert Follow to follow request: %s", err)  	} @@ -364,7 +364,7 @@ func (f *federatingDB) activityLike(ctx context.Context, asType vocab.Type, rece  		return errors.New("activityLike: could not convert type to like")  	} -	fave, err := f.typeConverter.ASLikeToFave(ctx, like) +	fave, err := f.converter.ASLikeToFave(ctx, like)  	if err != nil {  		return fmt.Errorf("activityLike: could not convert Like to fave: %w", err)  	} @@ -401,7 +401,7 @@ func (f *federatingDB) activityFlag(ctx context.Context, asType vocab.Type, rece  		return errors.New("activityFlag: could not convert type to flag")  	} -	report, err := f.typeConverter.ASFlagToReport(ctx, flag) +	report, err := f.converter.ASFlagToReport(ctx, flag)  	if err != nil {  		return fmt.Errorf("activityFlag: could not convert Flag to report: %w", err)  	} diff --git a/internal/federation/federatingdb/db.go b/internal/federation/federatingdb/db.go index bc1415dd5..3f35a96c3 100644 --- a/internal/federation/federatingdb/db.go +++ b/internal/federation/federatingdb/db.go @@ -39,17 +39,17 @@ type DB interface {  // FederatingDB uses the underlying DB interface to implement the go-fed pub.Database interface.  // It doesn't care what the underlying implementation of the DB interface is, as long as it works.  type federatingDB struct { -	locks         mutexes.MutexMap -	state         *state.State -	typeConverter typeutils.TypeConverter +	locks     mutexes.MutexMap +	state     *state.State +	converter *typeutils.Converter  }  // New returns a DB interface using the given database and config -func New(state *state.State, tc typeutils.TypeConverter) DB { +func New(state *state.State, converter *typeutils.Converter) DB {  	fdb := federatingDB{ -		locks:         mutexes.NewMap(-1, -1), // use defaults -		state:         state, -		typeConverter: tc, +		locks:     mutexes.NewMap(-1, -1), // use defaults +		state:     state, +		converter: converter,  	}  	return &fdb  } diff --git a/internal/federation/federatingdb/federatingdb_test.go b/internal/federation/federatingdb/federatingdb_test.go index ea5ebf0c3..5c1428ee1 100644 --- a/internal/federation/federatingdb/federatingdb_test.go +++ b/internal/federation/federatingdb/federatingdb_test.go @@ -35,7 +35,7 @@ import (  type FederatingDBTestSuite struct {  	suite.Suite  	db            db.DB -	tc            typeutils.TypeConverter +	tc            *typeutils.Converter  	fromFederator chan messages.FromFediAPI  	federatingDB  federatingdb.DB  	state         state.State @@ -79,7 +79,7 @@ func (suite *FederatingDBTestSuite) SetupTest() {  	suite.db = testrig.NewTestDB(&suite.state)  	suite.testActivities = testrig.NewTestActivities(suite.testAccounts) -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/federation/federatingdb/get.go b/internal/federation/federatingdb/get.go index 9ab30db0d..eba58853f 100644 --- a/internal/federation/federatingdb/get.go +++ b/internal/federation/federatingdb/get.go @@ -42,13 +42,13 @@ func (f *federatingDB) Get(ctx context.Context, id *url.URL) (value vocab.Type,  		if err != nil {  			return nil, err  		} -		return f.typeConverter.AccountToAS(ctx, acct) +		return f.converter.AccountToAS(ctx, acct)  	case uris.IsStatusesPath(id):  		status, err := f.state.DB.GetStatusByURI(ctx, id.String())  		if err != nil {  			return nil, err  		} -		return f.typeConverter.StatusToAS(ctx, status) +		return f.converter.StatusToAS(ctx, status)  	case uris.IsFollowersPath(id):  		return f.Followers(ctx, id)  	case uris.IsFollowingPath(id): diff --git a/internal/federation/federatingdb/reject.go b/internal/federation/federatingdb/reject.go index 10882db83..e02db18e0 100644 --- a/internal/federation/federatingdb/reject.go +++ b/internal/federation/federatingdb/reject.go @@ -85,7 +85,7 @@ func (f *federatingDB) Reject(ctx context.Context, reject vocab.ActivityStreamsR  			}  			// convert the follow to something we can understand -			gtsFollow, err := f.typeConverter.ASFollowToFollow(ctx, asFollow) +			gtsFollow, err := f.converter.ASFollowToFollow(ctx, asFollow)  			if err != nil {  				return fmt.Errorf("Reject: error converting asfollow to gtsfollow: %s", err)  			} diff --git a/internal/federation/federatingdb/undo.go b/internal/federation/federatingdb/undo.go index 704ca5502..84a5bdd47 100644 --- a/internal/federation/federatingdb/undo.go +++ b/internal/federation/federatingdb/undo.go @@ -97,7 +97,7 @@ func (f *federatingDB) undoFollow(  		return nil  	} -	follow, err := f.typeConverter.ASFollowToFollow(ctx, Follow) +	follow, err := f.converter.ASFollowToFollow(ctx, Follow)  	if err != nil {  		return fmt.Errorf("undoFollow: error converting ActivityStreams Follow to follow: %w", err)  	} @@ -139,7 +139,7 @@ func (f *federatingDB) undoLike(  		return nil  	} -	fave, err := f.typeConverter.ASLikeToFave(ctx, Like) +	fave, err := f.converter.ASLikeToFave(ctx, Like)  	if err != nil {  		return fmt.Errorf("undoLike: error converting ActivityStreams Like to fave: %w", err)  	} @@ -192,7 +192,7 @@ func (f *federatingDB) undoBlock(  		return nil  	} -	block, err := f.typeConverter.ASBlockToBlock(ctx, Block) +	block, err := f.converter.ASBlockToBlock(ctx, Block)  	if err != nil {  		return fmt.Errorf("undoBlock: error converting ActivityStreams Block to block: %w", err)  	} diff --git a/internal/federation/federator.go b/internal/federation/federator.go index ad6db8ff7..1d1df4714 100644 --- a/internal/federation/federator.go +++ b/internal/federation/federator.go @@ -59,7 +59,7 @@ type federator struct {  	db                  db.DB  	federatingDB        federatingdb.DB  	clock               pub.Clock -	typeConverter       typeutils.TypeConverter +	converter           *typeutils.Converter  	transportController transport.Controller  	mediaManager        *media.Manager  	actor               pub.FederatingActor @@ -67,15 +67,15 @@ type federator struct {  }  // NewFederator returns a new federator -func NewFederator(state *state.State, federatingDB federatingdb.DB, transportController transport.Controller, typeConverter typeutils.TypeConverter, mediaManager *media.Manager) Federator { -	dereferencer := dereferencing.NewDereferencer(state, typeConverter, transportController, mediaManager) +func NewFederator(state *state.State, federatingDB federatingdb.DB, transportController transport.Controller, converter *typeutils.Converter, mediaManager *media.Manager) Federator { +	dereferencer := dereferencing.NewDereferencer(state, converter, transportController, mediaManager)  	clock := &Clock{}  	f := &federator{  		db:                  state.DB,  		federatingDB:        federatingDB,  		clock:               &Clock{}, -		typeConverter:       typeConverter, +		converter:           converter,  		transportController: transportController,  		mediaManager:        mediaManager,  		Dereferencer:        dereferencer, diff --git a/internal/federation/federator_test.go b/internal/federation/federator_test.go index 3287cd11a..7c57dfff1 100644 --- a/internal/federation/federator_test.go +++ b/internal/federation/federator_test.go @@ -36,7 +36,7 @@ type FederatorStandardTestSuite struct {  	suite.Suite  	storage             *storage.Driver  	state               state.State -	typeconverter       typeutils.TypeConverter +	typeconverter       *typeutils.Converter  	transportController transport.Controller  	httpClient          *testrig.MockHTTPClient  	federator           federation.Federator @@ -65,7 +65,7 @@ func (suite *FederatorStandardTestSuite) SetupTest() {  	suite.testActivities = testrig.NewTestActivities(suite.testAccounts)  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.typeconverter = testrig.NewTestTypeConverter(suite.state.DB) +	suite.typeconverter = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/media/media_test.go b/internal/media/media_test.go index c7c73bae6..99c2da566 100644 --- a/internal/media/media_test.go +++ b/internal/media/media_test.go @@ -25,6 +25,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage"  	"github.com/superseriousbusiness/gotosocial/internal/transport" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -60,7 +61,7 @@ func (suite *MediaStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.testAttachments = testrig.NewTestAttachments() diff --git a/internal/processing/account/account.go b/internal/processing/account/account.go index a32a73ac1..4432fd5f3 100644 --- a/internal/processing/account/account.go +++ b/internal/processing/account/account.go @@ -37,7 +37,7 @@ type Processor struct {  	c *common.Processor  	state        *state.State -	tc           typeutils.TypeConverter +	converter    *typeutils.Converter  	mediaManager *media.Manager  	oauthServer  oauth.Server  	filter       *visibility.Filter @@ -50,7 +50,7 @@ type Processor struct {  func New(  	common *common.Processor,  	state *state.State, -	tc typeutils.TypeConverter, +	converter *typeutils.Converter,  	mediaManager *media.Manager,  	oauthServer oauth.Server,  	federator federation.Federator, @@ -60,7 +60,7 @@ func New(  	return Processor{  		c:            common,  		state:        state, -		tc:           tc, +		converter:    converter,  		mediaManager: mediaManager,  		oauthServer:  oauthServer,  		filter:       filter, diff --git a/internal/processing/account/account_test.go b/internal/processing/account/account_test.go index 2e4a64844..a23d324f8 100644 --- a/internal/processing/account/account_test.go +++ b/internal/processing/account/account_test.go @@ -43,7 +43,7 @@ type AccountStandardTestSuite struct {  	// standard suite interfaces  	suite.Suite  	db                  db.DB -	tc                  typeutils.TypeConverter +	tc                  *typeutils.Converter  	storage             *storage.Driver  	state               state.State  	mediaManager        *media.Manager @@ -88,7 +88,7 @@ func (suite *AccountStandardTestSuite) SetupTest() {  	suite.db = testrig.NewTestDB(&suite.state)  	suite.state.DB = suite.db -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/processing/account/block.go b/internal/processing/account/block.go index 270048100..58b0328a4 100644 --- a/internal/processing/account/block.go +++ b/internal/processing/account/block.go @@ -155,7 +155,7 @@ func (p *Processor) BlocksGet(  	for _, block := range blocks {  		// Convert target account to frontend API model. (target will never be nil) -		account, err := p.tc.AccountToAPIAccountBlocked(ctx, block.TargetAccount) +		account, err := p.converter.AccountToAPIAccountBlocked(ctx, block.TargetAccount)  		if err != nil {  			log.Errorf(ctx, "error converting account to public api account: %v", err)  			continue diff --git a/internal/processing/account/bookmarks.go b/internal/processing/account/bookmarks.go index c6b0c14c1..88a02786e 100644 --- a/internal/processing/account/bookmarks.go +++ b/internal/processing/account/bookmarks.go @@ -67,7 +67,7 @@ func (p *Processor) BookmarksGet(ctx context.Context, requestingAccount *gtsmode  		}  		// Convert the status. -		item, err := p.tc.StatusToAPIStatus(ctx, status, requestingAccount) +		item, err := p.converter.StatusToAPIStatus(ctx, status, requestingAccount)  		if err != nil {  			log.Errorf(ctx, "error converting bookmarked status to api: %s", err)  			continue diff --git a/internal/processing/account/get.go b/internal/processing/account/get.go index ddb7c14e0..500c0c2e5 100644 --- a/internal/processing/account/get.go +++ b/internal/processing/account/get.go @@ -80,7 +80,7 @@ func (p *Processor) getFor(ctx context.Context, requestingAccount *gtsmodel.Acco  		}  		if blocked { -			apiAccount, err := p.tc.AccountToAPIAccountBlocked(ctx, targetAccount) +			apiAccount, err := p.converter.AccountToAPIAccountBlocked(ctx, targetAccount)  			if err != nil {  				return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting account: %w", err))  			} @@ -107,9 +107,9 @@ func (p *Processor) getFor(ctx context.Context, requestingAccount *gtsmodel.Acco  	var apiAccount *apimodel.Account  	if requestingAccount != nil && targetAccount.ID == requestingAccount.ID { -		apiAccount, err = p.tc.AccountToAPIAccountSensitive(ctx, targetAccount) +		apiAccount, err = p.converter.AccountToAPIAccountSensitive(ctx, targetAccount)  	} else { -		apiAccount, err = p.tc.AccountToAPIAccountPublic(ctx, targetAccount) +		apiAccount, err = p.converter.AccountToAPIAccountPublic(ctx, targetAccount)  	}  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting account: %w", err)) diff --git a/internal/processing/account/lists.go b/internal/processing/account/lists.go index 167ed3358..12fbb884b 100644 --- a/internal/processing/account/lists.go +++ b/internal/processing/account/lists.go @@ -94,7 +94,7 @@ func (p *Processor) ListsGet(ctx context.Context, requestingAccount *gtsmodel.Ac  			continue  		} -		apiList, err := p.tc.ListToAPIList(ctx, list) +		apiList, err := p.converter.ListToAPIList(ctx, list)  		if err != nil {  			log.Debugf(ctx, "skipping list %s due to error %q", listEntry.ListID, err)  			continue diff --git a/internal/processing/account/relationships.go b/internal/processing/account/relationships.go index 58c98f3ba..b9e9086c9 100644 --- a/internal/processing/account/relationships.go +++ b/internal/processing/account/relationships.go @@ -130,7 +130,7 @@ func (p *Processor) RelationshipGet(ctx context.Context, requestingAccount *gtsm  		return nil, gtserror.NewErrorInternalError(gtserror.Newf("error getting relationship: %s", err))  	} -	r, err := p.tc.RelationshipToAPIRelationship(ctx, gtsR) +	r, err := p.converter.RelationshipToAPIRelationship(ctx, gtsR)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(gtserror.Newf("error converting relationship: %s", err))  	} diff --git a/internal/processing/account/rss.go b/internal/processing/account/rss.go index ddc07b9ad..df49af21f 100644 --- a/internal/processing/account/rss.go +++ b/internal/processing/account/rss.go @@ -122,7 +122,7 @@ func (p *Processor) GetRSSFeedForUsername(ctx context.Context, username string)  		// Add each status to the rss feed.  		for _, status := range statuses { -			item, err := p.tc.StatusToRSSItem(ctx, status) +			item, err := p.converter.StatusToRSSItem(ctx, status)  			if err != nil {  				err = gtserror.Newf("error converting status to feed item: %w", err)  				return "", gtserror.NewErrorInternalError(err) diff --git a/internal/processing/account/statuses.go b/internal/processing/account/statuses.go index 26684265c..99e9edbcf 100644 --- a/internal/processing/account/statuses.go +++ b/internal/processing/account/statuses.go @@ -103,7 +103,7 @@ func (p *Processor) StatusesGet(  	for _, s := range filtered {  		// Convert filtered statuses to API statuses. -		item, err := p.tc.StatusToAPIStatus(ctx, s, requestingAccount) +		item, err := p.converter.StatusToAPIStatus(ctx, s, requestingAccount)  		if err != nil {  			log.Errorf(ctx, "error convering to api status: %v", err)  			continue @@ -173,7 +173,7 @@ func (p *Processor) WebStatusesGet(ctx context.Context, targetAccountID string,  	for _, s := range statuses {  		// Convert fetched statuses to API statuses. -		item, err := p.tc.StatusToAPIStatus(ctx, s, nil) +		item, err := p.converter.StatusToAPIStatus(ctx, s, nil)  		if err != nil {  			log.Errorf(ctx, "error convering to api status: %v", err)  			continue diff --git a/internal/processing/account/update.go b/internal/processing/account/update.go index ec343f160..81485e165 100644 --- a/internal/processing/account/update.go +++ b/internal/processing/account/update.go @@ -274,7 +274,7 @@ func (p *Processor) Update(ctx context.Context, account *gtsmodel.Account, form  		OriginAccount:  account,  	}) -	acctSensitive, err := p.tc.AccountToAPIAccountSensitive(ctx, account) +	acctSensitive, err := p.converter.AccountToAPIAccountSensitive(ctx, account)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("could not convert account into apisensitive account: %s", err))  	} diff --git a/internal/processing/admin/admin.go b/internal/processing/admin/admin.go index 7353c0da8..51429c11c 100644 --- a/internal/processing/admin/admin.go +++ b/internal/processing/admin/admin.go @@ -30,7 +30,7 @@ import (  type Processor struct {  	state               *state.State  	cleaner             *cleaner.Cleaner -	tc                  typeutils.TypeConverter +	converter           *typeutils.Converter  	mediaManager        *media.Manager  	transportController transport.Controller  	emailSender         email.Sender @@ -45,11 +45,11 @@ func (p *Processor) Actions() *Actions {  }  // New returns a new admin processor. -func New(state *state.State, tc typeutils.TypeConverter, mediaManager *media.Manager, transportController transport.Controller, emailSender email.Sender) Processor { +func New(state *state.State, converter *typeutils.Converter, mediaManager *media.Manager, transportController transport.Controller, emailSender email.Sender) Processor {  	return Processor{  		state:               state,  		cleaner:             cleaner.New(state), -		tc:                  tc, +		converter:           converter,  		mediaManager:        mediaManager,  		transportController: transportController,  		emailSender:         emailSender, diff --git a/internal/processing/admin/admin_test.go b/internal/processing/admin/admin_test.go index c1c4d46c2..689f33f46 100644 --- a/internal/processing/admin/admin_test.go +++ b/internal/processing/admin/admin_test.go @@ -40,7 +40,7 @@ type AdminStandardTestSuite struct {  	// standard suite interfaces  	suite.Suite  	db                  db.DB -	tc                  typeutils.TypeConverter +	tc                  *typeutils.Converter  	storage             *storage.Driver  	state               state.State  	mediaManager        *media.Manager @@ -86,7 +86,7 @@ func (suite *AdminStandardTestSuite) SetupTest() {  	suite.db = testrig.NewTestDB(&suite.state)  	suite.state.DB = suite.db -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/processing/admin/domainpermission.go b/internal/processing/admin/domainpermission.go index c759c0f11..bedaf6a11 100644 --- a/internal/processing/admin/domainpermission.go +++ b/internal/processing/admin/domainpermission.go @@ -40,7 +40,7 @@ func (p *Processor) apiDomainPerm(  	domainPermission gtsmodel.DomainPermission,  	export bool,  ) (*apimodel.DomainPermission, gtserror.WithCode) { -	apiDomainPerm, err := p.tc.DomainPermToAPIDomainPerm(ctx, domainPermission, export) +	apiDomainPerm, err := p.converter.DomainPermToAPIDomainPerm(ctx, domainPermission, export)  	if err != nil {  		err := gtserror.NewfAt(3, "error converting domain permission to api model: %w", err)  		return nil, gtserror.NewErrorInternalError(err) diff --git a/internal/processing/admin/emoji.go b/internal/processing/admin/emoji.go index 96b0bef07..568c4350b 100644 --- a/internal/processing/admin/emoji.go +++ b/internal/processing/admin/emoji.go @@ -84,7 +84,7 @@ func (p *Processor) EmojiCreate(ctx context.Context, account *gtsmodel.Account,  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error loading emoji: %s", err), "error loading emoji")  	} -	apiEmoji, err := p.tc.EmojiToAPIEmoji(ctx, emoji) +	apiEmoji, err := p.converter.EmojiToAPIEmoji(ctx, emoji)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting emoji: %s", err), "error converting emoji to api representation")  	} @@ -122,7 +122,7 @@ func (p *Processor) EmojisGet(  	items := make([]interface{}, 0, count)  	for _, emoji := range emojis { -		adminEmoji, err := p.tc.EmojiToAdminAPIEmoji(ctx, emoji) +		adminEmoji, err := p.converter.EmojiToAdminAPIEmoji(ctx, emoji)  		if err != nil {  			err := fmt.Errorf("EmojisGet: error converting emoji to admin model emoji: %s", err)  			return nil, gtserror.NewErrorInternalError(err) @@ -185,7 +185,7 @@ func (p *Processor) EmojiGet(ctx context.Context, account *gtsmodel.Account, use  		return nil, gtserror.NewErrorInternalError(err)  	} -	adminEmoji, err := p.tc.EmojiToAdminAPIEmoji(ctx, emoji) +	adminEmoji, err := p.converter.EmojiToAdminAPIEmoji(ctx, emoji)  	if err != nil {  		err = fmt.Errorf("EmojiGet: error converting emoji to admin api emoji: %s", err)  		return nil, gtserror.NewErrorInternalError(err) @@ -211,7 +211,7 @@ func (p *Processor) EmojiDelete(ctx context.Context, id string) (*apimodel.Admin  		return nil, gtserror.NewErrorBadRequest(err, err.Error())  	} -	adminEmoji, err := p.tc.EmojiToAdminAPIEmoji(ctx, emoji) +	adminEmoji, err := p.converter.EmojiToAdminAPIEmoji(ctx, emoji)  	if err != nil {  		err = fmt.Errorf("EmojiDelete: error converting emoji to admin api emoji: %s", err)  		return nil, gtserror.NewErrorInternalError(err) @@ -260,7 +260,7 @@ func (p *Processor) EmojiCategoriesGet(ctx context.Context) ([]*apimodel.EmojiCa  	apiCategories := make([]*apimodel.EmojiCategory, 0, len(categories))  	for _, category := range categories { -		apiCategory, err := p.tc.EmojiCategoryToAPIEmojiCategory(ctx, category) +		apiCategory, err := p.converter.EmojiCategoryToAPIEmojiCategory(ctx, category)  		if err != nil {  			err := fmt.Errorf("EmojiCategoriesGet: error converting emoji category to api emoji category: %s", err)  			return nil, gtserror.NewErrorInternalError(err) @@ -367,7 +367,7 @@ func (p *Processor) emojiUpdateCopy(ctx context.Context, emoji *gtsmodel.Emoji,  		return nil, gtserror.NewErrorInternalError(err)  	} -	adminEmoji, err := p.tc.EmojiToAdminAPIEmoji(ctx, newEmoji) +	adminEmoji, err := p.converter.EmojiToAdminAPIEmoji(ctx, newEmoji)  	if err != nil {  		err = fmt.Errorf("emojiUpdateCopy: error converting updated emoji %s to admin emoji: %s", emoji.ID, err)  		return nil, gtserror.NewErrorInternalError(err) @@ -391,7 +391,7 @@ func (p *Processor) emojiUpdateDisable(ctx context.Context, emoji *gtsmodel.Emoj  		return nil, gtserror.NewErrorInternalError(err)  	} -	adminEmoji, err := p.tc.EmojiToAdminAPIEmoji(ctx, emoji) +	adminEmoji, err := p.converter.EmojiToAdminAPIEmoji(ctx, emoji)  	if err != nil {  		err = fmt.Errorf("emojiUpdateDisable: error converting updated emoji %s to admin emoji: %s", emoji.ID, err)  		return nil, gtserror.NewErrorInternalError(err) @@ -472,7 +472,7 @@ func (p *Processor) emojiUpdateModify(ctx context.Context, emoji *gtsmodel.Emoji  		}  	} -	adminEmoji, err := p.tc.EmojiToAdminAPIEmoji(ctx, emoji) +	adminEmoji, err := p.converter.EmojiToAdminAPIEmoji(ctx, emoji)  	if err != nil {  		err = fmt.Errorf("emojiUpdateModify: error converting updated emoji %s to admin emoji: %s", emoji.ID, err)  		return nil, gtserror.NewErrorInternalError(err) diff --git a/internal/processing/admin/report.go b/internal/processing/admin/report.go index e99cc2ec0..0f47cf839 100644 --- a/internal/processing/admin/report.go +++ b/internal/processing/admin/report.go @@ -58,7 +58,7 @@ func (p *Processor) ReportsGet(  	prevMinIDValue := reports[0].ID  	for _, r := range reports { -		item, err := p.tc.ReportToAdminAPIReport(ctx, r, account) +		item, err := p.converter.ReportToAdminAPIReport(ctx, r, account)  		if err != nil {  			return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting report to api: %s", err))  		} @@ -96,7 +96,7 @@ func (p *Processor) ReportGet(ctx context.Context, account *gtsmodel.Account, id  		return nil, gtserror.NewErrorInternalError(err)  	} -	apimodelReport, err := p.tc.ReportToAdminAPIReport(ctx, report, account) +	apimodelReport, err := p.converter.ReportToAdminAPIReport(ctx, report, account)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} @@ -144,7 +144,7 @@ func (p *Processor) ReportResolve(ctx context.Context, account *gtsmodel.Account  		TargetAccount:  report.Account,  	}) -	apimodelReport, err := p.tc.ReportToAdminAPIReport(ctx, updatedReport, account) +	apimodelReport, err := p.converter.ReportToAdminAPIReport(ctx, updatedReport, account)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} diff --git a/internal/processing/admin/rule.go b/internal/processing/admin/rule.go index 40a2bdcf3..d1ee63cc8 100644 --- a/internal/processing/admin/rule.go +++ b/internal/processing/admin/rule.go @@ -35,7 +35,6 @@ func (p *Processor) RulesGet(  	ctx context.Context,  ) ([]*apimodel.AdminInstanceRule, gtserror.WithCode) {  	rules, err := p.state.DB.GetActiveRules(ctx) -  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} @@ -43,7 +42,7 @@ func (p *Processor) RulesGet(  	apiRules := make([]*apimodel.AdminInstanceRule, len(rules))  	for i := range rules { -		apiRules[i] = p.tc.InstanceRuleToAdminAPIRule(&rules[i]) +		apiRules[i] = p.converter.InstanceRuleToAdminAPIRule(&rules[i])  	}  	return apiRules, nil @@ -59,7 +58,7 @@ func (p *Processor) RuleGet(ctx context.Context, id string) (*apimodel.AdminInst  		return nil, gtserror.NewErrorInternalError(err)  	} -	return p.tc.InstanceRuleToAdminAPIRule(rule), nil +	return p.converter.InstanceRuleToAdminAPIRule(rule), nil  }  // RuleCreate adds a new rule to the instance. @@ -78,7 +77,7 @@ func (p *Processor) RuleCreate(ctx context.Context, form *apimodel.InstanceRuleC  		return nil, gtserror.NewErrorInternalError(err)  	} -	return p.tc.InstanceRuleToAdminAPIRule(rule), nil +	return p.converter.InstanceRuleToAdminAPIRule(rule), nil  }  // RuleUpdate updates text for an existing rule. @@ -96,12 +95,11 @@ func (p *Processor) RuleUpdate(ctx context.Context, id string, form *apimodel.In  	rule.Text = form.Text  	updatedRule, err := p.state.DB.UpdateRule(ctx, rule) -  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} -	return p.tc.InstanceRuleToAdminAPIRule(updatedRule), nil +	return p.converter.InstanceRuleToAdminAPIRule(updatedRule), nil  }  // RuleDelete deletes an existing rule. @@ -118,10 +116,9 @@ func (p *Processor) RuleDelete(ctx context.Context, id string) (*apimodel.AdminI  	rule.Deleted = util.Ptr(true)  	deletedRule, err := p.state.DB.UpdateRule(ctx, rule) -  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} -	return p.tc.InstanceRuleToAdminAPIRule(deletedRule), nil +	return p.converter.InstanceRuleToAdminAPIRule(deletedRule), nil  } diff --git a/internal/processing/app.go b/internal/processing/app.go index d4a923e8a..eef4fae0d 100644 --- a/internal/processing/app.go +++ b/internal/processing/app.go @@ -79,7 +79,7 @@ func (p *Processor) AppCreate(ctx context.Context, authed *oauth.Auth, form *api  		return nil, gtserror.NewErrorInternalError(err)  	} -	apiApp, err := p.tc.AppToAPIAppSensitive(ctx, app) +	apiApp, err := p.converter.AppToAPIAppSensitive(ctx, app)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} diff --git a/internal/processing/common/common.go b/internal/processing/common/common.go index 53c298579..28fadc2a6 100644 --- a/internal/processing/common/common.go +++ b/internal/processing/common/common.go @@ -29,7 +29,7 @@ import (  // processing subsection of the codebase.  type Processor struct {  	state     *state.State -	converter typeutils.TypeConverter +	converter *typeutils.Converter  	federator federation.Federator  	filter    *visibility.Filter  } @@ -37,7 +37,7 @@ type Processor struct {  // New returns a new Processor instance.  func New(  	state *state.State, -	converter typeutils.TypeConverter, +	converter *typeutils.Converter,  	federator federation.Federator,  	filter *visibility.Filter,  ) Processor { diff --git a/internal/processing/fedi/collections.go b/internal/processing/fedi/collections.go index 5f9c117e1..cbabbfdd6 100644 --- a/internal/processing/fedi/collections.go +++ b/internal/processing/fedi/collections.go @@ -70,7 +70,7 @@ func (p *Processor) OutboxGet(ctx context.Context, requestedUsername string, pag  				"last": "https://example.org/users/whatever/outbox?min_id=0&page=true"  			}  		*/ -		collection, err := p.tc.OutboxToASCollection(ctx, requestedAccount.OutboxURI) +		collection, err := p.converter.OutboxToASCollection(ctx, requestedAccount.OutboxURI)  		if err != nil {  			return nil, gtserror.NewErrorInternalError(err)  		} @@ -90,7 +90,7 @@ func (p *Processor) OutboxGet(ctx context.Context, requestedUsername string, pag  		return nil, gtserror.NewErrorInternalError(err)  	} -	outboxPage, err := p.tc.StatusesToASOutboxPage(ctx, requestedAccount.OutboxURI, maxID, minID, publicStatuses) +	outboxPage, err := p.converter.StatusesToASOutboxPage(ctx, requestedAccount.OutboxURI, maxID, minID, publicStatuses)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} @@ -301,7 +301,7 @@ func (p *Processor) FeaturedCollectionGet(ctx context.Context, requestedUsername  		}  	} -	collection, err := p.tc.StatusesToASFeaturedCollection(ctx, requestedAccount.FeaturedCollectionURI, statuses) +	collection, err := p.converter.StatusesToASFeaturedCollection(ctx, requestedAccount.FeaturedCollectionURI, statuses)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} diff --git a/internal/processing/fedi/emoji.go b/internal/processing/fedi/emoji.go index ea7cb6082..4acf8c671 100644 --- a/internal/processing/fedi/emoji.go +++ b/internal/processing/fedi/emoji.go @@ -44,7 +44,7 @@ func (p *Processor) EmojiGet(ctx context.Context, requestedEmojiID string) (inte  		return nil, gtserror.NewErrorNotFound(fmt.Errorf("emoji with id %s has been disabled", requestedEmojiID))  	} -	apEmoji, err := p.tc.EmojiToAS(ctx, requestedEmoji) +	apEmoji, err := p.converter.EmojiToAS(ctx, requestedEmoji)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting gtsmodel emoji with id %s to ap emoji: %s", requestedEmojiID, err))  	} diff --git a/internal/processing/fedi/fedi.go b/internal/processing/fedi/fedi.go index 92a23a543..9fbcebefc 100644 --- a/internal/processing/fedi/fedi.go +++ b/internal/processing/fedi/fedi.go @@ -27,16 +27,16 @@ import (  type Processor struct {  	state     *state.State  	federator federation.Federator -	tc        typeutils.TypeConverter +	converter *typeutils.Converter  	filter    *visibility.Filter  }  // New returns a new fedi processor. -func New(state *state.State, tc typeutils.TypeConverter, federator federation.Federator, filter *visibility.Filter) Processor { +func New(state *state.State, converter *typeutils.Converter, federator federation.Federator, filter *visibility.Filter) Processor {  	return Processor{  		state:     state,  		federator: federator, -		tc:        tc, +		converter: converter,  		filter:    filter,  	}  } diff --git a/internal/processing/fedi/status.go b/internal/processing/fedi/status.go index c2a0e46d6..9b8c7dd95 100644 --- a/internal/processing/fedi/status.go +++ b/internal/processing/fedi/status.go @@ -56,7 +56,7 @@ func (p *Processor) StatusGet(ctx context.Context, requestedUsername string, req  		return nil, gtserror.NewErrorNotFound(err)  	} -	asStatus, err := p.tc.StatusToAS(ctx, status) +	asStatus, err := p.converter.StatusToAS(ctx, status)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} @@ -104,7 +104,7 @@ func (p *Processor) StatusRepliesGet(ctx context.Context, requestedUsername stri  	case !page:  		// scenario 1  		// get the collection -		collection, err := p.tc.StatusToASRepliesCollection(ctx, status, onlyOtherAccounts) +		collection, err := p.converter.StatusToASRepliesCollection(ctx, status, onlyOtherAccounts)  		if err != nil {  			return nil, gtserror.NewErrorInternalError(err)  		} @@ -116,7 +116,7 @@ func (p *Processor) StatusRepliesGet(ctx context.Context, requestedUsername stri  	case page && !onlyOtherAccountsSet:  		// scenario 2  		// get the collection -		collection, err := p.tc.StatusToASRepliesCollection(ctx, status, onlyOtherAccounts) +		collection, err := p.converter.StatusToASRepliesCollection(ctx, status, onlyOtherAccounts)  		if err != nil {  			return nil, gtserror.NewErrorInternalError(err)  		} @@ -166,7 +166,7 @@ func (p *Processor) StatusRepliesGet(ctx context.Context, requestedUsername stri  			replyURIs[r.ID] = rURI  		} -		repliesPage, err := p.tc.StatusURIsToASRepliesPage(ctx, status, onlyOtherAccounts, minID, replyURIs) +		repliesPage, err := p.converter.StatusURIsToASRepliesPage(ctx, status, onlyOtherAccounts, minID, replyURIs)  		if err != nil {  			return nil, gtserror.NewErrorInternalError(err)  		} diff --git a/internal/processing/fedi/user.go b/internal/processing/fedi/user.go index f3305c103..67f137f25 100644 --- a/internal/processing/fedi/user.go +++ b/internal/processing/fedi/user.go @@ -54,7 +54,7 @@ func (p *Processor) UserGet(ctx context.Context, requestedUsername string, reque  		// the bare minimum user profile needed for the pubkey.  		//  		// TODO: https://github.com/superseriousbusiness/gotosocial/issues/1186 -		minimalPerson, err := p.tc.AccountToASMinimal(ctx, requestedAccount) +		minimalPerson, err := p.converter.AccountToASMinimal(ctx, requestedAccount)  		if err != nil {  			return nil, gtserror.NewErrorInternalError(err)  		} @@ -72,7 +72,7 @@ func (p *Processor) UserGet(ctx context.Context, requestedUsername string, reque  	}  	// Auth passed, generate the proper AP representation. -	person, err := p.tc.AccountToAS(ctx, requestedAccount) +	person, err := p.converter.AccountToAS(ctx, requestedAccount)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} diff --git a/internal/processing/instance.go b/internal/processing/instance.go index 2faef7527..caf2b9fc1 100644 --- a/internal/processing/instance.go +++ b/internal/processing/instance.go @@ -48,7 +48,7 @@ func (p *Processor) InstanceGetV1(ctx context.Context) (*apimodel.InstanceV1, gt  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error fetching instance: %s", err))  	} -	ai, err := p.tc.InstanceToAPIV1Instance(ctx, i) +	ai, err := p.converter.InstanceToAPIV1Instance(ctx, i)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting instance to api representation: %s", err))  	} @@ -62,7 +62,7 @@ func (p *Processor) InstanceGetV2(ctx context.Context) (*apimodel.InstanceV2, gt  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error fetching instance: %s", err))  	} -	ai, err := p.tc.InstanceToAPIV2Instance(ctx, i) +	ai, err := p.converter.InstanceToAPIV2Instance(ctx, i)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting instance to api representation: %s", err))  	} @@ -142,7 +142,7 @@ func (p *Processor) InstanceGetRules(ctx context.Context) ([]apimodel.InstanceRu  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error fetching instance: %s", err))  	} -	return p.tc.InstanceRulesToAPIRules(i.Rules), nil +	return p.converter.InstanceRulesToAPIRules(i.Rules), nil  }  func (p *Processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSettingsUpdateRequest) (*apimodel.InstanceV1, gtserror.WithCode) { @@ -289,7 +289,7 @@ func (p *Processor) InstancePatch(ctx context.Context, form *apimodel.InstanceSe  		}  	} -	ai, err := p.tc.InstanceToAPIV1Instance(ctx, instance) +	ai, err := p.converter.InstanceToAPIV1Instance(ctx, instance)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting instance to api representation: %s", err))  	} diff --git a/internal/processing/list/get.go b/internal/processing/list/get.go index 1a03898ed..9a7e7716f 100644 --- a/internal/processing/list/get.go +++ b/internal/processing/list/get.go @@ -197,7 +197,7 @@ func (p *Processor) accountsFromListEntries(  			continue  		} -		apiAccount, err := p.tc.AccountToAPIAccountPublic(ctx, listEntry.Follow.TargetAccount) +		apiAccount, err := p.converter.AccountToAPIAccountPublic(ctx, listEntry.Follow.TargetAccount)  		if err != nil {  			log.Errorf(ctx, "error converting to public api account: %v", err)  			continue diff --git a/internal/processing/list/list.go b/internal/processing/list/list.go index f192beb60..0003816fb 100644 --- a/internal/processing/list/list.go +++ b/internal/processing/list/list.go @@ -23,13 +23,13 @@ import (  )  type Processor struct { -	state *state.State -	tc    typeutils.TypeConverter +	state     *state.State +	converter *typeutils.Converter  } -func New(state *state.State, tc typeutils.TypeConverter) Processor { +func New(state *state.State, converter *typeutils.Converter) Processor {  	return Processor{ -		state: state, -		tc:    tc, +		state:     state, +		converter: converter,  	}  } diff --git a/internal/processing/list/util.go b/internal/processing/list/util.go index 6186f58c7..c5b1e5081 100644 --- a/internal/processing/list/util.go +++ b/internal/processing/list/util.go @@ -53,7 +53,7 @@ func (p *Processor) getList(ctx context.Context, accountID string, listID string  // apiList is a shortcut to return the API version of the given  // list, or return an appropriate error if conversion fails.  func (p *Processor) apiList(ctx context.Context, list *gtsmodel.List) (*apimodel.List, gtserror.WithCode) { -	apiList, err := p.tc.ListToAPIList(ctx, list) +	apiList, err := p.converter.ListToAPIList(ctx, list)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting list to api: %w", err))  	} diff --git a/internal/processing/markers/get.go b/internal/processing/markers/get.go index dd94376f1..38e8b53dc 100644 --- a/internal/processing/markers/get.go +++ b/internal/processing/markers/get.go @@ -45,7 +45,7 @@ func (p *Processor) Get(ctx context.Context, account *gtsmodel.Account, names []  		markers = append(markers, marker)  	} -	apiMarker, err := p.tc.MarkersToAPIMarker(ctx, markers) +	apiMarker, err := p.converter.MarkersToAPIMarker(ctx, markers)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting marker to api: %w", err))  	} diff --git a/internal/processing/markers/markers.go b/internal/processing/markers/markers.go index 7a1215241..8817ed1a7 100644 --- a/internal/processing/markers/markers.go +++ b/internal/processing/markers/markers.go @@ -23,13 +23,13 @@ import (  )  type Processor struct { -	state *state.State -	tc    typeutils.TypeConverter +	state     *state.State +	converter *typeutils.Converter  } -func New(state *state.State, tc typeutils.TypeConverter) Processor { +func New(state *state.State, converter *typeutils.Converter) Processor {  	return Processor{ -		state: state, -		tc:    tc, +		state:     state, +		converter: converter,  	}  } diff --git a/internal/processing/markers/update.go b/internal/processing/markers/update.go index 96eb17833..22fe65faf 100644 --- a/internal/processing/markers/update.go +++ b/internal/processing/markers/update.go @@ -39,7 +39,7 @@ func (p *Processor) Update(ctx context.Context, markers []*gtsmodel.Marker) (*ap  		}  	} -	apiMarker, err := p.tc.MarkersToAPIMarker(ctx, markers) +	apiMarker, err := p.converter.MarkersToAPIMarker(ctx, markers)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting marker to api: %w", err))  	} diff --git a/internal/processing/media/create.go b/internal/processing/media/create.go index cdc65dfa4..b8c469dde 100644 --- a/internal/processing/media/create.go +++ b/internal/processing/media/create.go @@ -56,7 +56,7 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form  		return nil, gtserror.NewErrorUnprocessableEntity(err)  	} -	apiAttachment, err := p.tc.AttachmentToAPIAttachment(ctx, attachment) +	apiAttachment, err := p.converter.AttachmentToAPIAttachment(ctx, attachment)  	if err != nil {  		err := fmt.Errorf("error parsing media attachment to frontend type: %s", err)  		return nil, gtserror.NewErrorInternalError(err) diff --git a/internal/processing/media/getemoji.go b/internal/processing/media/getemoji.go index aef3482ae..06712756a 100644 --- a/internal/processing/media/getemoji.go +++ b/internal/processing/media/getemoji.go @@ -39,7 +39,7 @@ func (p *Processor) GetCustomEmojis(ctx context.Context) ([]*apimodel.Emoji, gts  	apiEmojis := make([]*apimodel.Emoji, 0, len(emojis))  	for _, gtsEmoji := range emojis { -		apiEmoji, err := p.tc.EmojiToAPIEmoji(ctx, gtsEmoji) +		apiEmoji, err := p.converter.EmojiToAPIEmoji(ctx, gtsEmoji)  		if err != nil {  			log.Errorf(ctx, "error converting emoji with id %s: %s", gtsEmoji.ID, err)  			continue diff --git a/internal/processing/media/getmedia.go b/internal/processing/media/getmedia.go index e815e8bcf..8f5b9d740 100644 --- a/internal/processing/media/getmedia.go +++ b/internal/processing/media/getmedia.go @@ -42,7 +42,7 @@ func (p *Processor) Get(ctx context.Context, account *gtsmodel.Account, mediaAtt  		return nil, gtserror.NewErrorNotFound(errors.New("attachment not owned by requesting account"))  	} -	a, err := p.tc.AttachmentToAPIAttachment(ctx, attachment) +	a, err := p.converter.AttachmentToAPIAttachment(ctx, attachment)  	if err != nil {  		return nil, gtserror.NewErrorNotFound(fmt.Errorf("error converting attachment: %s", err))  	} diff --git a/internal/processing/media/media.go b/internal/processing/media/media.go index cec912874..22c455920 100644 --- a/internal/processing/media/media.go +++ b/internal/processing/media/media.go @@ -26,16 +26,16 @@ import (  type Processor struct {  	state               *state.State -	tc                  typeutils.TypeConverter +	converter           *typeutils.Converter  	mediaManager        *media.Manager  	transportController transport.Controller  }  // New returns a new media processor. -func New(state *state.State, tc typeutils.TypeConverter, mediaManager *media.Manager, transportController transport.Controller) Processor { +func New(state *state.State, converter *typeutils.Converter, mediaManager *media.Manager, transportController transport.Controller) Processor {  	return Processor{  		state:               state, -		tc:                  tc, +		converter:           converter,  		mediaManager:        mediaManager,  		transportController: transportController,  	} diff --git a/internal/processing/media/media_test.go b/internal/processing/media/media_test.go index 97e490a9c..523428140 100644 --- a/internal/processing/media/media_test.go +++ b/internal/processing/media/media_test.go @@ -34,7 +34,7 @@ type MediaStandardTestSuite struct {  	// standard suite interfaces  	suite.Suite  	db                  db.DB -	tc                  typeutils.TypeConverter +	tc                  *typeutils.Converter  	storage             *storage.Driver  	state               state.State  	mediaManager        *media.Manager @@ -73,7 +73,7 @@ func (suite *MediaStandardTestSuite) SetupTest() {  	suite.db = testrig.NewTestDB(&suite.state)  	suite.state.DB = suite.db -	suite.tc = testrig.NewTestTypeConverter(suite.db) +	suite.tc = typeutils.NewConverter(&suite.state)  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/processing/media/unattach.go b/internal/processing/media/unattach.go index c6eeac604..ddf2dda20 100644 --- a/internal/processing/media/unattach.go +++ b/internal/processing/media/unattach.go @@ -49,7 +49,7 @@ func (p *Processor) Unattach(ctx context.Context, account *gtsmodel.Account, med  		return nil, gtserror.NewErrorNotFound(fmt.Errorf("db error updating attachment: %s", err))  	} -	a, err := p.tc.AttachmentToAPIAttachment(ctx, attachment) +	a, err := p.converter.AttachmentToAPIAttachment(ctx, attachment)  	if err != nil {  		return nil, gtserror.NewErrorNotFound(fmt.Errorf("error converting attachment: %s", err))  	} diff --git a/internal/processing/media/update.go b/internal/processing/media/update.go index 59ade9ca5..d3a9cfe61 100644 --- a/internal/processing/media/update.go +++ b/internal/processing/media/update.go @@ -65,7 +65,7 @@ func (p *Processor) Update(ctx context.Context, account *gtsmodel.Account, media  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("database error updating media: %s", err))  	} -	a, err := p.tc.AttachmentToAPIAttachment(ctx, attachment) +	a, err := p.converter.AttachmentToAPIAttachment(ctx, attachment)  	if err != nil {  		return nil, gtserror.NewErrorNotFound(fmt.Errorf("error converting attachment: %s", err))  	} diff --git a/internal/processing/processor.go b/internal/processing/processor.go index f814d5a96..92c7974c7 100644 --- a/internal/processing/processor.go +++ b/internal/processing/processor.go @@ -49,7 +49,7 @@ import (  // or sub processors will trigger asynchronous processing  // via the workers contained in state.  type Processor struct { -	tc          typeutils.TypeConverter +	converter   *typeutils.Converter  	oauthServer oauth.Server  	state       *state.State @@ -126,7 +126,7 @@ func (p *Processor) Workers() *workers.Processor {  // NewProcessor returns a new Processor.  func NewProcessor( -	tc typeutils.TypeConverter, +	converter *typeutils.Converter,  	federator federation.Federator,  	oauthServer oauth.Server,  	mediaManager *mm.Manager, @@ -139,7 +139,7 @@ func NewProcessor(  	)  	processor := &Processor{ -		tc:          tc, +		converter:   converter,  		oauthServer: oauthServer,  		state:       state,  	} @@ -148,23 +148,23 @@ func NewProcessor(  	//  	// Start with sub processors that will  	// be required by the workers processor. -	commonProcessor := common.New(state, tc, federator, filter) -	accountProcessor := account.New(&commonProcessor, state, tc, mediaManager, oauthServer, federator, filter, parseMentionFunc) -	mediaProcessor := media.New(state, tc, mediaManager, federator.TransportController()) +	commonProcessor := common.New(state, converter, federator, filter) +	accountProcessor := account.New(&commonProcessor, state, converter, mediaManager, oauthServer, federator, filter, parseMentionFunc) +	mediaProcessor := media.New(state, converter, mediaManager, federator.TransportController())  	streamProcessor := stream.New(state, oauthServer)  	// Instantiate the rest of the sub  	// processors + pin them to this struct.  	processor.account = accountProcessor -	processor.admin = admin.New(state, tc, mediaManager, federator.TransportController(), emailSender) -	processor.fedi = fedi.New(state, tc, federator, filter) -	processor.list = list.New(state, tc) -	processor.markers = markers.New(state, tc) +	processor.admin = admin.New(state, converter, mediaManager, federator.TransportController(), emailSender) +	processor.fedi = fedi.New(state, converter, federator, filter) +	processor.list = list.New(state, converter) +	processor.markers = markers.New(state, converter)  	processor.media = mediaProcessor -	processor.report = report.New(state, tc) -	processor.timeline = timeline.New(state, tc, filter) -	processor.search = search.New(state, federator, tc, filter) -	processor.status = status.New(state, federator, tc, filter, parseMentionFunc) +	processor.report = report.New(state, converter) +	processor.timeline = timeline.New(state, converter, filter) +	processor.search = search.New(state, federator, converter, filter) +	processor.status = status.New(state, federator, converter, filter, parseMentionFunc)  	processor.stream = streamProcessor  	processor.user = user.New(state, emailSender) @@ -174,7 +174,7 @@ func NewProcessor(  	processor.workers = workers.New(  		state,  		federator, -		tc, +		converter,  		filter,  		emailSender,  		&accountProcessor, diff --git a/internal/processing/processor_test.go b/internal/processing/processor_test.go index 383e1dc9f..15d943e86 100644 --- a/internal/processing/processor_test.go +++ b/internal/processing/processor_test.go @@ -44,7 +44,7 @@ type ProcessingStandardTestSuite struct {  	storage             *storage.Driver  	state               state.State  	mediaManager        *media.Manager -	typeconverter       typeutils.TypeConverter +	typeconverter       *typeutils.Converter  	httpClient          *testrig.MockHTTPClient  	transportController transport.Controller  	federator           federation.Federator @@ -104,7 +104,7 @@ func (suite *ProcessingStandardTestSuite) SetupTest() {  	suite.testActivities = testrig.NewTestActivities(suite.testAccounts)  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.typeconverter = testrig.NewTestTypeConverter(suite.db) +	suite.typeconverter = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/processing/report/create.go b/internal/processing/report/create.go index 48f9c1ee4..c65ae0d52 100644 --- a/internal/processing/report/create.go +++ b/internal/processing/report/create.go @@ -99,7 +99,7 @@ func (p *Processor) Create(ctx context.Context, account *gtsmodel.Account, form  		TargetAccount:  targetAccount,  	}) -	apiReport, err := p.tc.ReportToAPIReport(ctx, report) +	apiReport, err := p.converter.ReportToAPIReport(ctx, report)  	if err != nil {  		err = fmt.Errorf("error converting report to frontend representation: %w", err)  		return nil, gtserror.NewErrorInternalError(err) diff --git a/internal/processing/report/get.go b/internal/processing/report/get.go index f39648832..c5c4fc223 100644 --- a/internal/processing/report/get.go +++ b/internal/processing/report/get.go @@ -45,7 +45,7 @@ func (p *Processor) Get(ctx context.Context, account *gtsmodel.Account, id strin  		return nil, gtserror.NewErrorNotFound(err)  	} -	apiReport, err := p.tc.ReportToAPIReport(ctx, report) +	apiReport, err := p.converter.ReportToAPIReport(ctx, report)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting report to api: %s", err))  	} @@ -79,7 +79,7 @@ func (p *Processor) GetMultiple(  	prevMinIDValue := reports[0].ID  	for _, r := range reports { -		item, err := p.tc.ReportToAPIReport(ctx, r) +		item, err := p.converter.ReportToAPIReport(ctx, r)  		if err != nil {  			return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting report to api: %s", err))  		} diff --git a/internal/processing/report/report.go b/internal/processing/report/report.go index 2fb11bc7f..c871172bb 100644 --- a/internal/processing/report/report.go +++ b/internal/processing/report/report.go @@ -23,13 +23,13 @@ import (  )  type Processor struct { -	state *state.State -	tc    typeutils.TypeConverter +	state     *state.State +	converter *typeutils.Converter  } -func New(state *state.State, tc typeutils.TypeConverter) Processor { +func New(state *state.State, converter *typeutils.Converter) Processor {  	return Processor{ -		state: state, -		tc:    tc, +		state:     state, +		converter: converter,  	}  } diff --git a/internal/processing/search/search.go b/internal/processing/search/search.go index 907877789..a7b1d4ad3 100644 --- a/internal/processing/search/search.go +++ b/internal/processing/search/search.go @@ -27,16 +27,16 @@ import (  type Processor struct {  	state     *state.State  	federator federation.Federator -	tc        typeutils.TypeConverter +	converter *typeutils.Converter  	filter    *visibility.Filter  }  // New returns a new status processor. -func New(state *state.State, federator federation.Federator, tc typeutils.TypeConverter, filter *visibility.Filter) Processor { +func New(state *state.State, federator federation.Federator, converter *typeutils.Converter, filter *visibility.Filter) Processor {  	return Processor{  		state:     state,  		federator: federator, -		tc:        tc, +		converter: converter,  		filter:    filter,  	}  } diff --git a/internal/processing/search/util.go b/internal/processing/search/util.go index c0eac0ca3..9d9175246 100644 --- a/internal/processing/search/util.go +++ b/internal/processing/search/util.go @@ -70,7 +70,7 @@ func (p *Processor) packageAccounts(  			continue  		} -		apiAccount, err := p.tc.AccountToAPIAccountPublic(ctx, account) +		apiAccount, err := p.converter.AccountToAPIAccountPublic(ctx, account)  		if err != nil {  			log.Debugf(ctx, "skipping account %s because it couldn't be converted to its api representation: %s", account.ID, err)  			continue @@ -105,7 +105,7 @@ func (p *Processor) packageStatuses(  			continue  		} -		apiStatus, err := p.tc.StatusToAPIStatus(ctx, status, requestingAccount) +		apiStatus, err := p.converter.StatusToAPIStatus(ctx, status, requestingAccount)  		if err != nil {  			log.Debugf(ctx, "skipping status %s because it couldn't be converted to its api representation: %s", status.ID, err)  			continue @@ -137,7 +137,7 @@ func (p *Processor) packageHashtags(  	} else {  		// If API not version 1, provide slice of full tags.  		rangeF = func(tag *gtsmodel.Tag) { -			apiTag, err := p.tc.TagToAPITag(ctx, tag, true) +			apiTag, err := p.converter.TagToAPITag(ctx, tag, true)  			if err != nil {  				log.Debugf(  					ctx, diff --git a/internal/processing/status/boost.go b/internal/processing/status/boost.go index eccd81886..d4bdc3f43 100644 --- a/internal/processing/status/boost.go +++ b/internal/processing/status/boost.go @@ -63,7 +63,7 @@ func (p *Processor) BoostCreate(ctx context.Context, requestingAccount *gtsmodel  	}  	// it's visible! it's boostable! so let's boost the FUCK out of it -	boostWrapperStatus, err := p.tc.StatusToBoost(ctx, targetStatus, requestingAccount) +	boostWrapperStatus, err := p.converter.StatusToBoost(ctx, targetStatus, requestingAccount)  	if err != nil {  		return nil, gtserror.NewErrorInternalError(err)  	} @@ -199,7 +199,7 @@ func (p *Processor) StatusBoostedBy(ctx context.Context, requestingAccount *gtsm  			return nil, gtserror.NewErrorNotFound(wrapped)  		} -		apiAccount, err := p.tc.AccountToAPIAccountPublic(ctx, account) +		apiAccount, err := p.converter.AccountToAPIAccountPublic(ctx, account)  		if err != nil {  			err = fmt.Errorf("BoostedBy: error converting account to api model: %s", err)  			return nil, gtserror.NewErrorInternalError(err) diff --git a/internal/processing/status/common.go b/internal/processing/status/common.go index e557563f3..71eef70a1 100644 --- a/internal/processing/status/common.go +++ b/internal/processing/status/common.go @@ -29,7 +29,7 @@ import (  )  func (p *Processor) apiStatus(ctx context.Context, targetStatus *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*apimodel.Status, gtserror.WithCode) { -	apiStatus, err := p.tc.StatusToAPIStatus(ctx, targetStatus, requestingAccount) +	apiStatus, err := p.converter.StatusToAPIStatus(ctx, targetStatus, requestingAccount)  	if err != nil {  		err = gtserror.Newf("error converting status %s to frontend representation: %w", targetStatus.ID, err)  		return nil, gtserror.NewErrorInternalError(err) diff --git a/internal/processing/status/fave.go b/internal/processing/status/fave.go index 9da243312..e2bf03594 100644 --- a/internal/processing/status/fave.go +++ b/internal/processing/status/fave.go @@ -135,7 +135,7 @@ func (p *Processor) FavedBy(ctx context.Context, requestingAccount *gtsmodel.Acc  			continue  		} -		apiAccount, err := p.tc.AccountToAPIAccountPublic(ctx, fave.Account) +		apiAccount, err := p.converter.AccountToAPIAccountPublic(ctx, fave.Account)  		if err != nil {  			err = fmt.Errorf("FavedBy: error converting account %s to frontend representation: %w", fave.AccountID, err)  			return nil, gtserror.NewErrorInternalError(err) diff --git a/internal/processing/status/get.go b/internal/processing/status/get.go index 236f6f126..cf79b96a0 100644 --- a/internal/processing/status/get.go +++ b/internal/processing/status/get.go @@ -55,7 +55,7 @@ func (p *Processor) ContextGet(ctx context.Context, requestingAccount *gtsmodel.  	for _, status := range parents {  		if v, err := p.filter.StatusVisible(ctx, requestingAccount, status); err == nil && v { -			apiStatus, err := p.tc.StatusToAPIStatus(ctx, status, requestingAccount) +			apiStatus, err := p.converter.StatusToAPIStatus(ctx, status, requestingAccount)  			if err == nil {  				context.Ancestors = append(context.Ancestors, *apiStatus)  			} @@ -73,7 +73,7 @@ func (p *Processor) ContextGet(ctx context.Context, requestingAccount *gtsmodel.  	for _, status := range children {  		if v, err := p.filter.StatusVisible(ctx, requestingAccount, status); err == nil && v { -			apiStatus, err := p.tc.StatusToAPIStatus(ctx, status, requestingAccount) +			apiStatus, err := p.converter.StatusToAPIStatus(ctx, status, requestingAccount)  			if err == nil {  				context.Descendants = append(context.Descendants, *apiStatus)  			} diff --git a/internal/processing/status/status.go b/internal/processing/status/status.go index c34bff30f..bd8457eb8 100644 --- a/internal/processing/status/status.go +++ b/internal/processing/status/status.go @@ -29,18 +29,18 @@ import (  type Processor struct {  	state        *state.State  	federator    federation.Federator -	tc           typeutils.TypeConverter +	converter    *typeutils.Converter  	filter       *visibility.Filter  	formatter    text.Formatter  	parseMention gtsmodel.ParseMentionFunc  }  // New returns a new status processor. -func New(state *state.State, federator federation.Federator, tc typeutils.TypeConverter, filter *visibility.Filter, parseMention gtsmodel.ParseMentionFunc) Processor { +func New(state *state.State, federator federation.Federator, converter *typeutils.Converter, filter *visibility.Filter, parseMention gtsmodel.ParseMentionFunc) Processor {  	return Processor{  		state:        state,  		federator:    federator, -		tc:           tc, +		converter:    converter,  		filter:       filter,  		formatter:    text.NewFormatter(state.DB),  		parseMention: parseMention, diff --git a/internal/processing/status/status_test.go b/internal/processing/status/status_test.go index a64143df4..1f73530cb 100644 --- a/internal/processing/status/status_test.go +++ b/internal/processing/status/status_test.go @@ -36,7 +36,7 @@ import (  type StatusStandardTestSuite struct {  	suite.Suite  	db            db.DB -	typeConverter typeutils.TypeConverter +	typeConverter *typeutils.Converter  	tc            transport.Controller  	storage       *storage.Driver  	state         state.State @@ -78,7 +78,7 @@ func (suite *StatusStandardTestSuite) SetupTest() {  	testrig.InitTestLog()  	suite.db = testrig.NewTestDB(&suite.state) -	suite.typeConverter = testrig.NewTestTypeConverter(suite.db) +	suite.typeConverter = typeutils.NewConverter(&suite.state)  	suite.state.DB = suite.db  	suite.tc = testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../testrig/media")) @@ -91,7 +91,7 @@ func (suite *StatusStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		filter, -		testrig.NewTestTypeConverter(suite.db), +		suite.typeConverter,  	)  	suite.status = status.New(&suite.state, suite.federator, suite.typeConverter, filter, processing.GetParseMentionFunc(suite.db, suite.federator)) diff --git a/internal/processing/stream/notification_test.go b/internal/processing/stream/notification_test.go index 5db735db7..7ce8b95d5 100644 --- a/internal/processing/stream/notification_test.go +++ b/internal/processing/stream/notification_test.go @@ -25,7 +25,7 @@ import (  	"github.com/stretchr/testify/suite"  	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" -	"github.com/superseriousbusiness/gotosocial/testrig" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  )  type NotificationTestSuite struct { @@ -39,7 +39,7 @@ func (suite *NotificationTestSuite) TestStreamNotification() {  	suite.NoError(errWithCode)  	followAccount := suite.testAccounts["remote_account_1"] -	followAccountAPIModel, err := testrig.NewTestTypeConverter(suite.db).AccountToAPIAccountPublic(context.Background(), followAccount) +	followAccountAPIModel, err := typeutils.NewConverter(&suite.state).AccountToAPIAccountPublic(context.Background(), followAccount)  	suite.NoError(err)  	notification := &apimodel.Notification{ diff --git a/internal/processing/timeline/faved.go b/internal/processing/timeline/faved.go index 556ced4c3..205b15069 100644 --- a/internal/processing/timeline/faved.go +++ b/internal/processing/timeline/faved.go @@ -54,7 +54,7 @@ func (p *Processor) FavedTimelineGet(ctx context.Context, authed *oauth.Auth, ma  			continue  		} -		apiStatus, err := p.tc.StatusToAPIStatus(ctx, s, authed.Account) +		apiStatus, err := p.converter.StatusToAPIStatus(ctx, s, authed.Account)  		if err != nil {  			log.Errorf(ctx, "error convering to api status: %v", err)  			continue diff --git a/internal/processing/timeline/home.go b/internal/processing/timeline/home.go index 72940175f..126c9f668 100644 --- a/internal/processing/timeline/home.go +++ b/internal/processing/timeline/home.go @@ -84,7 +84,7 @@ func HomeTimelineFilter(state *state.State, filter *visibility.Filter) timeline.  }  // HomeTimelineStatusPrepare returns a function that satisfies PrepareFunction for home timelines. -func HomeTimelineStatusPrepare(state *state.State, tc typeutils.TypeConverter) timeline.PrepareFunction { +func HomeTimelineStatusPrepare(state *state.State, converter *typeutils.Converter) timeline.PrepareFunction {  	return func(ctx context.Context, accountID string, itemID string) (timeline.Preparable, error) {  		status, err := state.DB.GetStatusByID(ctx, itemID)  		if err != nil { @@ -98,7 +98,7 @@ func HomeTimelineStatusPrepare(state *state.State, tc typeutils.TypeConverter) t  			return nil, err  		} -		return tc.StatusToAPIStatus(ctx, status, requestingAccount) +		return converter.StatusToAPIStatus(ctx, status, requestingAccount)  	}  } diff --git a/internal/processing/timeline/list.go b/internal/processing/timeline/list.go index 80744df15..64de288db 100644 --- a/internal/processing/timeline/list.go +++ b/internal/processing/timeline/list.go @@ -90,7 +90,7 @@ func ListTimelineFilter(state *state.State, filter *visibility.Filter) timeline.  }  // ListTimelineStatusPrepare returns a function that satisfies PrepareFunction for list timelines. -func ListTimelineStatusPrepare(state *state.State, tc typeutils.TypeConverter) timeline.PrepareFunction { +func ListTimelineStatusPrepare(state *state.State, converter *typeutils.Converter) timeline.PrepareFunction {  	return func(ctx context.Context, listID string, itemID string) (timeline.Preparable, error) {  		status, err := state.DB.GetStatusByID(ctx, itemID)  		if err != nil { @@ -110,7 +110,7 @@ func ListTimelineStatusPrepare(state *state.State, tc typeutils.TypeConverter) t  			return nil, err  		} -		return tc.StatusToAPIStatus(ctx, status, requestingAccount) +		return converter.StatusToAPIStatus(ctx, status, requestingAccount)  	}  } diff --git a/internal/processing/timeline/notification.go b/internal/processing/timeline/notification.go index 4a79fb82a..09febdb46 100644 --- a/internal/processing/timeline/notification.go +++ b/internal/processing/timeline/notification.go @@ -87,7 +87,7 @@ func (p *Processor) NotificationsGet(ctx context.Context, authed *oauth.Auth, ma  			}  		} -		item, err := p.tc.NotificationToAPINotification(ctx, n) +		item, err := p.converter.NotificationToAPINotification(ctx, n)  		if err != nil {  			log.Debugf(ctx, "skipping notification %s because it couldn't be converted to its api representation: %s", n.ID, err)  			continue @@ -121,7 +121,7 @@ func (p *Processor) NotificationGet(ctx context.Context, account *gtsmodel.Accou  		return nil, gtserror.NewErrorNotFound(err)  	} -	apiNotif, err := p.tc.NotificationToAPINotification(ctx, notif) +	apiNotif, err := p.converter.NotificationToAPINotification(ctx, notif)  	if err != nil {  		if errors.Is(err, db.ErrNoEntries) {  			return nil, gtserror.NewErrorNotFound(err) diff --git a/internal/processing/timeline/public.go b/internal/processing/timeline/public.go index 78ca56734..eb8c0c381 100644 --- a/internal/processing/timeline/public.go +++ b/internal/processing/timeline/public.go @@ -62,7 +62,7 @@ func (p *Processor) PublicTimelineGet(ctx context.Context, authed *oauth.Auth, m  			continue  		} -		apiStatus, err := p.tc.StatusToAPIStatus(ctx, s, authed.Account) +		apiStatus, err := p.converter.StatusToAPIStatus(ctx, s, authed.Account)  		if err != nil {  			log.Errorf(ctx, "error convert to api status: %v", err)  			continue diff --git a/internal/processing/timeline/tag.go b/internal/processing/timeline/tag.go index 943aa1722..45632ce06 100644 --- a/internal/processing/timeline/tag.go +++ b/internal/processing/timeline/tag.go @@ -122,7 +122,7 @@ func (p *Processor) packageTagResponse(  			continue  		} -		apiStatus, err := p.tc.StatusToAPIStatus(ctx, s, requestingAcct) +		apiStatus, err := p.converter.StatusToAPIStatus(ctx, s, requestingAcct)  		if err != nil {  			log.Errorf(ctx, "error converting to api status: %v", err)  			continue diff --git a/internal/processing/timeline/timeline.go b/internal/processing/timeline/timeline.go index 7a95f9a11..bf9864398 100644 --- a/internal/processing/timeline/timeline.go +++ b/internal/processing/timeline/timeline.go @@ -24,15 +24,15 @@ import (  )  type Processor struct { -	state  *state.State -	tc     typeutils.TypeConverter -	filter *visibility.Filter +	state     *state.State +	converter *typeutils.Converter +	filter    *visibility.Filter  } -func New(state *state.State, tc typeutils.TypeConverter, filter *visibility.Filter) Processor { +func New(state *state.State, converter *typeutils.Converter, filter *visibility.Filter) Processor {  	return Processor{ -		state:  state, -		tc:     tc, -		filter: filter, +		state:     state, +		converter: converter, +		filter:    filter,  	}  } diff --git a/internal/processing/workers/federate.go b/internal/processing/workers/federate.go index 76bfc892e..4b2ca4de1 100644 --- a/internal/processing/workers/federate.go +++ b/internal/processing/workers/federate.go @@ -37,8 +37,8 @@ type federate struct {  	// Embed federator to give access  	// to send and retrieve functions.  	federation.Federator -	state *state.State -	tc    typeutils.TypeConverter +	state     *state.State +	converter *typeutils.Converter  }  // parseURI is a cheeky little @@ -160,12 +160,12 @@ func (f *federate) CreateStatus(ctx context.Context, status *gtsmodel.Status) er  	// Convert status to an ActivityStreams  	// Note, wrapped in a Create activity. -	asStatus, err := f.tc.StatusToAS(ctx, status) +	asStatus, err := f.converter.StatusToAS(ctx, status)  	if err != nil {  		return gtserror.Newf("error converting status to AS: %w", err)  	} -	create, err := f.tc.WrapNoteInCreate(asStatus, false) +	create, err := f.converter.WrapNoteInCreate(asStatus, false)  	if err != nil {  		return gtserror.Newf("error wrapping status in create: %w", err)  	} @@ -208,7 +208,7 @@ func (f *federate) DeleteStatus(ctx context.Context, status *gtsmodel.Status) er  	}  	// Wrap the status URI in a Delete activity. -	delete, err := f.tc.StatusToASDelete(ctx, status) +	delete, err := f.converter.StatusToASDelete(ctx, status)  	if err != nil {  		return gtserror.Newf("error creating Delete: %w", err)  	} @@ -245,7 +245,7 @@ func (f *federate) Follow(ctx context.Context, follow *gtsmodel.Follow) error {  	}  	// Convert follow to ActivityStreams Follow. -	asFollow, err := f.tc.FollowToAS(ctx, follow) +	asFollow, err := f.converter.FollowToAS(ctx, follow)  	if err != nil {  		return gtserror.Newf("error converting follow to AS: %s", err)  	} @@ -287,7 +287,7 @@ func (f *federate) UndoFollow(ctx context.Context, follow *gtsmodel.Follow) erro  	}  	// Recreate the ActivityStreams Follow. -	asFollow, err := f.tc.FollowToAS(ctx, follow) +	asFollow, err := f.converter.FollowToAS(ctx, follow)  	if err != nil {  		return gtserror.Newf("error converting follow to AS: %w", err)  	} @@ -351,7 +351,7 @@ func (f *federate) UndoLike(ctx context.Context, fave *gtsmodel.StatusFave) erro  	}  	// Recreate the ActivityStreams Like. -	like, err := f.tc.FaveToAS(ctx, fave) +	like, err := f.converter.FaveToAS(ctx, fave)  	if err != nil {  		return gtserror.Newf("error converting fave to AS: %w", err)  	} @@ -410,7 +410,7 @@ func (f *federate) UndoAnnounce(ctx context.Context, boost *gtsmodel.Status) err  	}  	// Recreate the ActivityStreams Announce. -	asAnnounce, err := f.tc.BoostToAS( +	asAnnounce, err := f.converter.BoostToAS(  		ctx,  		boost,  		boost.Account, @@ -493,7 +493,7 @@ func (f *federate) AcceptFollow(ctx context.Context, follow *gtsmodel.Follow) er  	}  	// Recreate the ActivityStreams Follow. -	asFollow, err := f.tc.FollowToAS(ctx, follow) +	asFollow, err := f.converter.FollowToAS(ctx, follow)  	if err != nil {  		return gtserror.Newf("error converting follow to AS: %w", err)  	} @@ -571,7 +571,7 @@ func (f *federate) RejectFollow(ctx context.Context, follow *gtsmodel.Follow) er  	}  	// Recreate the ActivityStreams Follow. -	asFollow, err := f.tc.FollowToAS(ctx, follow) +	asFollow, err := f.converter.FollowToAS(ctx, follow)  	if err != nil {  		return gtserror.Newf("error converting follow to AS: %w", err)  	} @@ -631,7 +631,7 @@ func (f *federate) Like(ctx context.Context, fave *gtsmodel.StatusFave) error {  	}  	// Create the ActivityStreams Like. -	like, err := f.tc.FaveToAS(ctx, fave) +	like, err := f.converter.FaveToAS(ctx, fave)  	if err != nil {  		return gtserror.Newf("error converting fave to AS Like: %w", err)  	} @@ -668,7 +668,7 @@ func (f *federate) Announce(ctx context.Context, boost *gtsmodel.Status) error {  	}  	// Create the ActivityStreams Announce. -	announce, err := f.tc.BoostToAS( +	announce, err := f.converter.BoostToAS(  		ctx,  		boost,  		boost.Account, @@ -704,13 +704,13 @@ func (f *federate) UpdateAccount(ctx context.Context, account *gtsmodel.Account)  	}  	// Convert account to ActivityStreams Person. -	person, err := f.tc.AccountToAS(ctx, account) +	person, err := f.converter.AccountToAS(ctx, account)  	if err != nil {  		return gtserror.Newf("error converting account to Person: %w", err)  	}  	// Use ActivityStreams Person as Object of Update. -	update, err := f.tc.WrapPersonInUpdate(person, account) +	update, err := f.converter.WrapPersonInUpdate(person, account)  	if err != nil {  		return gtserror.Newf("error wrapping Person in Update: %w", err)  	} @@ -747,7 +747,7 @@ func (f *federate) Block(ctx context.Context, block *gtsmodel.Block) error {  	}  	// Convert block to ActivityStreams Block. -	asBlock, err := f.tc.BlockToAS(ctx, block) +	asBlock, err := f.converter.BlockToAS(ctx, block)  	if err != nil {  		return gtserror.Newf("error converting block to AS: %w", err)  	} @@ -789,7 +789,7 @@ func (f *federate) UndoBlock(ctx context.Context, block *gtsmodel.Block) error {  	}  	// Convert block to ActivityStreams Block. -	asBlock, err := f.tc.BlockToAS(ctx, block) +	asBlock, err := f.converter.BlockToAS(ctx, block)  	if err != nil {  		return gtserror.Newf("error converting block to AS: %w", err)  	} @@ -861,7 +861,7 @@ func (f *federate) Flag(ctx context.Context, report *gtsmodel.Report) error {  	}  	// Convert report to ActivityStreams Flag. -	flag, err := f.tc.ReportToASFlag(ctx, report) +	flag, err := f.converter.ReportToASFlag(ctx, report)  	if err != nil {  		return gtserror.Newf("error converting report to AS: %w", err)  	} diff --git a/internal/processing/workers/fromclientapi.go b/internal/processing/workers/fromclientapi.go index c48bb7044..1c668db71 100644 --- a/internal/processing/workers/fromclientapi.go +++ b/internal/processing/workers/fromclientapi.go @@ -40,7 +40,7 @@ import (  // from the client/REST API.  type clientAPI struct {  	state      *state.State -	tc         typeutils.TypeConverter +	converter  *typeutils.Converter  	surface    *surface  	federate   *federate  	wipeStatus wipeStatus @@ -242,7 +242,7 @@ func (p *clientAPI) CreateFollowReq(ctx context.Context, cMsg messages.FromClien  	if err := p.federate.Follow(  		ctx, -		p.tc.FollowRequestToFollow(ctx, followRequest), +		p.converter.FollowRequestToFollow(ctx, followRequest),  	); err != nil {  		return gtserror.Newf("error federating follow: %w", err)  	} @@ -389,7 +389,7 @@ func (p *clientAPI) RejectFollowRequest(ctx context.Context, cMsg messages.FromC  	if err := p.federate.RejectFollow(  		ctx, -		p.tc.FollowRequestToFollow(ctx, followReq), +		p.converter.FollowRequestToFollow(ctx, followReq),  	); err != nil {  		return gtserror.Newf("error federating reject follow: %w", err)  	} diff --git a/internal/processing/workers/surface.go b/internal/processing/workers/surface.go index a3cf9a3e1..4012dcacc 100644 --- a/internal/processing/workers/surface.go +++ b/internal/processing/workers/surface.go @@ -33,7 +33,7 @@ import (  //   - sending an email  type surface struct {  	state       *state.State -	tc          typeutils.TypeConverter +	converter   *typeutils.Converter  	stream      *stream.Processor  	filter      *visibility.Filter  	emailSender email.Sender diff --git a/internal/processing/workers/surfacenotify.go b/internal/processing/workers/surfacenotify.go index 00e1205e6..5a4f77a64 100644 --- a/internal/processing/workers/surfacenotify.go +++ b/internal/processing/workers/surfacenotify.go @@ -34,7 +34,7 @@ func (s *surface) notifyMentions(  	ctx context.Context,  	mentions []*gtsmodel.Mention,  ) error { -	var errs = gtserror.NewMultiError(len(mentions)) +	errs := gtserror.NewMultiError(len(mentions))  	for _, mention := range mentions {  		if err := s.notify( @@ -208,7 +208,7 @@ func (s *surface) notify(  	}  	// Stream notification to the user. -	apiNotif, err := s.tc.NotificationToAPINotification(ctx, notif) +	apiNotif, err := s.converter.NotificationToAPINotification(ctx, notif)  	if err != nil {  		return gtserror.Newf("error converting notification to api representation: %w", err)  	} diff --git a/internal/processing/workers/surfacetimeline.go b/internal/processing/workers/surfacetimeline.go index 827cbe2f8..a13e6bc70 100644 --- a/internal/processing/workers/surfacetimeline.go +++ b/internal/processing/workers/surfacetimeline.go @@ -286,7 +286,6 @@ func (s *surface) listEligible(  			list.ID,  			status.InReplyToAccountID,  		) -  		if err != nil {  			err := gtserror.Newf(  				"db error checking if account %s in list %s: %w", @@ -352,7 +351,7 @@ func (s *surface) timelineStatus(  	}  	// The status was inserted so stream it to the user. -	apiStatus, err := s.tc.StatusToAPIStatus(ctx, status, account) +	apiStatus, err := s.converter.StatusToAPIStatus(ctx, status, account)  	if err != nil {  		err = gtserror.Newf("error converting status %s to frontend representation: %w", status.ID, err)  		return true, err diff --git a/internal/processing/workers/workers.go b/internal/processing/workers/workers.go index 24b18a405..e512a36bf 100644 --- a/internal/processing/workers/workers.go +++ b/internal/processing/workers/workers.go @@ -38,7 +38,7 @@ type Processor struct {  func New(  	state *state.State,  	federator federation.Federator, -	tc typeutils.TypeConverter, +	converter *typeutils.Converter,  	filter *visibility.Filter,  	emailSender email.Sender,  	account *account.Processor, @@ -49,7 +49,7 @@ func New(  	// wrapper struct.  	surface := &surface{  		state:       state, -		tc:          tc, +		converter:   converter,  		stream:      stream,  		filter:      filter,  		emailSender: emailSender, @@ -60,7 +60,7 @@ func New(  	federate := &federate{  		Federator: federator,  		state:     state, -		tc:        tc, +		converter: converter,  	}  	// Init shared logic wipe @@ -75,7 +75,7 @@ func New(  		workers: &state.Workers,  		clientAPI: &clientAPI{  			state:      state, -			tc:         tc, +			converter:  converter,  			surface:    surface,  			federate:   federate,  			wipeStatus: wipeStatus, diff --git a/internal/processing/workers/workers_test.go b/internal/processing/workers/workers_test.go index 2d5a7f5d3..5a7e645d6 100644 --- a/internal/processing/workers/workers_test.go +++ b/internal/processing/workers/workers_test.go @@ -44,7 +44,7 @@ type WorkersTestSuite struct {  	storage             *storage.Driver  	state               state.State  	mediaManager        *media.Manager -	typeconverter       typeutils.TypeConverter +	typeconverter       *typeutils.Converter  	httpClient          *testrig.MockHTTPClient  	transportController transport.Controller  	federator           federation.Federator @@ -106,7 +106,7 @@ func (suite *WorkersTestSuite) SetupTest() {  	suite.testActivities = testrig.NewTestActivities(suite.testAccounts)  	suite.storage = testrig.NewInMemoryStorage()  	suite.state.Storage = suite.storage -	suite.typeconverter = testrig.NewTestTypeConverter(suite.db) +	suite.typeconverter = typeutils.NewConverter(&suite.state)  	testrig.StartTimelines(  		&suite.state, diff --git a/internal/timeline/timeline_test.go b/internal/timeline/timeline_test.go index 2dc17e963..f678a6292 100644 --- a/internal/timeline/timeline_test.go +++ b/internal/timeline/timeline_test.go @@ -24,6 +24,7 @@ import (  	"github.com/stretchr/testify/suite"  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/state" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -57,7 +58,7 @@ func (suite *TimelineStandardTestSuite) SetupTest() {  	testrig.StartTimelines(  		suite.state,  		visibility.NewFilter(suite.state), -		testrig.NewTestTypeConverter(suite.state.DB), +		typeutils.NewConverter(suite.state),  	)  	testrig.StandardDBSetup(suite.state.DB, nil) diff --git a/internal/transport/transport_test.go b/internal/transport/transport_test.go index ab9b6a21a..9f4b13cce 100644 --- a/internal/transport/transport_test.go +++ b/internal/transport/transport_test.go @@ -30,6 +30,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/storage"  	"github.com/superseriousbusiness/gotosocial/internal/transport" +	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  	"github.com/superseriousbusiness/gotosocial/internal/visibility"  	"github.com/superseriousbusiness/gotosocial/testrig"  ) @@ -79,7 +80,7 @@ func (suite *TransportTestSuite) SetupTest() {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		typeutils.NewConverter(&suite.state),  	)  	suite.mediaManager = testrig.NewTestMediaManager(&suite.state) diff --git a/internal/typeutils/astointernal.go b/internal/typeutils/astointernal.go index 7b1ba0396..81dbc6f40 100644 --- a/internal/typeutils/astointernal.go +++ b/internal/typeutils/astointernal.go @@ -34,7 +34,10 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/util"  ) -func (c *converter) ASRepresentationToAccount(ctx context.Context, accountable ap.Accountable, accountDomain string) (*gtsmodel.Account, error) { +// ASRepresentationToAccount converts a remote account/person/application representation into a gts model account. +// +// If accountDomain is provided then this value will be used as the account's Domain, else the AP ID host. +func (c *Converter) ASRepresentationToAccount(ctx context.Context, accountable ap.Accountable, accountDomain string) (*gtsmodel.Account, error) {  	// first check if we actually already know this account  	uriProp := accountable.GetJSONLDId()  	if uriProp == nil || !uriProp.IsIRI() { @@ -213,7 +216,7 @@ func (c *converter) ASRepresentationToAccount(ctx context.Context, accountable a  	return acct, nil  } -func (c *converter) extractAttachments(i ap.WithAttachment) []*gtsmodel.MediaAttachment { +func (c *Converter) extractAttachments(i ap.WithAttachment) []*gtsmodel.MediaAttachment {  	attachmentProp := i.GetActivityStreamsAttachment()  	if attachmentProp == nil {  		return nil @@ -245,7 +248,8 @@ func (c *converter) extractAttachments(i ap.WithAttachment) []*gtsmodel.MediaAtt  	return attachments  } -func (c *converter) ASStatusToStatus(ctx context.Context, statusable ap.Statusable) (*gtsmodel.Status, error) { +// ASStatus converts a remote activitystreams 'status' representation into a gts model status. +func (c *Converter) ASStatusToStatus(ctx context.Context, statusable ap.Statusable) (*gtsmodel.Status, error) {  	status := new(gtsmodel.Status)  	// status.URI @@ -341,7 +345,7 @@ func (c *converter) ASStatusToStatus(ctx context.Context, statusable ap.Statusab  	}  	accountURI := attributedTo.String() -	account, err := c.db.GetAccountByURI(ctx, accountURI) +	account, err := c.state.DB.GetAccountByURI(ctx, accountURI)  	if err != nil {  		err = gtserror.Newf("db error getting status author account %s: %w", accountURI, err)  		return nil, err @@ -364,7 +368,7 @@ func (c *converter) ASStatusToStatus(ctx context.Context, statusable ap.Statusab  		status.InReplyToURI = inReplyToURI  		// Check if we already have the replied-to status. -		inReplyTo, err := c.db.GetStatusByURI(ctx, inReplyToURI) +		inReplyTo, err := c.state.DB.GetStatusByURI(ctx, inReplyToURI)  		if err != nil && !errors.Is(err, db.ErrNoEntries) {  			// Real database error.  			err = gtserror.Newf("db error getting replied-to status %s: %w", inReplyToURI, err) @@ -417,7 +421,8 @@ func (c *converter) ASStatusToStatus(ctx context.Context, statusable ap.Statusab  	return status, nil  } -func (c *converter) ASFollowToFollowRequest(ctx context.Context, followable ap.Followable) (*gtsmodel.FollowRequest, error) { +// ASFollowToFollowRequest converts a remote activitystreams `follow` representation into gts model follow request. +func (c *Converter) ASFollowToFollowRequest(ctx context.Context, followable ap.Followable) (*gtsmodel.FollowRequest, error) {  	idProp := followable.GetJSONLDId()  	if idProp == nil || !idProp.IsIRI() {  		return nil, errors.New("no id property set on follow, or was not an iri") @@ -428,7 +433,7 @@ func (c *converter) ASFollowToFollowRequest(ctx context.Context, followable ap.F  	if err != nil {  		return nil, errors.New("error extracting actor property from follow")  	} -	originAccount, err := c.db.GetAccountByURI(ctx, origin.String()) +	originAccount, err := c.state.DB.GetAccountByURI(ctx, origin.String())  	if err != nil {  		return nil, fmt.Errorf("error extracting account with uri %s from the database: %s", origin.String(), err)  	} @@ -437,7 +442,7 @@ func (c *converter) ASFollowToFollowRequest(ctx context.Context, followable ap.F  	if err != nil {  		return nil, errors.New("error extracting object property from follow")  	} -	targetAccount, err := c.db.GetAccountByURI(ctx, target.String()) +	targetAccount, err := c.state.DB.GetAccountByURI(ctx, target.String())  	if err != nil {  		return nil, fmt.Errorf("error extracting account with uri %s from the database: %s", origin.String(), err)  	} @@ -451,7 +456,8 @@ func (c *converter) ASFollowToFollowRequest(ctx context.Context, followable ap.F  	return followRequest, nil  } -func (c *converter) ASFollowToFollow(ctx context.Context, followable ap.Followable) (*gtsmodel.Follow, error) { +// ASFollowToFollowRequest converts a remote activitystreams `follow` representation into gts model follow. +func (c *Converter) ASFollowToFollow(ctx context.Context, followable ap.Followable) (*gtsmodel.Follow, error) {  	idProp := followable.GetJSONLDId()  	if idProp == nil || !idProp.IsIRI() {  		return nil, errors.New("no id property set on follow, or was not an iri") @@ -462,7 +468,7 @@ func (c *converter) ASFollowToFollow(ctx context.Context, followable ap.Followab  	if err != nil {  		return nil, errors.New("error extracting actor property from follow")  	} -	originAccount, err := c.db.GetAccountByURI(ctx, origin.String()) +	originAccount, err := c.state.DB.GetAccountByURI(ctx, origin.String())  	if err != nil {  		return nil, fmt.Errorf("error extracting account with uri %s from the database: %s", origin.String(), err)  	} @@ -471,7 +477,7 @@ func (c *converter) ASFollowToFollow(ctx context.Context, followable ap.Followab  	if err != nil {  		return nil, errors.New("error extracting object property from follow")  	} -	targetAccount, err := c.db.GetAccountByURI(ctx, target.String()) +	targetAccount, err := c.state.DB.GetAccountByURI(ctx, target.String())  	if err != nil {  		return nil, fmt.Errorf("error extracting account with uri %s from the database: %s", origin.String(), err)  	} @@ -485,7 +491,8 @@ func (c *converter) ASFollowToFollow(ctx context.Context, followable ap.Followab  	return follow, nil  } -func (c *converter) ASLikeToFave(ctx context.Context, likeable ap.Likeable) (*gtsmodel.StatusFave, error) { +// ASLikeToFave converts a remote activitystreams 'like' representation into a gts model status fave. +func (c *Converter) ASLikeToFave(ctx context.Context, likeable ap.Likeable) (*gtsmodel.StatusFave, error) {  	idProp := likeable.GetJSONLDId()  	if idProp == nil || !idProp.IsIRI() {  		return nil, errors.New("no id property set on like, or was not an iri") @@ -496,7 +503,7 @@ func (c *converter) ASLikeToFave(ctx context.Context, likeable ap.Likeable) (*gt  	if err != nil {  		return nil, errors.New("error extracting actor property from like")  	} -	originAccount, err := c.db.GetAccountByURI(ctx, origin.String()) +	originAccount, err := c.state.DB.GetAccountByURI(ctx, origin.String())  	if err != nil {  		return nil, fmt.Errorf("error extracting account with uri %s from the database: %s", origin.String(), err)  	} @@ -506,7 +513,7 @@ func (c *converter) ASLikeToFave(ctx context.Context, likeable ap.Likeable) (*gt  		return nil, errors.New("error extracting object property from like")  	} -	targetStatus, err := c.db.GetStatusByURI(ctx, target.String()) +	targetStatus, err := c.state.DB.GetStatusByURI(ctx, target.String())  	if err != nil {  		return nil, fmt.Errorf("error extracting status with uri %s from the database: %s", target.String(), err)  	} @@ -515,7 +522,7 @@ func (c *converter) ASLikeToFave(ctx context.Context, likeable ap.Likeable) (*gt  	if targetStatus.Account != nil {  		targetAccount = targetStatus.Account  	} else { -		a, err := c.db.GetAccountByID(ctx, targetStatus.AccountID) +		a, err := c.state.DB.GetAccountByID(ctx, targetStatus.AccountID)  		if err != nil {  			return nil, fmt.Errorf("error extracting account with id %s from the database: %s", targetStatus.AccountID, err)  		} @@ -533,7 +540,8 @@ func (c *converter) ASLikeToFave(ctx context.Context, likeable ap.Likeable) (*gt  	}, nil  } -func (c *converter) ASBlockToBlock(ctx context.Context, blockable ap.Blockable) (*gtsmodel.Block, error) { +// ASBlockToBlock converts a remote activity streams 'block' representation into a gts model block. +func (c *Converter) ASBlockToBlock(ctx context.Context, blockable ap.Blockable) (*gtsmodel.Block, error) {  	idProp := blockable.GetJSONLDId()  	if idProp == nil || !idProp.IsIRI() {  		return nil, errors.New("ASBlockToBlock: no id property set on block, or was not an iri") @@ -544,7 +552,7 @@ func (c *converter) ASBlockToBlock(ctx context.Context, blockable ap.Blockable)  	if err != nil {  		return nil, errors.New("ASBlockToBlock: error extracting actor property from block")  	} -	originAccount, err := c.db.GetAccountByURI(ctx, origin.String()) +	originAccount, err := c.state.DB.GetAccountByURI(ctx, origin.String())  	if err != nil {  		return nil, fmt.Errorf("error extracting account with uri %s from the database: %s", origin.String(), err)  	} @@ -554,7 +562,7 @@ func (c *converter) ASBlockToBlock(ctx context.Context, blockable ap.Blockable)  		return nil, errors.New("ASBlockToBlock: error extracting object property from block")  	} -	targetAccount, err := c.db.GetAccountByURI(ctx, target.String()) +	targetAccount, err := c.state.DB.GetAccountByURI(ctx, target.String())  	if err != nil {  		return nil, fmt.Errorf("error extracting account with uri %s from the database: %s", origin.String(), err)  	} @@ -568,6 +576,19 @@ func (c *converter) ASBlockToBlock(ctx context.Context, blockable ap.Blockable)  	}, nil  } +// 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. +//  // Implementation note: this function creates and returns a boost WRAPPER  // status which references the boosted status in its BoostOf field. No  // dereferencing is done on the boosted status by this function. Callers @@ -577,7 +598,7 @@ func (c *converter) ASBlockToBlock(ctx context.Context, blockable ap.Blockable)  // The returned boolean indicates whether or not the boost has already been  // seen before by this instance. If it was, then status.BoostOf should be a  // fully filled-out status. If not, then only status.BoostOf.URI will be set. -func (c *converter) ASAnnounceToStatus(ctx context.Context, announceable ap.Announceable) (*gtsmodel.Status, bool, error) { +func (c *Converter) ASAnnounceToStatus(ctx context.Context, announceable ap.Announceable) (*gtsmodel.Status, bool, error) {  	// Ensure item has an ID URI set.  	_, statusURIStr, err := getURI(announceable)  	if err != nil { @@ -591,7 +612,7 @@ func (c *converter) ASAnnounceToStatus(ctx context.Context, announceable ap.Anno  	)  	// Check if we already have this boost in the database. -	status, err = c.db.GetStatusByURI(ctx, statusURIStr) +	status, err = c.state.DB.GetStatusByURI(ctx, statusURIStr)  	if err != nil && !errors.Is(err, db.ErrNoEntries) {  		// Real database error.  		err = gtserror.Newf("db error trying to get status with uri %s: %w", statusURIStr, err) @@ -648,7 +669,7 @@ func (c *converter) ASAnnounceToStatus(ctx context.Context, announceable ap.Anno  	// This should have been dereferenced already before  	// we hit this point so we can confidently error out  	// if we don't have it. -	account, err := c.db.GetAccountByURI(ctx, accountURIStr) +	account, err := c.state.DB.GetAccountByURI(ctx, accountURIStr)  	if err != nil {  		err = gtserror.Newf("db error trying to get account with uri %s: %w", accountURIStr, err)  		return nil, isNew, err @@ -678,7 +699,8 @@ func (c *converter) ASAnnounceToStatus(ctx context.Context, announceable ap.Anno  	return status, isNew, nil  } -func (c *converter) ASFlagToReport(ctx context.Context, flaggable ap.Flaggable) (*gtsmodel.Report, error) { +// ASFlagToReport converts a remote activitystreams 'flag' representation into a gts model report. +func (c *Converter) ASFlagToReport(ctx context.Context, flaggable ap.Flaggable) (*gtsmodel.Report, error) {  	// Extract flag uri.  	idProp := flaggable.GetJSONLDId()  	if idProp == nil || !idProp.IsIRI() { @@ -692,7 +714,7 @@ func (c *converter) ASFlagToReport(ctx context.Context, flaggable ap.Flaggable)  	if err != nil {  		return nil, fmt.Errorf("ASFlagToReport: error extracting actor: %w", err)  	} -	account, err := c.db.GetAccountByURI(ctx, actor.String()) +	account, err := c.state.DB.GetAccountByURI(ctx, actor.String())  	if err != nil {  		return nil, fmt.Errorf("ASFlagToReport: error in db fetching account with uri %s: %w", actor.String(), err)  	} @@ -744,7 +766,7 @@ func (c *converter) ASFlagToReport(ctx context.Context, flaggable ap.Flaggable)  	if targetAccountURI == nil {  		return nil, errors.New("ASFlagToReport: flaggable objects contained no recognizable target account uri")  	} -	targetAccount, err := c.db.GetAccountByURI(ctx, targetAccountURI.String()) +	targetAccount, err := c.state.DB.GetAccountByURI(ctx, targetAccountURI.String())  	if err != nil {  		if errors.Is(err, db.ErrNoEntries) {  			return nil, fmt.Errorf("ASFlagToReport: account with uri %s could not be found in the db", targetAccountURI.String()) @@ -761,13 +783,13 @@ func (c *converter) ASFlagToReport(ctx context.Context, flaggable ap.Flaggable)  		statusURIString := statusURI.String()  		// try getting this status by URI first, then URL -		status, err := c.db.GetStatusByURI(ctx, statusURIString) +		status, err := c.state.DB.GetStatusByURI(ctx, statusURIString)  		if err != nil {  			if !errors.Is(err, db.ErrNoEntries) {  				return nil, fmt.Errorf("ASFlagToReport: db error getting status with uri %s: %w", statusURIString, err)  			} -			status, err = c.db.GetStatusByURL(ctx, statusURIString) +			status, err = c.state.DB.GetStatusByURL(ctx, statusURIString)  			if err != nil {  				if !errors.Is(err, db.ErrNoEntries) {  					return nil, fmt.Errorf("ASFlagToReport: db error getting status with url %s: %w", statusURIString, err) diff --git a/internal/typeutils/converter.go b/internal/typeutils/converter.go index af77734cc..5f849c39d 100644 --- a/internal/typeutils/converter.go +++ b/internal/typeutils/converter.go @@ -18,218 +18,20 @@  package typeutils  import ( -	"context" -	"net/url"  	"sync" -	"github.com/gorilla/feeds" -	"github.com/superseriousbusiness/activity/streams/vocab" -	"github.com/superseriousbusiness/gotosocial/internal/ap" -	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" -	"github.com/superseriousbusiness/gotosocial/internal/db" -	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +	"github.com/superseriousbusiness/gotosocial/internal/state"  ) -// 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 { -	/* -		INTERNAL (gts) MODEL TO FRONTEND (api) MODEL -	*/ - -	// AccountToAPIAccountSensitive takes a db model account as a param, and returns a populated apitype account, or an error -	// 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. -	AccountToAPIAccountSensitive(ctx context.Context, account *gtsmodel.Account) (*apimodel.Account, error) -	// AccountToAPIAccountPublic takes a db model account as a param, and returns a populated apitype account, or an error -	// 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. -	AccountToAPIAccountPublic(ctx context.Context, account *gtsmodel.Account) (*apimodel.Account, error) -	// AccountToAPIAccountBlocked takes a db model account as a param, and returns a apitype account, or an error if -	// 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. -	AccountToAPIAccountBlocked(ctx context.Context, account *gtsmodel.Account) (*apimodel.Account, error) -	// AppToAPIAppSensitive takes a db model application as a param, and returns a populated apitype application, or an error -	// 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. -	AppToAPIAppSensitive(ctx context.Context, application *gtsmodel.Application) (*apimodel.Application, error) -	// AppToAPIAppPublic takes a db model application as a param, and returns a populated apitype application, or an error -	// 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. -	AppToAPIAppPublic(ctx context.Context, application *gtsmodel.Application) (*apimodel.Application, error) -	// AttachmentToAPIAttachment converts a gts model media attacahment into its api representation for serialization on the API. -	AttachmentToAPIAttachment(ctx context.Context, attachment *gtsmodel.MediaAttachment) (apimodel.Attachment, error) -	// MentionToAPIMention converts a gts model mention into its api (frontend) representation for serialization on the API. -	MentionToAPIMention(ctx context.Context, m *gtsmodel.Mention) (apimodel.Mention, error) -	// EmojiToAPIEmoji converts a gts model emoji into its api (frontend) representation for serialization on the API. -	EmojiToAPIEmoji(ctx context.Context, e *gtsmodel.Emoji) (apimodel.Emoji, error) -	// EmojiToAdminAPIEmoji converts a gts model emoji into an API representation with extra admin information. -	EmojiToAdminAPIEmoji(ctx context.Context, e *gtsmodel.Emoji) (*apimodel.AdminEmoji, error) -	// EmojiCategoryToAPIEmojiCategory converts a gts model emoji category into its api (frontend) representation. -	EmojiCategoryToAPIEmojiCategory(ctx context.Context, category *gtsmodel.EmojiCategory) (*apimodel.EmojiCategory, error) -	// TagToAPITag converts a gts model tag into its api (frontend) representation for serialization on the API. -	// 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) -	// StatusToAPIStatus converts a gts model status into its api (frontend) representation for serialization on the API. -	// -	// Requesting account can be nil. -	StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*apimodel.Status, error) -	// VisToAPIVis converts a gts visibility into its api equivalent -	VisToAPIVis(ctx context.Context, m gtsmodel.Visibility) apimodel.Visibility -	// 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) -	// InstanceRulesToAPIRules converts all local instance rules into their api equivalent for serving at /api/v1/instance/rules -	InstanceRulesToAPIRules(r []gtsmodel.Rule) []apimodel.InstanceRule -	// InstanceRuleToAdminAPIRule converts a local instance rule into its api equivalent for serving at /api/v1/admin/instance/rules/:id -	InstanceRuleToAdminAPIRule(r *gtsmodel.Rule) *apimodel.AdminInstanceRule -	// RelationshipToAPIRelationship converts a gts relationship into its api equivalent for serving in various places -	RelationshipToAPIRelationship(ctx context.Context, r *gtsmodel.Relationship) (*apimodel.Relationship, error) -	// NotificationToAPINotification converts a gts notification into a api notification -	NotificationToAPINotification(ctx context.Context, n *gtsmodel.Notification) (*apimodel.Notification, error) -	// DomainPermToAPIDomainPerm converts a gts model domin block or allow into an api domain permission. -	DomainPermToAPIDomainPerm(ctx context.Context, d gtsmodel.DomainPermission, export bool) (*apimodel.DomainPermission, error) -	// 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) -	// 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) -	// 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) -	// 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) - -	/* -		INTERNAL (gts) MODEL TO FRONTEND (rss) MODEL -	*/ - -	StatusToRSSItem(ctx context.Context, s *gtsmodel.Status) (*feeds.Item, error) - -	/* -		ACTIVITYSTREAMS MODEL TO INTERNAL (gts) MODEL -	*/ - -	// ASRepresentationToAccount converts a remote account/person/application representation into a gts model account. -	// -	// 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) -	// ASStatus converts a remote activitystreams 'status' representation into a gts model status. -	ASStatusToStatus(ctx context.Context, statusable ap.Statusable) (*gtsmodel.Status, error) -	// ASFollowToFollowRequest converts a remote activitystreams `follow` representation into gts model follow request. -	ASFollowToFollowRequest(ctx context.Context, followable ap.Followable) (*gtsmodel.FollowRequest, error) -	// ASFollowToFollowRequest converts a remote activitystreams `follow` representation into gts model follow. -	ASFollowToFollow(ctx context.Context, followable ap.Followable) (*gtsmodel.Follow, error) -	// ASLikeToFave converts a remote activitystreams 'like' representation into a gts model status fave. -	ASLikeToFave(ctx context.Context, likeable ap.Likeable) (*gtsmodel.StatusFave, error) -	// ASBlockToBlock converts a remote activity streams 'block' representation into a gts model block. -	ASBlockToBlock(ctx context.Context, blockable ap.Blockable) (*gtsmodel.Block, error) -	// 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. -	ASAnnounceToStatus(ctx context.Context, announceable ap.Announceable) (status *gtsmodel.Status, new bool, err error) -	// ASFlagToReport converts a remote activitystreams 'flag' representation into a gts model report. -	ASFlagToReport(ctx context.Context, flaggable ap.Flaggable) (report *gtsmodel.Report, err error) - -	/* -		INTERNAL (gts) MODEL TO ACTIVITYSTREAMS MODEL -	*/ - -	// AccountToAS converts a gts model account into an activity streams person, suitable for federation -	AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) -	// 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). -	AccountToASMinimal(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) -	// StatusToAS converts a gts model status into an activity streams note, suitable for federation -	StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.ActivityStreamsNote, error) -	// 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) -	// FollowToASFollow converts a gts model Follow into an activity streams Follow, suitable for federation -	FollowToAS(ctx context.Context, f *gtsmodel.Follow) (vocab.ActivityStreamsFollow, error) -	// MentionToAS converts a gts model mention into an activity streams Mention, suitable for federation -	MentionToAS(ctx context.Context, m *gtsmodel.Mention) (vocab.ActivityStreamsMention, error) -	// EmojiToAS converts a gts emoji into a mastodon ns Emoji, suitable for federation -	EmojiToAS(ctx context.Context, e *gtsmodel.Emoji) (vocab.TootEmoji, error) -	// TagToAS converts a gts model tag into a toot Hashtag, suitable for federation. -	TagToAS(ctx context.Context, t *gtsmodel.Tag) (vocab.TootHashtag, error) -	// AttachmentToAS converts a gts model media attachment into an activity streams Attachment, suitable for federation -	AttachmentToAS(ctx context.Context, a *gtsmodel.MediaAttachment) (vocab.ActivityStreamsDocument, error) -	// FaveToAS converts a gts model status fave into an activityStreams LIKE, suitable for federation. -	FaveToAS(ctx context.Context, f *gtsmodel.StatusFave) (vocab.ActivityStreamsLike, error) -	// BoostToAS converts a gts model boost into an activityStreams ANNOUNCE, suitable for federation -	BoostToAS(ctx context.Context, boostWrapperStatus *gtsmodel.Status, boostingAccount *gtsmodel.Account, boostedAccount *gtsmodel.Account) (vocab.ActivityStreamsAnnounce, error) -	// BlockToAS converts a gts model block into an activityStreams BLOCK, suitable for federation. -	BlockToAS(ctx context.Context, block *gtsmodel.Block) (vocab.ActivityStreamsBlock, error) -	// StatusToASRepliesCollection converts a gts model status into an activityStreams REPLIES collection. -	StatusToASRepliesCollection(ctx context.Context, status *gtsmodel.Status, onlyOtherAccounts bool) (vocab.ActivityStreamsCollection, error) -	// StatusURIsToASRepliesPage returns a collection page with appropriate next/part of pagination. -	StatusURIsToASRepliesPage(ctx context.Context, status *gtsmodel.Status, onlyOtherAccounts bool, minID string, replies map[string]*url.URL) (vocab.ActivityStreamsCollectionPage, error) -	// 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) -	// 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) -	// ReportToASFlag converts a gts model report into an activitystreams FLAG, suitable for federation. -	ReportToASFlag(ctx context.Context, r *gtsmodel.Report) (vocab.ActivityStreamsFlag, error) - -	/* -		INTERNAL (gts) MODEL TO INTERNAL MODEL -	*/ - -	// FollowRequestToFollow just converts a follow request into a follow, that's it! No bells and whistles. -	FollowRequestToFollow(ctx context.Context, f *gtsmodel.FollowRequest) *gtsmodel.Follow -	// StatusToBoost wraps the given status into a boosting status. -	StatusToBoost(ctx context.Context, s *gtsmodel.Status, boostingAccount *gtsmodel.Account) (*gtsmodel.Status, error) - -	/* -		WRAPPER CONVENIENCE FUNCTIONS -	*/ - -	// WrapPersonInUpdate -	WrapPersonInUpdate(person vocab.ActivityStreamsPerson, originAccount *gtsmodel.Account) (vocab.ActivityStreamsUpdate, error) -	// 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) -} - -type converter struct { -	db             db.DB +type Converter struct { +	state          *state.State  	defaultAvatars []string  	randAvatars    sync.Map  } -// NewConverter returns a new Converter -func NewConverter(db db.DB) TypeConverter { -	return &converter{ -		db:             db, +func NewConverter(state *state.State) *Converter { +	return &Converter{ +		state:          state,  		defaultAvatars: populateDefaultAvatars(),  	}  } diff --git a/internal/typeutils/converter_test.go b/internal/typeutils/converter_test.go index a91e6a157..74b213431 100644 --- a/internal/typeutils/converter_test.go +++ b/internal/typeutils/converter_test.go @@ -481,7 +481,7 @@ type TypeUtilsTestSuite struct {  	testReports     map[string]*gtsmodel.Report  	testMentions    map[string]*gtsmodel.Mention -	typeconverter typeutils.TypeConverter +	typeconverter *typeutils.Converter  }  func (suite *TypeUtilsTestSuite) SetupTest() { @@ -502,7 +502,7 @@ func (suite *TypeUtilsTestSuite) SetupTest() {  	suite.testEmojis = testrig.NewTestEmojis()  	suite.testReports = testrig.NewTestReports()  	suite.testMentions = testrig.NewTestMentions() -	suite.typeconverter = typeutils.NewConverter(suite.db) +	suite.typeconverter = typeutils.NewConverter(&suite.state)  	testrig.StandardDBSetup(suite.db, nil)  } @@ -519,7 +519,7 @@ func (suite *TypeUtilsTestSuite) GetProcessor() *processing.Processor {  	testrig.StartTimelines(  		&suite.state,  		visibility.NewFilter(&suite.state), -		testrig.NewTestTypeConverter(suite.db), +		suite.typeconverter,  	)  	httpClient := testrig.NewMockHTTPClient(nil, "../../testrig/media") diff --git a/internal/typeutils/defaulticons.go b/internal/typeutils/defaulticons.go index eb7cca88c..bcb7b8c10 100644 --- a/internal/typeutils/defaulticons.go +++ b/internal/typeutils/defaulticons.go @@ -96,7 +96,7 @@ func populateDefaultAvatars() (defaultAvatars []string) {  //  // If there are no default avatars available, this function is a  // no-op. -func (c *converter) ensureAvatar(account *apimodel.Account) { +func (c *Converter) ensureAvatar(account *apimodel.Account) {  	if (account.Avatar != "" && account.AvatarStatic != "") || len(c.defaultAvatars) == 0 {  		return  	} @@ -126,7 +126,7 @@ func (c *converter) ensureAvatar(account *apimodel.Account) {  //  // If a value for the header URL is already set, this function is  // a no-op. -func (c *converter) ensureHeader(account *apimodel.Account) { +func (c *Converter) ensureHeader(account *apimodel.Account) {  	if account.Header != "" && account.HeaderStatic != "" {  		return  	} diff --git a/internal/typeutils/internal.go b/internal/typeutils/internal.go index 831aad63e..1824a4421 100644 --- a/internal/typeutils/internal.go +++ b/internal/typeutils/internal.go @@ -26,7 +26,8 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/uris"  ) -func (c *converter) FollowRequestToFollow(ctx context.Context, f *gtsmodel.FollowRequest) *gtsmodel.Follow { +// FollowRequestToFollow just converts a follow request into a follow, that's it! No bells and whistles. +func (c *Converter) FollowRequestToFollow(ctx context.Context, f *gtsmodel.FollowRequest) *gtsmodel.Follow {  	showReblogs := *f.ShowReblogs  	notify := *f.Notify  	return >smodel.Follow{ @@ -41,7 +42,8 @@ func (c *converter) FollowRequestToFollow(ctx context.Context, f *gtsmodel.Follo  	}  } -func (c *converter) StatusToBoost(ctx context.Context, s *gtsmodel.Status, boostingAccount *gtsmodel.Account) (*gtsmodel.Status, error) { +// StatusToBoost wraps the given status into a boosting status. +func (c *Converter) StatusToBoost(ctx context.Context, s *gtsmodel.Status, boostingAccount *gtsmodel.Account) (*gtsmodel.Status, error) {  	// the wrapper won't use the same ID as the boosted status so we generate some new UUIDs  	accountURIs := uris.GenerateURIsForAccount(boostingAccount.Username)  	boostWrapperStatusID := id.NewULID() diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go index 9404e2ec7..d82fe8e04 100644 --- a/internal/typeutils/internaltoas.go +++ b/internal/typeutils/internaltoas.go @@ -37,8 +37,8 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/uris"  ) -// Converts a gts model account into an Activity Streams person type. -func (c *converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) { +// AccountToAS converts a gts model account into an activity streams person, suitable for federation +func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) {  	person := streams.NewActivityStreamsPerson()  	// id should be the activitypub URI of this user @@ -220,7 +220,7 @@ func (c *converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab  	if len(a.EmojiIDs) > len(emojis) {  		emojis = []*gtsmodel.Emoji{}  		for _, emojiID := range a.EmojiIDs { -			emoji, err := c.db.GetEmojiByID(ctx, emojiID) +			emoji, err := c.state.DB.GetEmojiByID(ctx, emojiID)  			if err != nil {  				return nil, fmt.Errorf("AccountToAS: error getting emoji %s from database: %s", emojiID, err)  			} @@ -269,7 +269,7 @@ func (c *converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab  	// Used as profile avatar.  	if a.AvatarMediaAttachmentID != "" {  		if a.AvatarMediaAttachment == nil { -			avatar, err := c.db.GetAttachmentByID(ctx, a.AvatarMediaAttachmentID) +			avatar, err := c.state.DB.GetAttachmentByID(ctx, a.AvatarMediaAttachmentID)  			if err == nil {  				a.AvatarMediaAttachment = avatar  			} else { @@ -303,7 +303,7 @@ func (c *converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab  	// Used as profile header.  	if a.HeaderMediaAttachmentID != "" {  		if a.HeaderMediaAttachment == nil { -			header, err := c.db.GetAttachmentByID(ctx, a.HeaderMediaAttachmentID) +			header, err := c.state.DB.GetAttachmentByID(ctx, a.HeaderMediaAttachmentID)  			if err == nil {  				a.HeaderMediaAttachment = header  			} else { @@ -336,10 +336,12 @@ func (c *converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab  	return person, nil  } -// Converts a gts model account into a VERY MINIMAL Activity Streams person type. +// 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. -func (c *converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) { +// 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). +func (c *Converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) {  	person := streams.NewActivityStreamsPerson()  	// id should be the activitypub URI of this user @@ -401,13 +403,14 @@ func (c *converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account)  	return person, nil  } -func (c *converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.ActivityStreamsNote, error) { +// StatusToAS converts a gts model status into an activity streams note, suitable for federation +func (c *Converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.ActivityStreamsNote, error) {  	// ensure prerequisites here before we get stuck in  	// check if author account is already attached to status and attach it if not  	// if we can't retrieve this, bail here already because we can't attribute the status to anyone  	if s.Account == nil { -		a, err := c.db.GetAccountByID(ctx, s.AccountID) +		a, err := c.state.DB.GetAccountByID(ctx, s.AccountID)  		if err != nil {  			return nil, gtserror.Newf("error retrieving author account from db: %w", err)  		} @@ -478,7 +481,7 @@ func (c *converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.A  	// tag -- mentions  	mentions := s.Mentions  	if len(s.MentionIDs) > len(mentions) { -		mentions, err = c.db.GetMentions(ctx, s.MentionIDs) +		mentions, err = c.state.DB.GetMentions(ctx, s.MentionIDs)  		if err != nil {  			return nil, gtserror.Newf("error getting mentions: %w", err)  		} @@ -496,7 +499,7 @@ func (c *converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.A  	if len(s.EmojiIDs) > len(emojis) {  		emojis = []*gtsmodel.Emoji{}  		for _, emojiID := range s.EmojiIDs { -			emoji, err := c.db.GetEmojiByID(ctx, emojiID) +			emoji, err := c.state.DB.GetEmojiByID(ctx, emojiID)  			if err != nil {  				return nil, gtserror.Newf("error getting emoji %s from database: %w", emojiID, err)  			} @@ -514,7 +517,7 @@ func (c *converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.A  	// tag -- hashtags  	hashtags := s.Tags  	if len(s.TagIDs) > len(hashtags) { -		hashtags, err = c.db.GetTags(ctx, s.TagIDs) +		hashtags, err = c.state.DB.GetTags(ctx, s.TagIDs)  		if err != nil {  			return nil, gtserror.Newf("error getting tags: %w", err)  		} @@ -605,7 +608,7 @@ func (c *converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.A  	if len(s.AttachmentIDs) > len(attachments) {  		attachments = []*gtsmodel.MediaAttachment{}  		for _, attachmentID := range s.AttachmentIDs { -			attachment, err := c.db.GetAttachmentByID(ctx, attachmentID) +			attachment, err := c.state.DB.GetAttachmentByID(ctx, attachmentID)  			if err != nil {  				return nil, gtserror.Newf("error getting attachment %s from database: %w", attachmentID, err)  			} @@ -639,13 +642,15 @@ func (c *converter) StatusToAS(ctx context.Context, s *gtsmodel.Status) (vocab.A  	return status, nil  } -func (c *converter) StatusToASDelete(ctx context.Context, s *gtsmodel.Status) (vocab.ActivityStreamsDelete, error) { +// 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. +func (c *Converter) StatusToASDelete(ctx context.Context, s *gtsmodel.Status) (vocab.ActivityStreamsDelete, error) {  	// Parse / fetch some information  	// we need to create the Delete.  	if s.Account == nil {  		var err error -		s.Account, err = c.db.GetAccountByID(ctx, s.AccountID) +		s.Account, err = c.state.DB.GetAccountByID(ctx, s.AccountID)  		if err != nil {  			return nil, fmt.Errorf("StatusToASDelete: error retrieving author account from db: %w", err)  		} @@ -717,7 +722,7 @@ func (c *converter) StatusToASDelete(ctx context.Context, s *gtsmodel.Status) (v  	// Ensure mentions are populated.  	mentions := s.Mentions  	if len(s.MentionIDs) > len(mentions) { -		mentions, err = c.db.GetMentions(ctx, s.MentionIDs) +		mentions, err = c.state.DB.GetMentions(ctx, s.MentionIDs)  		if err != nil {  			return nil, fmt.Errorf("StatusToASDelete: error getting mentions: %w", err)  		} @@ -752,7 +757,7 @@ func (c *converter) StatusToASDelete(ctx context.Context, s *gtsmodel.Status) (v  			// Only address to this account if it  			// wasn't already included as a mention.  			if s.InReplyToAccount == nil { -				s.InReplyToAccount, err = c.db.GetAccountByID(ctx, s.InReplyToAccountID) +				s.InReplyToAccount, err = c.state.DB.GetAccountByID(ctx, s.InReplyToAccountID)  				if err != nil && !errors.Is(err, db.ErrNoEntries) {  					return nil, fmt.Errorf("StatusToASDelete: db error getting account %s: %w", s.InReplyToAccountID, err)  				} @@ -774,8 +779,9 @@ func (c *converter) StatusToASDelete(ctx context.Context, s *gtsmodel.Status) (v  	return delete, nil  } -func (c *converter) FollowToAS(ctx context.Context, f *gtsmodel.Follow) (vocab.ActivityStreamsFollow, error) { -	if err := c.db.PopulateFollow(ctx, f); err != nil { +// FollowToASFollow converts a gts model Follow into an activity streams Follow, suitable for federation +func (c *Converter) FollowToAS(ctx context.Context, f *gtsmodel.Follow) (vocab.ActivityStreamsFollow, error) { +	if err := c.state.DB.PopulateFollow(ctx, f); err != nil {  		return nil, gtserror.Newf("error populating follow: %w", err)  	} @@ -824,9 +830,10 @@ func (c *converter) FollowToAS(ctx context.Context, f *gtsmodel.Follow) (vocab.A  	return follow, nil  } -func (c *converter) MentionToAS(ctx context.Context, m *gtsmodel.Mention) (vocab.ActivityStreamsMention, error) { +// MentionToAS converts a gts model mention into an activity streams Mention, suitable for federation +func (c *Converter) MentionToAS(ctx context.Context, m *gtsmodel.Mention) (vocab.ActivityStreamsMention, error) {  	if m.TargetAccount == nil { -		a, err := c.db.GetAccountByID(ctx, m.TargetAccountID) +		a, err := c.state.DB.GetAccountByID(ctx, m.TargetAccountID)  		if err != nil {  			return nil, fmt.Errorf("MentionToAS: error getting target account from db: %s", err)  		} @@ -865,7 +872,8 @@ func (c *converter) MentionToAS(ctx context.Context, m *gtsmodel.Mention) (vocab  	return mention, nil  } -func (c *converter) TagToAS(ctx context.Context, t *gtsmodel.Tag) (vocab.TootHashtag, error) { +// TagToAS converts a gts model tag into a toot Hashtag, suitable for federation. +func (c *Converter) TagToAS(ctx context.Context, t *gtsmodel.Tag) (vocab.TootHashtag, error) {  	// This is probably already lowercase,  	// but let's err on the safe side.  	nameLower := strings.ToLower(t.Name) @@ -891,20 +899,20 @@ func (c *converter) TagToAS(ctx context.Context, t *gtsmodel.Tag) (vocab.TootHas  	return tag, nil  } -/* -	 we're making something like this: -		{ -			"id": "https://example.com/emoji/123", -			"type": "Emoji", -			"name": ":kappa:", -			"icon": { -				"type": "Image", -				"mediaType": "image/png", -				"url": "https://example.com/files/kappa.png" -			} -		} -*/ -func (c *converter) EmojiToAS(ctx context.Context, e *gtsmodel.Emoji) (vocab.TootEmoji, error) { +// EmojiToAS converts a gts emoji into a mastodon ns Emoji, suitable for federation. +// we're making something like this: +// +//	{ +//		"id": "https://example.com/emoji/123", +//		"type": "Emoji", +//		"name": ":kappa:", +//		"icon": { +//			"type": "Image", +//			"mediaType": "image/png", +//			"url": "https://example.com/files/kappa.png" +//		} +//	} +func (c *Converter) EmojiToAS(ctx context.Context, e *gtsmodel.Emoji) (vocab.TootEmoji, error) {  	// create the emoji  	emoji := streams.NewTootEmoji() @@ -947,7 +955,8 @@ func (c *converter) EmojiToAS(ctx context.Context, e *gtsmodel.Emoji) (vocab.Too  	return emoji, nil  } -func (c *converter) AttachmentToAS(ctx context.Context, a *gtsmodel.MediaAttachment) (vocab.ActivityStreamsDocument, error) { +// AttachmentToAS converts a gts model media attachment into an activity streams Attachment, suitable for federation +func (c *Converter) AttachmentToAS(ctx context.Context, a *gtsmodel.MediaAttachment) (vocab.ActivityStreamsDocument, error) {  	// type -- Document  	doc := streams.NewActivityStreamsDocument() @@ -981,21 +990,20 @@ func (c *converter) AttachmentToAS(ctx context.Context, a *gtsmodel.MediaAttachm  	return doc, nil  } -/* -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" -} -*/ -func (c *converter) FaveToAS(ctx context.Context, f *gtsmodel.StatusFave) (vocab.ActivityStreamsLike, error) { +// 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" +// } +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.db.GetStatusByID(ctx, f.StatusID) +		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)  		} @@ -1004,7 +1012,7 @@ func (c *converter) FaveToAS(ctx context.Context, f *gtsmodel.StatusFave) (vocab  	// check if the targetAccount is already pinned to this fave, and fetch it if not  	if f.TargetAccount == nil { -		a, err := c.db.GetAccountByID(ctx, f.TargetAccountID) +		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)  		} @@ -1013,7 +1021,7 @@ func (c *converter) FaveToAS(ctx context.Context, f *gtsmodel.StatusFave) (vocab  	// check if the faving account is already pinned to this fave, and fetch it if not  	if f.Account == nil { -		a, err := c.db.GetAccountByID(ctx, f.AccountID) +		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)  		} @@ -1062,10 +1070,11 @@ func (c *converter) FaveToAS(ctx context.Context, f *gtsmodel.StatusFave) (vocab  	return like, nil  } -func (c *converter) BoostToAS(ctx context.Context, boostWrapperStatus *gtsmodel.Status, boostingAccount *gtsmodel.Account, boostedAccount *gtsmodel.Account) (vocab.ActivityStreamsAnnounce, error) { +// 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.db.GetStatusByID(ctx, boostWrapperStatus.BoostOfID) +		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)  		} @@ -1139,20 +1148,19 @@ func (c *converter) BoostToAS(ctx context.Context, boostWrapperStatus *gtsmodel.  	return announce, nil  } -/* -we want to end up with something like this: - -	{ -		"@context": "https://www.w3.org/ns/activitystreams", -		"actor": "https://example.org/users/some_user", -		"id":"https://example.org/users/some_user/blocks/SOME_ULID_OF_A_BLOCK", -		"object":"https://some_other.instance/users/some_other_user", -		"type":"Block" -	} -*/ -func (c *converter) BlockToAS(ctx context.Context, b *gtsmodel.Block) (vocab.ActivityStreamsBlock, error) { +// BlockToAS converts a gts model block into an activityStreams BLOCK, suitable for federation. +// we want to end up with something like this: +// +//	{ +//		"@context": "https://www.w3.org/ns/activitystreams", +//		"actor": "https://example.org/users/some_user", +//		"id":"https://example.org/users/some_user/blocks/SOME_ULID_OF_A_BLOCK", +//		"object":"https://some_other.instance/users/some_other_user", +//		"type":"Block" +//	} +func (c *Converter) BlockToAS(ctx context.Context, b *gtsmodel.Block) (vocab.ActivityStreamsBlock, error) {  	if b.Account == nil { -		a, err := c.db.GetAccountByID(ctx, b.AccountID) +		a, err := c.state.DB.GetAccountByID(ctx, b.AccountID)  		if err != nil {  			return nil, fmt.Errorf("BlockToAS: error getting block owner account from database: %s", err)  		} @@ -1160,7 +1168,7 @@ func (c *converter) BlockToAS(ctx context.Context, b *gtsmodel.Block) (vocab.Act  	}  	if b.TargetAccount == nil { -		a, err := c.db.GetAccountByID(ctx, b.TargetAccountID) +		a, err := c.state.DB.GetAccountByID(ctx, b.TargetAccountID)  		if err != nil {  			return nil, fmt.Errorf("BlockToAS: error getting block target account from database: %s", err)  		} @@ -1209,23 +1217,22 @@ func (c *converter) BlockToAS(ctx context.Context, b *gtsmodel.Block) (vocab.Act  	return block, nil  } -/* -the goal is to end up with something like this: - -	{ -		"@context": "https://www.w3.org/ns/activitystreams", -		"id": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies", -		"type": "Collection", -		"first": { -		"id": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies?page=true", -		"type": "CollectionPage", -		"next": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies?only_other_accounts=true&page=true", -		"partOf": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies", -		"items": [] -		} -	} -*/ -func (c *converter) StatusToASRepliesCollection(ctx context.Context, status *gtsmodel.Status, onlyOtherAccounts bool) (vocab.ActivityStreamsCollection, error) { +// StatusToASRepliesCollection converts a gts model status into an activityStreams REPLIES collection. +// the goal is to end up with something like this: +// +//	{ +//		"@context": "https://www.w3.org/ns/activitystreams", +//		"id": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies", +//		"type": "Collection", +//		"first": { +//		"id": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies?page=true", +//		"type": "CollectionPage", +//		"next": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies?only_other_accounts=true&page=true", +//		"partOf": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies", +//		"items": [] +//		} +//	} +func (c *Converter) StatusToASRepliesCollection(ctx context.Context, status *gtsmodel.Status, onlyOtherAccounts bool) (vocab.ActivityStreamsCollection, error) {  	collectionID := fmt.Sprintf("%s/replies", status.URI)  	collectionIDURI, err := url.Parse(collectionID)  	if err != nil { @@ -1274,22 +1281,21 @@ func (c *converter) StatusToASRepliesCollection(ctx context.Context, status *gts  	return collection, nil  } -/* -the goal is to end up with something like this: - -	{ -		"@context": "https://www.w3.org/ns/activitystreams", -		"id": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies?only_other_accounts=true&page=true", -		"type": "CollectionPage", -		"next": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies?min_id=106720870266901180&only_other_accounts=true&page=true", -		"partOf": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies", -		"items": [ -			"https://example.com/users/someone/statuses/106720752853216226", -			"https://somewhere.online/users/eeeeeeeeeep/statuses/106720870163727231" -		] -	} -*/ -func (c *converter) StatusURIsToASRepliesPage(ctx context.Context, status *gtsmodel.Status, onlyOtherAccounts bool, minID string, replies map[string]*url.URL) (vocab.ActivityStreamsCollectionPage, error) { +// StatusURIsToASRepliesPage returns a collection page with appropriate next/part of pagination. +// the goal is to end up with something like this: +// +//	{ +//		"@context": "https://www.w3.org/ns/activitystreams", +//		"id": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies?only_other_accounts=true&page=true", +//		"type": "CollectionPage", +//		"next": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies?min_id=106720870266901180&only_other_accounts=true&page=true", +//		"partOf": "https://example.org/users/whatever/statuses/01FCNEXAGAKPEX1J7VJRPJP490/replies", +//		"items": [ +//			"https://example.com/users/someone/statuses/106720752853216226", +//			"https://somewhere.online/users/eeeeeeeeeep/statuses/106720870163727231" +//		] +//	} +func (c *Converter) StatusURIsToASRepliesPage(ctx context.Context, status *gtsmodel.Status, onlyOtherAccounts bool, minID string, replies map[string]*url.URL) (vocab.ActivityStreamsCollectionPage, error) {  	collectionID := fmt.Sprintf("%s/replies", status.URI)  	page := streams.NewActivityStreamsCollectionPage() @@ -1345,31 +1351,37 @@ func (c *converter) StatusURIsToASRepliesPage(ctx context.Context, status *gtsmo  	return page, nil  } -/* -the goal is to end up with something like this: - -	{ -		"id": "https://example.org/users/whatever/outbox?page=true", -		"type": "OrderedCollectionPage", -		"next": "https://example.org/users/whatever/outbox?max_id=01FJC1Q0E3SSQR59TD2M1KP4V8&page=true", -		"prev": "https://example.org/users/whatever/outbox?min_id=01FJC1Q0E3SSQR59TD2M1KP4V8&page=true", -		"partOf": "https://example.org/users/whatever/outbox", -		"orderedItems": [ -			"id": "https://example.org/users/whatever/statuses/01FJC1MKPVX2VMWP2ST93Q90K7/activity", -			"type": "Create", -			"actor": "https://example.org/users/whatever", -			"published": "2021-10-18T20:06:18Z", -			"to": [ -				"https://www.w3.org/ns/activitystreams#Public" -			], -			"cc": [ -				"https://example.org/users/whatever/followers" -			], -			"object": "https://example.org/users/whatever/statuses/01FJC1MKPVX2VMWP2ST93Q90K7" -		] -	} -*/ -func (c *converter) StatusesToASOutboxPage(ctx context.Context, outboxID string, maxID string, minID string, statuses []*gtsmodel.Status) (vocab.ActivityStreamsOrderedCollectionPage, 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. +// the goal is to end up with something like this: +// +//	{ +//		"id": "https://example.org/users/whatever/outbox?page=true", +//		"type": "OrderedCollectionPage", +//		"next": "https://example.org/users/whatever/outbox?max_id=01FJC1Q0E3SSQR59TD2M1KP4V8&page=true", +//		"prev": "https://example.org/users/whatever/outbox?min_id=01FJC1Q0E3SSQR59TD2M1KP4V8&page=true", +//		"partOf": "https://example.org/users/whatever/outbox", +//		"orderedItems": [ +//			"id": "https://example.org/users/whatever/statuses/01FJC1MKPVX2VMWP2ST93Q90K7/activity", +//			"type": "Create", +//			"actor": "https://example.org/users/whatever", +//			"published": "2021-10-18T20:06:18Z", +//			"to": [ +//				"https://www.w3.org/ns/activitystreams#Public" +//			], +//			"cc": [ +//				"https://example.org/users/whatever/followers" +//			], +//			"object": "https://example.org/users/whatever/statuses/01FJC1MKPVX2VMWP2ST93Q90K7" +//		] +//	} +func (c *Converter) StatusesToASOutboxPage(ctx context.Context, outboxID string, maxID string, minID string, statuses []*gtsmodel.Status) (vocab.ActivityStreamsOrderedCollectionPage, error) {  	page := streams.NewActivityStreamsOrderedCollectionPage()  	// .id @@ -1450,17 +1462,17 @@ func (c *converter) StatusesToASOutboxPage(ctx context.Context, outboxID string,  	return page, nil  } -/* -we want something that looks like this: - -	{ -		"@context": "https://www.w3.org/ns/activitystreams", -		"id": "https://example.org/users/whatever/outbox", -		"type": "OrderedCollection", -		"first": "https://example.org/users/whatever/outbox?page=true" -	} -*/ -func (c *converter) OutboxToASCollection(ctx context.Context, outboxID string) (vocab.ActivityStreamsOrderedCollection, error) { +// 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. +// we want something that looks like this: +// +//	{ +//		"@context": "https://www.w3.org/ns/activitystreams", +//		"id": "https://example.org/users/whatever/outbox", +//		"type": "OrderedCollection", +//		"first": "https://example.org/users/whatever/outbox?page=true" +//	} +func (c *Converter) OutboxToASCollection(ctx context.Context, outboxID string) (vocab.ActivityStreamsOrderedCollection, error) {  	collection := streams.NewActivityStreamsOrderedCollection()  	collectionIDProp := streams.NewJSONLDIdProperty() @@ -1483,7 +1495,9 @@ func (c *converter) OutboxToASCollection(ctx context.Context, outboxID string) (  	return collection, nil  } -func (c *converter) StatusesToASFeaturedCollection(ctx context.Context, featuredCollectionID string, statuses []*gtsmodel.Status) (vocab.ActivityStreamsOrderedCollection, error) { +// StatusesToASFeaturedCollection converts a slice of statuses into an ordered collection +// of URIs, suitable for serializing and serving via the activitypub API. +func (c *Converter) StatusesToASFeaturedCollection(ctx context.Context, featuredCollectionID string, statuses []*gtsmodel.Status) (vocab.ActivityStreamsOrderedCollection, error) {  	collection := streams.NewActivityStreamsOrderedCollection()  	collectionIDProp := streams.NewJSONLDIdProperty() @@ -1511,7 +1525,8 @@ func (c *converter) StatusesToASFeaturedCollection(ctx context.Context, featured  	return collection, nil  } -func (c *converter) ReportToASFlag(ctx context.Context, r *gtsmodel.Report) (vocab.ActivityStreamsFlag, error) { +// ReportToASFlag converts a gts model report into an activitystreams FLAG, suitable for federation. +func (c *Converter) ReportToASFlag(ctx context.Context, r *gtsmodel.Report) (vocab.ActivityStreamsFlag, error) {  	flag := streams.NewActivityStreamsFlag()  	flagIDProp := streams.NewJSONLDIdProperty() @@ -1524,7 +1539,7 @@ func (c *converter) ReportToASFlag(ctx context.Context, r *gtsmodel.Report) (voc  	// for privacy, set the actor as the INSTANCE ACTOR,  	// not as the actor who created the report -	instanceAccount, err := c.db.GetInstanceAccount(ctx, "") +	instanceAccount, err := c.state.DB.GetInstanceAccount(ctx, "")  	if err != nil {  		return nil, fmt.Errorf("error getting instance account: %w", err)  	} diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index 11838e2bd..155863e34 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -58,7 +58,10 @@ func toMastodonVersion(in string) string {  	return instanceMastodonVersion + "+" + strings.ReplaceAll(in, " ", "-")  } -func (c *converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmodel.Account) (*apimodel.Account, error) { +// AppToAPIAppSensitive takes a db model application as a param, and returns a populated apitype application, or an error +// 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. +func (c *Converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmodel.Account) (*apimodel.Account, error) {  	// we can build this sensitive account easily by first getting the public account....  	apiAccount, err := c.AccountToAPIAccountPublic(ctx, a)  	if err != nil { @@ -68,7 +71,7 @@ func (c *converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmode  	// then adding the Source object to it...  	// check pending follow requests aimed at this account -	frc, err := c.db.CountAccountFollowRequests(ctx, a.ID) +	frc, err := c.state.DB.CountAccountFollowRequests(ctx, a.ID)  	if err != nil {  		return nil, fmt.Errorf("error counting follow requests: %s", err)  	} @@ -91,8 +94,11 @@ func (c *converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmode  	return apiAccount, nil  } -func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.Account) (*apimodel.Account, error) { -	if err := c.db.PopulateAccount(ctx, a); err != nil { +// AccountToAPIAccountPublic takes a db model account as a param, and returns a populated apitype account, or an error +// 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. +func (c *Converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.Account) (*apimodel.Account, error) { +	if err := c.state.DB.PopulateAccount(ctx, a); err != nil {  		log.Errorf(ctx, "error(s) populating account, will continue: %s", err)  	} @@ -102,23 +108,23 @@ func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A  	//   - Statuses count  	//   - Last status time -	followersCount, err := c.db.CountAccountFollowers(ctx, a.ID) +	followersCount, err := c.state.DB.CountAccountFollowers(ctx, a.ID)  	if err != nil && !errors.Is(err, db.ErrNoEntries) {  		return nil, fmt.Errorf("AccountToAPIAccountPublic: error counting followers: %w", err)  	} -	followingCount, err := c.db.CountAccountFollows(ctx, a.ID) +	followingCount, err := c.state.DB.CountAccountFollows(ctx, a.ID)  	if err != nil && !errors.Is(err, db.ErrNoEntries) {  		return nil, fmt.Errorf("AccountToAPIAccountPublic: error counting following: %w", err)  	} -	statusesCount, err := c.db.CountAccountStatuses(ctx, a.ID) +	statusesCount, err := c.state.DB.CountAccountStatuses(ctx, a.ID)  	if err != nil && !errors.Is(err, db.ErrNoEntries) {  		return nil, fmt.Errorf("AccountToAPIAccountPublic: error counting statuses: %w", err)  	}  	var lastStatusAt *string -	lastPosted, err := c.db.GetAccountLastPosted(ctx, a.ID, false) +	lastPosted, err := c.state.DB.GetAccountLastPosted(ctx, a.ID, false)  	if err != nil && !errors.Is(err, db.ErrNoEntries) {  		return nil, fmt.Errorf("AccountToAPIAccountPublic: error counting statuses: %w", err)  	} @@ -182,7 +188,7 @@ func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A  		// fetch more info. Skip for instance  		// accounts since they have no user.  		if !a.IsInstance() { -			user, err := c.db.GetUserByAccountID(ctx, a.ID) +			user, err := c.state.DB.GetUserByAccountID(ctx, a.ID)  			if err != nil {  				return nil, fmt.Errorf("AccountToAPIAccountPublic: error getting user from database for account id %s: %w", a.ID, err)  			} @@ -238,7 +244,7 @@ func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A  	return accountFrontend, nil  } -func (c *converter) fieldsToAPIFields(f []*gtsmodel.Field) []apimodel.Field { +func (c *Converter) fieldsToAPIFields(f []*gtsmodel.Field) []apimodel.Field {  	fields := make([]apimodel.Field, len(f))  	for i, field := range f { @@ -257,7 +263,10 @@ func (c *converter) fieldsToAPIFields(f []*gtsmodel.Field) []apimodel.Field {  	return fields  } -func (c *converter) AccountToAPIAccountBlocked(ctx context.Context, a *gtsmodel.Account) (*apimodel.Account, error) { +// AccountToAPIAccountBlocked takes a db model account as a param, and returns a apitype account, or an error if +// 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. +func (c *Converter) AccountToAPIAccountBlocked(ctx context.Context, a *gtsmodel.Account) (*apimodel.Account, error) {  	var (  		acct string  		role *apimodel.AccountRole @@ -277,7 +286,7 @@ func (c *converter) AccountToAPIAccountBlocked(ctx context.Context, a *gtsmodel.  		// fetch more info. Skip for instance  		// accounts since they have no user.  		if !a.IsInstance() { -			user, err := c.db.GetUserByAccountID(ctx, a.ID) +			user, err := c.state.DB.GetUserByAccountID(ctx, a.ID)  			if err != nil {  				return nil, fmt.Errorf("AccountToAPIAccountPublic: error getting user from database for account id %s: %w", a.ID, err)  			} @@ -308,7 +317,7 @@ func (c *converter) AccountToAPIAccountBlocked(ctx context.Context, a *gtsmodel.  	}, nil  } -func (c *converter) AccountToAdminAPIAccount(ctx context.Context, a *gtsmodel.Account) (*apimodel.AdminAccountInfo, error) { +func (c *Converter) AccountToAdminAPIAccount(ctx context.Context, a *gtsmodel.Account) (*apimodel.AdminAccountInfo, error) {  	var (  		email                  string  		ip                     *string @@ -334,7 +343,7 @@ func (c *converter) AccountToAdminAPIAccount(ctx context.Context, a *gtsmodel.Ac  	} else if !a.IsInstance() {  		// This is a local, non-instance  		// acct; we can fetch more info. -		user, err := c.db.GetUserByAccountID(ctx, a.ID) +		user, err := c.state.DB.GetUserByAccountID(ctx, a.ID)  		if err != nil {  			return nil, fmt.Errorf("AccountToAdminAPIAccount: error getting user from database for account id %s: %w", a.ID, err)  		} @@ -393,7 +402,7 @@ func (c *converter) AccountToAdminAPIAccount(ctx context.Context, a *gtsmodel.Ac  	}, nil  } -func (c *converter) AppToAPIAppSensitive(ctx context.Context, a *gtsmodel.Application) (*apimodel.Application, error) { +func (c *Converter) AppToAPIAppSensitive(ctx context.Context, a *gtsmodel.Application) (*apimodel.Application, error) {  	return &apimodel.Application{  		ID:           a.ID,  		Name:         a.Name, @@ -404,14 +413,18 @@ func (c *converter) AppToAPIAppSensitive(ctx context.Context, a *gtsmodel.Applic  	}, nil  } -func (c *converter) AppToAPIAppPublic(ctx context.Context, a *gtsmodel.Application) (*apimodel.Application, error) { +// AppToAPIAppPublic takes a db model application as a param, and returns a populated apitype application, or an error +// 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. +func (c *Converter) AppToAPIAppPublic(ctx context.Context, a *gtsmodel.Application) (*apimodel.Application, error) {  	return &apimodel.Application{  		Name:    a.Name,  		Website: a.Website,  	}, nil  } -func (c *converter) AttachmentToAPIAttachment(ctx context.Context, a *gtsmodel.MediaAttachment) (apimodel.Attachment, error) { +// AttachmentToAPIAttachment converts a gts model media attacahment into its api representation for serialization on the API. +func (c *Converter) AttachmentToAPIAttachment(ctx context.Context, a *gtsmodel.MediaAttachment) (apimodel.Attachment, error) {  	apiAttachment := apimodel.Attachment{  		ID:         a.ID,  		Type:       strings.ToLower(string(a.Type)), @@ -479,9 +492,10 @@ func (c *converter) AttachmentToAPIAttachment(ctx context.Context, a *gtsmodel.M  	return apiAttachment, nil  } -func (c *converter) MentionToAPIMention(ctx context.Context, m *gtsmodel.Mention) (apimodel.Mention, error) { +// MentionToAPIMention converts a gts model mention into its api (frontend) representation for serialization on the API. +func (c *Converter) MentionToAPIMention(ctx context.Context, m *gtsmodel.Mention) (apimodel.Mention, error) {  	if m.TargetAccount == nil { -		targetAccount, err := c.db.GetAccountByID(ctx, m.TargetAccountID) +		targetAccount, err := c.state.DB.GetAccountByID(ctx, m.TargetAccountID)  		if err != nil {  			return apimodel.Mention{}, err  		} @@ -511,12 +525,13 @@ func (c *converter) MentionToAPIMention(ctx context.Context, m *gtsmodel.Mention  	}, nil  } -func (c *converter) EmojiToAPIEmoji(ctx context.Context, e *gtsmodel.Emoji) (apimodel.Emoji, error) { +// EmojiToAPIEmoji converts a gts model emoji into its api (frontend) representation for serialization on the API. +func (c *Converter) EmojiToAPIEmoji(ctx context.Context, e *gtsmodel.Emoji) (apimodel.Emoji, error) {  	var category string  	if e.CategoryID != "" {  		if e.Category == nil {  			var err error -			e.Category, err = c.db.GetEmojiCategory(ctx, e.CategoryID) +			e.Category, err = c.state.DB.GetEmojiCategory(ctx, e.CategoryID)  			if err != nil {  				return apimodel.Emoji{}, err  			} @@ -533,7 +548,8 @@ func (c *converter) EmojiToAPIEmoji(ctx context.Context, e *gtsmodel.Emoji) (api  	}, nil  } -func (c *converter) EmojiToAdminAPIEmoji(ctx context.Context, e *gtsmodel.Emoji) (*apimodel.AdminEmoji, error) { +// EmojiToAdminAPIEmoji converts a gts model emoji into an API representation with extra admin information. +func (c *Converter) EmojiToAdminAPIEmoji(ctx context.Context, e *gtsmodel.Emoji) (*apimodel.AdminEmoji, error) {  	emoji, err := c.EmojiToAPIEmoji(ctx, e)  	if err != nil {  		return nil, err @@ -562,14 +578,17 @@ func (c *converter) EmojiToAdminAPIEmoji(ctx context.Context, e *gtsmodel.Emoji)  	}, nil  } -func (c *converter) EmojiCategoryToAPIEmojiCategory(ctx context.Context, category *gtsmodel.EmojiCategory) (*apimodel.EmojiCategory, error) { +// EmojiCategoryToAPIEmojiCategory converts a gts model emoji category into its api (frontend) representation. +func (c *Converter) EmojiCategoryToAPIEmojiCategory(ctx context.Context, category *gtsmodel.EmojiCategory) (*apimodel.EmojiCategory, error) {  	return &apimodel.EmojiCategory{  		ID:   category.ID,  		Name: category.Name,  	}, nil  } -func (c *converter) TagToAPITag(ctx context.Context, t *gtsmodel.Tag, stubHistory bool) (apimodel.Tag, error) { +// TagToAPITag converts a gts model tag into its api (frontend) representation for serialization on the API. +// 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. +func (c *Converter) TagToAPITag(ctx context.Context, t *gtsmodel.Tag, stubHistory bool) (apimodel.Tag, error) {  	return apimodel.Tag{  		Name: strings.ToLower(t.Name),  		URL:  uris.GenerateURIForTag(t.Name), @@ -584,8 +603,11 @@ func (c *converter) TagToAPITag(ctx context.Context, t *gtsmodel.Tag, stubHistor  	}, nil  } -func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*apimodel.Status, error) { -	if err := c.db.PopulateStatus(ctx, s); err != nil { +// StatusToAPIStatus converts a gts model status into its api (frontend) representation for serialization on the API. +// +// Requesting account can be nil. +func (c *Converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*apimodel.Status, error) { +	if err := c.state.DB.PopulateStatus(ctx, s); err != nil {  		// Ensure author account present + correct;  		// can't really go further without this!  		if s.Account == nil { @@ -600,17 +622,17 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r  		return nil, fmt.Errorf("error converting status author: %w", err)  	} -	repliesCount, err := c.db.CountStatusReplies(ctx, s.ID) +	repliesCount, err := c.state.DB.CountStatusReplies(ctx, s.ID)  	if err != nil {  		return nil, fmt.Errorf("error counting replies: %w", err)  	} -	reblogsCount, err := c.db.CountStatusBoosts(ctx, s.ID) +	reblogsCount, err := c.state.DB.CountStatusBoosts(ctx, s.ID)  	if err != nil {  		return nil, fmt.Errorf("error counting reblogs: %w", err)  	} -	favesCount, err := c.db.CountStatusFaves(ctx, s.ID) +	favesCount, err := c.state.DB.CountStatusFaves(ctx, s.ID)  	if err != nil {  		return nil, fmt.Errorf("error counting faves: %w", err)  	} @@ -699,7 +721,7 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r  	}  	if appID := s.CreatedWithApplicationID; appID != "" { -		app, err := c.db.GetApplicationByID(ctx, appID) +		app, err := c.state.DB.GetApplicationByID(ctx, appID)  		if err != nil {  			return nil, fmt.Errorf("error getting application %s: %w", appID, err)  		} @@ -723,8 +745,8 @@ func (c *converter) StatusToAPIStatus(ctx context.Context, s *gtsmodel.Status, r  	return apiStatus, nil  } -// VisToapi converts a gts visibility into its api equivalent -func (c *converter) VisToAPIVis(ctx context.Context, m gtsmodel.Visibility) apimodel.Visibility { +// VisToAPIVis converts a gts visibility into its api equivalent +func (c *Converter) VisToAPIVis(ctx context.Context, m gtsmodel.Visibility) apimodel.Visibility {  	switch m {  	case gtsmodel.VisibilityPublic:  		return apimodel.VisibilityPublic @@ -738,14 +760,16 @@ func (c *converter) VisToAPIVis(ctx context.Context, m gtsmodel.Visibility) apim  	return ""  } -func (c *converter) InstanceRuleToAPIRule(r gtsmodel.Rule) apimodel.InstanceRule { +// InstanceRuleToAdminAPIRule converts a local instance rule into its api equivalent for serving at /api/v1/admin/instance/rules/:id +func (c *Converter) InstanceRuleToAPIRule(r gtsmodel.Rule) apimodel.InstanceRule {  	return apimodel.InstanceRule{  		ID:   r.ID,  		Text: r.Text,  	}  } -func (c *converter) InstanceRulesToAPIRules(r []gtsmodel.Rule) []apimodel.InstanceRule { +// InstanceRulesToAPIRules converts all local instance rules into their api equivalent for serving at /api/v1/instance/rules +func (c *Converter) InstanceRulesToAPIRules(r []gtsmodel.Rule) []apimodel.InstanceRule {  	rules := make([]apimodel.InstanceRule, len(r))  	for i, v := range r { @@ -755,7 +779,8 @@ func (c *converter) InstanceRulesToAPIRules(r []gtsmodel.Rule) []apimodel.Instan  	return rules  } -func (c *converter) InstanceRuleToAdminAPIRule(r *gtsmodel.Rule) *apimodel.AdminInstanceRule { +// InstanceRuleToAdminAPIRule converts a local instance rule into its api equivalent for serving at /api/v1/admin/instance/rules/:id +func (c *Converter) InstanceRuleToAdminAPIRule(r *gtsmodel.Rule) *apimodel.AdminInstanceRule {  	return &apimodel.AdminInstanceRule{  		ID:        r.ID,  		CreatedAt: util.FormatISO8601(r.CreatedAt), @@ -764,7 +789,8 @@ func (c *converter) InstanceRuleToAdminAPIRule(r *gtsmodel.Rule) *apimodel.Admin  	}  } -func (c *converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Instance) (*apimodel.InstanceV1, error) { +// InstanceToAPIV1Instance converts a gts instance into its api equivalent for serving at /api/v1/instance +func (c *Converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Instance) (*apimodel.InstanceV1, error) {  	instance := &apimodel.InstanceV1{  		URI:              i.URI,  		AccountDomain:    config.GetAccountDomain(), @@ -810,19 +836,19 @@ func (c *converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins  	// statistics  	stats := make(map[string]int, 3) -	userCount, err := c.db.CountInstanceUsers(ctx, i.Domain) +	userCount, err := c.state.DB.CountInstanceUsers(ctx, i.Domain)  	if err != nil {  		return nil, fmt.Errorf("InstanceToAPIV1Instance: db error getting counting instance users: %w", err)  	}  	stats["user_count"] = userCount -	statusCount, err := c.db.CountInstanceStatuses(ctx, i.Domain) +	statusCount, err := c.state.DB.CountInstanceStatuses(ctx, i.Domain)  	if err != nil {  		return nil, fmt.Errorf("InstanceToAPIV1Instance: db error getting counting instance statuses: %w", err)  	}  	stats["status_count"] = statusCount -	domainCount, err := c.db.CountInstanceDomains(ctx, i.Domain) +	domainCount, err := c.state.DB.CountInstanceDomains(ctx, i.Domain)  	if err != nil {  		return nil, fmt.Errorf("InstanceToAPIV1Instance: db error getting counting instance domains: %w", err)  	} @@ -830,14 +856,14 @@ func (c *converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins  	instance.Stats = stats  	// thumbnail -	iAccount, err := c.db.GetInstanceAccount(ctx, "") +	iAccount, err := c.state.DB.GetInstanceAccount(ctx, "")  	if err != nil {  		return nil, fmt.Errorf("InstanceToAPIV1Instance: db error getting instance account: %w", err)  	}  	if iAccount.AvatarMediaAttachmentID != "" {  		if iAccount.AvatarMediaAttachment == nil { -			avi, err := c.db.GetAttachmentByID(ctx, iAccount.AvatarMediaAttachmentID) +			avi, err := c.state.DB.GetAttachmentByID(ctx, iAccount.AvatarMediaAttachmentID)  			if err != nil {  				return nil, fmt.Errorf("InstanceToAPIInstance: error getting instance avatar attachment with id %s: %w", iAccount.AvatarMediaAttachmentID, err)  			} @@ -854,7 +880,7 @@ func (c *converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins  	// contact account  	if i.ContactAccountID != "" {  		if i.ContactAccount == nil { -			contactAccount, err := c.db.GetAccountByID(ctx, i.ContactAccountID) +			contactAccount, err := c.state.DB.GetAccountByID(ctx, i.ContactAccountID)  			if err != nil {  				return nil, fmt.Errorf("InstanceToAPIV1Instance: db error getting instance contact account %s: %w", i.ContactAccountID, err)  			} @@ -871,7 +897,8 @@ func (c *converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins  	return instance, nil  } -func (c *converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Instance) (*apimodel.InstanceV2, error) { +// InstanceToAPIV2Instance converts a gts instance into its api equivalent for serving at /api/v2/instance +func (c *Converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Instance) (*apimodel.InstanceV2, error) {  	instance := &apimodel.InstanceV2{  		Domain:        i.Domain,  		AccountDomain: config.GetAccountDomain(), @@ -891,14 +918,14 @@ func (c *converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins  	// thumbnail  	thumbnail := apimodel.InstanceV2Thumbnail{} -	iAccount, err := c.db.GetInstanceAccount(ctx, "") +	iAccount, err := c.state.DB.GetInstanceAccount(ctx, "")  	if err != nil {  		return nil, fmt.Errorf("InstanceToAPIV2Instance: db error getting instance account: %w", err)  	}  	if iAccount.AvatarMediaAttachmentID != "" {  		if iAccount.AvatarMediaAttachment == nil { -			avi, err := c.db.GetAttachmentByID(ctx, iAccount.AvatarMediaAttachmentID) +			avi, err := c.state.DB.GetAttachmentByID(ctx, iAccount.AvatarMediaAttachmentID)  			if err != nil {  				return nil, fmt.Errorf("InstanceToAPIV2Instance: error getting instance avatar attachment with id %s: %w", iAccount.AvatarMediaAttachmentID, err)  			} @@ -945,7 +972,7 @@ func (c *converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins  	instance.Contact.Email = i.ContactEmail  	if i.ContactAccountID != "" {  		if i.ContactAccount == nil { -			contactAccount, err := c.db.GetAccountByID(ctx, i.ContactAccountID) +			contactAccount, err := c.state.DB.GetAccountByID(ctx, i.ContactAccountID)  			if err != nil {  				return nil, fmt.Errorf("InstanceToAPIV2Instance: db error getting instance contact account %s: %w", i.ContactAccountID, err)  			} @@ -962,7 +989,8 @@ func (c *converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins  	return instance, nil  } -func (c *converter) RelationshipToAPIRelationship(ctx context.Context, r *gtsmodel.Relationship) (*apimodel.Relationship, error) { +// RelationshipToAPIRelationship converts a gts relationship into its api equivalent for serving in various places +func (c *Converter) RelationshipToAPIRelationship(ctx context.Context, r *gtsmodel.Relationship) (*apimodel.Relationship, error) {  	return &apimodel.Relationship{  		ID:                  r.ID,  		Following:           r.Following, @@ -980,9 +1008,10 @@ func (c *converter) RelationshipToAPIRelationship(ctx context.Context, r *gtsmod  	}, nil  } -func (c *converter) NotificationToAPINotification(ctx context.Context, n *gtsmodel.Notification) (*apimodel.Notification, error) { +// NotificationToAPINotification converts a gts notification into a api notification +func (c *Converter) NotificationToAPINotification(ctx context.Context, n *gtsmodel.Notification) (*apimodel.Notification, error) {  	if n.TargetAccount == nil { -		tAccount, err := c.db.GetAccountByID(ctx, n.TargetAccountID) +		tAccount, err := c.state.DB.GetAccountByID(ctx, n.TargetAccountID)  		if err != nil {  			return nil, fmt.Errorf("NotificationToapi: error getting target account with id %s from the db: %s", n.TargetAccountID, err)  		} @@ -990,7 +1019,7 @@ func (c *converter) NotificationToAPINotification(ctx context.Context, n *gtsmod  	}  	if n.OriginAccount == nil { -		ogAccount, err := c.db.GetAccountByID(ctx, n.OriginAccountID) +		ogAccount, err := c.state.DB.GetAccountByID(ctx, n.OriginAccountID)  		if err != nil {  			return nil, fmt.Errorf("NotificationToapi: error getting origin account with id %s from the db: %s", n.OriginAccountID, err)  		} @@ -1005,7 +1034,7 @@ func (c *converter) NotificationToAPINotification(ctx context.Context, n *gtsmod  	var apiStatus *apimodel.Status  	if n.StatusID != "" {  		if n.Status == nil { -			status, err := c.db.GetStatusByID(ctx, n.StatusID) +			status, err := c.state.DB.GetStatusByID(ctx, n.StatusID)  			if err != nil {  				return nil, fmt.Errorf("NotificationToapi: error getting status with id %s from the db: %s", n.StatusID, err)  			} @@ -1041,7 +1070,8 @@ func (c *converter) NotificationToAPINotification(ctx context.Context, n *gtsmod  	}, nil  } -func (c *converter) DomainPermToAPIDomainPerm( +// DomainPermToAPIDomainPerm converts a gts model domin block or allow into an api domain permission. +func (c *Converter) DomainPermToAPIDomainPerm(  	ctx context.Context,  	d gtsmodel.DomainPermission,  	export bool, @@ -1076,7 +1106,8 @@ func (c *converter) DomainPermToAPIDomainPerm(  	return domainPerm, nil  } -func (c *converter) ReportToAPIReport(ctx context.Context, r *gtsmodel.Report) (*apimodel.Report, error) { +// ReportToAPIReport converts a gts model report into an api model report, for serving at /api/v1/reports +func (c *Converter) ReportToAPIReport(ctx context.Context, r *gtsmodel.Report) (*apimodel.Report, error) {  	report := &apimodel.Report{  		ID:          r.ID,  		CreatedAt:   util.FormatISO8601(r.CreatedAt), @@ -1098,7 +1129,7 @@ func (c *converter) ReportToAPIReport(ctx context.Context, r *gtsmodel.Report) (  	}  	if r.TargetAccount == nil { -		tAccount, err := c.db.GetAccountByID(ctx, r.TargetAccountID) +		tAccount, err := c.state.DB.GetAccountByID(ctx, r.TargetAccountID)  		if err != nil {  			return nil, fmt.Errorf("ReportToAPIReport: error getting target account with id %s from the db: %s", r.TargetAccountID, err)  		} @@ -1114,7 +1145,8 @@ func (c *converter) ReportToAPIReport(ctx context.Context, r *gtsmodel.Report) (  	return report, nil  } -func (c *converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Report, requestingAccount *gtsmodel.Account) (*apimodel.AdminReport, error) { +// ReportToAdminAPIReport converts a gts model report into an admin view report, for serving at /api/v1/admin/reports +func (c *Converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Report, requestingAccount *gtsmodel.Account) (*apimodel.AdminReport, error) {  	var (  		err                  error  		actionTakenAt        *string @@ -1128,7 +1160,7 @@ func (c *converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Repo  	}  	if r.Account == nil { -		r.Account, err = c.db.GetAccountByID(ctx, r.AccountID) +		r.Account, err = c.state.DB.GetAccountByID(ctx, r.AccountID)  		if err != nil {  			return nil, fmt.Errorf("ReportToAdminAPIReport: error getting account with id %s from the db: %w", r.AccountID, err)  		} @@ -1139,7 +1171,7 @@ func (c *converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Repo  	}  	if r.TargetAccount == nil { -		r.TargetAccount, err = c.db.GetAccountByID(ctx, r.TargetAccountID) +		r.TargetAccount, err = c.state.DB.GetAccountByID(ctx, r.TargetAccountID)  		if err != nil {  			return nil, fmt.Errorf("ReportToAdminAPIReport: error getting target account with id %s from the db: %w", r.TargetAccountID, err)  		} @@ -1151,7 +1183,7 @@ func (c *converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Repo  	if r.ActionTakenByAccountID != "" {  		if r.ActionTakenByAccount == nil { -			r.ActionTakenByAccount, err = c.db.GetAccountByID(ctx, r.ActionTakenByAccountID) +			r.ActionTakenByAccount, err = c.state.DB.GetAccountByID(ctx, r.ActionTakenByAccountID)  			if err != nil {  				return nil, fmt.Errorf("ReportToAdminAPIReport: error getting action taken by account with id %s from the db: %w", r.ActionTakenByAccountID, err)  			} @@ -1165,7 +1197,7 @@ func (c *converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Repo  	statuses := make([]*apimodel.Status, 0, len(r.StatusIDs))  	if len(r.StatusIDs) != 0 && len(r.Statuses) == 0 { -		r.Statuses, err = c.db.GetStatusesByIDs(ctx, r.StatusIDs) +		r.Statuses, err = c.state.DB.GetStatusesByIDs(ctx, r.StatusIDs)  		if err != nil {  			return nil, fmt.Errorf("ReportToAdminAPIReport: error getting statuses from the db: %w", err)  		} @@ -1180,7 +1212,7 @@ func (c *converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Repo  	rules := make([]*apimodel.InstanceRule, 0, len(r.RuleIDs))  	if len(r.RuleIDs) != 0 && len(r.Rules) == 0 { -		r.Rules, err = c.db.GetRulesByIDs(ctx, r.RuleIDs) +		r.Rules, err = c.state.DB.GetRulesByIDs(ctx, r.RuleIDs)  		if err != nil {  			return nil, fmt.Errorf("ReportToAdminAPIReport: error getting rules from the db: %w", err)  		} @@ -1215,7 +1247,8 @@ func (c *converter) ReportToAdminAPIReport(ctx context.Context, r *gtsmodel.Repo  	}, nil  } -func (c *converter) ListToAPIList(ctx context.Context, l *gtsmodel.List) (*apimodel.List, error) { +// ListToAPIList converts one gts model list into an api model list, for serving at /api/v1/lists/{id} +func (c *Converter) ListToAPIList(ctx context.Context, l *gtsmodel.List) (*apimodel.List, error) {  	return &apimodel.List{  		ID:            l.ID,  		Title:         l.Title, @@ -1223,7 +1256,8 @@ func (c *converter) ListToAPIList(ctx context.Context, l *gtsmodel.List) (*apimo  	}, nil  } -func (c *converter) MarkersToAPIMarker(ctx context.Context, markers []*gtsmodel.Marker) (*apimodel.Marker, error) { +// MarkersToAPIMarker converts several gts model markers into an api marker, for serving at /api/v1/markers +func (c *Converter) MarkersToAPIMarker(ctx context.Context, markers []*gtsmodel.Marker) (*apimodel.Marker, error) {  	apiMarker := &apimodel.Marker{}  	for _, marker := range markers {  		apiTimelineMarker := &apimodel.TimelineMarker{ @@ -1244,7 +1278,7 @@ func (c *converter) MarkersToAPIMarker(ctx context.Context, markers []*gtsmodel.  }  // convertAttachmentsToAPIAttachments will convert a slice of GTS model attachments to frontend API model attachments, falling back to IDs if no GTS models supplied. -func (c *converter) convertAttachmentsToAPIAttachments(ctx context.Context, attachments []*gtsmodel.MediaAttachment, attachmentIDs []string) ([]apimodel.Attachment, error) { +func (c *Converter) convertAttachmentsToAPIAttachments(ctx context.Context, attachments []*gtsmodel.MediaAttachment, attachmentIDs []string) ([]apimodel.Attachment, error) {  	var errs gtserror.MultiError  	if len(attachments) == 0 { @@ -1255,7 +1289,7 @@ func (c *converter) convertAttachmentsToAPIAttachments(ctx context.Context, atta  		// Fetch GTS models for attachment IDs  		for _, id := range attachmentIDs { -			attachment, err := c.db.GetAttachmentByID(ctx, id) +			attachment, err := c.state.DB.GetAttachmentByID(ctx, id)  			if err != nil {  				errs.Appendf("error fetching attachment %s from database: %v", id, err)  				continue @@ -1281,7 +1315,7 @@ func (c *converter) convertAttachmentsToAPIAttachments(ctx context.Context, atta  }  // convertEmojisToAPIEmojis will convert a slice of GTS model emojis to frontend API model emojis, falling back to IDs if no GTS models supplied. -func (c *converter) convertEmojisToAPIEmojis(ctx context.Context, emojis []*gtsmodel.Emoji, emojiIDs []string) ([]apimodel.Emoji, error) { +func (c *Converter) convertEmojisToAPIEmojis(ctx context.Context, emojis []*gtsmodel.Emoji, emojiIDs []string) ([]apimodel.Emoji, error) {  	var errs gtserror.MultiError  	if len(emojis) == 0 { @@ -1292,7 +1326,7 @@ func (c *converter) convertEmojisToAPIEmojis(ctx context.Context, emojis []*gtsm  		// Fetch GTS models for emoji IDs  		for _, id := range emojiIDs { -			emoji, err := c.db.GetEmojiByID(ctx, id) +			emoji, err := c.state.DB.GetEmojiByID(ctx, id)  			if err != nil {  				errs.Appendf("error fetching emoji %s from database: %v", id, err)  				continue @@ -1318,7 +1352,7 @@ func (c *converter) convertEmojisToAPIEmojis(ctx context.Context, emojis []*gtsm  }  // convertMentionsToAPIMentions will convert a slice of GTS model mentions to frontend API model mentions, falling back to IDs if no GTS models supplied. -func (c *converter) convertMentionsToAPIMentions(ctx context.Context, mentions []*gtsmodel.Mention, mentionIDs []string) ([]apimodel.Mention, error) { +func (c *Converter) convertMentionsToAPIMentions(ctx context.Context, mentions []*gtsmodel.Mention, mentionIDs []string) ([]apimodel.Mention, error) {  	var errs gtserror.MultiError  	if len(mentions) == 0 { @@ -1327,7 +1361,7 @@ func (c *converter) convertMentionsToAPIMentions(ctx context.Context, mentions [  		// GTS model mentions were not populated  		//  		// Fetch GTS models for mention IDs -		mentions, err = c.db.GetMentions(ctx, mentionIDs) +		mentions, err = c.state.DB.GetMentions(ctx, mentionIDs)  		if err != nil {  			errs.Appendf("error fetching mentions from database: %v", err)  		} @@ -1350,13 +1384,13 @@ func (c *converter) convertMentionsToAPIMentions(ctx context.Context, mentions [  }  // convertTagsToAPITags will convert a slice of GTS model tags to frontend API model tags, falling back to IDs if no GTS models supplied. -func (c *converter) convertTagsToAPITags(ctx context.Context, tags []*gtsmodel.Tag, tagIDs []string) ([]apimodel.Tag, error) { +func (c *Converter) convertTagsToAPITags(ctx context.Context, tags []*gtsmodel.Tag, tagIDs []string) ([]apimodel.Tag, error) {  	var errs gtserror.MultiError  	if len(tags) == 0 {  		var err error -		tags, err = c.db.GetTags(ctx, tagIDs) +		tags, err = c.state.DB.GetTags(ctx, tagIDs)  		if err != nil {  			errs.Appendf("error fetching tags from database: %v", err)  		} diff --git a/internal/typeutils/internaltorss.go b/internal/typeutils/internaltorss.go index adec26a30..e70b11aae 100644 --- a/internal/typeutils/internaltorss.go +++ b/internal/typeutils/internaltorss.go @@ -36,7 +36,7 @@ const (  	rssDescriptionMaxRunes = 256  ) -func (c *converter) StatusToRSSItem(ctx context.Context, s *gtsmodel.Status) (*feeds.Item, error) { +func (c *Converter) StatusToRSSItem(ctx context.Context, s *gtsmodel.Status) (*feeds.Item, error) {  	// see https://cyber.harvard.edu/rss/rss.html  	// Title -- The title of the item. @@ -57,7 +57,7 @@ func (c *converter) StatusToRSSItem(ctx context.Context, s *gtsmodel.Status) (*f  	// Author -- Email address of the author of the item.  	// example: oprah\@oxygen.net  	if s.Account == nil { -		a, err := c.db.GetAccountByID(ctx, s.AccountID) +		a, err := c.state.DB.GetAccountByID(ctx, s.AccountID)  		if err != nil {  			return nil, fmt.Errorf("error getting status author: %s", err)  		} @@ -110,7 +110,7 @@ func (c *converter) StatusToRSSItem(ctx context.Context, s *gtsmodel.Status) (*f  	if len(s.Attachments) > 0 {  		attachment = s.Attachments[0]  	} else if len(s.AttachmentIDs) > 0 { -		a, err := c.db.GetAttachmentByID(ctx, s.AttachmentIDs[0]) +		a, err := c.state.DB.GetAttachmentByID(ctx, s.AttachmentIDs[0])  		if err == nil {  			attachment = a  		} @@ -139,7 +139,7 @@ func (c *converter) StatusToRSSItem(ctx context.Context, s *gtsmodel.Status) (*f  	} else {  		for _, e := range s.EmojiIDs {  			gtsEmoji := >smodel.Emoji{} -			if err := c.db.GetByID(ctx, e, gtsEmoji); err != nil { +			if err := c.state.DB.GetByID(ctx, e, gtsEmoji); err != nil {  				log.Errorf(ctx, "error getting emoji with id %s: %s", e, err)  				continue  			} diff --git a/internal/typeutils/util.go b/internal/typeutils/util.go index 42387afec..86acf4595 100644 --- a/internal/typeutils/util.go +++ b/internal/typeutils/util.go @@ -36,29 +36,29 @@ type statusInteractions struct {  	Pinned     bool  } -func (c *converter) interactionsWithStatusForAccount(ctx context.Context, s *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*statusInteractions, error) { +func (c *Converter) interactionsWithStatusForAccount(ctx context.Context, s *gtsmodel.Status, requestingAccount *gtsmodel.Account) (*statusInteractions, error) {  	si := &statusInteractions{}  	if requestingAccount != nil { -		faved, err := c.db.IsStatusFavedBy(ctx, s.ID, requestingAccount.ID) +		faved, err := c.state.DB.IsStatusFavedBy(ctx, s.ID, requestingAccount.ID)  		if err != nil {  			return nil, fmt.Errorf("error checking if requesting account has faved status: %s", err)  		}  		si.Faved = faved -		reblogged, err := c.db.IsStatusBoostedBy(ctx, s.ID, requestingAccount.ID) +		reblogged, err := c.state.DB.IsStatusBoostedBy(ctx, s.ID, requestingAccount.ID)  		if err != nil {  			return nil, fmt.Errorf("error checking if requesting account has reblogged status: %s", err)  		}  		si.Reblogged = reblogged -		muted, err := c.db.IsStatusMutedBy(ctx, s, requestingAccount.ID) +		muted, err := c.state.DB.IsStatusMutedBy(ctx, s, requestingAccount.ID)  		if err != nil {  			return nil, fmt.Errorf("error checking if requesting account has muted status: %s", err)  		}  		si.Muted = muted -		bookmarked, err := c.db.IsStatusBookmarkedBy(ctx, s, requestingAccount.ID) +		bookmarked, err := c.state.DB.IsStatusBookmarkedBy(ctx, s, requestingAccount.ID)  		if err != nil {  			return nil, fmt.Errorf("error checking if requesting account has bookmarked status: %s", err)  		} diff --git a/internal/typeutils/wrap.go b/internal/typeutils/wrap.go index 71099cbee..67d3c2b5c 100644 --- a/internal/typeutils/wrap.go +++ b/internal/typeutils/wrap.go @@ -30,7 +30,8 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/uris"  ) -func (c *converter) WrapPersonInUpdate(person vocab.ActivityStreamsPerson, originAccount *gtsmodel.Account) (vocab.ActivityStreamsUpdate, error) { +// WrapPersonInUpdate ... +func (c *Converter) WrapPersonInUpdate(person vocab.ActivityStreamsPerson, originAccount *gtsmodel.Account) (vocab.ActivityStreamsUpdate, error) {  	update := streams.NewActivityStreamsUpdate()  	// set the actor @@ -84,7 +85,12 @@ func (c *converter) WrapPersonInUpdate(person vocab.ActivityStreamsPerson, origi  	return update, nil  } -func (c *converter) WrapNoteInCreate(note vocab.ActivityStreamsNote, objectIRIOnly bool) (vocab.ActivityStreamsCreate, error) { +// 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. +func (c *Converter) WrapNoteInCreate(note vocab.ActivityStreamsNote, objectIRIOnly bool) (vocab.ActivityStreamsCreate, error) {  	create := streams.NewActivityStreamsCreate()  	// Object property  | 
