[feature] add support for receiving federated status edits (#3597)

* add support for extracting Updated field from Statusable implementers

* add support for status edits in the database, and update status dereferencer to handle them

* remove unused AdditionalInfo{}.CreatedAt

* remove unused AdditionalEmojiInfo{}.CreatedAt

* update new mention creation to use status.UpdatedAt

* remove mention.UpdatedAt, fixes related to NewULIDFromTime() change

* add migration to remove Mention{}.UpdatedAt field

* add migration to add the StatusEdit{} table

* start adding tests, add delete function for status edits

* add more of status edit migrations, fill in more of the necessary edit delete functionality

* remove unused function

* allow generating gotosocial compatible ulid via CLI with `go run ./cmd/gen-ulid`

* add StatusEdit{} test models

* fix new statusedits sql

* use model instead of table name

* actually remove the Mention.UpdatedAt field...

* fix tests now new models are added, add more status edit DB tests

* fix panic wording

* add test for deleting status edits

* don't automatically set `updated_at` field on updated statuses

* flesh out more of the dereferencer status edit tests, ensure updated at field set on outgoing AS statuses

* remove media_attachments.updated_at column

* fix up more tests, further complete the dereferencer status edit tests

* update more status serialization tests not expecting 'updated' AS property

* gah!! json serialization tests!!

* undo some gtscontext wrapping changes

* more serialization test fixing 🥲

* more test fixing, ensure the edit.status_id field is actually set 🤦

* fix status edit test

* grrr linter

* add edited_at field to apimodel status

* remove the choice of paging on the timeline public filtered test (otherwise it needs updating every time you add statuses ...)

* ensure that status.updated_at always fits chronologically

* fix more serialization tests ...

* add more code comments

* fix envparsing

* update swagger file

* properly handle media description changes during status edits

* slight formatting tweak

* code comment
This commit is contained in:
kim
2024-12-05 13:35:07 +00:00
committed by GitHub
parent 3e18d97a6e
commit 23fc70f4e6
86 changed files with 2557 additions and 651 deletions

View File

@ -75,6 +75,21 @@ func (u *utils) wipeStatus(
}
}
// Before handling media, ensure
// historic edits are populated.
if !status.EditsPopulated() {
var err error
// Fetch all historical edits of status from database.
status.Edits, err = u.state.DB.GetStatusEditsByIDs(
gtscontext.SetBarebones(ctx),
status.EditIDs,
)
if err != nil {
errs.Appendf("error getting status edits from database: %w", err)
}
}
// Either delete all attachments for this status,
// or simply detach + clean them separately later.
//
@ -83,20 +98,27 @@ func (u *utils) wipeStatus(
// status immediately (in case of delete + redraft).
if deleteAttachments {
// todo:u.state.DB.DeleteAttachmentsForStatus
for _, id := range status.AttachmentIDs {
for _, id := range status.AllAttachmentIDs() {
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 status.AttachmentIDs {
for _, id := range status.AllAttachmentIDs() {
if _, err := u.media.Unattach(ctx, status.Account, id); err != nil {
errs.Appendf("error unattaching media: %w", err)
}
}
}
// Delete all historical edits of status.
if ids := status.EditIDs; len(ids) > 0 {
if err := u.state.DB.DeleteStatusEdits(ctx, ids); err != nil {
errs.Appendf("error deleting status edits: %w", err)
}
}
// Delete all mentions generated by this status.
// todo:u.state.DB.DeleteMentionsForStatus
for _, id := range status.MentionIDs {
@ -120,19 +142,20 @@ func (u *utils) wipeStatus(
errs.Appendf("error deleting status faves: %w", err)
}
if pollID := status.PollID; pollID != "" {
if id := status.PollID; id != "" {
// Delete this poll by ID from the database.
if err := u.state.DB.DeletePollByID(ctx, pollID); err != nil {
if err := u.state.DB.DeletePollByID(ctx, id); err != nil {
errs.Appendf("error deleting status poll: %w", err)
}
// Cancel any scheduled expiry task for poll.
_ = u.state.Workers.Scheduler.Cancel(pollID)
_ = u.state.Workers.Scheduler.Cancel(id)
}
// 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,
// as depending on where it came from the
// original BoostOf may already be gone.
@ -537,11 +560,7 @@ func (u *utils) requestFave(
}
// Create + store new interaction request.
req, err = typeutils.StatusFaveToInteractionRequest(ctx, fave)
if err != nil {
return gtserror.Newf("error creating interaction request: %w", err)
}
req = typeutils.StatusFaveToInteractionRequest(fave)
if err := u.state.DB.PutInteractionRequest(ctx, req); err != nil {
return gtserror.Newf("db error storing interaction request: %w", err)
}
@ -584,11 +603,7 @@ func (u *utils) requestReply(
}
// Create + store interaction request.
req, err = typeutils.StatusToInteractionRequest(ctx, reply)
if err != nil {
return gtserror.Newf("error creating interaction request: %w", err)
}
req = typeutils.StatusToInteractionRequest(reply)
if err := u.state.DB.PutInteractionRequest(ctx, req); err != nil {
return gtserror.Newf("db error storing interaction request: %w", err)
}
@ -631,11 +646,7 @@ func (u *utils) requestAnnounce(
}
// Create + store interaction request.
req, err = typeutils.StatusToInteractionRequest(ctx, boost)
if err != nil {
return gtserror.Newf("error creating interaction request: %w", err)
}
req = typeutils.StatusToInteractionRequest(boost)
if err := u.state.DB.PutInteractionRequest(ctx, req); err != nil {
return gtserror.Newf("db error storing interaction request: %w", err)
}