diff options
Diffstat (limited to 'internal/processing')
-rw-r--r-- | internal/processing/common/account.go | 17 | ||||
-rw-r--r-- | internal/processing/common/status.go | 76 | ||||
-rw-r--r-- | internal/processing/status/context.go | 61 | ||||
-rw-r--r-- | internal/processing/workers/surfacetimeline.go | 19 |
4 files changed, 115 insertions, 58 deletions
diff --git a/internal/processing/common/account.go b/internal/processing/common/account.go index 05e974513..ae26e4ebd 100644 --- a/internal/processing/common/account.go +++ b/internal/processing/common/account.go @@ -42,6 +42,7 @@ func (p *Processor) GetTargetAccountBy( // Fetch the target account from db. target, err := getTargetFromDB() if err != nil && !errors.Is(err, db.ErrNoEntries) { + err := gtserror.Newf("error getting from db: %w", err) return nil, false, gtserror.NewErrorInternalError(err) } @@ -57,6 +58,7 @@ func (p *Processor) GetTargetAccountBy( // Check whether target account is visible to requesting account. visible, err = p.visFilter.AccountVisible(ctx, requester, target) if err != nil { + err := gtserror.Newf("error checking visibility: %w", err) return nil, false, gtserror.NewErrorInternalError(err) } @@ -128,7 +130,8 @@ func (p *Processor) GetVisibleTargetAccount( return target, nil } -// GetAPIAccount fetches the appropriate API account model depending on whether requester = target. +// GetAPIAccount fetches the appropriate API account +// model depending on whether requester = target. func (p *Processor) GetAPIAccount( ctx context.Context, requester *gtsmodel.Account, @@ -148,14 +151,15 @@ func (p *Processor) GetAPIAccount( } if err != nil { - err := gtserror.Newf("error converting account: %w", err) + err := gtserror.Newf("error converting: %w", err) return nil, gtserror.NewErrorInternalError(err) } return apiAcc, nil } -// GetAPIAccountBlocked fetches the limited "blocked" account model for given target. +// GetAPIAccountBlocked fetches the limited +// "blocked" account model for given target. func (p *Processor) GetAPIAccountBlocked( ctx context.Context, targetAcc *gtsmodel.Account, @@ -165,7 +169,7 @@ func (p *Processor) GetAPIAccountBlocked( ) { apiAccount, err := p.converter.AccountToAPIAccountBlocked(ctx, targetAcc) if err != nil { - err = gtserror.Newf("error converting account: %w", err) + err := gtserror.Newf("error converting: %w", err) return nil, gtserror.NewErrorInternalError(err) } return apiAccount, nil @@ -182,7 +186,7 @@ func (p *Processor) GetAPIAccountSensitive( ) { apiAccount, err := p.converter.AccountToAPIAccountSensitive(ctx, targetAcc) if err != nil { - err = gtserror.Newf("error converting account: %w", err) + err := gtserror.Newf("error converting: %w", err) return nil, gtserror.NewErrorInternalError(err) } return apiAccount, nil @@ -226,8 +230,7 @@ func (p *Processor) getVisibleAPIAccounts( ) []*apimodel.Account { // Start new log entry with // the above calling func's name. - l := log. - WithContext(ctx). + l := log.WithContext(ctx). WithField("caller", log.Caller(calldepth+1)) // Preallocate slice according to expected length. diff --git a/internal/processing/common/status.go b/internal/processing/common/status.go index a1d432eb0..dd83a2cc5 100644 --- a/internal/processing/common/status.go +++ b/internal/processing/common/status.go @@ -25,6 +25,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing" statusfilter "github.com/superseriousbusiness/gotosocial/internal/filter/status" + "github.com/superseriousbusiness/gotosocial/internal/filter/usermute" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/log" @@ -50,6 +51,7 @@ func (p *Processor) GetTargetStatusBy( // Fetch the target status from db. target, err := getTargetFromDB() if err != nil && !errors.Is(err, db.ErrNoEntries) { + err := gtserror.Newf("error getting from db: %w", err) return nil, false, gtserror.NewErrorInternalError(err) } @@ -65,6 +67,7 @@ func (p *Processor) GetTargetStatusBy( // Check whether target status is visible to requesting account. visible, err = p.visFilter.StatusVisible(ctx, requester, target) if err != nil { + err := gtserror.Newf("error checking visibility: %w", err) return nil, false, gtserror.NewErrorInternalError(err) } @@ -174,14 +177,83 @@ func (p *Processor) GetAPIStatus( apiStatus *apimodel.Status, errWithCode gtserror.WithCode, ) { - apiStatus, err := p.converter.StatusToAPIStatus(ctx, target, requester, statusfilter.FilterContextNone, nil, nil) + apiStatus, err := p.converter.StatusToAPIStatus(ctx, + target, + requester, + statusfilter.FilterContextNone, + nil, + nil, + ) if err != nil { - err = gtserror.Newf("error converting status: %w", err) + err := gtserror.Newf("error converting: %w", err) return nil, gtserror.NewErrorInternalError(err) } return apiStatus, nil } +// GetVisibleAPIStatuses converts a slice of statuses to API +// model statuses, filtering according to visibility to requester +// along with given filter context, filters and user mutes. +// +// Please note that all errors will be logged at ERROR level, +// but will not be returned. Callers are likely to run into +// show-stopping errors in the lead-up to this function. +func (p *Processor) GetVisibleAPIStatuses( + ctx context.Context, + requester *gtsmodel.Account, + statuses []*gtsmodel.Status, + filterContext statusfilter.FilterContext, + filters []*gtsmodel.Filter, + userMutes []*gtsmodel.UserMute, +) []apimodel.Status { + + // Start new log entry with + // the calling function name + // as a field in each entry. + 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 { + + // Check whether status is visible to requester. + visible, err := p.visFilter.StatusVisible(ctx, + requester, + status, + ) + if err != nil { + l.Errorf("error checking visibility: %v", err) + continue + } + + if !visible { + 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) + continue + } + + // Append converted status to return slice. + apiStatuses = append(apiStatuses, *apiStatus) + } + + return apiStatuses +} + // InvalidateTimelinedStatus is a shortcut function for invalidating the cached // representation one status in the home timeline and all list timelines of the // given accountID. It should only be called in cases where a status update diff --git a/internal/processing/status/context.go b/internal/processing/status/context.go index 9f3a7d089..19c6cac18 100644 --- a/internal/processing/status/context.go +++ b/internal/processing/status/context.go @@ -24,7 +24,6 @@ import ( apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" statusfilter "github.com/superseriousbusiness/gotosocial/internal/filter/status" - "github.com/superseriousbusiness/gotosocial/internal/filter/usermute" "github.com/superseriousbusiness/gotosocial/internal/gtscontext" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -308,22 +307,7 @@ func (p *Processor) ContextGet( return nil, gtserror.NewErrorInternalError(err) } - convert := func( - ctx context.Context, - status *gtsmodel.Status, - requestingAccount *gtsmodel.Account, - ) (*apimodel.Status, error) { - return p.converter.StatusToAPIStatus( - ctx, - status, - requestingAccount, - statusfilter.FilterContextThread, - filters, - usermute.NewCompiledUserMuteList(mutes), - ) - } - - // Retrieve the thread context. + // Retrieve the full thread context. threadContext, errWithCode := p.contextGet( ctx, requester, @@ -333,34 +317,27 @@ func (p *Processor) ContextGet( return nil, errWithCode } - apiContext := &apimodel.ThreadContext{ - Ancestors: make([]apimodel.Status, 0, len(threadContext.ancestors)), - Descendants: make([]apimodel.Status, 0, len(threadContext.descendants)), - } + var apiContext apimodel.ThreadContext - // Convert ancestors + filter - // out ones that aren't visible. - for _, status := range threadContext.ancestors { - if v, err := p.visFilter.StatusVisible(ctx, requester, status); err == nil && v { - status, err := convert(ctx, status, requester) - if err == nil { - apiContext.Ancestors = append(apiContext.Ancestors, *status) - } - } - } + // Convert and filter the thread context ancestors. + apiContext.Ancestors = p.c.GetVisibleAPIStatuses(ctx, + requester, + threadContext.ancestors, + statusfilter.FilterContextThread, + filters, + mutes, + ) - // Convert descendants + filter - // out ones that aren't visible. - for _, status := range threadContext.descendants { - if v, err := p.visFilter.StatusVisible(ctx, requester, status); err == nil && v { - status, err := convert(ctx, status, requester) - if err == nil { - apiContext.Descendants = append(apiContext.Descendants, *status) - } - } - } + // Convert and filter the thread context descendants + apiContext.Descendants = p.c.GetVisibleAPIStatuses(ctx, + requester, + threadContext.descendants, + statusfilter.FilterContextThread, + filters, + mutes, + ) - return apiContext, nil + return &apiContext, nil } // WebContextGet is like ContextGet, but is explicitly diff --git a/internal/processing/workers/surfacetimeline.go b/internal/processing/workers/surfacetimeline.go index 90cb1fed3..b071bd72e 100644 --- a/internal/processing/workers/surfacetimeline.go +++ b/internal/processing/workers/surfacetimeline.go @@ -384,8 +384,9 @@ func (s *Surface) timelineStatus( ) (bool, error) { // Ingest status into given timeline using provided function. - if inserted, err := ingest(ctx, timelineID, status); err != nil { - err = gtserror.Newf("error ingesting status %s: %w", status.ID, err) + if inserted, err := ingest(ctx, timelineID, status); err != nil && + !errors.Is(err, statusfilter.ErrHideStatus) { + err := gtserror.Newf("error ingesting status %s: %w", status.ID, err) return false, err } else if !inserted { // Nothing more to do. @@ -400,15 +401,19 @@ func (s *Surface) timelineStatus( filters, mutes, ) - if err != nil { - err = gtserror.Newf("error converting status %s to frontend representation: %w", status.ID, err) + if err != nil && !errors.Is(err, statusfilter.ErrHideStatus) { + err := gtserror.Newf("error converting status %s to frontend representation: %w", status.ID, err) return true, err } - // The status was inserted so stream it to the user. - s.Stream.Update(ctx, account, apiStatus, streamType) + if apiStatus != nil { + // The status was inserted so stream it to the user. + s.Stream.Update(ctx, account, apiStatus, streamType) + return true, nil + } - return true, nil + // Status was hidden. + return false, nil } // timelineAndNotifyStatusForTagFollowers inserts the status into the |