Skip to content

Commit

Permalink
[bugfix] Ensure pre renders as expected, fix orderedCollectionPage (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
tsmethurst committed Dec 10, 2023
1 parent cc91ea0 commit d60edf7
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 78 deletions.
19 changes: 11 additions & 8 deletions internal/ap/serialize.go
Expand Up @@ -35,13 +35,15 @@ import (
// Currently, the following things will be custom serialized:
//
// - OrderedCollection: 'orderedItems' property will always be made into an array.
// - OrderedCollectionPage: 'orderedItems' property will always be made into an array.
// - Any Accountable type: 'attachment' property will always be made into an array.
// - Any Statusable type: 'attachment' property will always be made into an array; 'content' and 'contentMap' will be normalized.
// - Any Activityable type: any 'object's set on an activity will be custom serialized as above.
func Serialize(t vocab.Type) (m map[string]interface{}, e error) {
switch tn := t.GetTypeName(); {
case tn == ObjectOrderedCollection:
return serializeOrderedCollection(t)
case tn == ObjectOrderedCollection ||
tn == ObjectOrderedCollectionPage:
return serializeWithOrderedItems(t)
case IsAccountable(tn):
return serializeAccountable(t, true)
case IsStatusable(tn):
Expand All @@ -54,16 +56,17 @@ func Serialize(t vocab.Type) (m map[string]interface{}, e error) {
}
}

// serializeOrderedCollection is a custom serializer for an ActivityStreamsOrderedCollection.
// Unlike the standard streams.Serialize function, this serializer normalizes the orderedItems
// value to always be an array/slice, regardless of how many items are contained therein.
//
// TODO: Remove this function if we can fix the underlying issue in Go-Fed.
// serializeWithOrderedItems is a custom serializer
// for any type that has an `orderedItems` property.
// Unlike the standard streams.Serialize function,
// this serializer normalizes the orderedItems
// value to always be an array/slice, regardless
// of how many items are contained therein.
//
// See:
// - https://github.com/go-fed/activity/issues/139
// - https://github.com/mastodon/mastodon/issues/24225
func serializeOrderedCollection(t vocab.Type) (map[string]interface{}, error) {
func serializeWithOrderedItems(t vocab.Type) (map[string]interface{}, error) {
data, err := streams.Serialize(t)
if err != nil {
return nil, err
Expand Down
56 changes: 38 additions & 18 deletions internal/api/activitypub/users/outboxget_test.go
Expand Up @@ -140,16 +140,26 @@ func (suite *OutboxGetTestSuite) TestGetOutboxFirstPage() {
"@context": "https://www.w3.org/ns/activitystreams",
"id": "http://localhost:8080/users/the_mighty_zork/outbox?page=true",
"next": "http://localhost:8080/users/the_mighty_zork/outbox?page=true\u0026max_id=01F8MHAMCHF6Y650WCRSCP4WMY",
"orderedItems": {
"actor": "http://localhost:8080/users/the_mighty_zork",
"cc": "http://localhost:8080/users/the_mighty_zork/followers",
"id": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/activity#Create",
"object": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY",
"to": "https://www.w3.org/ns/activitystreams#Public",
"type": "Create"
},
"orderedItems": [
{
"actor": "http://localhost:8080/users/the_mighty_zork",
"cc": "http://localhost:8080/users/the_mighty_zork/followers",
"id": "http://localhost:8080/users/the_mighty_zork/statuses/01HH9KYNQPA416TNJ53NSATP40/activity#Create",
"object": "http://localhost:8080/users/the_mighty_zork/statuses/01HH9KYNQPA416TNJ53NSATP40",
"to": "https://www.w3.org/ns/activitystreams#Public",
"type": "Create"
},
{
"actor": "http://localhost:8080/users/the_mighty_zork",
"cc": "http://localhost:8080/users/the_mighty_zork/followers",
"id": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/activity#Create",
"object": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY",
"to": "https://www.w3.org/ns/activitystreams#Public",
"type": "Create"
}
],
"partOf": "http://localhost:8080/users/the_mighty_zork/outbox",
"prev": "http://localhost:8080/users/the_mighty_zork/outbox?page=true\u0026min_id=01F8MHAMCHF6Y650WCRSCP4WMY",
"prev": "http://localhost:8080/users/the_mighty_zork/outbox?page=true\u0026min_id=01HH9KYNQPA416TNJ53NSATP40",
"type": "OrderedCollectionPage"
}`, dst.String())

Expand Down Expand Up @@ -237,22 +247,32 @@ func checkDropPublished(t *testing.T, b []byte, at ...string) []byte {
if err := json.Unmarshal(b, &m); err != nil {
t.Fatalf("error unmarshaling json into map: %v", err)
}
mm := m

entries := make([]map[string]any, 0)
for _, key := range at {
switch vt := mm[key].(type) {
case map[string]any:
mm = vt
switch vt := m[key].(type) {
case []interface{}:
for _, t := range vt {
if entry, ok := t.(map[string]any); ok {
entries = append(entries, entry)
}
}
}
}
if s, ok := mm["published"].(string); !ok {
t.Fatal("missing published data on json")
} else if _, err := time.Parse(time.RFC3339, s); err != nil {
t.Fatalf("error parsing published time: %v", err)

for _, entry := range entries {
if s, ok := entry["published"].(string); !ok {
t.Fatal("missing published data on json")
} else if _, err := time.Parse(time.RFC3339, s); err != nil {
t.Fatalf("error parsing published time: %v", err)
}
delete(entry, "published")
}
delete(mm, "published")

b, err := json.Marshal(m)
if err != nil {
t.Fatalf("error remarshaling json: %v", err)
}

return b
}
2 changes: 1 addition & 1 deletion internal/api/activitypub/users/repliesget_test.go
Expand Up @@ -163,7 +163,7 @@ func (suite *RepliesGetTestSuite) TestGetRepliesNext() {
"partOf": targetStatus.URI + "/replies?only_other_accounts=false",
"next": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?limit=20&min_id=01FF25D5Q0DH7CHD57CTRS6WK0&only_other_accounts=false",
"prev": "http://localhost:8080/users/the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY/replies?limit=20&max_id=01FF25D5Q0DH7CHD57CTRS6WK0&only_other_accounts=false",
"orderedItems": "http://localhost:8080/users/admin/statuses/01FF25D5Q0DH7CHD57CTRS6WK0",
"orderedItems": []string{"http://localhost:8080/users/admin/statuses/01FF25D5Q0DH7CHD57CTRS6WK0"},
"totalItems": 1,
})
assert.Equal(suite.T(), expect, string(b))
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/accounts/accountverify_test.go
Expand Up @@ -79,7 +79,7 @@ func (suite *AccountVerifyTestSuite) TestAccountVerifyGet() {
suite.Equal("http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/small/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg", apimodelAccount.HeaderStatic)
suite.Equal(2, apimodelAccount.FollowersCount)
suite.Equal(2, apimodelAccount.FollowingCount)
suite.Equal(6, apimodelAccount.StatusesCount)
suite.Equal(7, apimodelAccount.StatusesCount)
suite.EqualValues(gtsmodel.VisibilityPublic, apimodelAccount.Source.Privacy)
suite.Equal(testAccount.Language, apimodelAccount.Source.Language)
suite.Equal(testAccount.NoteRaw, apimodelAccount.Source.Note)
Expand Down
12 changes: 6 additions & 6 deletions internal/api/client/instance/instancepatch_test.go
Expand Up @@ -133,7 +133,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() {
},
"stats": {
"domain_count": 2,
"status_count": 18,
"status_count": 19,
"user_count": 4
},
"thumbnail": "http://localhost:8080/assets/logo.png",
Expand Down Expand Up @@ -250,7 +250,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() {
},
"stats": {
"domain_count": 2,
"status_count": 18,
"status_count": 19,
"user_count": 4
},
"thumbnail": "http://localhost:8080/assets/logo.png",
Expand Down Expand Up @@ -367,7 +367,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() {
},
"stats": {
"domain_count": 2,
"status_count": 18,
"status_count": 19,
"user_count": 4
},
"thumbnail": "http://localhost:8080/assets/logo.png",
Expand Down Expand Up @@ -535,7 +535,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() {
},
"stats": {
"domain_count": 2,
"status_count": 18,
"status_count": 19,
"user_count": 4
},
"thumbnail": "http://localhost:8080/assets/logo.png",
Expand Down Expand Up @@ -674,7 +674,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
},
"stats": {
"domain_count": 2,
"status_count": 18,
"status_count": 19,
"user_count": 4
},
"thumbnail": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/original/`+instanceAccount.AvatarMediaAttachment.ID+`.gif",`+`
Expand Down Expand Up @@ -828,7 +828,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch9() {
},
"stats": {
"domain_count": 2,
"status_count": 18,
"status_count": 19,
"user_count": 4
},
"thumbnail": "http://localhost:8080/assets/logo.png",
Expand Down
6 changes: 3 additions & 3 deletions internal/api/client/search/searchget_test.go
Expand Up @@ -877,7 +877,7 @@ func (suite *SearchGetTestSuite) TestSearchAAny() {
}

suite.Len(searchResult.Accounts, 5)
suite.Len(searchResult.Statuses, 5)
suite.Len(searchResult.Statuses, 6)
suite.Len(searchResult.Hashtags, 0)
}

Expand Down Expand Up @@ -918,7 +918,7 @@ func (suite *SearchGetTestSuite) TestSearchAAnyFollowingOnly() {
}

suite.Len(searchResult.Accounts, 2)
suite.Len(searchResult.Statuses, 5)
suite.Len(searchResult.Statuses, 6)
suite.Len(searchResult.Hashtags, 0)
}

Expand Down Expand Up @@ -959,7 +959,7 @@ func (suite *SearchGetTestSuite) TestSearchAStatuses() {
}

suite.Len(searchResult.Accounts, 0)
suite.Len(searchResult.Statuses, 5)
suite.Len(searchResult.Statuses, 6)
suite.Len(searchResult.Hashtags, 0)
}

Expand Down
8 changes: 4 additions & 4 deletions internal/api/client/statuses/statusmute_test.go
Expand Up @@ -130,8 +130,8 @@ func (suite *StatusMuteTestSuite) TestMuteUnmuteStatus() {
"header_static": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/small/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg",
"followers_count": 2,
"following_count": 2,
"statuses_count": 6,
"last_status_at": "2022-05-20T11:41:10.000Z",
"statuses_count": 7,
"last_status_at": "2023-12-10T09:24:00.000Z",
"emojis": [],
"fields": [],
"enable_rss": true,
Expand Down Expand Up @@ -193,8 +193,8 @@ func (suite *StatusMuteTestSuite) TestMuteUnmuteStatus() {
"header_static": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/small/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg",
"followers_count": 2,
"following_count": 2,
"statuses_count": 6,
"last_status_at": "2022-05-20T11:41:10.000Z",
"statuses_count": 7,
"last_status_at": "2023-12-10T09:24:00.000Z",
"emojis": [],
"fields": [],
"enable_rss": true,
Expand Down
24 changes: 12 additions & 12 deletions internal/db/bundb/account_test.go
Expand Up @@ -42,47 +42,47 @@ type AccountTestSuite struct {
func (suite *AccountTestSuite) TestGetAccountStatuses() {
statuses, err := suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 20, false, false, "", "", false, false)
suite.NoError(err)
suite.Len(statuses, 6)
suite.Len(statuses, 7)
}

func (suite *AccountTestSuite) TestGetAccountStatusesPageDown() {
// get the first page
statuses, err := suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 2, false, false, "", "", false, false)
statuses, err := suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 3, false, false, "", "", false, false)
if err != nil {
suite.FailNow(err.Error())
}
suite.Len(statuses, 2)
suite.Len(statuses, 3)

// get the second page
statuses, err = suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 2, false, false, statuses[len(statuses)-1].ID, "", false, false)
statuses, err = suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 3, false, false, statuses[len(statuses)-1].ID, "", false, false)
if err != nil {
suite.FailNow(err.Error())
}
suite.Len(statuses, 2)
suite.Len(statuses, 3)

// get the third page
statuses, err = suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 2, false, false, statuses[len(statuses)-1].ID, "", false, false)
statuses, err = suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 3, false, false, statuses[len(statuses)-1].ID, "", false, false)
if err != nil {
suite.FailNow(err.Error())
}
suite.Len(statuses, 2)
suite.Len(statuses, 1)

// try to get the last page (should be empty)
statuses, err = suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 2, false, false, statuses[len(statuses)-1].ID, "", false, false)
statuses, err = suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 3, false, false, statuses[len(statuses)-1].ID, "", false, false)
suite.ErrorIs(err, db.ErrNoEntries)
suite.Empty(statuses)
}

func (suite *AccountTestSuite) TestGetAccountStatusesExcludeRepliesAndReblogs() {
statuses, err := suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 20, true, true, "", "", false, false)
suite.NoError(err)
suite.Len(statuses, 6)
suite.Len(statuses, 7)
}

func (suite *AccountTestSuite) TestGetAccountStatusesExcludeRepliesAndReblogsPublicOnly() {
statuses, err := suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 20, true, true, "", "", false, true)
suite.NoError(err)
suite.Len(statuses, 1)
suite.Len(statuses, 2)
}

func (suite *AccountTestSuite) TestGetAccountStatusesMediaOnly() {
Expand Down Expand Up @@ -306,13 +306,13 @@ func (suite *AccountTestSuite) TestUpdateAccount() {
func (suite *AccountTestSuite) TestGetAccountLastPosted() {
lastPosted, err := suite.db.GetAccountLastPosted(context.Background(), suite.testAccounts["local_account_1"].ID, false)
suite.NoError(err)
suite.EqualValues(1653046870, lastPosted.Unix())
suite.EqualValues(1702200240, lastPosted.Unix())
}

func (suite *AccountTestSuite) TestGetAccountLastPostedWebOnly() {
lastPosted, err := suite.db.GetAccountLastPosted(context.Background(), suite.testAccounts["local_account_1"].ID, true)
suite.NoError(err)
suite.EqualValues(1634726437, lastPosted.Unix())
suite.EqualValues(1702200240, lastPosted.Unix())
}

func (suite *AccountTestSuite) TestInsertAccountWithDefaults() {
Expand Down
2 changes: 1 addition & 1 deletion internal/db/bundb/basic_test.go
Expand Up @@ -121,7 +121,7 @@ func (suite *BasicTestSuite) TestGetAllStatuses() {
s := []*gtsmodel.Status{}
err := suite.db.GetAll(context.Background(), &s)
suite.NoError(err)
suite.Len(s, 22)
suite.Len(s, 23)
}

func (suite *BasicTestSuite) TestGetAllNotNull() {
Expand Down
2 changes: 1 addition & 1 deletion internal/db/bundb/instance_test.go
Expand Up @@ -47,7 +47,7 @@ func (suite *InstanceTestSuite) TestCountInstanceUsersRemote() {
func (suite *InstanceTestSuite) TestCountInstanceStatuses() {
count, err := suite.db.CountInstanceStatuses(context.Background(), config.GetHost())
suite.NoError(err)
suite.Equal(18, count)
suite.Equal(19, count)
}

func (suite *InstanceTestSuite) TestCountInstanceStatusesRemote() {
Expand Down
10 changes: 5 additions & 5 deletions internal/db/bundb/timeline_test.go
Expand Up @@ -157,7 +157,7 @@ func (suite *TimelineTestSuite) TestGetHomeTimeline() {
suite.FailNow(err.Error())
}

suite.checkStatuses(s, id.Highest, id.Lowest, 18)
suite.checkStatuses(s, id.Highest, id.Lowest, 19)
}

func (suite *TimelineTestSuite) TestGetHomeTimelineNoFollowing() {
Expand Down Expand Up @@ -189,7 +189,7 @@ func (suite *TimelineTestSuite) TestGetHomeTimelineNoFollowing() {
suite.FailNow(err.Error())
}

suite.checkStatuses(s, id.Highest, id.Lowest, 6)
suite.checkStatuses(s, id.Highest, id.Lowest, 7)
}

func (suite *TimelineTestSuite) TestGetHomeTimelineWithFutureStatus() {
Expand All @@ -211,7 +211,7 @@ func (suite *TimelineTestSuite) TestGetHomeTimelineWithFutureStatus() {
}

suite.NotContains(s, futureStatus)
suite.checkStatuses(s, id.Highest, id.Lowest, 18)
suite.checkStatuses(s, id.Highest, id.Lowest, 19)
}

func (suite *TimelineTestSuite) TestGetHomeTimelineBackToFront() {
Expand Down Expand Up @@ -242,8 +242,8 @@ func (suite *TimelineTestSuite) TestGetHomeTimelineFromHighest() {
}

suite.checkStatuses(s, id.Highest, id.Lowest, 5)
suite.Equal("01HEN2RZ8BG29Y5Z9VJC73HZW7", s[0].ID)
suite.Equal("01FN3VJGFH10KR7S2PB0GFJZYG", s[len(s)-1].ID)
suite.Equal("01HH9KYNQPA416TNJ53NSATP40", s[0].ID)
suite.Equal("01G20ZM733MGN8J344T4ZDDFY1", s[len(s)-1].ID)
}

func (suite *TimelineTestSuite) TestGetListTimelineNoParams() {
Expand Down

0 comments on commit d60edf7

Please sign in to comment.