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)  			}  		}  | 
