diff options
Diffstat (limited to 'internal/processing/conversations')
| -rw-r--r-- | internal/processing/conversations/conversations.go | 41 | ||||
| -rw-r--r-- | internal/processing/conversations/conversations_test.go | 9 | ||||
| -rw-r--r-- | internal/processing/conversations/get.go | 9 | ||||
| -rw-r--r-- | internal/processing/conversations/read.go | 6 | ||||
| -rw-r--r-- | internal/processing/conversations/update.go | 125 |
5 files changed, 72 insertions, 118 deletions
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 |
