summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2022-05-23 17:40:03 +0200
committerLibravatar GitHub <noreply@github.com>2022-05-23 16:40:03 +0100
commitf0c9f4169be6c5c7dd913f348cdd294a19038d63 (patch)
tree7d06da6edc0ed92c78b79938a20c7e82f784fac4 /internal
parent[docs] document a checklist for how to go about a release (#592) (diff)
downloadgotosocial-f0c9f4169be6c5c7dd913f348cdd294a19038d63.tar.xz
[bugfix] Fix multiple dereferences of boosted status causing media duplication (#589)
* add some announces to test models * start on announce test logic * test federatingDB.Announce * change signature of GetRemoteStatus * remove 'refresh' logic and replace it with refetch * go fmt * remove timeline manager from processor test * make zork created at determinate * test get account statuses * test get + serialize zork * make account keys determinate * make admin accountCreate time determinate * test account to as * init test config before test log * test status to frontend * remove daft Within check * hack around a bit * use index of slice
Diffstat (limited to 'internal')
-rw-r--r--internal/api/client/account/accountverify_test.go3
-rw-r--r--internal/db/bundb/account_test.go6
-rw-r--r--internal/federation/dereference.go4
-rw-r--r--internal/federation/dereferencing/announce.go2
-rw-r--r--internal/federation/dereferencing/dereferencer.go2
-rw-r--r--internal/federation/dereferencing/status.go85
-rw-r--r--internal/federation/dereferencing/status_test.go12
-rw-r--r--internal/federation/dereferencing/thread.go13
-rw-r--r--internal/federation/federatingdb/announce_test.go93
-rw-r--r--internal/federation/federatingdb/federatingdb_test.go3
-rw-r--r--internal/federation/federator.go2
-rw-r--r--internal/processing/fromfederator.go2
-rw-r--r--internal/processing/processor_test.go2
-rw-r--r--internal/processing/search.go2
-rw-r--r--internal/typeutils/converter_test.go2
-rw-r--r--internal/typeutils/internaltoas_test.go9
-rw-r--r--internal/typeutils/internaltofrontend_test.go58
17 files changed, 214 insertions, 86 deletions
diff --git a/internal/api/client/account/accountverify_test.go b/internal/api/client/account/accountverify_test.go
index 4d6820881..6b199d83e 100644
--- a/internal/api/client/account/accountverify_test.go
+++ b/internal/api/client/account/accountverify_test.go
@@ -65,8 +65,6 @@ func (suite *AccountVerifyTestSuite) TestAccountVerifyGet() {
createdAt, err := time.Parse(time.RFC3339, apimodelAccount.CreatedAt)
suite.NoError(err)
- lastStatusAt, err := time.Parse(time.RFC3339, apimodelAccount.LastStatusAt)
- suite.NoError(err)
suite.Equal(testAccount.ID, apimodelAccount.ID)
suite.Equal(testAccount.Username, apimodelAccount.Username)
@@ -83,7 +81,6 @@ func (suite *AccountVerifyTestSuite) TestAccountVerifyGet() {
suite.Equal(2, apimodelAccount.FollowersCount)
suite.Equal(2, apimodelAccount.FollowingCount)
suite.Equal(5, apimodelAccount.StatusesCount)
- suite.WithinDuration(time.Now(), lastStatusAt, 5*time.Minute)
suite.EqualValues(gtsmodel.VisibilityPublic, apimodelAccount.Source.Privacy)
suite.Equal(testAccount.Language, apimodelAccount.Source.Language)
suite.Equal(testAccount.NoteRaw, apimodelAccount.Source.Note)
diff --git a/internal/db/bundb/account_test.go b/internal/db/bundb/account_test.go
index 90824416d..33c6b7ee6 100644
--- a/internal/db/bundb/account_test.go
+++ b/internal/db/bundb/account_test.go
@@ -34,6 +34,12 @@ type AccountTestSuite struct {
BunDBStandardTestSuite
}
+func (suite *AccountTestSuite) TestGetAccountStatuses() {
+ statuses, err := suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 20, false, false, "", "", false, false, false)
+ suite.NoError(err)
+ suite.Len(statuses, 5)
+}
+
func (suite *AccountTestSuite) TestGetAccountByIDWithExtras() {
account, err := suite.db.GetAccountByID(context.Background(), suite.testAccounts["local_account_1"].ID)
if err != nil {
diff --git a/internal/federation/dereference.go b/internal/federation/dereference.go
index 8cb23a91f..8efa0cc7e 100644
--- a/internal/federation/dereference.go
+++ b/internal/federation/dereference.go
@@ -30,8 +30,8 @@ func (f *federator) GetRemoteAccount(ctx context.Context, username string, remot
return f.dereferencer.GetRemoteAccount(ctx, username, remoteAccountID, blocking, refresh)
}
-func (f *federator) GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refresh, includeParent bool) (*gtsmodel.Status, ap.Statusable, bool, error) {
- return f.dereferencer.GetRemoteStatus(ctx, username, remoteStatusID, refresh, includeParent)
+func (f *federator) GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refetch, includeParent bool) (*gtsmodel.Status, ap.Statusable, error) {
+ return f.dereferencer.GetRemoteStatus(ctx, username, remoteStatusID, refetch, includeParent)
}
func (f *federator) EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error) {
diff --git a/internal/federation/dereferencing/announce.go b/internal/federation/dereferencing/announce.go
index 7bde7d2ce..c740bb20a 100644
--- a/internal/federation/dereferencing/announce.go
+++ b/internal/federation/dereferencing/announce.go
@@ -46,7 +46,7 @@ func (d *deref) DereferenceAnnounce(ctx context.Context, announce *gtsmodel.Stat
return fmt.Errorf("DereferenceAnnounce: error dereferencing thread of boosted status: %s", err)
}
- boostedStatus, _, _, err := d.GetRemoteStatus(ctx, requestingUsername, boostedStatusURI, false, true)
+ boostedStatus, _, err := d.GetRemoteStatus(ctx, requestingUsername, boostedStatusURI, false, true)
if err != nil {
return fmt.Errorf("DereferenceAnnounce: error dereferencing remote status with id %s: %s", announce.BoostOf.URI, err)
}
diff --git a/internal/federation/dereferencing/dereferencer.go b/internal/federation/dereferencing/dereferencer.go
index 855c4baf8..cae24d0fd 100644
--- a/internal/federation/dereferencing/dereferencer.go
+++ b/internal/federation/dereferencing/dereferencer.go
@@ -35,7 +35,7 @@ import (
type Dereferencer interface {
GetRemoteAccount(ctx context.Context, username string, remoteAccountID *url.URL, blocking bool, refresh bool) (*gtsmodel.Account, error)
- GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refresh, includeParent bool) (*gtsmodel.Status, ap.Statusable, bool, error)
+ GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refetch, includeParent bool) (*gtsmodel.Status, ap.Statusable, error)
EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error)
GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error)
diff --git a/internal/federation/dereferencing/status.go b/internal/federation/dereferencing/status.go
index cacca91b2..7c4d588bb 100644
--- a/internal/federation/dereferencing/status.go
+++ b/internal/federation/dereferencing/status.go
@@ -53,79 +53,63 @@ func (d *deref) EnrichRemoteStatus(ctx context.Context, username string, status
}
// GetRemoteStatus completely dereferences a remote status, converts it to a GtS model status,
-// puts it in the database, and returns it to a caller. The boolean indicates whether the status is new
-// to us or not. If we haven't seen the status before, bool will be true. If we have seen the status before,
-// it will be false.
+// puts it in the database, and returns it to a caller.
//
-// If refresh is true, then even if we have the status in our database already, it will be dereferenced from its
-// remote representation, as will its owner.
+// If refetch is true, then regardless of whether we have the original status in the database or not,
+// the ap.Statusable representation of the status will be dereferenced and returned.
//
-// If a dereference was performed, then the function also returns the ap.Statusable representation for further processing.
+// If refetch is false, the ap.Statusable will only be returned if this is a new status, so callers
+// should check whether or not this is nil.
//
// SIDE EFFECTS: remote status will be stored in the database, and the remote status owner will also be stored.
-func (d *deref) GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refresh, includeParent bool) (*gtsmodel.Status, ap.Statusable, bool, error) {
- new := true
-
- // check if we already have the status in our db
+func (d *deref) GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refetch, includeParent bool) (*gtsmodel.Status, ap.Statusable, error) {
maybeStatus, err := d.db.GetStatusByURI(ctx, remoteStatusID.String())
- if err == nil {
- // we've seen this status before so it's not new
- new = false
-
- // if we're not being asked to refresh, we can just return the maybeStatus as-is and avoid doing any external calls
- if !refresh {
- return maybeStatus, nil, new, nil
- }
+ if err == nil && !refetch {
+ // we already had the status and we aren't being asked to refetch the AP representation
+ return maybeStatus, nil, nil
}
statusable, err := d.dereferenceStatusable(ctx, username, remoteStatusID)
if err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error dereferencing statusable: %s", err)
+ return nil, nil, fmt.Errorf("GetRemoteStatus: error dereferencing statusable: %s", err)
+ }
+
+ if maybeStatus != nil && refetch {
+ // we already had the status and we've successfully fetched the AP representation as requested
+ return maybeStatus, statusable, nil
}
+ // from here on out we can consider this to be a 'new' status because we didn't have the status in the db already
accountURI, err := ap.ExtractAttributedTo(statusable)
if err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error extracting attributedTo: %s", err)
+ return nil, nil, fmt.Errorf("GetRemoteStatus: error extracting attributedTo: %s", err)
}
- // do this so we know we have the remote account of the status in the db
_, err = d.GetRemoteAccount(ctx, username, accountURI, true, false)
if err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: couldn't derive status author: %s", err)
+ return nil, nil, fmt.Errorf("GetRemoteStatus: couldn't get status author: %s", err)
}
gtsStatus, err := d.typeConverter.ASStatusToStatus(ctx, statusable)
if err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error converting statusable to status: %s", err)
+ return nil, statusable, fmt.Errorf("GetRemoteStatus: error converting statusable to status: %s", err)
}
- if new {
- ulid, err := id.NewULIDFromTime(gtsStatus.CreatedAt)
- if err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error generating new id for status: %s", err)
- }
- gtsStatus.ID = ulid
-
- if err := d.populateStatusFields(ctx, gtsStatus, username, includeParent); err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error populating status fields: %s", err)
- }
-
- if err := d.db.PutStatus(ctx, gtsStatus); err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error putting new status: %s", err)
- }
- } else {
- gtsStatus.ID = maybeStatus.ID
+ ulid, err := id.NewULIDFromTime(gtsStatus.CreatedAt)
+ if err != nil {
+ return nil, nil, fmt.Errorf("GetRemoteStatus: error generating new id for status: %s", err)
+ }
+ gtsStatus.ID = ulid
- if err := d.populateStatusFields(ctx, gtsStatus, username, includeParent); err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error populating status fields: %s", err)
- }
+ if err := d.populateStatusFields(ctx, gtsStatus, username, includeParent); err != nil {
+ return nil, nil, fmt.Errorf("GetRemoteStatus: error populating status fields: %s", err)
+ }
- if err := d.db.UpdateByPrimaryKey(ctx, gtsStatus); err != nil {
- return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error updating status: %s", err)
- }
+ if err := d.db.PutStatus(ctx, gtsStatus); err != nil {
+ return nil, nil, fmt.Errorf("GetRemoteStatus: error putting new status: %s", err)
}
- return gtsStatus, statusable, new, nil
+ return gtsStatus, statusable, nil
}
func (d *deref) dereferenceStatusable(ctx context.Context, username string, remoteStatusID *url.URL) (ap.Statusable, error) {
@@ -429,14 +413,9 @@ func (d *deref) populateStatusRepliedTo(ctx context.Context, status *gtsmodel.St
return err
}
- // see if we have the status in our db already
- replyToStatus, err := d.db.GetStatusByURI(ctx, status.InReplyToURI)
+ replyToStatus, _, err := d.GetRemoteStatus(ctx, requestingUsername, statusURI, false, false)
if err != nil {
- // Status was not in the DB, try fetch
- replyToStatus, _, _, err = d.GetRemoteStatus(ctx, requestingUsername, statusURI, false, false)
- if err != nil {
- return fmt.Errorf("populateStatusRepliedTo: couldn't get reply to status with uri %s: %s", status.InReplyToURI, err)
- }
+ return fmt.Errorf("populateStatusRepliedTo: couldn't get reply to status with uri %s: %s", status.InReplyToURI, err)
}
// we have the status
diff --git a/internal/federation/dereferencing/status_test.go b/internal/federation/dereferencing/status_test.go
index 08363f580..ab6efad38 100644
--- a/internal/federation/dereferencing/status_test.go
+++ b/internal/federation/dereferencing/status_test.go
@@ -38,11 +38,9 @@ func (suite *StatusTestSuite) TestDereferenceSimpleStatus() {
fetchingAccount := suite.testAccounts["local_account_1"]
statusURL := testrig.URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839")
- status, statusable, new, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
+ status, _, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
suite.NoError(err)
suite.NotNil(status)
- suite.NotNil(statusable)
- suite.True(new)
// status values should be set
suite.Equal("https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839", status.URI)
@@ -80,11 +78,9 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithMention() {
fetchingAccount := suite.testAccounts["local_account_1"]
statusURL := testrig.URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV")
- status, statusable, new, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
+ status, _, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
suite.NoError(err)
suite.NotNil(status)
- suite.NotNil(statusable)
- suite.True(new)
// status values should be set
suite.Equal("https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV", status.URI)
@@ -135,11 +131,9 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithImageAndNoContent() {
fetchingAccount := suite.testAccounts["local_account_1"]
statusURL := testrig.URLMustParse("https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042")
- status, statusable, new, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
+ status, _, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
suite.NoError(err)
suite.NotNil(status)
- suite.NotNil(statusable)
- suite.True(new)
// status values should be set
suite.Equal("https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042", status.URI)
diff --git a/internal/federation/dereferencing/thread.go b/internal/federation/dereferencing/thread.go
index f527b99cd..469defd5e 100644
--- a/internal/federation/dereferencing/thread.go
+++ b/internal/federation/dereferencing/thread.go
@@ -52,9 +52,9 @@ func (d *deref) DereferenceThread(ctx context.Context, username string, statusIR
}
// first make sure we have this status in our db
- _, statusable, _, err := d.GetRemoteStatus(ctx, username, statusIRI, true, false)
+ _, statusable, err := d.GetRemoteStatus(ctx, username, statusIRI, true, false)
if err != nil {
- return fmt.Errorf("DereferenceThread: error getting status with id %s: %s", statusIRI.String(), err)
+ return fmt.Errorf("DereferenceThread: error getting initial status with id %s: %s", statusIRI.String(), err)
}
// first iterate up through ancestors, dereferencing if necessary as we go
@@ -106,9 +106,8 @@ func (d *deref) iterateAncestors(ctx context.Context, username string, statusIRI
return d.iterateAncestors(ctx, username, *nextIRI)
}
- // If we reach here, we're looking at a remote status -- make sure we have it in our db by calling GetRemoteStatus
- // We call it with refresh to true because we want the statusable representation to parse inReplyTo from.
- _, statusable, _, err := d.GetRemoteStatus(ctx, username, &statusIRI, true, false)
+ // If we reach here, we're looking at a remote status
+ _, statusable, err := d.GetRemoteStatus(ctx, username, &statusIRI, true, false)
if err != nil {
l.Debugf("error getting remote status: %s", err)
return nil
@@ -220,8 +219,8 @@ pageLoop:
foundReplies++
// get the remote statusable and put it in the db
- _, statusable, new, err := d.GetRemoteStatus(ctx, username, itemURI, false, false)
- if new && err == nil && statusable != nil {
+ _, statusable, err := d.GetRemoteStatus(ctx, username, itemURI, false, false)
+ if err == nil {
// now iterate descendants of *that* status
if err := d.iterateDescendants(ctx, username, *itemURI, statusable); err != nil {
continue
diff --git a/internal/federation/federatingdb/announce_test.go b/internal/federation/federatingdb/announce_test.go
new file mode 100644
index 000000000..f63910298
--- /dev/null
+++ b/internal/federation/federatingdb/announce_test.go
@@ -0,0 +1,93 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package federatingdb_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+ "github.com/superseriousbusiness/activity/streams/vocab"
+ "github.com/superseriousbusiness/gotosocial/internal/ap"
+ "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+)
+
+type AnnounceTestSuite struct {
+ FederatingDBTestSuite
+}
+
+func (suite *AnnounceTestSuite) TestNewAnnounce() {
+ receivingAccount1 := suite.testAccounts["local_account_1"]
+ announcingAccount := suite.testAccounts["remote_account_1"]
+
+ ctx := createTestContext(receivingAccount1, announcingAccount)
+ announce1 := suite.testActivities["announce_forwarded_1_zork"]
+
+ err := suite.federatingDB.Announce(ctx, announce1.Activity.(vocab.ActivityStreamsAnnounce))
+ suite.NoError(err)
+
+ // should be a message heading to the processor now, which we can intercept here
+ msg := <-suite.fromFederator
+ suite.Equal(ap.ActivityAnnounce, msg.APObjectType)
+ suite.Equal(ap.ActivityCreate, msg.APActivityType)
+
+ boost, ok := msg.GTSModel.(*gtsmodel.Status)
+ suite.True(ok)
+ suite.Equal(announcingAccount.ID, boost.AccountID)
+
+ // only the URI will be set on the boosted status because it still needs to be dereferenced
+ suite.NotEmpty(boost.BoostOf.URI)
+}
+
+func (suite *AnnounceTestSuite) TestAnnounceTwice() {
+ receivingAccount1 := suite.testAccounts["local_account_1"]
+ receivingAccount2 := suite.testAccounts["local_account_2"]
+
+ announcingAccount := suite.testAccounts["remote_account_1"]
+
+ ctx1 := createTestContext(receivingAccount1, announcingAccount)
+ announce1 := suite.testActivities["announce_forwarded_1_zork"]
+
+ err := suite.federatingDB.Announce(ctx1, announce1.Activity.(vocab.ActivityStreamsAnnounce))
+ suite.NoError(err)
+
+ // should be a message heading to the processor now, which we can intercept here
+ msg := <-suite.fromFederator
+ suite.Equal(ap.ActivityAnnounce, msg.APObjectType)
+ suite.Equal(ap.ActivityCreate, msg.APActivityType)
+ boost, ok := msg.GTSModel.(*gtsmodel.Status)
+ suite.True(ok)
+ suite.Equal(announcingAccount.ID, boost.AccountID)
+
+ // only the URI will be set on the boosted status because it still needs to be dereferenced
+ suite.NotEmpty(boost.BoostOf.URI)
+
+ ctx2 := createTestContext(receivingAccount2, announcingAccount)
+ announce2 := suite.testActivities["announce_forwarded_1_turtle"]
+
+ err = suite.federatingDB.Announce(ctx2, announce2.Activity.(vocab.ActivityStreamsAnnounce))
+ suite.NoError(err)
+
+ // since this is a repeat announce with the same URI, just delivered to a different inbox,
+ // we should have nothing in the messages channel...
+ suite.Empty(suite.fromFederator)
+}
+
+func TestAnnounceTestSuite(t *testing.T) {
+ suite.Run(t, &AnnounceTestSuite{})
+}
diff --git a/internal/federation/federatingdb/federatingdb_test.go b/internal/federation/federatingdb/federatingdb_test.go
index 8e6c1802d..ded817c98 100644
--- a/internal/federation/federatingdb/federatingdb_test.go
+++ b/internal/federation/federatingdb/federatingdb_test.go
@@ -63,8 +63,9 @@ func (suite *FederatingDBTestSuite) SetupSuite() {
}
func (suite *FederatingDBTestSuite) SetupTest() {
- testrig.InitTestLog()
testrig.InitTestConfig()
+ testrig.InitTestLog()
+
suite.fedWorker = concurrency.NewWorkerPool[messages.FromFederator](-1, -1)
suite.fromFederator = make(chan messages.FromFederator, 10)
suite.fedWorker.SetProcessor(func(ctx context.Context, msg messages.FromFederator) error {
diff --git a/internal/federation/federator.go b/internal/federation/federator.go
index 61d7f3e17..6412c9ee1 100644
--- a/internal/federation/federator.go
+++ b/internal/federation/federator.go
@@ -62,7 +62,7 @@ type Federator interface {
GetRemoteAccount(ctx context.Context, username string, remoteAccountID *url.URL, blocking bool, refresh bool) (*gtsmodel.Account, error)
- GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refresh, includeParent bool) (*gtsmodel.Status, ap.Statusable, bool, error)
+ GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refetch, includeParent bool) (*gtsmodel.Status, ap.Statusable, error)
EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error)
GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error)
diff --git a/internal/processing/fromfederator.go b/internal/processing/fromfederator.go
index 06df17d91..a2eaa9bd1 100644
--- a/internal/processing/fromfederator.go
+++ b/internal/processing/fromfederator.go
@@ -108,7 +108,7 @@ func (p *processor) processCreateStatusFromFederator(ctx context.Context, federa
return errors.New("ProcessFromFederator: status was not pinned to federatorMsg, and neither was an IRI for us to dereference")
}
var err error
- status, _, _, err = p.federator.GetRemoteStatus(ctx, federatorMsg.ReceivingAccount.Username, federatorMsg.APIri, false, false)
+ status, _, err = p.federator.GetRemoteStatus(ctx, federatorMsg.ReceivingAccount.Username, federatorMsg.APIri, false, false)
if err != nil {
return err
}
diff --git a/internal/processing/processor_test.go b/internal/processing/processor_test.go
index 5946e6718..7032f8e28 100644
--- a/internal/processing/processor_test.go
+++ b/internal/processing/processor_test.go
@@ -38,7 +38,6 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/messages"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
"github.com/superseriousbusiness/gotosocial/internal/processing"
- "github.com/superseriousbusiness/gotosocial/internal/timeline"
"github.com/superseriousbusiness/gotosocial/internal/transport"
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
"github.com/superseriousbusiness/gotosocial/testrig"
@@ -54,7 +53,6 @@ type ProcessingStandardTestSuite struct {
transportController transport.Controller
federator federation.Federator
oauthServer oauth.Server
- timelineManager timeline.Manager
emailSender email.Sender
// standard suite models
diff --git a/internal/processing/search.go b/internal/processing/search.go
index 6c3d7da39..03f158187 100644
--- a/internal/processing/search.go
+++ b/internal/processing/search.go
@@ -127,7 +127,7 @@ func (p *processor) searchStatusByURI(ctx context.Context, authed *oauth.Auth, u
// we don't have it locally so dereference it if we're allowed to
if resolve {
- status, _, _, err := p.federator.GetRemoteStatus(ctx, authed.Account.Username, uri, true, true)
+ status, _, err := p.federator.GetRemoteStatus(ctx, authed.Account.Username, uri, false, true)
if err == nil {
if err := p.federator.DereferenceRemoteThread(ctx, authed.Account.Username, uri); err != nil {
// try to deref the thread while we're here
diff --git a/internal/typeutils/converter_test.go b/internal/typeutils/converter_test.go
index d85cb1b16..4d782c822 100644
--- a/internal/typeutils/converter_test.go
+++ b/internal/typeutils/converter_test.go
@@ -427,8 +427,8 @@ type TypeUtilsTestSuite struct {
}
func (suite *TypeUtilsTestSuite) SetupSuite() {
- testrig.InitTestLog()
testrig.InitTestConfig()
+ testrig.InitTestLog()
suite.db = testrig.NewTestDB()
suite.testAccounts = testrig.NewTestAccounts()
diff --git a/internal/typeutils/internaltoas_test.go b/internal/typeutils/internaltoas_test.go
index 72b928237..53403669e 100644
--- a/internal/typeutils/internaltoas_test.go
+++ b/internal/typeutils/internaltoas_test.go
@@ -21,7 +21,7 @@ package typeutils_test
import (
"context"
"encoding/json"
- "fmt"
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -45,8 +45,11 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
bytes, err := json.Marshal(ser)
suite.NoError(err)
- fmt.Println(string(bytes))
- // TODO: write assertions here, rn we're just eyeballing the output
+ // trim off everything up to 'discoverable';
+ // this is necessary because the order of multiple 'context' entries is not determinate
+ trimmed := strings.Split(string(bytes), "\"discoverable\"")[1]
+
+ suite.Equal(`:true,"featured":"http://localhost:8080/users/the_mighty_zork/collections/featured","followers":"http://localhost:8080/users/the_mighty_zork/followers","following":"http://localhost:8080/users/the_mighty_zork/following","icon":{"mediaType":"image/jpeg","type":"Image","url":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpeg"},"id":"http://localhost:8080/users/the_mighty_zork","image":{"mediaType":"image/jpeg","type":"Image","url":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpeg"},"inbox":"http://localhost:8080/users/the_mighty_zork/inbox","manuallyApprovesFollowers":false,"name":"original zork (he/they)","outbox":"http://localhost:8080/users/the_mighty_zork/outbox","preferredUsername":"the_mighty_zork","publicKey":{"id":"http://localhost:8080/users/the_mighty_zork/main-key","owner":"http://localhost:8080/users/the_mighty_zork","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwXTcOAvM1Jiw5Ffpk0qn\nr0cwbNvFe/5zQ+Tp7tumK/ZnT37o7X0FUEXrxNi+dkhmeJ0gsaiN+JQGNUewvpSk\nPIAXKvi908aSfCGjs7bGlJCJCuDuL5d6m7hZnP9rt9fJc70GElPpG0jc9fXwlz7T\nlsPb2ecatmG05Y4jPwdC+oN4MNCv9yQzEvCVMzl76EJaM602kIHC1CISn0rDFmYd\n9rSN7XPlNJw1F6PbpJ/BWQ+pXHKw3OEwNTETAUNYiVGnZU+B7a7bZC9f6/aPbJuV\nt8Qmg+UnDvW1Y8gmfHnxaWG2f5TDBvCHmcYtucIZPLQD4trAozC4ryqlmCWQNKbt\n0wIDAQAB\n-----END PUBLIC KEY-----\n"},"summary":"\u003cp\u003ehey yo this is my profile!\u003c/p\u003e","type":"Person","url":"http://localhost:8080/@the_mighty_zork"}`, trimmed)
}
func (suite *InternalToASTestSuite) TestOutboxToASCollection() {
diff --git a/internal/typeutils/internaltofrontend_test.go b/internal/typeutils/internaltofrontend_test.go
new file mode 100644
index 000000000..c7aa31905
--- /dev/null
+++ b/internal/typeutils/internaltofrontend_test.go
@@ -0,0 +1,58 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package typeutils_test
+
+import (
+ "context"
+ "encoding/json"
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+)
+
+type InternalToFrontendTestSuite struct {
+ TypeUtilsTestSuite
+}
+
+func (suite *InternalToFrontendTestSuite) TestAccountToFrontend() {
+ testAccount := suite.testAccounts["local_account_1"] // take zork for this test
+ apiAccount, err := suite.typeconverter.AccountToAPIAccountPublic(context.Background(), testAccount)
+ suite.NoError(err)
+ suite.NotNil(apiAccount)
+
+ b, err := json.Marshal(apiAccount)
+ suite.NoError(err)
+ suite.Equal(`{"id":"01F8MH1H7YV1Z7D2C8K2730QBF","username":"the_mighty_zork","acct":"the_mighty_zork","display_name":"original zork (he/they)","locked":false,"bot":false,"created_at":"2022-05-20T11:09:18Z","note":"\u003cp\u003ehey yo this is my profile!\u003c/p\u003e","url":"http://localhost:8080/@the_mighty_zork","avatar":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpeg","avatar_static":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/small/01F8MH58A357CV5K7R7TJMSH6S.jpeg","header":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpeg","header_static":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/small/01PFPMWK2FF0D9WMHEJHR07C3Q.jpeg","followers_count":2,"following_count":2,"statuses_count":5,"last_status_at":"2022-05-20T11:37:55Z","emojis":[],"fields":[]}`, string(b))
+}
+
+func (suite *InternalToFrontendTestSuite) TestStatusToFrontend() {
+ testStatus := suite.testStatuses["admin_account_status_1"]
+ requestingAccount := suite.testAccounts["local_account_1"]
+ apiStatus, err := suite.typeconverter.StatusToAPIStatus(context.Background(), testStatus, requestingAccount)
+ suite.NoError(err)
+
+ b, err := json.Marshal(apiStatus)
+ suite.NoError(err)
+
+ suite.Equal(`{"id":"01F8MH75CBF9JFX4ZAD54N0W0R","created_at":"2021-10-20T11:36:45Z","sensitive":false,"spoiler_text":"","visibility":"public","language":"en","uri":"http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","url":"http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","replies_count":0,"reblogs_count":0,"favourites_count":1,"favourited":true,"reblogged":false,"muted":false,"bookmarked":false,"content":"hello world! #welcome ! first post on the instance :rainbow: !","application":{"name":"superseriousbusiness","website":"https://superserious.business"},"account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37Z","emojis":[],"fields":[]},"media_attachments":[{"id":"01F8MH6NEM8D7527KZAECTCR76","type":"image","url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpeg","preview_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/small/01F8MH6NEM8D7527KZAECTCR76.jpeg","meta":{"original":{"width":1200,"height":630,"size":"1200x630","aspect":1.9047619},"small":{"width":256,"height":134,"size":"256x134","aspect":1.9104477},"focus":{"x":0,"y":0}},"description":"Black and white image of some 50's style text saying: Welcome On Board","blurhash":"LNJRdVM{00Rj%Mayt7j[4nWBofRj"}],"mentions":[],"tags":[{"name":"welcome","url":"http://localhost:8080/tags/welcome"}],"emojis":[{"shortcode":"rainbow","url":"http://localhost:8080/fileserver/01F8MH261H1KSV3GW3016GZRY3/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","static_url":"http://localhost:8080/fileserver/01F8MH261H1KSV3GW3016GZRY3/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","visible_in_picker":true}],"card":null,"poll":null,"text":""}`, string(b))
+}
+
+func TestInternalToFrontendTestSuite(t *testing.T) {
+ suite.Run(t, new(InternalToFrontendTestSuite))
+}