mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-02 17:18:07 -06:00
[chore] move status filtering from type converter (#4306)
This finalizes the moving status filtering out of the type converter, and into its own `./internal/filter/` subpkg :) Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4306 Co-authored-by: kim <grufwub@gmail.com> Co-committed-by: kim <grufwub@gmail.com>
This commit is contained in:
parent
79914bdbf7
commit
66e1ec14aa
38 changed files with 565 additions and 846 deletions
|
|
@ -25,6 +25,7 @@ import (
|
|||
|
||||
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/cache"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtscontext"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
|
@ -159,6 +160,31 @@ func (f *Filter) getStatusFilterResults(
|
|||
return results, nil
|
||||
}
|
||||
|
||||
// Check if status is boost.
|
||||
if status.BoostOfID != "" {
|
||||
if status.BoostOf == nil {
|
||||
var err error
|
||||
|
||||
// Ensure original status is loaded on boost.
|
||||
status.BoostOf, err = f.state.DB.GetStatusByID(
|
||||
gtscontext.SetBarebones(ctx),
|
||||
status.BoostOfID,
|
||||
)
|
||||
if err != nil {
|
||||
return results, gtserror.Newf("error getting boosted status of %s: %w", status.URI, err)
|
||||
}
|
||||
}
|
||||
|
||||
// From here look at details
|
||||
// for original boosted status.
|
||||
status = status.BoostOf
|
||||
}
|
||||
|
||||
// For proper status filtering we need all fields populated.
|
||||
if err := f.state.DB.PopulateStatus(ctx, status); err != nil {
|
||||
return results, gtserror.Newf("error populating status: %w", err)
|
||||
}
|
||||
|
||||
// Get the string fields status is
|
||||
// filterable on for keyword matching.
|
||||
fields := getFilterableFields(status)
|
||||
|
|
@ -169,11 +195,6 @@ func (f *Filter) getStatusFilterResults(
|
|||
return results, gtserror.Newf("error getting account filters: %w", err)
|
||||
}
|
||||
|
||||
// For proper status filtering we need all fields populated.
|
||||
if err := f.state.DB.PopulateStatus(ctx, status); err != nil {
|
||||
return results, gtserror.Newf("error populating status: %w", err)
|
||||
}
|
||||
|
||||
// Generate result for each filter.
|
||||
for _, filter := range filters {
|
||||
|
||||
|
|
|
|||
201
internal/filter/status/status_test.go
Normal file
201
internal/filter/status/status_test.go
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
// 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 status_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/filter/status"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/id"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/state"
|
||||
"code.superseriousbusiness.org/gotosocial/internal/typeutils"
|
||||
"code.superseriousbusiness.org/gotosocial/testrig"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type StatusFilterTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
state state.State
|
||||
filter *status.Filter
|
||||
converter *typeutils.Converter
|
||||
|
||||
testAccounts map[string]*gtsmodel.Account
|
||||
testFilters map[string]*gtsmodel.Filter
|
||||
testStatuses map[string]*gtsmodel.Status
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) SetupTest() {
|
||||
suite.state.Caches.Init()
|
||||
|
||||
testrig.InitTestConfig()
|
||||
testrig.InitTestLog()
|
||||
|
||||
db := testrig.NewTestDB(&suite.state)
|
||||
suite.state.DB = db
|
||||
|
||||
suite.filter = status.NewFilter(&suite.state)
|
||||
|
||||
suite.converter = typeutils.NewConverter(&suite.state)
|
||||
|
||||
suite.testAccounts = testrig.NewTestAccounts()
|
||||
suite.testFilters = testrig.NewTestFilters()
|
||||
suite.testStatuses = testrig.NewTestStatuses()
|
||||
|
||||
testrig.StandardDBSetup(suite.state.DB, nil)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TearDownTest() {
|
||||
testrig.StandardDBTeardown(suite.state.DB)
|
||||
testrig.StopWorkers(&suite.state)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TestHideFilteredStatus() {
|
||||
filtered, hide, err := suite.testFilterStatus(gtsmodel.FilterActionHide, false)
|
||||
suite.NoError(err)
|
||||
suite.True(hide)
|
||||
suite.Empty(filtered)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TestWarnFilteredStatus() {
|
||||
filtered, hide, err := suite.testFilterStatus(gtsmodel.FilterActionWarn, false)
|
||||
suite.NoError(err)
|
||||
suite.False(hide)
|
||||
suite.NotEmpty(filtered)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TestHideFilteredBoost() {
|
||||
filtered, hide, err := suite.testFilterStatus(gtsmodel.FilterActionHide, true)
|
||||
suite.NoError(err)
|
||||
suite.True(hide)
|
||||
suite.Empty(filtered)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TestWarnFilteredBoost() {
|
||||
filtered, hide, err := suite.testFilterStatus(gtsmodel.FilterActionWarn, true)
|
||||
suite.NoError(err)
|
||||
suite.False(hide)
|
||||
suite.NotEmpty(filtered)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TestHashtagWholewordStatusFiltered() {
|
||||
suite.testFilteredStatusWithHashtag(true, false)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TestHashtagWholewordBoostFiltered() {
|
||||
suite.testFilteredStatusWithHashtag(true, true)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TestHashtagAnywhereStatusFiltered() {
|
||||
suite.testFilteredStatusWithHashtag(false, false)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) TestHashtagAnywhereBoostFiltered() {
|
||||
suite.testFilteredStatusWithHashtag(false, true)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) testFilterStatus(action gtsmodel.FilterAction, boost bool) ([]apimodel.FilterResult, bool, error) {
|
||||
ctx := suite.T().Context()
|
||||
|
||||
status := suite.testStatuses["admin_account_status_1"]
|
||||
status.Content += " fnord"
|
||||
status.Text += " fnord"
|
||||
|
||||
if boost {
|
||||
// Modify a fixture boost into a boost of the above status.
|
||||
boost := suite.testStatuses["admin_account_status_4"]
|
||||
boost.BoostOf = status
|
||||
boost.BoostOfID = status.ID
|
||||
status = boost
|
||||
}
|
||||
|
||||
requester := suite.testAccounts["local_account_1"]
|
||||
|
||||
filter := suite.testFilters["local_account_1_filter_1"]
|
||||
filter.Action = action
|
||||
|
||||
err := suite.state.DB.UpdateFilter(ctx, filter, "action")
|
||||
suite.NoError(err)
|
||||
|
||||
return suite.filter.StatusFilterResultsInContext(ctx,
|
||||
requester,
|
||||
status,
|
||||
gtsmodel.FilterContextHome,
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *StatusFilterTestSuite) testFilteredStatusWithHashtag(wholeword, boost bool) {
|
||||
ctx := suite.T().Context()
|
||||
|
||||
status := new(gtsmodel.Status)
|
||||
*status = *suite.testStatuses["admin_account_status_1"]
|
||||
status.Content = `<p>doggo doggin' it</p><p><a href="https://example.test/tags/dogsofmastodon" class="mention hashtag" rel="tag nofollow noreferrer noopener" target="_blank">#<span>dogsofmastodon</span></a></p>`
|
||||
|
||||
if boost {
|
||||
boost, err := suite.converter.StatusToBoost(
|
||||
suite.T().Context(),
|
||||
status,
|
||||
suite.testAccounts["admin_account"],
|
||||
"",
|
||||
)
|
||||
suite.NoError(err)
|
||||
status = boost
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
requester := suite.testAccounts["local_account_1"]
|
||||
|
||||
filter := >smodel.Filter{
|
||||
ID: id.NewULID(),
|
||||
Title: id.NewULID(),
|
||||
AccountID: requester.ID,
|
||||
Action: gtsmodel.FilterActionWarn,
|
||||
Contexts: gtsmodel.FilterContexts(gtsmodel.FilterContextHome),
|
||||
}
|
||||
|
||||
filterKeyword := >smodel.FilterKeyword{
|
||||
ID: id.NewULID(),
|
||||
FilterID: filter.ID,
|
||||
Keyword: "#dogsofmastodon",
|
||||
WholeWord: &wholeword,
|
||||
}
|
||||
|
||||
filter.KeywordIDs = []string{filterKeyword.ID}
|
||||
|
||||
err = suite.state.DB.PutFilterKeyword(ctx, filterKeyword)
|
||||
suite.NoError(err)
|
||||
|
||||
err = suite.state.DB.PutFilter(ctx, filter)
|
||||
suite.NoError(err)
|
||||
|
||||
filtered, hide, err := suite.filter.StatusFilterResultsInContext(ctx,
|
||||
requester,
|
||||
status,
|
||||
gtsmodel.FilterContextHome,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.False(hide)
|
||||
suite.NotEmpty(filtered)
|
||||
}
|
||||
|
||||
func TestStatusFilterTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(StatusFilterTestSuite))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue