diff options
Diffstat (limited to 'internal/processing/workers')
-rw-r--r-- | internal/processing/workers/federate.go | 64 | ||||
-rw-r--r-- | internal/processing/workers/fromclientapi.go | 21 | ||||
-rw-r--r-- | internal/processing/workers/fromfediapi.go | 36 | ||||
-rw-r--r-- | internal/processing/workers/wipestatus.go | 17 |
4 files changed, 117 insertions, 21 deletions
diff --git a/internal/processing/workers/federate.go b/internal/processing/workers/federate.go index 4b2ca4de1..a87a89fd2 100644 --- a/internal/processing/workers/federate.go +++ b/internal/processing/workers/federate.go @@ -147,27 +147,27 @@ func (f *federate) CreateStatus(ctx context.Context, status *gtsmodel.Status) er return nil } - // Populate model. + // Ensure the status model is fully populated. if err := f.state.DB.PopulateStatus(ctx, status); err != nil { return gtserror.Newf("error populating status: %w", err) } - // Parse relevant URI(s). + // Parse the outbox URI of the status author. outboxIRI, err := parseURI(status.Account.OutboxURI) if err != nil { return err } - // Convert status to an ActivityStreams - // Note, wrapped in a Create activity. - asStatus, err := f.converter.StatusToAS(ctx, status) + // Convert status to ActivityStreams Statusable implementing type. + statusable, err := f.converter.StatusToAS(ctx, status) if err != nil { - return gtserror.Newf("error converting status to AS: %w", err) + return gtserror.Newf("error converting status to Statusable: %w", err) } - create, err := f.converter.WrapNoteInCreate(asStatus, false) + // Use ActivityStreams Statusable type as Object of Create. + create, err := f.converter.WrapStatusableInCreate(statusable, false) if err != nil { - return gtserror.Newf("error wrapping status in create: %w", err) + return gtserror.Newf("error wrapping Statusable in Create: %w", err) } // Send the Create via the Actor's outbox. @@ -196,12 +196,12 @@ func (f *federate) DeleteStatus(ctx context.Context, status *gtsmodel.Status) er return nil } - // Populate model. + // Ensure the status model is fully populated. if err := f.state.DB.PopulateStatus(ctx, status); err != nil { return gtserror.Newf("error populating status: %w", err) } - // Parse relevant URI(s). + // Parse the outbox URI of the status author. outboxIRI, err := parseURI(status.Account.OutboxURI) if err != nil { return err @@ -226,6 +226,50 @@ func (f *federate) DeleteStatus(ctx context.Context, status *gtsmodel.Status) er return nil } +func (f *federate) UpdateStatus(ctx context.Context, status *gtsmodel.Status) error { + // Do nothing if the status + // shouldn't be federated. + if !*status.Federated { + return nil + } + + // Do nothing if this + // isn't our status. + if !*status.Local { + return nil + } + + // Ensure the status model is fully populated. + if err := f.state.DB.PopulateStatus(ctx, status); err != nil { + return gtserror.Newf("error populating status: %w", err) + } + + // Parse the outbox URI of the status author. + outboxIRI, err := parseURI(status.Account.OutboxURI) + if err != nil { + return err + } + + // Convert status to ActivityStreams Statusable implementing type. + statusable, err := f.converter.StatusToAS(ctx, status) + if err != nil { + return gtserror.Newf("error converting status to Statusable: %w", err) + } + + // Use ActivityStreams Statusable type as Object of Update. + update, err := f.converter.WrapStatusableInUpdate(statusable, false) + if err != nil { + return gtserror.Newf("error wrapping Statusable in Update: %w", err) + } + + // Send the Update activity with Statusable via the Actor's outbox. + if _, err := f.FederatingActor().Send(ctx, outboxIRI, update); err != nil { + return gtserror.Newf("error sending Update activity via outbox %s: %w", outboxIRI, err) + } + + return nil +} + func (f *federate) Follow(ctx context.Context, follow *gtsmodel.Follow) error { // Populate model. if err := f.state.DB.PopulateFollow(ctx, follow); err != nil { diff --git a/internal/processing/workers/fromclientapi.go b/internal/processing/workers/fromclientapi.go index 1c668db71..ff316b1f4 100644 --- a/internal/processing/workers/fromclientapi.go +++ b/internal/processing/workers/fromclientapi.go @@ -114,6 +114,10 @@ func (p *Processor) ProcessFromClientAPI(ctx context.Context, cMsg messages.From case ap.ActivityUpdate: switch cMsg.APObjectType { + // UPDATE NOTE/STATUS + case ap.ObjectNote: + return p.clientAPI.UpdateStatus(ctx, cMsg) + // UPDATE PROFILE/ACCOUNT case ap.ObjectProfile, ap.ActorPerson: return p.clientAPI.UpdateAccount(ctx, cMsg) @@ -332,10 +336,25 @@ func (p *clientAPI) CreateBlock(ctx context.Context, cMsg messages.FromClientAPI return nil } +func (p *clientAPI) UpdateStatus(ctx context.Context, cMsg messages.FromClientAPI) error { + // Cast the updated Status model attached to msg. + status, ok := cMsg.GTSModel.(*gtsmodel.Status) + if !ok { + return gtserror.Newf("cannot cast %T -> *gtsmodel.Status", cMsg.GTSModel) + } + + // Federate the updated status changes out remotely. + if err := p.federate.UpdateStatus(ctx, status); err != nil { + return gtserror.Newf("error federating status update: %w", err) + } + + return nil +} + func (p *clientAPI) UpdateAccount(ctx context.Context, cMsg messages.FromClientAPI) error { account, ok := cMsg.GTSModel.(*gtsmodel.Account) if !ok { - return gtserror.Newf("%T not parseable as *gtsmodel.Account", cMsg.GTSModel) + return gtserror.Newf("cannot cast %T -> *gtsmodel.Account", cMsg.GTSModel) } if err := p.federate.UpdateAccount(ctx, account); err != nil { diff --git a/internal/processing/workers/fromfediapi.go b/internal/processing/workers/fromfediapi.go index 57e087499..598480cfb 100644 --- a/internal/processing/workers/fromfediapi.go +++ b/internal/processing/workers/fromfediapi.go @@ -119,6 +119,10 @@ func (p *Processor) ProcessFromFediAPI(ctx context.Context, fMsg messages.FromFe case ap.ActivityUpdate: switch fMsg.APObjectType { //nolint:gocritic + // UPDATE NOTE/STATUS + case ap.ObjectNote: + return p.fediAPI.UpdateStatus(ctx, fMsg) + // UPDATE PROFILE/ACCOUNT case ap.ObjectProfile: return p.fediAPI.UpdateAccount(ctx, fMsg) @@ -485,13 +489,13 @@ func (p *fediAPI) UpdateAccount(ctx context.Context, fMsg messages.FromFediAPI) // Parse the old/existing account model. account, ok := fMsg.GTSModel.(*gtsmodel.Account) if !ok { - return gtserror.Newf("%T not parseable as *gtsmodel.Account", fMsg.GTSModel) + return gtserror.Newf("cannot cast %T -> *gtsmodel.Account", fMsg.GTSModel) } // Because this was an Update, the new Accountable should be set on the message. apubAcc, ok := fMsg.APObjectModel.(ap.Accountable) if !ok { - return gtserror.Newf("%T not parseable as ap.Accountable", fMsg.APObjectModel) + return gtserror.Newf("cannot cast %T -> ap.Accountable", fMsg.APObjectModel) } // Fetch up-to-date bio, avatar, header, etc. @@ -509,6 +513,34 @@ func (p *fediAPI) UpdateAccount(ctx context.Context, fMsg messages.FromFediAPI) return nil } +func (p *fediAPI) UpdateStatus(ctx context.Context, fMsg messages.FromFediAPI) error { + // Cast the existing Status model attached to msg. + existing, ok := fMsg.GTSModel.(*gtsmodel.Status) + if !ok { + return gtserror.Newf("cannot cast %T -> *gtsmodel.Status", fMsg.GTSModel) + } + + // Cast the updated ActivityPub statusable object . + apStatus, ok := fMsg.APObjectModel.(ap.Statusable) + if !ok { + return gtserror.Newf("cannot cast %T -> ap.Statusable", fMsg.APObjectModel) + } + + // Fetch up-to-date attach status attachments, etc. + _, _, err := p.federate.RefreshStatus( + ctx, + fMsg.ReceivingAccount.Username, + existing, + apStatus, + false, + ) + if err != nil { + return gtserror.Newf("error refreshing updated status: %w", err) + } + + return nil +} + 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 diff --git a/internal/processing/workers/wipestatus.go b/internal/processing/workers/wipestatus.go index 0891d9e24..ab59f14be 100644 --- a/internal/processing/workers/wipestatus.go +++ b/internal/processing/workers/wipestatus.go @@ -38,7 +38,7 @@ func wipeStatusF(state *state.State, media *media.Processor, surface *surface) w statusToDelete *gtsmodel.Status, deleteAttachments bool, ) error { - errs := new(gtserror.MultiError) + var errs gtserror.MultiError // Either delete all attachments for this status, // or simply unattach + clean them separately later. @@ -48,15 +48,15 @@ func wipeStatusF(state *state.State, media *media.Processor, surface *surface) w // 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 { + for _, id := range statusToDelete.AttachmentIDs { + if err := media.Delete(ctx, id); 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 { + for _, id := range statusToDelete.AttachmentIDs { + if _, err := media.Unattach(ctx, statusToDelete.Account, id); err != nil { errs.Appendf("error unattaching media: %w", err) } } @@ -95,11 +95,12 @@ func wipeStatusF(state *state.State, media *media.Processor, surface *surface) w if err != nil { errs.Appendf("error fetching status boosts: %w", err) } - for _, b := range boosts { - if err := surface.deleteStatusFromTimelines(ctx, b.ID); err != nil { + + for _, boost := range boosts { + if err := surface.deleteStatusFromTimelines(ctx, boost.ID); err != nil { errs.Appendf("error deleting boost from timelines: %w", err) } - if err := state.DB.DeleteStatusByID(ctx, b.ID); err != nil { + if err := state.DB.DeleteStatusByID(ctx, boost.ID); err != nil { errs.Appendf("error deleting boost: %w", err) } } |