summaryrefslogtreecommitdiff
path: root/internal/processing/fromfederator.go
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2023-06-11 11:18:44 +0200
committerLibravatar GitHub <noreply@github.com>2023-06-11 10:18:44 +0100
commit5e2897e35cd2bea889fa37a2a857f4dcc076dafc (patch)
treeb1ac6203ffa20f5fff1c460fed942854a6e5c6bd /internal/processing/fromfederator.go
parent[docs] Revamp the installation guide (#1877) (diff)
downloadgotosocial-5e2897e35cd2bea889fa37a2a857f4dcc076dafc.tar.xz
[bugfix] Invalidate timeline entries for status when stats change (#1879)
Diffstat (limited to 'internal/processing/fromfederator.go')
-rw-r--r--internal/processing/fromfederator.go134
1 files changed, 60 insertions, 74 deletions
diff --git a/internal/processing/fromfederator.go b/internal/processing/fromfederator.go
index 17d60c77f..f165b2835 100644
--- a/internal/processing/fromfederator.go
+++ b/internal/processing/fromfederator.go
@@ -26,6 +26,7 @@ import (
"codeberg.org/gruf/go-kv"
"codeberg.org/gruf/go-logger/v2/level"
"github.com/superseriousbusiness/gotosocial/internal/ap"
+ "github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/id"
"github.com/superseriousbusiness/gotosocial/internal/log"
@@ -120,7 +121,7 @@ func (p *Processor) processCreateStatusFromFederator(ctx context.Context, federa
// there's a gts model already pinned to the message, it should be a status
if status, ok = federatorMsg.GTSModel.(*gtsmodel.Status); !ok {
- return errors.New("ProcessFromFederator: note was not parseable as *gtsmodel.Status")
+ return gtserror.New("Note was not parseable as *gtsmodel.Status")
}
// Since this was a create originating AP object
@@ -140,7 +141,7 @@ func (p *Processor) processCreateStatusFromFederator(ctx context.Context, federa
} else {
// no model pinned, we need to dereference based on the IRI
if federatorMsg.APIri == nil {
- return errors.New("ProcessFromFederator: status was not pinned to federatorMsg, and neither was an IRI for us to dereference")
+ return gtserror.New("status was not pinned to federatorMsg, and neither was an IRI for us to dereference")
}
status, _, err = p.federator.GetStatusByURI(ctx, federatorMsg.ReceivingAccount.Username, federatorMsg.APIri)
@@ -167,44 +168,35 @@ func (p *Processor) processCreateStatusFromFederator(ctx context.Context, federa
}
}
- return p.timelineAndNotifyStatus(ctx, status)
+ if status.InReplyToID != "" {
+ // Interaction counts changed on the replied status;
+ // uncache the prepared version from all timelines.
+ p.invalidateStatusFromTimelines(ctx, status.InReplyToID)
+ }
+
+ if err := p.timelineAndNotifyStatus(ctx, status); err != nil {
+ return gtserror.Newf("error timelining status: %w", err)
+ }
+
+ return nil
}
-// processCreateFaveFromFederator handles Activity Create and Object Like
+// processCreateFaveFromFederator handles Activity Create with Object Like.
func (p *Processor) processCreateFaveFromFederator(ctx context.Context, federatorMsg messages.FromFederator) error {
- incomingFave, ok := federatorMsg.GTSModel.(*gtsmodel.StatusFave)
+ statusFave, ok := federatorMsg.GTSModel.(*gtsmodel.StatusFave)
if !ok {
- return errors.New("like was not parseable as *gtsmodel.StatusFave")
+ return gtserror.New("Like was not parseable as *gtsmodel.StatusFave")
}
- // make sure the account is pinned
- if incomingFave.Account == nil {
- a, err := p.state.DB.GetAccountByID(ctx, incomingFave.AccountID)
- if err != nil {
- return err
- }
- incomingFave.Account = a
+ if err := p.notifyFave(ctx, statusFave); err != nil {
+ return gtserror.Newf("error notifying status fave: %w", err)
}
- // Get the remote account to make sure the avi and header are cached.
- if incomingFave.Account.Domain != "" {
- remoteAccountID, err := url.Parse(incomingFave.Account.URI)
- if err != nil {
- return err
- }
-
- a, _, err := p.federator.GetAccountByURI(ctx,
- federatorMsg.ReceivingAccount.Username,
- remoteAccountID,
- )
- if err != nil {
- return err
- }
-
- incomingFave.Account = a
- }
+ // Interaction counts changed on the faved status;
+ // uncache the prepared version from all timelines.
+ p.invalidateStatusFromTimelines(ctx, statusFave.StatusID)
- return p.notifyFave(ctx, incomingFave)
+ return nil
}
// processCreateFollowRequestFromFederator handles Activity Create and Object Follow
@@ -267,59 +259,43 @@ func (p *Processor) processCreateFollowRequestFromFederator(ctx context.Context,
return p.notifyFollow(ctx, follow, followRequest.TargetAccount)
}
-// processCreateAnnounceFromFederator handles Activity Create and Object Announce
+// processCreateAnnounceFromFederator handles Activity Create with Object Announce.
func (p *Processor) processCreateAnnounceFromFederator(ctx context.Context, federatorMsg messages.FromFederator) error {
- incomingAnnounce, ok := federatorMsg.GTSModel.(*gtsmodel.Status)
+ status, ok := federatorMsg.GTSModel.(*gtsmodel.Status)
if !ok {
- return errors.New("announce was not parseable as *gtsmodel.Status")
+ return gtserror.New("Announce was not parseable as *gtsmodel.Status")
}
- // make sure the account is pinned
- if incomingAnnounce.Account == nil {
- a, err := p.state.DB.GetAccountByID(ctx, incomingAnnounce.AccountID)
- if err != nil {
- return err
- }
- incomingAnnounce.Account = a
+ // Dereference status that this status boosts.
+ if err := p.federator.DereferenceAnnounce(ctx, status, federatorMsg.ReceivingAccount.Username); err != nil {
+ return gtserror.Newf("error dereferencing announce: %w", err)
}
- // Get the remote account to make sure the avi and header are cached.
- if incomingAnnounce.Account.Domain != "" {
- remoteAccountID, err := url.Parse(incomingAnnounce.Account.URI)
- if err != nil {
- return err
- }
-
- a, _, err := p.federator.GetAccountByURI(ctx,
- federatorMsg.ReceivingAccount.Username,
- remoteAccountID,
- )
- if err != nil {
- return err
- }
-
- incomingAnnounce.Account = a
+ // Generate an ID for the boost wrapper status.
+ statusID, err := id.NewULIDFromTime(status.CreatedAt)
+ if err != nil {
+ return gtserror.Newf("error generating id: %w", err)
}
+ status.ID = statusID
- if err := p.federator.DereferenceAnnounce(ctx, incomingAnnounce, federatorMsg.ReceivingAccount.Username); err != nil {
- return fmt.Errorf("error dereferencing announce from federator: %s", err)
+ // Store, timeline, and notify.
+ if err := p.state.DB.PutStatus(ctx, status); err != nil {
+ return gtserror.Newf("db error inserting status: %w", err)
}
- incomingAnnounceID, err := id.NewULIDFromTime(incomingAnnounce.CreatedAt)
- if err != nil {
- return err
+ if err := p.timelineAndNotifyStatus(ctx, status); err != nil {
+ return gtserror.Newf("error timelining status: %w", err)
}
- incomingAnnounce.ID = incomingAnnounceID
- if err := p.state.DB.PutStatus(ctx, incomingAnnounce); err != nil {
- return fmt.Errorf("error adding dereferenced announce to the db: %s", err)
+ if err := p.notifyAnnounce(ctx, status); err != nil {
+ return gtserror.Newf("error notifying status: %w", err)
}
- if err := p.timelineAndNotifyStatus(ctx, incomingAnnounce); err != nil {
- return err
- }
+ // Interaction counts changed on the boosted status;
+ // uncache the prepared version from all timelines.
+ p.invalidateStatusFromTimelines(ctx, status.ID)
- return p.notifyAnnounce(ctx, incomingAnnounce)
+ return nil
}
// processCreateBlockFromFederator handles Activity Create and Object Block
@@ -384,16 +360,26 @@ func (p *Processor) processUpdateAccountFromFederator(ctx context.Context, feder
// processDeleteStatusFromFederator handles Activity Delete and Object Note
func (p *Processor) processDeleteStatusFromFederator(ctx context.Context, federatorMsg messages.FromFederator) error {
- statusToDelete, ok := federatorMsg.GTSModel.(*gtsmodel.Status)
+ status, ok := federatorMsg.GTSModel.(*gtsmodel.Status)
if !ok {
- return errors.New("note was not parseable as *gtsmodel.Status")
+ return errors.New("Note was not parseable as *gtsmodel.Status")
}
- // delete attachments from this status since this request
+ // Delete attachments from this status, since this request
// comes from the federating API, and there's no way the
- // poster can do a delete + redraft for it on our instance
+ // poster can do a delete + redraft for it on our instance.
deleteAttachments := true
- return p.wipeStatus(ctx, statusToDelete, deleteAttachments)
+ if err := p.wipeStatus(ctx, status, deleteAttachments); err != nil {
+ return gtserror.Newf("error wiping status: %w", err)
+ }
+
+ if status.InReplyToID != "" {
+ // Interaction counts changed on the replied status;
+ // uncache the prepared version from all timelines.
+ p.invalidateStatusFromTimelines(ctx, status.InReplyToID)
+ }
+
+ return nil
}
// processDeleteAccountFromFederator handles Activity Delete and Object Profile