summaryrefslogtreecommitdiff
path: root/internal/processing
diff options
context:
space:
mode:
Diffstat (limited to 'internal/processing')
-rw-r--r--internal/processing/interactionrequests/reject_test.go10
-rw-r--r--internal/processing/workers/fromclientapi.go62
-rw-r--r--internal/processing/workers/fromfediapi.go151
-rw-r--r--internal/processing/workers/util.go99
-rw-r--r--internal/processing/workers/workers.go9
5 files changed, 270 insertions, 61 deletions
diff --git a/internal/processing/interactionrequests/reject_test.go b/internal/processing/interactionrequests/reject_test.go
index f1f6aed72..6e4aac691 100644
--- a/internal/processing/interactionrequests/reject_test.go
+++ b/internal/processing/interactionrequests/reject_test.go
@@ -71,6 +71,16 @@ func (suite *RejectTestSuite) TestReject() {
)
return status == nil && errors.Is(err, db.ErrNoEntries)
})
+
+ // Wait for a copy of the status
+ // to be hurled into the sin bin.
+ testrig.WaitFor(func() bool {
+ sbStatus, err := state.DB.GetSinBinStatusByURI(
+ gtscontext.SetBarebones(ctx),
+ dbReq.InteractionURI,
+ )
+ return err == nil && sbStatus != nil
+ })
}
func TestRejectTestSuite(t *testing.T) {
diff --git a/internal/processing/workers/fromclientapi.go b/internal/processing/workers/fromclientapi.go
index c723a6001..c8bc8352f 100644
--- a/internal/processing/workers/fromclientapi.go
+++ b/internal/processing/workers/fromclientapi.go
@@ -911,11 +911,6 @@ func (p *clientAPI) UndoAnnounce(ctx context.Context, cMsg *messages.FromClientA
}
func (p *clientAPI) DeleteStatus(ctx context.Context, cMsg *messages.FromClientAPI) error {
- // Don't delete attachments, just unattach them:
- // this request comes from the client API and the
- // poster may want to use attachments again later.
- const deleteAttachments = false
-
status, ok := cMsg.GTSModel.(*gtsmodel.Status)
if !ok {
return gtserror.Newf("%T not parseable as *gtsmodel.Status", cMsg.GTSModel)
@@ -942,8 +937,22 @@ func (p *clientAPI) DeleteStatus(ctx context.Context, cMsg *messages.FromClientA
// (stops processing of remote origin data targeting this status).
p.state.Workers.Federator.Queue.Delete("TargetURI", status.URI)
- // First perform the actual status deletion.
- if err := p.utils.wipeStatus(ctx, status, deleteAttachments); err != nil {
+ // Don't delete attachments, just unattach them:
+ // this request comes from the client API and the
+ // poster may want to use attachments again later.
+ const deleteAttachments = false
+
+ // This is just a deletion, not a Reject,
+ // we don't need to take a copy of this status.
+ const copyToSinBin = false
+
+ // Perform the actual status deletion.
+ if err := p.utils.wipeStatus(
+ ctx,
+ status,
+ deleteAttachments,
+ copyToSinBin,
+ ); err != nil {
log.Errorf(ctx, "error wiping status: %v", err)
}
@@ -1275,9 +1284,23 @@ func (p *clientAPI) RejectReply(ctx context.Context, cMsg *messages.FromClientAP
return gtserror.Newf("db error getting rejected reply: %w", err)
}
- // Totally wipe the status.
- if err := p.utils.wipeStatus(ctx, status, true); err != nil {
- return gtserror.Newf("error wiping status: %w", err)
+ // Delete attachments from this status.
+ // It's rejected so there's no possibility
+ // for the poster to delete + redraft it.
+ const deleteAttachments = true
+
+ // Keep a copy of the status in
+ // the sin bin for future review.
+ const copyToSinBin = true
+
+ // Perform the actual status deletion.
+ if err := p.utils.wipeStatus(
+ ctx,
+ status,
+ deleteAttachments,
+ copyToSinBin,
+ ); err != nil {
+ log.Errorf(ctx, "error wiping reply: %v", err)
}
return nil
@@ -1306,9 +1329,22 @@ func (p *clientAPI) RejectAnnounce(ctx context.Context, cMsg *messages.FromClien
return gtserror.Newf("db error getting rejected announce: %w", err)
}
- // Totally wipe the status.
- if err := p.utils.wipeStatus(ctx, boost, true); err != nil {
- return gtserror.Newf("error wiping status: %w", err)
+ // Boosts don't have attachments anyway
+ // so it doesn't matter what we set here.
+ const deleteAttachments = true
+
+ // This is just a boost, don't
+ // keep a copy in the sin bin.
+ const copyToSinBin = true
+
+ // Perform the actual status deletion.
+ if err := p.utils.wipeStatus(
+ ctx,
+ boost,
+ deleteAttachments,
+ copyToSinBin,
+ ); err != nil {
+ log.Errorf(ctx, "error wiping announce: %v", err)
}
return nil
diff --git a/internal/processing/workers/fromfediapi.go b/internal/processing/workers/fromfediapi.go
index 42e5e9db2..d8abaa865 100644
--- a/internal/processing/workers/fromfediapi.go
+++ b/internal/processing/workers/fromfediapi.go
@@ -27,6 +27,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing"
+ "github.com/superseriousbusiness/gotosocial/internal/gtscontext"
"github.com/superseriousbusiness/gotosocial/internal/id"
"github.com/superseriousbusiness/gotosocial/internal/uris"
@@ -146,6 +147,23 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg *messages.FromF
return p.fediAPI.AcceptAnnounce(ctx, fMsg)
}
+ // REJECT SOMETHING
+ case ap.ActivityReject:
+ switch fMsg.APObjectType {
+
+ // REJECT LIKE
+ case ap.ActivityLike:
+ return p.fediAPI.RejectLike(ctx, fMsg)
+
+ // REJECT NOTE/STATUS (ie., reject a reply)
+ case ap.ObjectNote:
+ return p.fediAPI.RejectReply(ctx, fMsg)
+
+ // REJECT BOOST
+ case ap.ActivityAnnounce:
+ return p.fediAPI.RejectAnnounce(ctx, fMsg)
+ }
+
// DELETE SOMETHING
case ap.ActivityDelete:
switch fMsg.APObjectType {
@@ -878,11 +896,6 @@ func (p *fediAPI) UpdateStatus(ctx context.Context, fMsg *messages.FromFediAPI)
}
func (p *fediAPI) DeleteStatus(ctx context.Context, fMsg *messages.FromFediAPI) error {
- // Delete attachments from this status, since this request
- // comes from the federating API, and there's no way the
- // poster can do a delete + redraft for it on our instance.
- const deleteAttachments = true
-
status, ok := fMsg.GTSModel.(*gtsmodel.Status)
if !ok {
return gtserror.Newf("%T not parseable as *gtsmodel.Status", fMsg.GTSModel)
@@ -909,8 +922,22 @@ func (p *fediAPI) DeleteStatus(ctx context.Context, fMsg *messages.FromFediAPI)
// (stops processing of remote origin data targeting this status).
p.state.Workers.Federator.Queue.Delete("TargetURI", status.URI)
- // First perform the actual status deletion.
- if err := p.utils.wipeStatus(ctx, status, deleteAttachments); err != nil {
+ // Delete attachments from this status, since this request
+ // comes from the federating API, and there's no way the
+ // poster can do a delete + redraft for it on our instance.
+ const deleteAttachments = true
+
+ // This is just a deletion, not a Reject,
+ // we don't need to take a copy of this status.
+ const copyToSinBin = false
+
+ // Perform the actual status deletion.
+ if err := p.utils.wipeStatus(
+ ctx,
+ status,
+ deleteAttachments,
+ copyToSinBin,
+ ); err != nil {
log.Errorf(ctx, "error wiping status: %v", err)
}
@@ -956,3 +983,113 @@ func (p *fediAPI) DeleteAccount(ctx context.Context, fMsg *messages.FromFediAPI)
return nil
}
+
+func (p *fediAPI) RejectLike(ctx context.Context, fMsg *messages.FromFediAPI) error {
+ req, ok := fMsg.GTSModel.(*gtsmodel.InteractionRequest)
+ if !ok {
+ return gtserror.Newf("%T not parseable as *gtsmodel.InteractionRequest", fMsg.GTSModel)
+ }
+
+ // At this point the InteractionRequest should already
+ // be in the database, we just need to do side effects.
+
+ // Send out the Reject.
+ if err := p.federate.RejectInteraction(ctx, req); err != nil {
+ log.Errorf(ctx, "error federating rejection of like: %v", err)
+ }
+
+ // Get the rejected fave.
+ fave, err := p.state.DB.GetStatusFaveByURI(
+ gtscontext.SetBarebones(ctx),
+ req.InteractionURI,
+ )
+ if err != nil {
+ return gtserror.Newf("db error getting rejected fave: %w", err)
+ }
+
+ // Delete the fave.
+ if err := p.state.DB.DeleteStatusFaveByID(ctx, fave.ID); err != nil {
+ return gtserror.Newf("db error deleting fave: %w", err)
+ }
+
+ return nil
+}
+
+func (p *fediAPI) RejectReply(ctx context.Context, fMsg *messages.FromFediAPI) error {
+ req, ok := fMsg.GTSModel.(*gtsmodel.InteractionRequest)
+ if !ok {
+ return gtserror.Newf("%T not parseable as *gtsmodel.InteractionRequest", fMsg.GTSModel)
+ }
+
+ // At this point the InteractionRequest should already
+ // be in the database, we just need to do side effects.
+
+ // Get the rejected status.
+ status, err := p.state.DB.GetStatusByURI(
+ gtscontext.SetBarebones(ctx),
+ req.InteractionURI,
+ )
+ if err != nil {
+ return gtserror.Newf("db error getting rejected reply: %w", err)
+ }
+
+ // Delete attachments from this status.
+ // It's rejected so there's no possibility
+ // for the poster to delete + redraft it.
+ const deleteAttachments = true
+
+ // Keep a copy of the status in
+ // the sin bin for future review.
+ const copyToSinBin = true
+
+ // Perform the actual status deletion.
+ if err := p.utils.wipeStatus(
+ ctx,
+ status,
+ deleteAttachments,
+ copyToSinBin,
+ ); err != nil {
+ log.Errorf(ctx, "error wiping reply: %v", err)
+ }
+
+ return nil
+}
+
+func (p *fediAPI) RejectAnnounce(ctx context.Context, fMsg *messages.FromFediAPI) error {
+ req, ok := fMsg.GTSModel.(*gtsmodel.InteractionRequest)
+ if !ok {
+ return gtserror.Newf("%T not parseable as *gtsmodel.InteractionRequest", fMsg.GTSModel)
+ }
+
+ // At this point the InteractionRequest should already
+ // be in the database, we just need to do side effects.
+
+ // Get the rejected boost.
+ boost, err := p.state.DB.GetStatusByURI(
+ gtscontext.SetBarebones(ctx),
+ req.InteractionURI,
+ )
+ if err != nil {
+ return gtserror.Newf("db error getting rejected announce: %w", err)
+ }
+
+ // Boosts don't have attachments anyway
+ // so it doesn't matter what we set here.
+ const deleteAttachments = true
+
+ // This is just a boost, don't
+ // keep a copy in the sin bin.
+ const copyToSinBin = true
+
+ // Perform the actual status deletion.
+ if err := p.utils.wipeStatus(
+ ctx,
+ boost,
+ deleteAttachments,
+ copyToSinBin,
+ ); err != nil {
+ log.Errorf(ctx, "error wiping announce: %v", err)
+ }
+
+ return nil
+}
diff --git a/internal/processing/workers/util.go b/internal/processing/workers/util.go
index bb7faffbf..042f4827c 100644
--- a/internal/processing/workers/util.go
+++ b/internal/processing/workers/util.go
@@ -37,69 +37,90 @@ import (
// util provides util functions used by both
// the fromClientAPI and fromFediAPI functions.
type utils struct {
- state *state.State
- media *media.Processor
- account *account.Processor
- surface *Surface
+ state *state.State
+ media *media.Processor
+ account *account.Processor
+ surface *Surface
+ converter *typeutils.Converter
}
-// wipeStatus encapsulates common logic
-// used to totally delete a status + all
-// its attachments, notifications, boosts,
-// and timeline entries.
+// wipeStatus encapsulates common logic used to
+// totally delete a status + all its attachments,
+// notifications, boosts, and timeline entries.
+//
+// If deleteAttachments is true, then any status
+// attachments will also be deleted, else they
+// will just be detached.
+//
+// If copyToSinBin is true, then a version of the
+// status will be put in the `sin_bin_statuses`
+// table prior to deletion.
func (u *utils) wipeStatus(
ctx context.Context,
- statusToDelete *gtsmodel.Status,
+ status *gtsmodel.Status,
deleteAttachments bool,
+ copyToSinBin bool,
) error {
var errs gtserror.MultiError
+ if copyToSinBin {
+ // Copy this status to the sin bin before we delete it.
+ sbStatus, err := u.converter.StatusToSinBinStatus(ctx, status)
+ if err != nil {
+ errs.Appendf("error converting status to sinBinStatus: %w", err)
+ } else {
+ if err := u.state.DB.PutSinBinStatus(ctx, sbStatus); err != nil {
+ errs.Appendf("db error storing sinBinStatus: %w", err)
+ }
+ }
+ }
+
// Either delete all attachments for this status,
- // or simply unattach + clean them separately later.
+ // or simply detach + clean them separately later.
//
- // Reason to unattach rather than delete is that
- // the poster might want to reattach them to another
- // status immediately (in case of delete + redraft)
+ // Reason to detach rather than delete is that
+ // the author might want to reattach them to another
+ // status immediately (in case of delete + redraft).
if deleteAttachments {
// todo:u.state.DB.DeleteAttachmentsForStatus
- for _, id := range statusToDelete.AttachmentIDs {
+ for _, id := range status.AttachmentIDs {
if err := u.media.Delete(ctx, id); err != nil {
errs.Appendf("error deleting media: %w", err)
}
}
} else {
// todo:u.state.DB.UnattachAttachmentsForStatus
- for _, id := range statusToDelete.AttachmentIDs {
- if _, err := u.media.Unattach(ctx, statusToDelete.Account, id); err != nil {
+ for _, id := range status.AttachmentIDs {
+ if _, err := u.media.Unattach(ctx, status.Account, id); err != nil {
errs.Appendf("error unattaching media: %w", err)
}
}
}
- // delete all mention entries generated by this status
+ // Delete all mentions generated by this status.
// todo:u.state.DB.DeleteMentionsForStatus
- for _, id := range statusToDelete.MentionIDs {
+ for _, id := range status.MentionIDs {
if err := u.state.DB.DeleteMentionByID(ctx, id); err != nil {
errs.Appendf("error deleting status mention: %w", err)
}
}
- // delete all notification entries generated by this status
- if err := u.state.DB.DeleteNotificationsForStatus(ctx, statusToDelete.ID); err != nil {
+ // Delete all notifications generated by this status.
+ if err := u.state.DB.DeleteNotificationsForStatus(ctx, status.ID); err != nil {
errs.Appendf("error deleting status notifications: %w", err)
}
- // delete all bookmarks that point to this status
- if err := u.state.DB.DeleteStatusBookmarksForStatus(ctx, statusToDelete.ID); err != nil {
+ // Delete all bookmarks of this status.
+ if err := u.state.DB.DeleteStatusBookmarksForStatus(ctx, status.ID); err != nil {
errs.Appendf("error deleting status bookmarks: %w", err)
}
- // delete all faves of this status
- if err := u.state.DB.DeleteStatusFavesForStatus(ctx, statusToDelete.ID); err != nil {
+ // Delete all faves of this status.
+ if err := u.state.DB.DeleteStatusFavesForStatus(ctx, status.ID); err != nil {
errs.Appendf("error deleting status faves: %w", err)
}
- if pollID := statusToDelete.PollID; pollID != "" {
+ if pollID := status.PollID; pollID != "" {
// Delete this poll by ID from the database.
if err := u.state.DB.DeletePollByID(ctx, pollID); err != nil {
errs.Appendf("error deleting status poll: %w", err)
@@ -114,38 +135,42 @@ func (u *utils) wipeStatus(
_ = u.state.Workers.Scheduler.Cancel(pollID)
}
- // delete all boosts for this status + remove them from timelines
+ // Get all boost of this status so that we can
+ // delete those boosts + remove them from timelines.
boosts, err := u.state.DB.GetStatusBoosts(
- // we MUST set a barebones context here,
+ // We MUST set a barebones context here,
// as depending on where it came from the
// original BoostOf may already be gone.
gtscontext.SetBarebones(ctx),
- statusToDelete.ID)
+ status.ID)
if err != nil {
errs.Appendf("error fetching status boosts: %w", err)
}
for _, boost := range boosts {
- if err := u.surface.deleteStatusFromTimelines(ctx, boost.ID); err != nil {
- errs.Appendf("error deleting boost from timelines: %w", err)
- }
+ // Delete the boost itself.
if err := u.state.DB.DeleteStatusByID(ctx, boost.ID); err != nil {
errs.Appendf("error deleting boost: %w", err)
}
+
+ // Remove the boost from any and all timelines.
+ if err := u.surface.deleteStatusFromTimelines(ctx, boost.ID); err != nil {
+ errs.Appendf("error deleting boost from timelines: %w", err)
+ }
}
- // delete this status from any and all timelines
- if err := u.surface.deleteStatusFromTimelines(ctx, statusToDelete.ID); err != nil {
+ // Delete the status itself from any and all timelines.
+ if err := u.surface.deleteStatusFromTimelines(ctx, status.ID); err != nil {
errs.Appendf("error deleting status from timelines: %w", err)
}
- // delete this status from any conversations that it's part of
- if err := u.state.DB.DeleteStatusFromConversations(ctx, statusToDelete.ID); err != nil {
+ // Delete this status from any conversations it's part of.
+ if err := u.state.DB.DeleteStatusFromConversations(ctx, status.ID); err != nil {
errs.Appendf("error deleting status from conversations: %w", err)
}
- // finally, delete the status itself
- if err := u.state.DB.DeleteStatusByID(ctx, statusToDelete.ID); err != nil {
+ // Finally delete the status itself.
+ if err := u.state.DB.DeleteStatusByID(ctx, status.ID); err != nil {
errs.Appendf("error deleting status: %w", err)
}
diff --git a/internal/processing/workers/workers.go b/internal/processing/workers/workers.go
index d4b525783..ad673481b 100644
--- a/internal/processing/workers/workers.go
+++ b/internal/processing/workers/workers.go
@@ -70,10 +70,11 @@ func New(
// Init shared util funcs.
utils := &utils{
- state: state,
- media: media,
- account: account,
- surface: surface,
+ state: state,
+ media: media,
+ account: account,
+ surface: surface,
+ converter: converter,
}
return Processor{