diff options
Diffstat (limited to 'internal/db')
| -rw-r--r-- | internal/db/account.go | 2 | ||||
| -rw-r--r-- | internal/db/bundb/account.go | 67 | ||||
| -rw-r--r-- | internal/db/bundb/account_test.go | 10 | ||||
| -rw-r--r-- | internal/db/bundb/basic_test.go | 2 | ||||
| -rw-r--r-- | internal/db/bundb/instance_test.go | 4 | ||||
| -rw-r--r-- | internal/db/bundb/migrations/20250314120945_add_gallery_web_layout.go | 85 |
6 files changed, 136 insertions, 34 deletions
diff --git a/internal/db/account.go b/internal/db/account.go index aa0dfd985..cfb81308f 100644 --- a/internal/db/account.go +++ b/internal/db/account.go @@ -121,7 +121,7 @@ type Account interface { // returning statuses that should be visible via the web view of a *LOCAL* account. // // In the case of no statuses, this function will return db.ErrNoEntries. - GetAccountWebStatuses(ctx context.Context, account *gtsmodel.Account, limit int, maxID string) ([]*gtsmodel.Status, error) + GetAccountWebStatuses(ctx context.Context, account *gtsmodel.Account, mediaOnly bool, limit int, maxID string) ([]*gtsmodel.Status, error) // GetInstanceAccount returns the instance account for the given domain. // If domain is empty, this instance account will be returned. diff --git a/internal/db/bundb/account.go b/internal/db/bundb/account.go index f905101e4..aacfcd247 100644 --- a/internal/db/bundb/account.go +++ b/internal/db/bundb/account.go @@ -878,6 +878,29 @@ func (a *accountDB) GetAccountFaves(ctx context.Context, accountID string) ([]*g return *faves, nil } +func qMediaOnly(q *bun.SelectQuery) *bun.SelectQuery { + // Attachments are stored as a json object; this + // implementation differs between SQLite and Postgres, + // so we have to be thorough to cover all eventualities + return q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery { + switch d := q.Dialect().Name(); d { + case dialect.PG: + return q. + Where("? IS NOT NULL", bun.Ident("status.attachments")). + Where("? != '{}'", bun.Ident("status.attachments")) + + case dialect.SQLite: + return q. + Where("? IS NOT NULL", bun.Ident("status.attachments")). + Where("? != 'null'", bun.Ident("status.attachments")). + Where("? != '[]'", bun.Ident("status.attachments")) + + default: + panic("dialect " + d.String() + " was neither pg nor sqlite") + } + }) +} + func (a *accountDB) GetAccountStatuses(ctx context.Context, accountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, mediaOnly bool, publicOnly bool) ([]*gtsmodel.Status, error) { // Ensure reasonable if limit < 0 { @@ -918,28 +941,9 @@ func (a *accountDB) GetAccountStatuses(ctx context.Context, accountID string, li q = q.Where("? IS NULL", bun.Ident("status.boost_of_id")) } + // Respect media-only preference. if mediaOnly { - // Attachments are stored as a json object; this - // implementation differs between SQLite and Postgres, - // so we have to be thorough to cover all eventualities - q = q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery { - switch a.db.Dialect().Name() { - case dialect.PG: - return q. - Where("? IS NOT NULL", bun.Ident("status.attachments")). - Where("? != '{}'", bun.Ident("status.attachments")) - case dialect.SQLite: - return q. - Where("? IS NOT NULL", bun.Ident("status.attachments")). - Where("? != ''", bun.Ident("status.attachments")). - Where("? != 'null'", bun.Ident("status.attachments")). - Where("? != '{}'", bun.Ident("status.attachments")). - Where("? != '[]'", bun.Ident("status.attachments")) - default: - log.Panic(ctx, "db dialect was neither pg nor sqlite") - return q - } - }) + q = qMediaOnly(q) } if publicOnly { @@ -1018,6 +1022,7 @@ func (a *accountDB) GetAccountPinnedStatuses(ctx context.Context, accountID stri func (a *accountDB) GetAccountWebStatuses( ctx context.Context, account *gtsmodel.Account, + mediaOnly bool, limit int, maxID string, ) ([]*gtsmodel.Status, error) { @@ -1046,10 +1051,7 @@ func (a *accountDB) GetAccountWebStatuses( TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")). // Select only IDs from table Column("status.id"). - Where("? = ?", bun.Ident("status.account_id"), account.ID). - // Don't show replies or boosts. - Where("? IS NULL", bun.Ident("status.in_reply_to_uri")). - Where("? IS NULL", bun.Ident("status.boost_of_id")) + Where("? = ?", bun.Ident("status.account_id"), account.ID) // Select statuses for this account according // to their web visibility preference. @@ -1074,10 +1076,19 @@ func (a *accountDB) GetAccountWebStatuses( ) } - // Don't show local-only statuses on the web view. - q = q.Where("? = ?", bun.Ident("status.federated"), true) + // Don't show replies, boosts, or + // local-only statuses on the web view. + q = q. + Where("? IS NULL", bun.Ident("status.in_reply_to_uri")). + Where("? IS NULL", bun.Ident("status.boost_of_id")). + Where("? = ?", bun.Ident("status.federated"), true) + + // Respect media-only preference. + if mediaOnly { + q = qMediaOnly(q) + } - // return only statuses LOWER (ie., older) than maxID + // Return only statuses LOWER (ie., older) than maxID if maxID == "" { maxID = id.Highest } diff --git a/internal/db/bundb/account_test.go b/internal/db/bundb/account_test.go index 879250408..e3d36855e 100644 --- a/internal/db/bundb/account_test.go +++ b/internal/db/bundb/account_test.go @@ -49,6 +49,12 @@ func (suite *AccountTestSuite) TestGetAccountStatuses() { suite.Len(statuses, 9) } +func (suite *AccountTestSuite) TestGetAccountWebStatusesMediaOnly() { + statuses, err := suite.db.GetAccountWebStatuses(context.Background(), suite.testAccounts["local_account_3"], true, 20, "") + suite.NoError(err) + suite.Len(statuses, 2) +} + func (suite *AccountTestSuite) TestGetAccountStatusesPageDown() { // get the first page statuses, err := suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 3, false, false, "", "", false, false) @@ -490,7 +496,7 @@ func (suite *AccountTestSuite) TestGetAccountsAll() { suite.FailNow(err.Error()) } - suite.Len(accounts, 9) + suite.Len(accounts, 10) } func (suite *AccountTestSuite) TestGetAccountsMaxID() { @@ -564,7 +570,7 @@ func (suite *AccountTestSuite) TestGetAccountsMinID() { suite.FailNow(err.Error()) } - suite.Len(accounts, 3) + suite.Len(accounts, 4) } func (suite *AccountTestSuite) TestGetAccountsModsOnly() { diff --git a/internal/db/bundb/basic_test.go b/internal/db/bundb/basic_test.go index e20aab765..1f2d1ac48 100644 --- a/internal/db/bundb/basic_test.go +++ b/internal/db/bundb/basic_test.go @@ -114,7 +114,7 @@ func (suite *BasicTestSuite) TestGetAllStatuses() { s := []*gtsmodel.Status{} err := suite.db.GetAll(context.Background(), &s) suite.NoError(err) - suite.Len(s, 28) + suite.Len(s, 30) } func (suite *BasicTestSuite) TestGetAllNotNull() { diff --git a/internal/db/bundb/instance_test.go b/internal/db/bundb/instance_test.go index 1364bacc2..c0d63003d 100644 --- a/internal/db/bundb/instance_test.go +++ b/internal/db/bundb/instance_test.go @@ -35,7 +35,7 @@ type InstanceTestSuite struct { func (suite *InstanceTestSuite) TestCountInstanceUsers() { count, err := suite.db.CountInstanceUsers(context.Background(), config.GetHost()) suite.NoError(err) - suite.Equal(4, count) + suite.Equal(5, count) } func (suite *InstanceTestSuite) TestCountInstanceUsersRemote() { @@ -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(21, count) + suite.Equal(23, count) } func (suite *InstanceTestSuite) TestCountInstanceStatusesRemote() { diff --git a/internal/db/bundb/migrations/20250314120945_add_gallery_web_layout.go b/internal/db/bundb/migrations/20250314120945_add_gallery_web_layout.go new file mode 100644 index 000000000..64b133cd5 --- /dev/null +++ b/internal/db/bundb/migrations/20250314120945_add_gallery_web_layout.go @@ -0,0 +1,85 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +package migrations + +import ( + "context" + + "github.com/superseriousbusiness/gotosocial/internal/log" + "github.com/uptrace/bun" +) + +func init() { + up := func(ctx context.Context, db *bun.DB) error { + return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { + + // Add new column to settings. + if _, err := tx. + NewAddColumn(). + Table("account_settings"). + ColumnExpr( + "? SMALLINT NOT NULL DEFAULT ?", + bun.Ident("web_layout"), 1, + ). + Exec(ctx); err != nil { + return err + } + + // Drop existing statuses web index as it's out of date. + log.Info(ctx, "updating statuses_profile_web_view_idx, this may take a while, please wait!") + if _, err := tx. + NewDropIndex(). + Index("statuses_profile_web_view_idx"). + IfExists(). + Exec(ctx); err != nil { + return err + } + + // Note: "attachments" field is not included in + // the index below as SQLite is fussy about using it, + // and it prevents this index from being used + // properly in non media-only queries. + if _, err := tx. + NewCreateIndex(). + Table("statuses"). + Index("statuses_profile_web_view_idx"). + Column( + "account_id", + "visibility", + "in_reply_to_uri", + "boost_of_id", + "federated", + ). + ColumnExpr("? DESC", bun.Ident("id")). + IfNotExists(). + Exec(ctx); err != nil { + return err + } + + return nil + }) + } + + down := func(ctx context.Context, db *bun.DB) error { + return nil + } + + if err := Migrations.Register(up, down); err != nil { + panic(err) + } +} |
