diff options
Diffstat (limited to 'internal/processing/workers/wipestatus.go')
-rw-r--r-- | internal/processing/workers/wipestatus.go | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/internal/processing/workers/wipestatus.go b/internal/processing/workers/wipestatus.go new file mode 100644 index 000000000..0891d9e24 --- /dev/null +++ b/internal/processing/workers/wipestatus.go @@ -0,0 +1,119 @@ +// GoToSocial +// Copyright (C) GoToSocial Authors admin@gotosocial.org +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +package workers + +import ( + "context" + + "github.com/superseriousbusiness/gotosocial/internal/gtscontext" + "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + "github.com/superseriousbusiness/gotosocial/internal/processing/media" + "github.com/superseriousbusiness/gotosocial/internal/state" +) + +// wipeStatus encapsulates common logic used to totally delete a status +// + all its attachments, notifications, boosts, and timeline entries. +type wipeStatus func(context.Context, *gtsmodel.Status, bool) error + +// wipeStatusF returns a wipeStatus util function. +func wipeStatusF(state *state.State, media *media.Processor, surface *surface) wipeStatus { + return func( + ctx context.Context, + statusToDelete *gtsmodel.Status, + deleteAttachments bool, + ) error { + errs := new(gtserror.MultiError) + + // Either delete all attachments for this status, + // or simply unattach + 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) + if deleteAttachments { + // todo:state.DB.DeleteAttachmentsForStatus + for _, a := range statusToDelete.AttachmentIDs { + if err := media.Delete(ctx, a); err != nil { + errs.Appendf("error deleting media: %w", err) + } + } + } else { + // todo:state.DB.UnattachAttachmentsForStatus + for _, a := range statusToDelete.AttachmentIDs { + if _, err := media.Unattach(ctx, statusToDelete.Account, a); err != nil { + errs.Appendf("error unattaching media: %w", err) + } + } + } + + // delete all mention entries generated by this status + // todo:state.DB.DeleteMentionsForStatus + for _, id := range statusToDelete.MentionIDs { + if err := 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 := state.DB.DeleteNotificationsForStatus(ctx, statusToDelete.ID); err != nil { + errs.Appendf("error deleting status notifications: %w", err) + } + + // delete all bookmarks that point to this status + if err := state.DB.DeleteStatusBookmarksForStatus(ctx, statusToDelete.ID); err != nil { + errs.Appendf("error deleting status bookmarks: %w", err) + } + + // delete all faves of this status + if err := state.DB.DeleteStatusFavesForStatus(ctx, statusToDelete.ID); err != nil { + errs.Appendf("error deleting status faves: %w", err) + } + + // delete all boosts for this status + remove them from timelines + boosts, err := state.DB.GetStatusBoosts( + // 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) + if err != nil { + errs.Appendf("error fetching status boosts: %w", err) + } + for _, b := range boosts { + if err := surface.deleteStatusFromTimelines(ctx, b.ID); err != nil { + errs.Appendf("error deleting boost from timelines: %w", err) + } + if err := state.DB.DeleteStatusByID(ctx, b.ID); err != nil { + errs.Appendf("error deleting boost: %w", err) + } + } + + // delete this status from any and all timelines + if err := surface.deleteStatusFromTimelines(ctx, statusToDelete.ID); err != nil { + errs.Appendf("error deleting status from timelines: %w", err) + } + + // finally, delete the status itself + if err := state.DB.DeleteStatusByID(ctx, statusToDelete.ID); err != nil { + errs.Appendf("error deleting status: %w", err) + } + + return errs.Combine() + } +} |