mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[feature] User muting (#2960)
* User muting * Address review feedback * Rename uniqueness constraint on user_mutes to match convention * Remove unused account_id from where clause * Add UserMute to NewTestDB * Update test/envparsing.sh with new and fixed cache stuff * Address tobi's review comments * Make compiledUserMuteListEntry.expired consistent with UserMute.Expired * Make sure mute_expires_at is serialized as an explicit null for indefinite mutes --------- Co-authored-by: tobi <tobi.smethurst@protonmail.com>
This commit is contained in:
@@ -157,6 +157,7 @@ func (suite *FromClientAPITestSuite) statusJSON(
|
||||
requestingAccount,
|
||||
statusfilter.FilterContextNone,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
@@ -261,7 +262,7 @@ func (suite *FromClientAPITestSuite) TestProcessCreateStatusWithNotification() {
|
||||
suite.FailNow("timed out waiting for new status notification")
|
||||
}
|
||||
|
||||
apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif, nil)
|
||||
apiNotif, err := testStructs.TypeConverter.NotificationToAPINotification(ctx, notif, nil, nil)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
@@ -23,6 +23,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"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"
|
||||
@@ -472,8 +474,17 @@ func (s *Surface) Notify(
|
||||
return gtserror.Newf("couldn't retrieve filters for account %s: %w", targetAccount.ID, err)
|
||||
}
|
||||
|
||||
apiNotif, err := s.Converter.NotificationToAPINotification(ctx, notif, filters)
|
||||
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)
|
||||
}
|
||||
compiledMutes := usermute.NewCompiledUserMuteList(mutes)
|
||||
|
||||
apiNotif, err := s.Converter.NotificationToAPINotification(ctx, notif, filters, compiledMutes)
|
||||
if err != nil {
|
||||
if errors.Is(err, status.ErrHideStatus) {
|
||||
return nil
|
||||
}
|
||||
return gtserror.Newf("error converting notification to api representation: %w", err)
|
||||
}
|
||||
s.Stream.Notify(ctx, targetAccount, apiNotif)
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
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"
|
||||
@@ -117,6 +118,12 @@ func (s *Surface) timelineAndNotifyStatusForFollowers(
|
||||
return gtserror.Newf("couldn't retrieve filters for account %s: %w", follow.AccountID, err)
|
||||
}
|
||||
|
||||
mutes, err := s.State.DB.GetAccountMutes(gtscontext.SetBarebones(ctx), follow.AccountID, nil)
|
||||
if err != nil {
|
||||
return gtserror.Newf("couldn't retrieve mutes for account %s: %w", follow.AccountID, err)
|
||||
}
|
||||
compiledMutes := usermute.NewCompiledUserMuteList(mutes)
|
||||
|
||||
// Add status to any relevant lists
|
||||
// for this follow, if applicable.
|
||||
s.listTimelineStatusForFollow(
|
||||
@@ -125,6 +132,7 @@ func (s *Surface) timelineAndNotifyStatusForFollowers(
|
||||
follow,
|
||||
&errs,
|
||||
filters,
|
||||
compiledMutes,
|
||||
)
|
||||
|
||||
// Add status to home timeline for owner
|
||||
@@ -137,6 +145,7 @@ func (s *Surface) timelineAndNotifyStatusForFollowers(
|
||||
status,
|
||||
stream.TimelineHome,
|
||||
filters,
|
||||
compiledMutes,
|
||||
)
|
||||
if err != nil {
|
||||
errs.Appendf("error home timelining status: %w", err)
|
||||
@@ -189,6 +198,7 @@ func (s *Surface) listTimelineStatusForFollow(
|
||||
follow *gtsmodel.Follow,
|
||||
errs *gtserror.MultiError,
|
||||
filters []*gtsmodel.Filter,
|
||||
mutes *usermute.CompiledUserMuteList,
|
||||
) {
|
||||
// To put this status in appropriate list timelines,
|
||||
// we need to get each listEntry that pertains to
|
||||
@@ -232,6 +242,7 @@ func (s *Surface) listTimelineStatusForFollow(
|
||||
status,
|
||||
stream.TimelineList+":"+listEntry.ListID, // key streamType to this specific list
|
||||
filters,
|
||||
mutes,
|
||||
); err != nil {
|
||||
errs.Appendf("error adding status to timeline for list %s: %w", listEntry.ListID, err)
|
||||
// implicit continue
|
||||
@@ -343,6 +354,7 @@ func (s *Surface) timelineStatus(
|
||||
status *gtsmodel.Status,
|
||||
streamType string,
|
||||
filters []*gtsmodel.Filter,
|
||||
mutes *usermute.CompiledUserMuteList,
|
||||
) (bool, error) {
|
||||
// Ingest status into given timeline using provided function.
|
||||
if inserted, err := ingest(ctx, timelineID, status); err != nil {
|
||||
@@ -359,6 +371,7 @@ func (s *Surface) timelineStatus(
|
||||
account,
|
||||
statusfilter.FilterContextHome,
|
||||
filters,
|
||||
mutes,
|
||||
)
|
||||
if err != nil {
|
||||
err = gtserror.Newf("error converting status %s to frontend representation: %w", status.ID, err)
|
||||
@@ -478,6 +491,12 @@ func (s *Surface) timelineStatusUpdateForFollowers(
|
||||
return gtserror.Newf("couldn't retrieve filters for account %s: %w", follow.AccountID, err)
|
||||
}
|
||||
|
||||
mutes, err := s.State.DB.GetAccountMutes(gtscontext.SetBarebones(ctx), follow.AccountID, nil)
|
||||
if err != nil {
|
||||
return gtserror.Newf("couldn't retrieve mutes for account %s: %w", follow.AccountID, err)
|
||||
}
|
||||
compiledMutes := usermute.NewCompiledUserMuteList(mutes)
|
||||
|
||||
// Add status to any relevant lists
|
||||
// for this follow, if applicable.
|
||||
s.listTimelineStatusUpdateForFollow(
|
||||
@@ -486,6 +505,7 @@ func (s *Surface) timelineStatusUpdateForFollowers(
|
||||
follow,
|
||||
&errs,
|
||||
filters,
|
||||
compiledMutes,
|
||||
)
|
||||
|
||||
// Add status to home timeline for owner
|
||||
@@ -496,6 +516,7 @@ func (s *Surface) timelineStatusUpdateForFollowers(
|
||||
status,
|
||||
stream.TimelineHome,
|
||||
filters,
|
||||
compiledMutes,
|
||||
)
|
||||
if err != nil {
|
||||
errs.Appendf("error home timelining status: %w", err)
|
||||
@@ -514,6 +535,7 @@ func (s *Surface) listTimelineStatusUpdateForFollow(
|
||||
follow *gtsmodel.Follow,
|
||||
errs *gtserror.MultiError,
|
||||
filters []*gtsmodel.Filter,
|
||||
mutes *usermute.CompiledUserMuteList,
|
||||
) {
|
||||
// To put this status in appropriate list timelines,
|
||||
// we need to get each listEntry that pertains to
|
||||
@@ -555,6 +577,7 @@ func (s *Surface) listTimelineStatusUpdateForFollow(
|
||||
status,
|
||||
stream.TimelineList+":"+listEntry.ListID, // key streamType to this specific list
|
||||
filters,
|
||||
mutes,
|
||||
); err != nil {
|
||||
errs.Appendf("error adding status to timeline for list %s: %w", listEntry.ListID, err)
|
||||
// implicit continue
|
||||
@@ -570,8 +593,9 @@ func (s *Surface) timelineStreamStatusUpdate(
|
||||
status *gtsmodel.Status,
|
||||
streamType string,
|
||||
filters []*gtsmodel.Filter,
|
||||
mutes *usermute.CompiledUserMuteList,
|
||||
) error {
|
||||
apiStatus, err := s.Converter.StatusToAPIStatus(ctx, status, account, statusfilter.FilterContextHome, filters)
|
||||
apiStatus, err := s.Converter.StatusToAPIStatus(ctx, status, account, statusfilter.FilterContextHome, filters, mutes)
|
||||
if errors.Is(err, statusfilter.ErrHideStatus) {
|
||||
// Don't put this status in the stream.
|
||||
return nil
|
||||
|
Reference in New Issue
Block a user