summaryrefslogtreecommitdiff
path: root/internal/processing
diff options
context:
space:
mode:
Diffstat (limited to 'internal/processing')
-rw-r--r--internal/processing/account/account_test.go8
-rw-r--r--internal/processing/account/bookmarks.go2
-rw-r--r--internal/processing/account/statuses.go2
-rw-r--r--internal/processing/admin/admin_test.go2
-rw-r--r--internal/processing/common/common.go24
-rw-r--r--internal/processing/common/status.go18
-rw-r--r--internal/processing/conversations/conversations.go41
-rw-r--r--internal/processing/conversations/conversations_test.go9
-rw-r--r--internal/processing/conversations/get.go9
-rw-r--r--internal/processing/conversations/read.go6
-rw-r--r--internal/processing/conversations/update.go125
-rw-r--r--internal/processing/media/media_test.go6
-rw-r--r--internal/processing/polls/poll_test.go17
-rw-r--r--internal/processing/processor.go9
-rw-r--r--internal/processing/processor_test.go2
-rw-r--r--internal/processing/search/util.go2
-rw-r--r--internal/processing/status/context.go27
-rw-r--r--internal/processing/status/status_test.go4
-rw-r--r--internal/processing/stream/statusupdate_test.go2
-rw-r--r--internal/processing/timeline/faved.go2
-rw-r--r--internal/processing/timeline/home.go17
-rw-r--r--internal/processing/timeline/list.go17
-rw-r--r--internal/processing/timeline/notification.go92
-rw-r--r--internal/processing/timeline/public.go32
-rw-r--r--internal/processing/timeline/tag.go17
-rw-r--r--internal/processing/timeline/timeline.go33
-rw-r--r--internal/processing/timeline/timeline_test.go2
-rw-r--r--internal/processing/workers/fromclientapi.go15
-rw-r--r--internal/processing/workers/fromclientapi_test.go8
-rw-r--r--internal/processing/workers/fromfediapi.go15
-rw-r--r--internal/processing/workers/surface.go2
-rw-r--r--internal/processing/workers/surfacenotify.go121
-rw-r--r--internal/processing/workers/surfacenotify_test.go5
-rw-r--r--internal/processing/workers/surfacetimeline.go65
-rw-r--r--internal/processing/workers/workers.go3
35 files changed, 417 insertions, 344 deletions
diff --git a/internal/processing/account/account_test.go b/internal/processing/account/account_test.go
index 4af63d1b3..d4fb6ddfb 100644
--- a/internal/processing/account/account_test.go
+++ b/internal/processing/account/account_test.go
@@ -25,6 +25,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/db"
"code.superseriousbusiness.org/gotosocial/internal/email"
"code.superseriousbusiness.org/gotosocial/internal/federation"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/media"
@@ -104,9 +105,10 @@ func (suite *AccountStandardTestSuite) SetupTest() {
suite.sentEmails = make(map[string]string)
suite.emailSender = testrig.NewEmailSender("../../../web/template/", suite.sentEmails)
- filter := visibility.NewFilter(&suite.state)
- common := common.New(&suite.state, suite.mediaManager, suite.tc, suite.federator, filter)
- suite.accountProcessor = account.New(&common, &suite.state, suite.tc, suite.mediaManager, suite.federator, filter, processing.GetParseMentionFunc(&suite.state, suite.federator))
+ visFilter := visibility.NewFilter(&suite.state)
+ mutesFilter := mutes.NewFilter(&suite.state)
+ common := common.New(&suite.state, suite.mediaManager, suite.tc, suite.federator, visFilter, mutesFilter)
+ suite.accountProcessor = account.New(&common, &suite.state, suite.tc, suite.mediaManager, suite.federator, visFilter, processing.GetParseMentionFunc(&suite.state, suite.federator))
testrig.StandardDBSetup(suite.db, nil)
testrig.StandardStorageSetup(suite.storage, "../../../testrig/media")
}
diff --git a/internal/processing/account/bookmarks.go b/internal/processing/account/bookmarks.go
index 7c7f7cb07..329bcf30c 100644
--- a/internal/processing/account/bookmarks.go
+++ b/internal/processing/account/bookmarks.go
@@ -75,7 +75,7 @@ func (p *Processor) BookmarksGet(ctx context.Context, requestingAccount *gtsmode
}
// Convert the status.
- item, err := p.converter.StatusToAPIStatus(ctx, status, requestingAccount, statusfilter.FilterContextNone, nil, nil)
+ item, err := p.converter.StatusToAPIStatus(ctx, status, requestingAccount, statusfilter.FilterContextNone, nil)
if err != nil {
log.Errorf(ctx, "error converting bookmarked status to api: %s", err)
continue
diff --git a/internal/processing/account/statuses.go b/internal/processing/account/statuses.go
index 191fdcb5f..0ff9ef7e1 100644
--- a/internal/processing/account/statuses.go
+++ b/internal/processing/account/statuses.go
@@ -105,7 +105,7 @@ func (p *Processor) StatusesGet(
for _, s := range filtered {
// Convert filtered statuses to API statuses.
- item, err := p.converter.StatusToAPIStatus(ctx, s, requestingAccount, statusfilter.FilterContextAccount, filters, nil)
+ item, err := p.converter.StatusToAPIStatus(ctx, s, requestingAccount, statusfilter.FilterContextAccount, filters)
if err != nil {
log.Errorf(ctx, "error convering to api status: %v", err)
continue
diff --git a/internal/processing/admin/admin_test.go b/internal/processing/admin/admin_test.go
index db46fb17f..8f2eb23f2 100644
--- a/internal/processing/admin/admin_test.go
+++ b/internal/processing/admin/admin_test.go
@@ -24,6 +24,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/email"
"code.superseriousbusiness.org/gotosocial/internal/federation"
"code.superseriousbusiness.org/gotosocial/internal/filter/interaction"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/media"
@@ -113,6 +114,7 @@ func (suite *AdminStandardTestSuite) SetupTest() {
suite.emailSender,
testrig.NewNoopWebPushSender(),
visibility.NewFilter(&suite.state),
+ mutes.NewFilter(&suite.state),
interaction.NewFilter(&suite.state),
)
diff --git a/internal/processing/common/common.go b/internal/processing/common/common.go
index 9f4753147..bebbdffea 100644
--- a/internal/processing/common/common.go
+++ b/internal/processing/common/common.go
@@ -19,6 +19,7 @@ package common
import (
"code.superseriousbusiness.org/gotosocial/internal/federation"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/media"
"code.superseriousbusiness.org/gotosocial/internal/state"
@@ -29,11 +30,12 @@ import (
// common to multiple logical domains of the
// processing subsection of the codebase.
type Processor struct {
- state *state.State
- media *media.Manager
- converter *typeutils.Converter
- federator *federation.Federator
- visFilter *visibility.Filter
+ state *state.State
+ media *media.Manager
+ converter *typeutils.Converter
+ federator *federation.Federator
+ visFilter *visibility.Filter
+ muteFilter *mutes.Filter
}
// New returns a new Processor instance.
@@ -43,12 +45,14 @@ func New(
converter *typeutils.Converter,
federator *federation.Federator,
visFilter *visibility.Filter,
+ muteFilter *mutes.Filter,
) Processor {
return Processor{
- state: state,
- media: media,
- converter: converter,
- federator: federator,
- visFilter: visFilter,
+ state: state,
+ media: media,
+ converter: converter,
+ federator: federator,
+ visFilter: visFilter,
+ muteFilter: muteFilter,
}
}
diff --git a/internal/processing/common/status.go b/internal/processing/common/status.go
index 14245f88a..441a58384 100644
--- a/internal/processing/common/status.go
+++ b/internal/processing/common/status.go
@@ -25,7 +25,6 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/db"
"code.superseriousbusiness.org/gotosocial/internal/federation/dereferencing"
statusfilter "code.superseriousbusiness.org/gotosocial/internal/filter/status"
- "code.superseriousbusiness.org/gotosocial/internal/filter/usermute"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/log"
@@ -216,7 +215,6 @@ func (p *Processor) GetAPIStatus(
requester,
statusfilter.FilterContextNone,
nil,
- nil,
)
if err != nil {
err := gtserror.Newf("error converting: %w", err)
@@ -238,7 +236,6 @@ func (p *Processor) GetVisibleAPIStatuses(
statuses []*gtsmodel.Status,
filterContext statusfilter.FilterContext,
filters []*gtsmodel.Filter,
- userMutes []*gtsmodel.UserMute,
) []apimodel.Status {
// Start new log entry with
@@ -247,9 +244,6 @@ func (p *Processor) GetVisibleAPIStatuses(
l := log.WithContext(ctx).
WithField("caller", log.Caller(3))
- // Compile mutes to useable user mutes for type converter.
- compUserMutes := usermute.NewCompiledUserMuteList(userMutes)
-
// Iterate filtered statuses for conversion to API model.
apiStatuses := make([]apimodel.Status, 0, len(statuses))
for _, status := range statuses {
@@ -268,13 +262,23 @@ func (p *Processor) GetVisibleAPIStatuses(
continue
}
+ // Check whether this status is muted by requesting account.
+ muted, err := p.muteFilter.StatusMuted(ctx, requester, status)
+ if err != nil {
+ log.Errorf(ctx, "error checking mute: %v", err)
+ continue
+ }
+
+ if muted {
+ continue
+ }
+
// Convert to API status, taking mute / filter into account.
apiStatus, err := p.converter.StatusToAPIStatus(ctx,
status,
requester,
filterContext,
filters,
- compUserMutes,
)
if err != nil && !errors.Is(err, statusfilter.ErrHideStatus) {
l.Errorf("error converting: %v", err)
diff --git a/internal/processing/conversations/conversations.go b/internal/processing/conversations/conversations.go
index a4b8b7234..e31f60500 100644
--- a/internal/processing/conversations/conversations.go
+++ b/internal/processing/conversations/conversations.go
@@ -22,9 +22,8 @@ import (
"errors"
"code.superseriousbusiness.org/gotosocial/internal/db"
- "code.superseriousbusiness.org/gotosocial/internal/filter/usermute"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
- "code.superseriousbusiness.org/gotosocial/internal/gtscontext"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/state"
@@ -32,20 +31,23 @@ import (
)
type Processor struct {
- state *state.State
- converter *typeutils.Converter
- filter *visibility.Filter
+ state *state.State
+ converter *typeutils.Converter
+ visFilter *visibility.Filter
+ muteFilter *mutes.Filter
}
func New(
state *state.State,
converter *typeutils.Converter,
- filter *visibility.Filter,
+ visFilter *visibility.Filter,
+ muteFilter *mutes.Filter,
) Processor {
return Processor{
- state: state,
- converter: converter,
- filter: filter,
+ state: state,
+ converter: converter,
+ visFilter: visFilter,
+ muteFilter: muteFilter,
}
}
@@ -95,13 +97,13 @@ func (p *Processor) getConversationOwnedBy(
}
// getFiltersAndMutes gets the given account's filters and compiled mute list.
-func (p *Processor) getFiltersAndMutes(
+func (p *Processor) getFilters(
ctx context.Context,
requestingAccount *gtsmodel.Account,
-) ([]*gtsmodel.Filter, *usermute.CompiledUserMuteList, gtserror.WithCode) {
+) ([]*gtsmodel.Filter, gtserror.WithCode) {
filters, err := p.state.DB.GetFiltersForAccountID(ctx, requestingAccount.ID)
if err != nil {
- return nil, nil, gtserror.NewErrorInternalError(
+ return nil, gtserror.NewErrorInternalError(
gtserror.Newf(
"DB error getting filters for account %s: %w",
requestingAccount.ID,
@@ -109,18 +111,5 @@ func (p *Processor) getFiltersAndMutes(
),
)
}
-
- mutes, err := p.state.DB.GetAccountMutes(gtscontext.SetBarebones(ctx), requestingAccount.ID, nil)
- if err != nil {
- return nil, nil, gtserror.NewErrorInternalError(
- gtserror.Newf(
- "DB error getting mutes for account %s: %w",
- requestingAccount.ID,
- err,
- ),
- )
- }
- compiledMutes := usermute.NewCompiledUserMuteList(mutes)
-
- return filters, compiledMutes, nil
+ return filters, nil
}
diff --git a/internal/processing/conversations/conversations_test.go b/internal/processing/conversations/conversations_test.go
index 40145c2fb..383938564 100644
--- a/internal/processing/conversations/conversations_test.go
+++ b/internal/processing/conversations/conversations_test.go
@@ -27,6 +27,7 @@ import (
dbtest "code.superseriousbusiness.org/gotosocial/internal/db/test"
"code.superseriousbusiness.org/gotosocial/internal/email"
"code.superseriousbusiness.org/gotosocial/internal/federation"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/log"
@@ -53,7 +54,8 @@ type ConversationsTestSuite struct {
federator *federation.Federator
emailSender email.Sender
sentEmails map[string]string
- filter *visibility.Filter
+ visFilter *visibility.Filter
+ muteFilter *mutes.Filter
// standard suite models
testTokens map[string]*gtsmodel.Token
@@ -104,7 +106,8 @@ func (suite *ConversationsTestSuite) SetupTest() {
suite.state.DB = suite.db
suite.state.AdminActions = admin.New(suite.state.DB, &suite.state.Workers)
suite.tc = typeutils.NewConverter(&suite.state)
- suite.filter = visibility.NewFilter(&suite.state)
+ suite.visFilter = visibility.NewFilter(&suite.state)
+ suite.muteFilter = mutes.NewFilter(&suite.state)
suite.storage = testrig.NewInMemoryStorage()
suite.state.Storage = suite.storage
@@ -115,7 +118,7 @@ func (suite *ConversationsTestSuite) SetupTest() {
suite.sentEmails = make(map[string]string)
suite.emailSender = testrig.NewEmailSender("../../../web/template/", suite.sentEmails)
- suite.conversationsProcessor = conversations.New(&suite.state, suite.tc, suite.filter)
+ suite.conversationsProcessor = conversations.New(&suite.state, suite.tc, suite.visFilter, suite.muteFilter)
testrig.StandardDBSetup(suite.db, nil)
testrig.StandardStorageSetup(suite.storage, "../../../testrig/media")
diff --git a/internal/processing/conversations/get.go b/internal/processing/conversations/get.go
index 9218942bf..5324466c9 100644
--- a/internal/processing/conversations/get.go
+++ b/internal/processing/conversations/get.go
@@ -64,23 +64,20 @@ func (p *Processor) GetAll(
items := make([]interface{}, 0, count)
- filters, mutes, errWithCode := p.getFiltersAndMutes(ctx, requestingAccount)
+ filters, errWithCode := p.getFilters(ctx, requestingAccount)
if errWithCode != nil {
return nil, errWithCode
}
for _, conversation := range conversations {
// Convert conversation to frontend API model.
- apiConversation, err := p.converter.ConversationToAPIConversation(
- ctx,
+ apiConversation, err := p.converter.ConversationToAPIConversation(ctx,
conversation,
requestingAccount,
filters,
- mutes,
)
if err != nil {
- log.Errorf(
- ctx,
+ log.Errorf(ctx,
"error converting conversation %s to API representation: %v",
conversation.ID,
err,
diff --git a/internal/processing/conversations/read.go b/internal/processing/conversations/read.go
index 42f369582..4d16a4eeb 100644
--- a/internal/processing/conversations/read.go
+++ b/internal/processing/conversations/read.go
@@ -44,17 +44,15 @@ func (p *Processor) Read(
return nil, gtserror.NewErrorInternalError(err)
}
- filters, mutes, errWithCode := p.getFiltersAndMutes(ctx, requestingAccount)
+ filters, errWithCode := p.getFilters(ctx, requestingAccount)
if errWithCode != nil {
return nil, errWithCode
}
- apiConversation, err := p.converter.ConversationToAPIConversation(
- ctx,
+ apiConversation, err := p.converter.ConversationToAPIConversation(ctx,
conversation,
requestingAccount,
filters,
- mutes,
)
if err != nil {
err = gtserror.Newf("error converting conversation %s to API representation: %w", id, err)
diff --git a/internal/processing/conversations/update.go b/internal/processing/conversations/update.go
index 1651d5367..e4024a24a 100644
--- a/internal/processing/conversations/update.go
+++ b/internal/processing/conversations/update.go
@@ -31,10 +31,14 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/util"
)
-// ConversationNotification carries the arguments to processing/stream.Processor.Conversation.
+// ConversationNotification carries the arguments
+// to processing/stream.Processor.Conversation.
type ConversationNotification struct {
- // AccountID of a local account to deliver the notification to.
+
+ // AccountID of a local account to
+ // deliver the notification to.
AccountID string
+
// Conversation as the notification payload.
Conversation *apimodel.Conversation
}
@@ -46,11 +50,13 @@ func (p *Processor) UpdateConversationsForStatus(ctx context.Context, status *gt
// Only DMs are considered part of conversations.
return nil, nil
}
+
if status.BoostOfID != "" {
// Boosts can't be part of conversations.
// FUTURE: This may change if we ever implement quote posts.
return nil, nil
}
+
if status.ThreadID == "" {
// If the status doesn't have a thread ID, it didn't mention a local account,
// and thus can't be part of a conversation.
@@ -77,51 +83,15 @@ func (p *Processor) UpdateConversationsForStatus(ctx context.Context, status *gt
}
localAccount := participant
- // If the status is not visible to this account, skip processing it for this account.
- visible, err := p.filter.StatusVisible(ctx, localAccount, status)
+ // If status not visible to this account, skip further processing.
+ visible, err := p.visFilter.StatusVisible(ctx, localAccount, status)
if err != nil {
- log.Errorf(
- ctx,
- "error checking status %s visibility for account %s: %v",
- status.ID,
- localAccount.ID,
- err,
- )
+ log.Errorf(ctx, "error checking status %s visibility for account %s: %v", status.URI, localAccount.URI, err)
continue
} else if !visible {
continue
}
- // Is the status filtered or muted for this user?
- // Converting the status to an API status runs the filter/mute checks.
- filters, mutes, errWithCode := p.getFiltersAndMutes(ctx, localAccount)
- if errWithCode != nil {
- log.Error(ctx, errWithCode)
- continue
- }
- _, err = p.converter.StatusToAPIStatus(
- ctx,
- status,
- localAccount,
- statusfilter.FilterContextNotifications,
- filters,
- mutes,
- )
- if err != nil {
- // If the status matched a hide filter, skip processing it for this account.
- // If there was another kind of error, log that and skip it anyway.
- if !errors.Is(err, statusfilter.ErrHideStatus) {
- log.Errorf(
- ctx,
- "error checking status %s filtering/muting for account %s: %v",
- status.ID,
- localAccount.ID,
- err,
- )
- }
- continue
- }
-
// Collect other accounts participating in the conversation.
otherAccounts := make([]*gtsmodel.Account, 0, len(allParticipantsSet)-1)
otherAccountIDs := make([]string, 0, len(allParticipantsSet)-1)
@@ -133,20 +103,14 @@ func (p *Processor) UpdateConversationsForStatus(ctx context.Context, status *gt
}
// Check for a previously existing conversation, if there is one.
- conversation, err := p.state.DB.GetConversationByThreadAndAccountIDs(
- ctx,
+ conversation, err := p.state.DB.GetConversationByThreadAndAccountIDs(ctx,
status.ThreadID,
localAccount.ID,
otherAccountIDs,
)
if err != nil && !errors.Is(err, db.ErrNoEntries) {
- log.Errorf(
- ctx,
- "error trying to find a previous conversation for status %s and account %s: %v",
- status.ID,
- localAccount.ID,
- err,
- )
+ log.Errorf(ctx, "error finding previous conversation for status %s and account %s: %v",
+ status.URI, localAccount.URI, err)
continue
}
@@ -172,6 +136,7 @@ func (p *Processor) UpdateConversationsForStatus(ctx context.Context, status *gt
conversation.LastStatusID = status.ID
conversation.LastStatus = status
}
+
// If the conversation is unread, leave it marked as unread.
// If the conversation is read but this status might not have been, mark the conversation as unread.
if !statusAuthoredByConversationOwner {
@@ -181,43 +146,29 @@ func (p *Processor) UpdateConversationsForStatus(ctx context.Context, status *gt
// Create or update the conversation.
err = p.state.DB.UpsertConversation(ctx, conversation)
if err != nil {
- log.Errorf(
- ctx,
- "error creating or updating conversation %s for status %s and account %s: %v",
- conversation.ID,
- status.ID,
- localAccount.ID,
- err,
- )
+ log.Errorf(ctx, "error creating or updating conversation %s for status %s and account %s: %v",
+ conversation.ID, status.URI, localAccount.URI, err)
continue
}
// Link the conversation to the status.
if err := p.state.DB.LinkConversationToStatus(ctx, conversation.ID, status.ID); err != nil {
- log.Errorf(
- ctx,
- "error linking conversation %s to status %s: %v",
- conversation.ID,
- status.ID,
- err,
- )
+ log.Errorf(ctx, "error linking conversation %s to status %s: %v",
+ conversation.ID, status.URI, err)
continue
}
// Convert the conversation to API representation.
- apiConversation, err := p.converter.ConversationToAPIConversation(
- ctx,
+ apiConversation, err := p.converter.ConversationToAPIConversation(ctx,
conversation,
localAccount,
- filters,
- mutes,
+ nil,
)
if err != nil {
// If the conversation's last status matched a hide filter, skip it.
// If there was another kind of error, log that and skip it anyway.
if !errors.Is(err, statusfilter.ErrHideStatus) {
- log.Errorf(
- ctx,
+ log.Errorf(ctx,
"error converting conversation %s to API representation for account %s: %v",
status.ID,
localAccount.ID,
@@ -227,15 +178,31 @@ func (p *Processor) UpdateConversationsForStatus(ctx context.Context, status *gt
continue
}
- // Generate a notification,
- // unless the status was authored by the user who would be notified,
- // in which case they already know.
- if status.AccountID != localAccount.ID {
- notifications = append(notifications, ConversationNotification{
- AccountID: localAccount.ID,
- Conversation: apiConversation,
- })
+ // If status was authored by this participant,
+ // don't bother notifying, they already know!
+ if status.AccountID == localAccount.ID {
+ continue
}
+
+ // Check whether status is muted to local participant.
+ muted, err := p.muteFilter.StatusNotificationsMuted(ctx,
+ localAccount,
+ status,
+ )
+ if err != nil {
+ log.Errorf(ctx, "error checking status mute: %v", err)
+ continue
+ }
+
+ if muted {
+ continue
+ }
+
+ // Generate a notification,
+ notifications = append(notifications, ConversationNotification{
+ AccountID: localAccount.ID,
+ Conversation: apiConversation,
+ })
}
return notifications, nil
diff --git a/internal/processing/media/media_test.go b/internal/processing/media/media_test.go
index b074ae768..f2462a972 100644
--- a/internal/processing/media/media_test.go
+++ b/internal/processing/media/media_test.go
@@ -20,6 +20,7 @@ package media_test
import (
"code.superseriousbusiness.org/gotosocial/internal/admin"
"code.superseriousbusiness.org/gotosocial/internal/db"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/media"
@@ -82,8 +83,9 @@ func (suite *MediaStandardTestSuite) SetupTest() {
suite.transportController = testrig.NewTestTransportController(&suite.state, testrig.NewMockHTTPClient(nil, "../../../testrig/media"))
federator := testrig.NewTestFederator(&suite.state, suite.transportController, suite.mediaManager)
- filter := visibility.NewFilter(&suite.state)
- common := common.New(&suite.state, suite.mediaManager, suite.tc, federator, filter)
+ visFilter := visibility.NewFilter(&suite.state)
+ muteFilter := mutes.NewFilter(&suite.state)
+ common := common.New(&suite.state, suite.mediaManager, suite.tc, federator, visFilter, muteFilter)
suite.mediaProcessor = mediaprocessing.New(&common, &suite.state, suite.tc, federator, suite.mediaManager, suite.transportController)
testrig.StandardDBSetup(suite.db, nil)
diff --git a/internal/processing/polls/poll_test.go b/internal/processing/polls/poll_test.go
index f7c0f9f02..848c3f169 100644
--- a/internal/processing/polls/poll_test.go
+++ b/internal/processing/polls/poll_test.go
@@ -24,6 +24,7 @@ import (
"testing"
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
@@ -38,9 +39,10 @@ import (
type PollTestSuite struct {
suite.Suite
- state state.State
- filter *visibility.Filter
- polls polls.Processor
+ state state.State
+ visFilter *visibility.Filter
+ muteFilter *mutes.Filter
+ polls polls.Processor
testAccounts map[string]*gtsmodel.Account
testPolls map[string]*gtsmodel.Poll
@@ -56,8 +58,9 @@ func (suite *PollTestSuite) SetupTest() {
controller := testrig.NewTestTransportController(&suite.state, nil)
mediaMgr := media.NewManager(&suite.state)
federator := testrig.NewTestFederator(&suite.state, controller, mediaMgr)
- suite.filter = visibility.NewFilter(&suite.state)
- common := common.New(&suite.state, mediaMgr, converter, federator, suite.filter)
+ suite.visFilter = visibility.NewFilter(&suite.state)
+ suite.muteFilter = mutes.NewFilter(&suite.state)
+ common := common.New(&suite.state, mediaMgr, converter, federator, suite.visFilter, suite.muteFilter)
suite.polls = polls.New(&common, &suite.state, converter)
}
@@ -88,7 +91,7 @@ func (suite *PollTestSuite) testPollGet(ctx context.Context, requester *gtsmodel
var check func(*apimodel.Poll, gtserror.WithCode) bool
switch {
- case !pollIsVisible(suite.filter, ctx, requester, poll):
+ case !pollIsVisible(suite.visFilter, ctx, requester, poll):
// Poll should not be visible to requester, this should
// return an error code 404 (to prevent info leak).
check = func(poll *apimodel.Poll, err gtserror.WithCode) bool {
@@ -188,7 +191,7 @@ func (suite *PollTestSuite) testPollVote(ctx context.Context, requester *gtsmode
return poll == nil && err.Code() == http.StatusUnprocessableEntity
}
- case !pollIsVisible(suite.filter, ctx, requester, poll):
+ case !pollIsVisible(suite.visFilter, ctx, requester, poll):
// Poll should not be visible to requester, this should
// return an error code 404 (to prevent info leak).
check = func(poll *apimodel.Poll, err gtserror.WithCode) bool {
diff --git a/internal/processing/processor.go b/internal/processing/processor.go
index 63e996b38..b8adb9bb8 100644
--- a/internal/processing/processor.go
+++ b/internal/processing/processor.go
@@ -22,6 +22,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/email"
"code.superseriousbusiness.org/gotosocial/internal/federation"
"code.superseriousbusiness.org/gotosocial/internal/filter/interaction"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
mm "code.superseriousbusiness.org/gotosocial/internal/media"
@@ -203,6 +204,7 @@ func NewProcessor(
emailSender email.Sender,
webPushSender webpush.Sender,
visFilter *visibility.Filter,
+ muteFilter *mutes.Filter,
intFilter *interaction.Filter,
) *Processor {
parseMentionFunc := GetParseMentionFunc(state, federator)
@@ -218,7 +220,7 @@ func NewProcessor(
//
// Start with sub processors that will
// be required by the workers processor.
- common := common.New(state, mediaManager, converter, federator, visFilter)
+ common := common.New(state, mediaManager, converter, federator, visFilter, muteFilter)
processor.account = account.New(&common, state, converter, mediaManager, federator, visFilter, parseMentionFunc)
processor.media = media.New(&common, state, converter, federator, mediaManager, federator.TransportController())
processor.stream = stream.New(state, oauthServer)
@@ -228,7 +230,7 @@ func NewProcessor(
processor.account = account.New(&common, state, converter, mediaManager, federator, visFilter, parseMentionFunc)
processor.admin = admin.New(&common, state, cleaner, subscriptions, federator, converter, mediaManager, federator.TransportController(), emailSender)
processor.application = application.New(state, converter)
- processor.conversations = conversations.New(state, converter, visFilter)
+ processor.conversations = conversations.New(state, converter, visFilter, muteFilter)
processor.fedi = fedi.New(state, &common, converter, federator, visFilter)
processor.filtersv1 = filtersv1.New(state, converter, &processor.stream)
processor.filtersv2 = filtersv2.New(state, converter, &processor.stream)
@@ -239,7 +241,7 @@ func NewProcessor(
processor.push = push.New(state, converter)
processor.report = report.New(state, converter)
processor.tags = tags.New(state, converter)
- processor.timeline = timeline.New(state, converter, visFilter)
+ processor.timeline = timeline.New(state, converter, visFilter, muteFilter)
processor.search = search.New(state, federator, converter, visFilter)
processor.status = status.New(state, &common, &processor.polls, &processor.interactionRequests, federator, converter, visFilter, intFilter, parseMentionFunc)
processor.user = user.New(state, converter, oauthServer, emailSender)
@@ -256,6 +258,7 @@ func NewProcessor(
federator,
converter,
visFilter,
+ muteFilter,
emailSender,
webPushSender,
&processor.account,
diff --git a/internal/processing/processor_test.go b/internal/processing/processor_test.go
index 6f5e79afd..847de29cf 100644
--- a/internal/processing/processor_test.go
+++ b/internal/processing/processor_test.go
@@ -27,6 +27,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/email"
"code.superseriousbusiness.org/gotosocial/internal/federation"
"code.superseriousbusiness.org/gotosocial/internal/filter/interaction"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/media"
@@ -130,6 +131,7 @@ func (suite *ProcessingStandardTestSuite) SetupTest() {
suite.emailSender,
testrig.NewNoopWebPushSender(),
visibility.NewFilter(&suite.state),
+ mutes.NewFilter(&suite.state),
interaction.NewFilter(&suite.state),
)
testrig.StartWorkers(&suite.state, suite.processor.Workers())
diff --git a/internal/processing/search/util.go b/internal/processing/search/util.go
index 5d8e34960..97eb813db 100644
--- a/internal/processing/search/util.go
+++ b/internal/processing/search/util.go
@@ -114,7 +114,7 @@ func (p *Processor) packageStatuses(
continue
}
- apiStatus, err := p.converter.StatusToAPIStatus(ctx, status, requestingAccount, statusfilter.FilterContextNone, nil, nil)
+ apiStatus, err := p.converter.StatusToAPIStatus(ctx, status, requestingAccount, statusfilter.FilterContextNone, nil)
if err != nil {
log.Debugf(ctx, "skipping status %s because it couldn't be converted to its api representation: %s", status.ID, err)
continue
diff --git a/internal/processing/status/context.go b/internal/processing/status/context.go
index c18a4f7bd..6f3e7a4fd 100644
--- a/internal/processing/status/context.go
+++ b/internal/processing/status/context.go
@@ -25,7 +25,6 @@ import (
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
statusfilter "code.superseriousbusiness.org/gotosocial/internal/filter/status"
- "code.superseriousbusiness.org/gotosocial/internal/gtscontext"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
)
@@ -291,26 +290,8 @@ func (p *Processor) ContextGet(
return nil, gtserror.NewErrorInternalError(err)
}
- // Retrieve mutes as they affect
- // what should be shown to requester.
- mutes, err := p.state.DB.GetAccountMutes(
- // No need to populate mutes,
- // IDs are enough here.
- gtscontext.SetBarebones(ctx),
- requester.ID,
- nil, // No paging - get all.
- )
- if err != nil {
- err = gtserror.Newf(
- "couldn't retrieve mutes for account %s: %w",
- requester.ID, err,
- )
- return nil, gtserror.NewErrorInternalError(err)
- }
-
// Retrieve the full thread context.
- threadContext, errWithCode := p.contextGet(
- ctx,
+ threadContext, errWithCode := p.contextGet(ctx,
requester,
targetStatusID,
)
@@ -326,7 +307,6 @@ func (p *Processor) ContextGet(
threadContext.ancestors,
statusfilter.FilterContextThread,
filters,
- mutes,
)
// Convert and filter the thread context descendants
@@ -335,7 +315,6 @@ func (p *Processor) ContextGet(
threadContext.descendants,
statusfilter.FilterContextThread,
filters,
- mutes,
)
return &apiContext, nil
@@ -352,8 +331,8 @@ func (p *Processor) WebContextGet(
targetStatusID string,
) (*apimodel.WebThreadContext, gtserror.WithCode) {
// Retrieve the internal thread context.
- iCtx, errWithCode := p.contextGet(
- ctx,
+ iCtx, errWithCode := p.contextGet(ctx,
+
nil, // No authed requester.
targetStatusID,
)
diff --git a/internal/processing/status/status_test.go b/internal/processing/status/status_test.go
index 75775cf8a..091d9716b 100644
--- a/internal/processing/status/status_test.go
+++ b/internal/processing/status/status_test.go
@@ -22,6 +22,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/db"
"code.superseriousbusiness.org/gotosocial/internal/federation"
"code.superseriousbusiness.org/gotosocial/internal/filter/interaction"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/media"
@@ -92,9 +93,10 @@ func (suite *StatusStandardTestSuite) SetupTest() {
suite.federator = testrig.NewTestFederator(&suite.state, suite.tc, suite.mediaManager)
visFilter := visibility.NewFilter(&suite.state)
+ muteFilter := mutes.NewFilter(&suite.state)
intFilter := interaction.NewFilter(&suite.state)
- common := common.New(&suite.state, suite.mediaManager, suite.typeConverter, suite.federator, visFilter)
+ common := common.New(&suite.state, suite.mediaManager, suite.typeConverter, suite.federator, visFilter, muteFilter)
polls := polls.New(&common, &suite.state, suite.typeConverter)
intReqs := interactionrequests.New(&common, &suite.state, suite.typeConverter)
diff --git a/internal/processing/stream/statusupdate_test.go b/internal/processing/stream/statusupdate_test.go
index 483388823..8fc4bcfe8 100644
--- a/internal/processing/stream/statusupdate_test.go
+++ b/internal/processing/stream/statusupdate_test.go
@@ -39,7 +39,7 @@ func (suite *StatusUpdateTestSuite) TestStreamNotification() {
suite.NoError(errWithCode)
editedStatus := suite.testStatuses["remote_account_1_status_1"]
- apiStatus, err := typeutils.NewConverter(&suite.state).StatusToAPIStatus(suite.T().Context(), editedStatus, account, statusfilter.FilterContextNotifications, nil, nil)
+ apiStatus, err := typeutils.NewConverter(&suite.state).StatusToAPIStatus(suite.T().Context(), editedStatus, account, statusfilter.FilterContextNotifications, nil)
suite.NoError(err)
suite.streamProcessor.StatusUpdate(suite.T().Context(), account, apiStatus, stream.TimelineHome)
diff --git a/internal/processing/timeline/faved.go b/internal/processing/timeline/faved.go
index 4cb3c30a5..84788a8fa 100644
--- a/internal/processing/timeline/faved.go
+++ b/internal/processing/timeline/faved.go
@@ -56,7 +56,7 @@ func (p *Processor) FavedTimelineGet(ctx context.Context, authed *apiutil.Auth,
continue
}
- apiStatus, err := p.converter.StatusToAPIStatus(ctx, s, authed.Account, statusfilter.FilterContextNone, nil, nil)
+ apiStatus, err := p.converter.StatusToAPIStatus(ctx, s, authed.Account, statusfilter.FilterContextNone, nil)
if err != nil {
log.Errorf(ctx, "error convering to api status: %v", err)
continue
diff --git a/internal/processing/timeline/home.go b/internal/processing/timeline/home.go
index bcb63fcff..ba74b770c 100644
--- a/internal/processing/timeline/home.go
+++ b/internal/processing/timeline/home.go
@@ -91,9 +91,22 @@ func (p *Processor) HomeTimelineGet(
// Check the visibility of passed status to requesting user.
ok, err := p.visFilter.StatusHomeTimelineable(ctx, requester, s)
if err != nil {
- log.Errorf(ctx, "error filtering status %s: %v", s.URI, err)
+ log.Errorf(ctx, "error checking status %s visibility: %v", s.URI, err)
+ return true // default assume not visible
+ } else if !ok {
+ return true
}
- return !ok
+
+ // Check if status been muted by requester from timelines.
+ muted, err := p.muteFilter.StatusMuted(ctx, requester, s)
+ if err != nil {
+ log.Errorf(ctx, "error checking status %s mutes: %v", s.URI, err)
+ return true // default assume muted
+ } else if muted {
+ return true
+ }
+
+ return false
},
// Post filtering funtion,
diff --git a/internal/processing/timeline/list.go b/internal/processing/timeline/list.go
index dbf07cdd4..c8e6bc5f1 100644
--- a/internal/processing/timeline/list.go
+++ b/internal/processing/timeline/list.go
@@ -102,9 +102,22 @@ func (p *Processor) ListTimelineGet(
// Check the visibility of passed status to requesting user.
ok, err := p.visFilter.StatusHomeTimelineable(ctx, requester, s)
if err != nil {
- log.Errorf(ctx, "error filtering status %s: %v", s.URI, err)
+ log.Errorf(ctx, "error checking status %s visibility: %v", s.URI, err)
+ return true // default assume not visible
+ } else if !ok {
+ return true
}
- return !ok
+
+ // Check if status been muted by requester from timelines.
+ muted, err := p.muteFilter.StatusMuted(ctx, requester, s)
+ if err != nil {
+ log.Errorf(ctx, "error checking status %s mutes: %v", s.URI, err)
+ return true // default assume muted
+ } else if muted {
+ return true
+ }
+
+ return false
},
// Post filtering funtion,
diff --git a/internal/processing/timeline/notification.go b/internal/processing/timeline/notification.go
index 0da9fb55e..ad60fd90c 100644
--- a/internal/processing/timeline/notification.go
+++ b/internal/processing/timeline/notification.go
@@ -21,14 +21,13 @@ import (
"context"
"errors"
"fmt"
+ "net/http"
"net/url"
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
apiutil "code.superseriousbusiness.org/gotosocial/internal/api/util"
"code.superseriousbusiness.org/gotosocial/internal/db"
"code.superseriousbusiness.org/gotosocial/internal/filter/status"
- "code.superseriousbusiness.org/gotosocial/internal/filter/usermute"
- "code.superseriousbusiness.org/gotosocial/internal/gtscontext"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/log"
@@ -39,14 +38,13 @@ import (
// NotificationsGet ...
func (p *Processor) NotificationsGet(
ctx context.Context,
- authed *apiutil.Auth,
+ requester *gtsmodel.Account,
page *paging.Page,
types []gtsmodel.NotificationType,
excludeTypes []gtsmodel.NotificationType,
) (*apimodel.PageableResponse, gtserror.WithCode) {
- notifs, err := p.state.DB.GetAccountNotifications(
- ctx,
- authed.Account.ID,
+ notifs, err := p.state.DB.GetAccountNotifications(ctx,
+ requester.ID,
page,
types,
excludeTypes,
@@ -61,19 +59,12 @@ func (p *Processor) NotificationsGet(
return util.EmptyPageableResponse(), nil
}
- filters, err := p.state.DB.GetFiltersForAccountID(ctx, authed.Account.ID)
+ filters, err := p.state.DB.GetFiltersForAccountID(ctx, requester.ID)
if err != nil {
- err = gtserror.Newf("couldn't retrieve filters for account %s: %w", authed.Account.ID, err)
+ err = gtserror.Newf("error getting account %s filters: %w", requester.ID, err)
return nil, gtserror.NewErrorInternalError(err)
}
- mutes, err := p.state.DB.GetAccountMutes(gtscontext.SetBarebones(ctx), authed.Account.ID, nil)
- if err != nil {
- err = gtserror.Newf("couldn't retrieve mutes for account %s: %w", authed.Account.ID, err)
- return nil, gtserror.NewErrorInternalError(err)
- }
- compiledMutes := usermute.NewCompiledUserMuteList(mutes)
-
var (
items = make([]interface{}, 0, count)
@@ -84,7 +75,7 @@ func (p *Processor) NotificationsGet(
)
for _, n := range notifs {
- visible, err := p.notifVisible(ctx, n, authed.Account)
+ visible, err := p.notifVisible(ctx, n, requester)
if err != nil {
log.Debugf(ctx, "skipping notification %s because of an error checking notification visibility: %v", n.ID, err)
continue
@@ -94,7 +85,37 @@ func (p *Processor) NotificationsGet(
continue
}
- item, err := p.converter.NotificationToAPINotification(ctx, n, filters, compiledMutes)
+ // Check whether notification origin account is muted.
+ muted, err := p.muteFilter.AccountNotificationsMuted(ctx,
+ requester,
+ n.OriginAccount,
+ )
+ if err != nil {
+ log.Errorf(ctx, "error checking account mute: %v", err)
+ continue
+ }
+
+ if muted {
+ continue
+ }
+
+ if n.Status != nil {
+ // A status is attached, check whether status muted.
+ muted, err = p.muteFilter.StatusNotificationsMuted(ctx,
+ requester,
+ n.Status,
+ )
+ if err != nil {
+ log.Errorf(ctx, "error checking status mute: %v", err)
+ continue
+ }
+
+ if muted {
+ continue
+ }
+ }
+
+ item, err := p.converter.NotificationToAPINotification(ctx, n, filters)
if err != nil {
if !errors.Is(err, status.ErrHideStatus) {
log.Debugf(ctx, "skipping notification %s because it couldn't be converted to its api representation: %s", n.ID, err)
@@ -125,41 +146,24 @@ func (p *Processor) NotificationsGet(
func (p *Processor) NotificationGet(ctx context.Context, account *gtsmodel.Account, targetNotifID string) (*apimodel.Notification, gtserror.WithCode) {
notif, err := p.state.DB.GetNotificationByID(ctx, targetNotifID)
- if err != nil {
- if errors.Is(err, db.ErrNoEntries) {
- return nil, gtserror.NewErrorNotFound(err)
- }
-
- // Real error.
+ if err != nil && !errors.Is(err, db.ErrNoEntries) {
+ err := gtserror.Newf("error getting from db: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
- if notifTargetAccountID := notif.TargetAccountID; notifTargetAccountID != account.ID {
- err = fmt.Errorf("account %s does not have permission to view notification belong to account %s", account.ID, notifTargetAccountID)
+ if notif.TargetAccountID != account.ID {
+ err := gtserror.New("requester does not match notification target")
return nil, gtserror.NewErrorNotFound(err)
}
- filters, err := p.state.DB.GetFiltersForAccountID(ctx, account.ID)
- if err != nil {
- err = gtserror.Newf("couldn't retrieve filters for account %s: %w", account.ID, err)
- return nil, gtserror.NewErrorInternalError(err)
- }
+ // NOTE: we specifically don't do any filtering
+ // or mute checking for a notification directly
+ // fetched by ID. only from timelines etc.
- mutes, err := p.state.DB.GetAccountMutes(gtscontext.SetBarebones(ctx), account.ID, nil)
+ apiNotif, err := p.converter.NotificationToAPINotification(ctx, notif, nil)
if err != nil {
- err = gtserror.Newf("couldn't retrieve mutes for account %s: %w", account.ID, err)
- return nil, gtserror.NewErrorInternalError(err)
- }
- compiledMutes := usermute.NewCompiledUserMuteList(mutes)
-
- apiNotif, err := p.converter.NotificationToAPINotification(ctx, notif, filters, compiledMutes)
- if err != nil {
- if errors.Is(err, db.ErrNoEntries) {
- return nil, gtserror.NewErrorNotFound(err)
- }
-
- // Real error.
- return nil, gtserror.NewErrorInternalError(err)
+ err := gtserror.Newf("error converting to api model: %w", err)
+ return nil, gtserror.WrapWithCode(http.StatusInternalServerError, err)
}
return apiNotif, nil
diff --git a/internal/processing/timeline/public.go b/internal/processing/timeline/public.go
index 527000166..cfb58201d 100644
--- a/internal/processing/timeline/public.go
+++ b/internal/processing/timeline/public.go
@@ -93,9 +93,22 @@ func (p *Processor) publicTimelineGet(
// Check the visibility of passed status to requesting user.
ok, err := p.visFilter.StatusPublicTimelineable(ctx, requester, s)
if err != nil {
- log.Errorf(ctx, "error filtering status %s: %v", s.URI, err)
+ log.Errorf(ctx, "error checking status %s visibility: %v", s.URI, err)
+ return true // default assume not visible
+ } else if !ok {
+ return true
}
- return !ok
+
+ // Check if status been muted by requester from timelines.
+ muted, err := p.muteFilter.StatusMuted(ctx, requester, s)
+ if err != nil {
+ log.Errorf(ctx, "error checking status %s mutes: %v", s.URI, err)
+ return true // default assume muted
+ } else if muted {
+ return true
+ }
+
+ return false
},
// Post filtering funtion,
@@ -149,9 +162,20 @@ func (p *Processor) localTimelineGet(
// Check the visibility of passed status to requesting user.
ok, err := p.visFilter.StatusPublicTimelineable(ctx, requester, s)
if err != nil {
- log.Errorf(ctx, "error filtering status %s: %v", s.URI, err)
+ log.Errorf(ctx, "error checking status %s visibility: %v", s.URI, err)
+ } else if !ok {
+ return true
}
- return !ok
+
+ // Check if status been muted by requester from timelines.
+ muted, err := p.muteFilter.StatusMuted(ctx, requester, s)
+ if err != nil {
+ log.Errorf(ctx, "error checking status %s mutes: %v", s.URI, err)
+ } else if muted {
+ return true
+ }
+
+ return false
},
// Post filtering funtion,
diff --git a/internal/processing/timeline/tag.go b/internal/processing/timeline/tag.go
index f48f89049..88333d343 100644
--- a/internal/processing/timeline/tag.go
+++ b/internal/processing/timeline/tag.go
@@ -101,9 +101,22 @@ func (p *Processor) TagTimelineGet(
// Check the visibility of passed status to requesting user.
ok, err := p.visFilter.StatusPublicTimelineable(ctx, requester, s)
if err != nil {
- log.Errorf(ctx, "error filtering status %s: %v", s.URI, err)
+ log.Errorf(ctx, "error checking status %s visibility: %v", s.URI, err)
+ return true // default assume not visible
+ } else if !ok {
+ return true
}
- return !ok
+
+ // Check if status been muted by requester from timelines.
+ muted, err := p.muteFilter.StatusMuted(ctx, requester, s)
+ if err != nil {
+ log.Errorf(ctx, "error checking status %s mutes: %v", s.URI, err)
+ return true // default assume muted
+ } else if muted {
+ return true
+ }
+
+ return false
},
// Post filtering funtion,
diff --git a/internal/processing/timeline/timeline.go b/internal/processing/timeline/timeline.go
index 2eab57195..a86702d42 100644
--- a/internal/processing/timeline/timeline.go
+++ b/internal/processing/timeline/timeline.go
@@ -26,8 +26,8 @@ import (
apimodel "code.superseriousbusiness.org/gotosocial/internal/api/model"
timelinepkg "code.superseriousbusiness.org/gotosocial/internal/cache/timeline"
"code.superseriousbusiness.org/gotosocial/internal/db"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
statusfilter "code.superseriousbusiness.org/gotosocial/internal/filter/status"
- "code.superseriousbusiness.org/gotosocial/internal/filter/usermute"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
@@ -48,16 +48,18 @@ var (
)
type Processor struct {
- state *state.State
- converter *typeutils.Converter
- visFilter *visibility.Filter
+ state *state.State
+ converter *typeutils.Converter
+ visFilter *visibility.Filter
+ muteFilter *mutes.Filter
}
-func New(state *state.State, converter *typeutils.Converter, visFilter *visibility.Filter) Processor {
+func New(state *state.State, converter *typeutils.Converter, visFilter *visibility.Filter, muteFilter *mutes.Filter) Processor {
return Processor{
- state: state,
- converter: converter,
- visFilter: visFilter,
+ state: state,
+ converter: converter,
+ visFilter: visFilter,
+ muteFilter: muteFilter,
}
}
@@ -78,7 +80,6 @@ func (p *Processor) getStatusTimeline(
) {
var err error
var filters []*gtsmodel.Filter
- var mutes *usermute.CompiledUserMuteList
if requester != nil {
// Fetch all filters relevant for requesting account.
@@ -89,19 +90,6 @@ func (p *Processor) getStatusTimeline(
err := gtserror.Newf("error getting account filters: %w", err)
return nil, gtserror.NewErrorInternalError(err)
}
-
- // Get a list of all account mutes for requester.
- allMutes, err := p.state.DB.GetAccountMutes(ctx,
- requester.ID,
- nil, // i.e. all
- )
- if err != nil && !errors.Is(err, db.ErrNoEntries) {
- err := gtserror.Newf("error getting account mutes: %w", err)
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // Compile all account mutes to useable form.
- mutes = usermute.NewCompiledUserMuteList(allMutes)
}
// Ensure we have valid
@@ -148,7 +136,6 @@ func (p *Processor) getStatusTimeline(
requester,
filterCtx,
filters,
- mutes,
)
if err != nil && !errors.Is(err, statusfilter.ErrHideStatus) {
return nil, err
diff --git a/internal/processing/timeline/timeline_test.go b/internal/processing/timeline/timeline_test.go
index 5afbb2353..01197b767 100644
--- a/internal/processing/timeline/timeline_test.go
+++ b/internal/processing/timeline/timeline_test.go
@@ -20,6 +20,7 @@ package timeline_test
import (
"code.superseriousbusiness.org/gotosocial/internal/admin"
"code.superseriousbusiness.org/gotosocial/internal/db"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
"code.superseriousbusiness.org/gotosocial/internal/processing/timeline"
@@ -62,6 +63,7 @@ func (suite *TimelineStandardTestSuite) SetupTest() {
&suite.state,
typeutils.NewConverter(&suite.state),
visibility.NewFilter(&suite.state),
+ mutes.NewFilter(&suite.state),
)
testrig.StandardDBSetup(suite.db, suite.testAccounts)
diff --git a/internal/processing/workers/fromclientapi.go b/internal/processing/workers/fromclientapi.go
index 5d9ebf41a..04ad4152c 100644
--- a/internal/processing/workers/fromclientapi.go
+++ b/internal/processing/workers/fromclientapi.go
@@ -748,10 +748,17 @@ func (p *clientAPI) UpdateStatus(ctx context.Context, cMsg *messages.FromClientA
}
}
- // Notify of the latest edit.
- if editsLen := len(status.EditIDs); editsLen != 0 {
- editID := status.EditIDs[editsLen-1]
- if err := p.surface.notifyStatusEdit(ctx, status, editID); err != nil {
+ if len(status.EditIDs) > 0 {
+ // Ensure edits are fully populated for this status before anything.
+ if err := p.surface.State.DB.PopulateStatusEdits(ctx, status); err != nil {
+ log.Error(ctx, "error populating updated status edits: %v")
+
+ // Then send notifications of a status edit
+ // to any local interactors of the status.
+ } else if err := p.surface.notifyStatusEdit(ctx,
+ status,
+ status.Edits[len(status.Edits)-1], // latest
+ ); err != nil {
log.Errorf(ctx, "error notifying status edit: %v", err)
}
}
diff --git a/internal/processing/workers/fromclientapi_test.go b/internal/processing/workers/fromclientapi_test.go
index 3abd05295..3f6964259 100644
--- a/internal/processing/workers/fromclientapi_test.go
+++ b/internal/processing/workers/fromclientapi_test.go
@@ -215,7 +215,6 @@ func (suite *FromClientAPITestSuite) statusJSON(
requestingAccount,
statusfilter.FilterContextNone,
nil,
- nil,
)
if err != nil {
suite.FailNow(err.Error())
@@ -240,7 +239,6 @@ func (suite *FromClientAPITestSuite) conversationJSON(
conversation,
requestingAccount,
nil,
- nil,
)
if err != nil {
suite.FailNow(err.Error())
@@ -348,7 +346,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() {
suite.FailNow("timed out waiting for new status notification")
}
- apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif, nil, nil)
+ apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif, nil)
if err != nil {
suite.FailNow(err.Error())
}
@@ -2035,7 +2033,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithAuthorOnExclusiv
suite.FailNow("timed out waiting for new status notification")
}
- apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif, nil, nil)
+ apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif, nil)
if err != nil {
suite.FailNow(err.Error())
}
@@ -2220,7 +2218,7 @@ func (suite *FromClientAPITestSuite) TestProcessUpdateStatusInteractedWith() {
suite.FailNow("timed out waiting for edited status notification")
}
- apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif, nil, nil)
+ apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif, nil)
if err != nil {
suite.FailNow(err.Error())
}
diff --git a/internal/processing/workers/fromfediapi.go b/internal/processing/workers/fromfediapi.go
index d1e5bb2f7..5dbb8ba2e 100644
--- a/internal/processing/workers/fromfediapi.go
+++ b/internal/processing/workers/fromfediapi.go
@@ -1010,10 +1010,17 @@ func (p *fediAPI) UpdateStatus(ctx context.Context, fMsg *messages.FromFediAPI)
}
}
- // Notify of the latest edit.
- if editsLen := len(status.EditIDs); editsLen != 0 {
- editID := status.EditIDs[editsLen-1]
- if err := p.surface.notifyStatusEdit(ctx, status, editID); err != nil {
+ if len(status.EditIDs) > 0 {
+ // Ensure edits are fully populated for this status before anything.
+ if err := p.surface.State.DB.PopulateStatusEdits(ctx, status); err != nil {
+ log.Error(ctx, "error populating updated status edits: %v")
+
+ // Then send notifications of a status edit
+ // to any local interactors of the status.
+ } else if err := p.surface.notifyStatusEdit(ctx,
+ status,
+ status.Edits[len(status.Edits)-1], // latest
+ ); err != nil {
log.Errorf(ctx, "error notifying status edit: %v", err)
}
}
diff --git a/internal/processing/workers/surface.go b/internal/processing/workers/surface.go
index 5604ad71d..69758692f 100644
--- a/internal/processing/workers/surface.go
+++ b/internal/processing/workers/surface.go
@@ -19,6 +19,7 @@ package workers
import (
"code.superseriousbusiness.org/gotosocial/internal/email"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/processing/conversations"
"code.superseriousbusiness.org/gotosocial/internal/processing/stream"
@@ -38,6 +39,7 @@ type Surface struct {
Converter *typeutils.Converter
Stream *stream.Processor
VisFilter *visibility.Filter
+ MuteFilter *mutes.Filter
EmailSender email.Sender
WebPushSender webpush.Sender
Conversations *conversations.Processor
diff --git a/internal/processing/workers/surfacenotify.go b/internal/processing/workers/surfacenotify.go
index 11c3fd059..044315349 100644
--- a/internal/processing/workers/surfacenotify.go
+++ b/internal/processing/workers/surfacenotify.go
@@ -23,8 +23,7 @@ import (
"strings"
"code.superseriousbusiness.org/gotosocial/internal/db"
- "code.superseriousbusiness.org/gotosocial/internal/filter/status"
- "code.superseriousbusiness.org/gotosocial/internal/filter/usermute"
+ statusfilter "code.superseriousbusiness.org/gotosocial/internal/filter/status"
"code.superseriousbusiness.org/gotosocial/internal/gtscontext"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
@@ -59,8 +58,7 @@ func (s *Surface) notifyPendingReply(
// Ensure thread not muted
// by replied-to account.
- muted, err := s.State.DB.IsThreadMutedByAccount(
- ctx,
+ muted, err := s.State.DB.IsThreadMutedByAccount(ctx,
status.ThreadID,
status.InReplyToAccountID,
)
@@ -81,7 +79,8 @@ func (s *Surface) notifyPendingReply(
gtsmodel.NotificationPendingReply,
status.InReplyToAccount,
status.Account,
- status.ID,
+ status,
+ nil,
); err != nil {
return gtserror.Newf("error notifying replied-to account %s: %w", status.InReplyToAccountID, err)
}
@@ -135,8 +134,7 @@ func (s *Surface) notifyMention(
// Ensure thread not muted
// by mentioned account.
- muted, err := s.State.DB.IsThreadMutedByAccount(
- ctx,
+ muted, err := s.State.DB.IsThreadMutedByAccount(ctx,
mention.Status.ThreadID,
mention.TargetAccountID,
)
@@ -160,7 +158,8 @@ func (s *Surface) notifyMention(
gtsmodel.NotificationMention,
mention.TargetAccount,
mention.OriginAccount,
- mention.StatusID,
+ mention.Status,
+ nil,
); err != nil {
return gtserror.Newf(
"error notifying mention target %s: %w",
@@ -193,7 +192,8 @@ func (s *Surface) notifyFollowRequest(
gtsmodel.NotificationFollowRequest,
followReq.TargetAccount,
followReq.Account,
- "",
+ nil,
+ nil,
); err != nil {
return gtserror.Newf("error notifying follow target %s: %w", followReq.TargetAccountID, err)
}
@@ -245,7 +245,8 @@ func (s *Surface) notifyFollow(
gtsmodel.NotificationFollow,
follow.TargetAccount,
follow.Account,
- "",
+ nil,
+ nil,
); err != nil {
return gtserror.Newf("error notifying follow target %s: %w", follow.TargetAccountID, err)
}
@@ -275,7 +276,8 @@ func (s *Surface) notifyFave(
gtsmodel.NotificationFavourite,
fave.TargetAccount,
fave.Account,
- fave.StatusID,
+ fave.Status,
+ nil,
); err != nil {
return gtserror.Newf("error notifying status author %s: %w", fave.TargetAccountID, err)
}
@@ -306,7 +308,8 @@ func (s *Surface) notifyPendingFave(
gtsmodel.NotificationPendingFave,
fave.TargetAccount,
fave.Account,
- fave.StatusID,
+ fave.Status,
+ nil,
); err != nil {
return gtserror.Newf("error notifying status author %s: %w", fave.TargetAccountID, err)
}
@@ -339,8 +342,7 @@ func (s *Surface) notifyableFave(
// Ensure favee hasn't
// muted the thread.
- muted, err := s.State.DB.IsThreadMutedByAccount(
- ctx,
+ muted, err := s.State.DB.IsThreadMutedByAccount(ctx,
fave.Status.ThreadID,
fave.TargetAccountID,
)
@@ -379,7 +381,8 @@ func (s *Surface) notifyAnnounce(
gtsmodel.NotificationReblog,
boost.BoostOfAccount,
boost.Account,
- boost.ID,
+ boost,
+ nil,
); err != nil {
return gtserror.Newf("error notifying boost target %s: %w", boost.BoostOfAccountID, err)
}
@@ -410,7 +413,8 @@ func (s *Surface) notifyPendingAnnounce(
gtsmodel.NotificationPendingReblog,
boost.BoostOfAccount,
boost.Account,
- boost.ID,
+ boost,
+ nil,
); err != nil {
return gtserror.Newf("error notifying boost target %s: %w", boost.BoostOfAccountID, err)
}
@@ -448,8 +452,7 @@ func (s *Surface) notifyableAnnounce(
// Ensure boostee hasn't
// muted the thread.
- muted, err := s.State.DB.IsThreadMutedByAccount(
- ctx,
+ muted, err := s.State.DB.IsThreadMutedByAccount(ctx,
status.BoostOf.ThreadID,
status.BoostOfAccountID,
)
@@ -488,7 +491,8 @@ func (s *Surface) notifyPollClose(ctx context.Context, status *gtsmodel.Status)
gtsmodel.NotificationPoll,
status.Account,
status.Account,
- status.ID,
+ status,
+ nil,
); err != nil {
errs.Appendf("error notifying poll author: %w", err)
}
@@ -507,7 +511,8 @@ func (s *Surface) notifyPollClose(ctx context.Context, status *gtsmodel.Status)
gtsmodel.NotificationPoll,
vote.Account,
status.Account,
- status.ID,
+ status,
+ nil,
); err != nil {
errs.Appendf("error notifying poll voter %s: %w", vote.AccountID, err)
continue
@@ -546,7 +551,8 @@ func (s *Surface) notifySignup(ctx context.Context, newUser *gtsmodel.User) erro
gtsmodel.NotificationAdminSignup,
mod,
newUser.Account,
- "",
+ nil,
+ nil,
); err != nil {
errs.Appendf("error notifying moderator %s: %w", mod.ID, err)
continue
@@ -559,7 +565,7 @@ func (s *Surface) notifySignup(ctx context.Context, newUser *gtsmodel.User) erro
func (s *Surface) notifyStatusEdit(
ctx context.Context,
status *gtsmodel.Status,
- editID string,
+ edit *gtsmodel.StatusEdit,
) error {
// Get local-only interactions (we can't/don't notify remotes).
interactions, err := s.State.DB.GetStatusInteractions(ctx, status.ID, true)
@@ -594,7 +600,8 @@ func (s *Surface) notifyStatusEdit(
gtsmodel.NotificationUpdate,
targetAcct,
status.Account,
- editID,
+ status,
+ edit,
); err != nil {
errs.Appendf("error notifying status edit: %w", err)
continue
@@ -637,22 +644,32 @@ func (s *Surface) Notify(
notificationType gtsmodel.NotificationType,
targetAccount *gtsmodel.Account,
originAccount *gtsmodel.Account,
- statusOrEditID string,
+ status *gtsmodel.Status,
+ edit *gtsmodel.StatusEdit,
) error {
if targetAccount.IsRemote() {
// nothing to do.
return nil
}
+ // Get status / edit ID
+ // if either was provided.
+ // (prefer edit though!)
+ var statusOrEditID string
+ if edit != nil {
+ statusOrEditID = edit.ID
+ } else if status != nil {
+ statusOrEditID = status.ID
+ }
+
// We're doing state-y stuff so get a
// lock on this combo of notif params.
- lockURI := getNotifyLockURI(
+ unlock := s.State.ProcessingLocks.Lock(getNotifyLockURI(
notificationType,
targetAccount,
originAccount,
statusOrEditID,
- )
- unlock := s.State.ProcessingLocks.Lock(lockURI)
+ ))
// Wrap the unlock so we
// can do granular unlocking.
@@ -696,29 +713,57 @@ func (s *Surface) Notify(
// with the state-y stuff.
unlock()
- // Stream notification to the user.
- filters, err := s.State.DB.GetFiltersForAccountID(ctx, targetAccount.ID)
+ // Check whether origin account is muted by target account.
+ muted, err := s.MuteFilter.AccountNotificationsMuted(ctx,
+ targetAccount,
+ originAccount,
+ )
if err != nil {
- return gtserror.Newf("couldn't retrieve filters for account %s: %w", targetAccount.ID, err)
+ return gtserror.Newf("error checking account mute: %w", err)
}
- mutes, err := s.State.DB.GetAccountMutes(gtscontext.SetBarebones(ctx), targetAccount.ID, nil)
- if err != nil {
- return gtserror.Newf("couldn't retrieve mutes for account %s: %w", targetAccount.ID, err)
+ if muted {
+ // Don't notify.
+ return nil
}
- compiledMutes := usermute.NewCompiledUserMuteList(mutes)
- apiNotif, err := s.Converter.NotificationToAPINotification(ctx, notif, filters, compiledMutes)
- if err != nil {
- if errors.Is(err, status.ErrHideStatus) {
+ if status != nil {
+ // Check whether status is muted by the target account.
+ muted, err := s.MuteFilter.StatusNotificationsMuted(ctx,
+ targetAccount,
+ status,
+ )
+ if err != nil {
+ return gtserror.Newf("error checking status mute: %w", err)
+ }
+
+ if muted {
+ // Don't notify.
return nil
}
+ }
+
+ filters, err := s.State.DB.GetFiltersForAccountID(ctx, targetAccount.ID)
+ if err != nil {
+ return gtserror.Newf("couldn't retrieve filters for account %s: %w", targetAccount.ID, err)
+ }
+
+ // Convert the notification to frontend API model for streaming / push.
+ apiNotif, err := s.Converter.NotificationToAPINotification(ctx, notif, filters)
+ if err != nil && !errors.Is(err, statusfilter.ErrHideStatus) {
return gtserror.Newf("error converting notification to api representation: %w", err)
}
+
+ if apiNotif == nil {
+ // Filtered.
+ return nil
+ }
+
+ // Stream notification to the user.
s.Stream.Notify(ctx, targetAccount, apiNotif)
// Send Web Push notification to the user.
- if err = s.WebPushSender.Send(ctx, notif, filters, compiledMutes); err != nil {
+ if err = s.WebPushSender.Send(ctx, notif, apiNotif); err != nil {
return gtserror.Newf("error sending Web Push notifications: %w", err)
}
diff --git a/internal/processing/workers/surfacenotify_test.go b/internal/processing/workers/surfacenotify_test.go
index 459b3e125..a5124a3af 100644
--- a/internal/processing/workers/surfacenotify_test.go
+++ b/internal/processing/workers/surfacenotify_test.go
@@ -22,6 +22,7 @@ import (
"testing"
"time"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/gtscontext"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
@@ -43,6 +44,7 @@ func (suite *SurfaceNotifyTestSuite) TestSpamNotifs() {
Converter: testStructs.TypeConverter,
Stream: testStructs.Processor.Stream(),
VisFilter: visibility.NewFilter(testStructs.State),
+ MuteFilter: mutes.NewFilter(testStructs.State),
EmailSender: testStructs.EmailSender,
WebPushSender: testStructs.WebPushSender,
Conversations: testStructs.Processor.Conversations(),
@@ -74,7 +76,8 @@ func (suite *SurfaceNotifyTestSuite) TestSpamNotifs() {
notificationType,
targetAccount,
originAccount,
- "",
+ nil,
+ nil,
); err != nil {
suite.FailNow(err.Error())
}
diff --git a/internal/processing/workers/surfacetimeline.go b/internal/processing/workers/surfacetimeline.go
index 018ef976e..7ef5fee87 100644
--- a/internal/processing/workers/surfacetimeline.go
+++ b/internal/processing/workers/surfacetimeline.go
@@ -23,7 +23,6 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/cache/timeline"
statusfilter "code.superseriousbusiness.org/gotosocial/internal/filter/status"
- "code.superseriousbusiness.org/gotosocial/internal/filter/usermute"
"code.superseriousbusiness.org/gotosocial/internal/gtscontext"
"code.superseriousbusiness.org/gotosocial/internal/gtserror"
"code.superseriousbusiness.org/gotosocial/internal/gtsmodel"
@@ -119,11 +118,12 @@ func (s *Surface) timelineAndNotifyStatusForFollowers(
// if something is hometimelineable according to this filter,
// it's also eligible to appear in exclusive lists,
// even if it ultimately doesn't appear on the home timeline.
- timelineable, err := s.VisFilter.StatusHomeTimelineable(
- ctx, follow.Account, status,
+ timelineable, err := s.VisFilter.StatusHomeTimelineable(ctx,
+ follow.Account,
+ status,
)
if err != nil {
- log.Errorf(ctx, "error checking status home visibility for follow: %v", err)
+ log.Errorf(ctx, "error checking status home visibility: %v", err)
continue
}
@@ -132,9 +132,24 @@ func (s *Surface) timelineAndNotifyStatusForFollowers(
continue
}
- // Get relevant filters and mutes for this follow's account.
+ // Check if the status is muted by this follower.
+ muted, err := s.MuteFilter.StatusMuted(ctx,
+ follow.Account,
+ status,
+ )
+ if err != nil {
+ log.Errorf(ctx, "error checking status mute: %v", err)
+ continue
+ }
+
+ if muted {
+ // Nothing to do.
+ continue
+ }
+
+ // Get relevant filters for this follow's account.
// (note the origin account of the follow is receiver of status).
- filters, mutes, err := s.getFiltersAndMutes(ctx, follow.AccountID)
+ filters, err := s.getFilters(ctx, follow.AccountID)
if err != nil {
log.Error(ctx, err)
continue
@@ -145,7 +160,6 @@ func (s *Surface) timelineAndNotifyStatusForFollowers(
status,
follow,
filters,
- mutes,
)
if err != nil {
log.Errorf(ctx, "error list timelining status: %v", err)
@@ -168,7 +182,6 @@ func (s *Surface) timelineAndNotifyStatusForFollowers(
stream.TimelineHome,
statusfilter.FilterContextHome,
filters,
- mutes,
); homeTimelined {
// If hometimelined, add to list of returned account IDs.
@@ -205,7 +218,8 @@ func (s *Surface) timelineAndNotifyStatusForFollowers(
gtsmodel.NotificationStatus,
follow.Account,
status.Account,
- status.ID,
+ status,
+ nil,
); err != nil {
log.Errorf(ctx, "error notifying status for account: %v", err)
continue
@@ -226,7 +240,6 @@ func (s *Surface) listTimelineStatusForFollow(
status *gtsmodel.Status,
follow *gtsmodel.Follow,
filters []*gtsmodel.Filter,
- mutes *usermute.CompiledUserMuteList,
) (timelined bool, exclusive bool, err error) {
// Get all lists that contain this given follow.
@@ -264,7 +277,6 @@ func (s *Surface) listTimelineStatusForFollow(
stream.TimelineList+":"+list.ID, // key streamType to this specific list
statusfilter.FilterContextHome,
filters,
- mutes,
)
// Update flag based on if timelined.
@@ -275,19 +287,12 @@ func (s *Surface) listTimelineStatusForFollow(
}
// getFiltersAndMutes returns an account's filters and mutes.
-func (s *Surface) getFiltersAndMutes(ctx context.Context, accountID string) ([]*gtsmodel.Filter, *usermute.CompiledUserMuteList, error) {
+func (s *Surface) getFilters(ctx context.Context, accountID string) ([]*gtsmodel.Filter, error) {
filters, err := s.State.DB.GetFiltersForAccountID(ctx, accountID)
if err != nil {
- return nil, nil, gtserror.Newf("couldn't retrieve filters for account %s: %w", accountID, err)
+ return nil, gtserror.Newf("couldn't retrieve filters for account %s: %w", accountID, err)
}
-
- mutes, err := s.State.DB.GetAccountMutes(gtscontext.SetBarebones(ctx), accountID, nil)
- if err != nil {
- return nil, nil, gtserror.Newf("couldn't retrieve mutes for account %s: %w", accountID, err)
- }
-
- compiledMutes := usermute.NewCompiledUserMuteList(mutes)
- return filters, compiledMutes, err
+ return filters, err
}
// listEligible checks if the given status is eligible
@@ -366,7 +371,6 @@ func (s *Surface) timelineStatus(
streamType string,
filterCtx statusfilter.FilterContext,
filters []*gtsmodel.Filter,
- mutes *usermute.CompiledUserMuteList,
) bool {
// Attempt to convert status to frontend API representation,
@@ -376,7 +380,6 @@ func (s *Surface) timelineStatus(
account,
filterCtx,
filters,
- mutes,
)
if err != nil && !errors.Is(err, statusfilter.ErrHideStatus) {
log.Error(ctx, "error converting status %s to frontend: %v", status.URI, err)
@@ -388,7 +391,7 @@ func (s *Surface) timelineStatus(
if apiModel == nil {
// Status was
- // filtered / muted.
+ // filtered.
return false
}
@@ -422,7 +425,7 @@ func (s *Surface) timelineAndNotifyStatusForTagFollowers(
// Insert the status into the home timeline of each tag follower.
errs := gtserror.MultiError{}
for _, tagFollowerAccount := range tagFollowerAccounts {
- filters, mutes, err := s.getFiltersAndMutes(ctx, tagFollowerAccount.ID)
+ filters, err := s.getFilters(ctx, tagFollowerAccount.ID)
if err != nil {
errs.Append(err)
continue
@@ -435,7 +438,6 @@ func (s *Surface) timelineAndNotifyStatusForTagFollowers(
stream.TimelineHome,
statusfilter.FilterContextHome,
filters,
- mutes,
)
}
@@ -605,7 +607,7 @@ func (s *Surface) timelineStatusUpdateForFollowers(
// Get relevant filters and mutes for this follow's account.
// (note the origin account of the follow is receiver of status).
- filters, mutes, err := s.getFiltersAndMutes(ctx, follow.AccountID)
+ filters, err := s.getFilters(ctx, follow.AccountID)
if err != nil {
log.Error(ctx, err)
continue
@@ -616,7 +618,6 @@ func (s *Surface) timelineStatusUpdateForFollowers(
status,
follow,
filters,
- mutes,
)
if err != nil {
log.Errorf(ctx, "error list timelining status: %v", err)
@@ -637,7 +638,6 @@ func (s *Surface) timelineStatusUpdateForFollowers(
status,
stream.TimelineHome,
filters,
- mutes,
)
if err != nil {
log.Errorf(ctx, "error home timelining status: %v", err)
@@ -663,7 +663,6 @@ func (s *Surface) listTimelineStatusUpdateForFollow(
status *gtsmodel.Status,
follow *gtsmodel.Follow,
filters []*gtsmodel.Filter,
- mutes *usermute.CompiledUserMuteList,
) (bool, bool, error) {
// Get all lists that contain this given follow.
@@ -703,7 +702,6 @@ func (s *Surface) listTimelineStatusUpdateForFollow(
status,
stream.TimelineList+":"+list.ID, // key streamType to this specific list
filters,
- mutes,
)
if err != nil {
log.Errorf(ctx, "error adding status to list timeline: %v", err)
@@ -727,7 +725,6 @@ func (s *Surface) timelineStreamStatusUpdate(
status *gtsmodel.Status,
streamType string,
filters []*gtsmodel.Filter,
- mutes *usermute.CompiledUserMuteList,
) (bool, error) {
// Convert updated database model to frontend model.
@@ -736,7 +733,6 @@ func (s *Surface) timelineStreamStatusUpdate(
account,
statusfilter.FilterContextHome,
filters,
- mutes,
)
switch {
@@ -778,7 +774,7 @@ func (s *Surface) timelineStatusUpdateForTagFollowers(
// Stream the update to the home timeline of each tag follower.
errs := gtserror.MultiError{}
for _, tagFollowerAccount := range tagFollowerAccounts {
- filters, mutes, err := s.getFiltersAndMutes(ctx, tagFollowerAccount.ID)
+ filters, err := s.getFilters(ctx, tagFollowerAccount.ID)
if err != nil {
errs.Append(err)
continue
@@ -790,7 +786,6 @@ func (s *Surface) timelineStatusUpdateForTagFollowers(
status,
stream.TimelineHome,
filters,
- mutes,
); err != nil {
errs.Appendf(
"error updating status %s on home timeline for account %s: %w",
diff --git a/internal/processing/workers/workers.go b/internal/processing/workers/workers.go
index c5b5f6ce2..1f4ef465f 100644
--- a/internal/processing/workers/workers.go
+++ b/internal/processing/workers/workers.go
@@ -20,6 +20,7 @@ package workers
import (
"code.superseriousbusiness.org/gotosocial/internal/email"
"code.superseriousbusiness.org/gotosocial/internal/federation"
+ "code.superseriousbusiness.org/gotosocial/internal/filter/mutes"
"code.superseriousbusiness.org/gotosocial/internal/filter/visibility"
"code.superseriousbusiness.org/gotosocial/internal/processing/account"
"code.superseriousbusiness.org/gotosocial/internal/processing/common"
@@ -44,6 +45,7 @@ func New(
federator *federation.Federator,
converter *typeutils.Converter,
visFilter *visibility.Filter,
+ muteFilter *mutes.Filter,
emailSender email.Sender,
webPushSender webpush.Sender,
account *account.Processor,
@@ -66,6 +68,7 @@ func New(
Converter: converter,
Stream: stream,
VisFilter: visFilter,
+ MuteFilter: muteFilter,
EmailSender: emailSender,
WebPushSender: webPushSender,
Conversations: conversations,