diff options
Diffstat (limited to 'internal/timeline')
-rw-r--r-- | internal/timeline/index.go | 50 | ||||
-rw-r--r-- | internal/timeline/manager.go | 2 | ||||
-rw-r--r-- | internal/timeline/postindex.go | 15 | ||||
-rw-r--r-- | internal/timeline/prepare.go | 18 | ||||
-rw-r--r-- | internal/timeline/preparedposts.go | 18 | ||||
-rw-r--r-- | internal/timeline/timeline.go | 7 |
6 files changed, 46 insertions, 64 deletions
diff --git a/internal/timeline/index.go b/internal/timeline/index.go index 56f5c14df..bc1bf996b 100644 --- a/internal/timeline/index.go +++ b/internal/timeline/index.go @@ -10,41 +10,6 @@ import ( ) func (t *timeline) IndexBefore(statusID string, include bool, amount int) error { - // filtered := []*gtsmodel.Status{} - // offsetStatus := statusID - - // grabloop: - // for len(filtered) < amount { - // statuses, err := t.db.GetStatusesWhereFollowing(t.accountID, amount, offsetStatus, include, true) - // if err != nil { - // if _, ok := err.(db.ErrNoEntries); !ok { - // return fmt.Errorf("IndexBeforeAndIncluding: error getting statuses from db: %s", err) - // } - // break grabloop // we just don't have enough statuses left in the db so index what we've got and then bail - // } - - // for _, s := range statuses { - // relevantAccounts, err := t.db.PullRelevantAccountsFromStatus(s) - // if err != nil { - // continue - // } - // visible, err := t.db.StatusVisible(s, t.account, relevantAccounts) - // if err != nil { - // continue - // } - // if visible { - // filtered = append(filtered, s) - // } - // offsetStatus = s.ID - // } - // } - - // for _, s := range filtered { - // if err := t.IndexOne(s.CreatedAt, s.ID); err != nil { - // return fmt.Errorf("IndexBeforeAndIncluding: error indexing status with id %s: %s", s.ID, err) - // } - // } - return nil } @@ -63,15 +28,11 @@ grabloop: } for _, s := range statuses { - relevantAccounts, err := t.db.PullRelevantAccountsFromStatus(s) + timelineable, err := t.filter.StatusHometimelineable(s, t.account) if err != nil { continue } - visible, err := t.db.StatusVisible(s, t.account, relevantAccounts) - if err != nil { - continue - } - if visible { + if timelineable { filtered = append(filtered, s) } offsetStatus = s.ID @@ -79,7 +40,7 @@ grabloop: } for _, s := range filtered { - if err := t.IndexOne(s.CreatedAt, s.ID); err != nil { + if err := t.IndexOne(s.CreatedAt, s.ID, s.BoostOfID); err != nil { return fmt.Errorf("IndexBehindAndIncluding: error indexing status with id %s: %s", s.ID, err) } } @@ -91,12 +52,13 @@ func (t *timeline) IndexOneByID(statusID string) error { return nil } -func (t *timeline) IndexOne(statusCreatedAt time.Time, statusID string) error { +func (t *timeline) IndexOne(statusCreatedAt time.Time, statusID string, boostOfID string) error { t.Lock() defer t.Unlock() postIndexEntry := &postIndexEntry{ - statusID: statusID, + statusID: statusID, + boostOfID: boostOfID, } return t.postIndex.insertIndexed(postIndexEntry) diff --git a/internal/timeline/manager.go b/internal/timeline/manager.go index 9d28b5060..c389a6b8a 100644 --- a/internal/timeline/manager.go +++ b/internal/timeline/manager.go @@ -105,7 +105,7 @@ func (m *manager) Ingest(status *gtsmodel.Status, timelineAccountID string) erro t := m.getOrCreateTimeline(timelineAccountID) l.Trace("ingesting status") - return t.IndexOne(status.CreatedAt, status.ID) + return t.IndexOne(status.CreatedAt, status.ID, status.BoostOfID) } func (m *manager) IngestAndPrepare(status *gtsmodel.Status, timelineAccountID string) error { diff --git a/internal/timeline/postindex.go b/internal/timeline/postindex.go index 2ab65e087..7142035a7 100644 --- a/internal/timeline/postindex.go +++ b/internal/timeline/postindex.go @@ -10,7 +10,8 @@ type postIndex struct { } type postIndexEntry struct { - statusID string + statusID string + boostOfID string } func (p *postIndex) insertIndexed(i *postIndexEntry) error { @@ -25,14 +26,26 @@ func (p *postIndex) insertIndexed(i *postIndexEntry) error { } var insertMark *list.Element + var position int // We need to iterate through the index to make sure we put this post in the appropriate place according to when it was created. // We also need to make sure we're not inserting a duplicate post -- this can happen sometimes and it's not nice UX (*shudder*). for e := p.data.Front(); e != nil; e = e.Next() { + position = position + 1 + entry, ok := e.Value.(*postIndexEntry) if !ok { return errors.New("index: could not parse e as a postIndexEntry") } + // don't insert this if it's a boost of a status we've seen recently + if i.boostOfID != "" { + if i.boostOfID == entry.boostOfID || i.boostOfID == entry.statusID { + if position < boostReinsertionDepth { + return nil + } + } + } + // if the post to index is newer than e, insert it before e in the list if insertMark == nil { if i.statusID > entry.statusID { diff --git a/internal/timeline/prepare.go b/internal/timeline/prepare.go index 1fb1cd714..cd740993c 100644 --- a/internal/timeline/prepare.go +++ b/internal/timeline/prepare.go @@ -163,24 +163,8 @@ func (t *timeline) prepare(statusID string) error { t.account = timelineOwnerAccount } - // to convert the status we need relevant accounts from it, so pull them out here - relevantAccounts, err := t.db.PullRelevantAccountsFromStatus(gtsStatus) - if err != nil { - return err - } - - // check if this is a boost... - var reblogOfStatus *gtsmodel.Status - if gtsStatus.BoostOfID != "" { - s := >smodel.Status{} - if err := t.db.GetByID(gtsStatus.BoostOfID, s); err != nil { - return err - } - reblogOfStatus = s - } - // serialize the status (or, at least, convert it to a form that's ready to be serialized) - apiModelStatus, err := t.tc.StatusToMasto(gtsStatus, relevantAccounts.StatusAuthor, t.account, relevantAccounts.BoostedAccount, relevantAccounts.ReplyToAccount, reblogOfStatus) + apiModelStatus, err := t.tc.StatusToMasto(gtsStatus, t.account) if err != nil { return err } diff --git a/internal/timeline/preparedposts.go b/internal/timeline/preparedposts.go index 429ce5415..1976189c8 100644 --- a/internal/timeline/preparedposts.go +++ b/internal/timeline/preparedposts.go @@ -28,14 +28,32 @@ func (p *preparedPosts) insertPrepared(i *preparedPostsEntry) error { } var insertMark *list.Element + var position int // We need to iterate through the index to make sure we put this post in the appropriate place according to when it was created. // We also need to make sure we're not inserting a duplicate post -- this can happen sometimes and it's not nice UX (*shudder*). for e := p.data.Front(); e != nil; e = e.Next() { + position = position + 1 + entry, ok := e.Value.(*preparedPostsEntry) if !ok { return errors.New("index: could not parse e as a preparedPostsEntry") } + // don't insert this if it's a boost of a status we've seen recently + if i.prepared.Reblog != nil { + if entry.prepared.Reblog != nil && i.prepared.Reblog.ID == entry.prepared.Reblog.ID { + if position < boostReinsertionDepth { + return nil + } + } + + if i.prepared.Reblog.ID == entry.statusID { + if position < boostReinsertionDepth { + return nil + } + } + } + // if the post to index is newer than e, insert it before e in the list if insertMark == nil { if i.statusID > entry.statusID { diff --git a/internal/timeline/timeline.go b/internal/timeline/timeline.go index 7408436dc..363c0999c 100644 --- a/internal/timeline/timeline.go +++ b/internal/timeline/timeline.go @@ -27,8 +27,11 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/typeutils" + "github.com/superseriousbusiness/gotosocial/internal/visibility" ) +const boostReinsertionDepth = 50 + // Timeline represents a timeline for one account, and contains indexed and prepared posts. type Timeline interface { /* @@ -59,7 +62,7 @@ type Timeline interface { */ // IndexOne puts a status into the timeline at the appropriate place according to its 'createdAt' property. - IndexOne(statusCreatedAt time.Time, statusID string) error + IndexOne(statusCreatedAt time.Time, statusID string, boostOfID string) error // OldestIndexedPostID returns the id of the rearmost (ie., the oldest) indexed post, or an error if something goes wrong. // If nothing goes wrong but there's no oldest post, an empty string will be returned so make sure to check for this. @@ -109,6 +112,7 @@ type timeline struct { accountID string account *gtsmodel.Account db db.DB + filter visibility.Filter tc typeutils.TypeConverter log *logrus.Logger sync.Mutex @@ -121,6 +125,7 @@ func NewTimeline(accountID string, db db.DB, typeConverter typeutils.TypeConvert preparedPosts: &preparedPosts{}, accountID: accountID, db: db, + filter: visibility.NewFilter(db, log), tc: typeConverter, log: log, } |