diff options
| -rw-r--r-- | internal/processing/account/follow.go | 46 | ||||
| -rw-r--r-- | internal/processing/workers/fromclientapi.go | 24 | 
2 files changed, 49 insertions, 21 deletions
| diff --git a/internal/processing/account/follow.go b/internal/processing/account/follow.go index 402c764e8..6c066d6a6 100644 --- a/internal/processing/account/follow.go +++ b/internal/processing/account/follow.go @@ -30,6 +30,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/id"  	"github.com/superseriousbusiness/gotosocial/internal/messages"  	"github.com/superseriousbusiness/gotosocial/internal/uris" +	"github.com/superseriousbusiness/gotosocial/internal/util"  )  // FollowCreate handles a follow request to an account, either remote or local. @@ -98,35 +99,38 @@ func (p *Processor) FollowCreate(ctx context.Context, requestingAccount *gtsmode  		Notify:          form.Notify,  	} +	// Insert the new follow request.  	if err := p.state.DB.PutFollowRequest(ctx, fr); err != nil {  		err = gtserror.Newf("error creating follow request in db: %s", err)  		return nil, gtserror.NewErrorInternalError(err)  	} +	// And get the new relationship state. +	rel, errWithCode := p.RelationshipGet(ctx, requestingAccount, form.ID) +	if errWithCode != nil { +		return nil, errWithCode +	} + +	// For unlocked accounts on the same instance, +	// we can already optimistically show the follow +	// request as accepted in the returned relationship.  	if targetAccount.IsLocal() && !*targetAccount.Locked { -		// If the target account is local and not locked, -		// we can already accept the follow request and -		// skip any further processing. -		// -		// Because we know the requestingAccount is also -		// local, we don't need to federate the accept out. -		if _, err := p.state.DB.AcceptFollowRequest(ctx, requestingAccount.ID, form.ID); err != nil { -			err = gtserror.Newf("error accepting follow request for local unlocked account: %w", err) -			return nil, gtserror.NewErrorInternalError(err) -		} -	} else { -		// Otherwise we leave the follow request as it is, -		// and we handle the rest of the process async. -		p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{ -			APObjectType:   ap.ActivityFollow, -			APActivityType: ap.ActivityCreate, -			GTSModel:       fr, -			Origin:         requestingAccount, -			Target:         targetAccount, -		}) +		rel.Requested = false +		rel.Following = true +		rel.ShowingReblogs = util.PtrValueOr(fr.ShowReblogs, true) +		rel.Notifying = util.PtrValueOr(fr.Notify, false)  	} -	return p.RelationshipGet(ctx, requestingAccount, form.ID) +	// Handle side effects async. +	p.state.Workers.Client.Queue.Push(&messages.FromClientAPI{ +		APObjectType:   ap.ActivityFollow, +		APActivityType: ap.ActivityCreate, +		GTSModel:       fr, +		Origin:         requestingAccount, +		Target:         targetAccount, +	}) + +	return rel, nil  }  // FollowRemove handles the removal of a follow/follow request to an account, either remote or local. diff --git a/internal/processing/workers/fromclientapi.go b/internal/processing/workers/fromclientapi.go index 89b8f546f..d5d4265e1 100644 --- a/internal/processing/workers/fromclientapi.go +++ b/internal/processing/workers/fromclientapi.go @@ -305,6 +305,30 @@ func (p *clientAPI) CreateFollowReq(ctx context.Context, cMsg *messages.FromClie  		return gtserror.Newf("%T not parseable as *gtsmodel.FollowRequest", cMsg.GTSModel)  	} +	// If target is a local, unlocked account, +	// we can skip side effects for the follow +	// request and accept the follow immediately. +	if cMsg.Target.IsLocal() && !*cMsg.Target.Locked { +		// Accept the FR first to get the Follow. +		follow, err := p.state.DB.AcceptFollowRequest( +			ctx, +			cMsg.Origin.ID, +			cMsg.Target.ID, +		) +		if err != nil { +			return gtserror.Newf("db error accepting follow req: %w", err) +		} + +		// Use AcceptFollow to do side effects. +		return p.AcceptFollow(ctx, &messages.FromClientAPI{ +			APObjectType:   ap.ActivityFollow, +			APActivityType: ap.ActivityAccept, +			GTSModel:       follow, +			Origin:         cMsg.Origin, +			Target:         cMsg.Target, +		}) +	} +  	// Update stats for the target account.  	if err := p.utils.incrementFollowRequestsCount(ctx, cMsg.Target); err != nil {  		log.Errorf(ctx, "error updating account stats: %v", err) | 
