Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bugfix] Ensure pre renders as expected, fix orderedCollectionPage #2434

Merged
merged 1 commit into from Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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