mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
Timeline manager (#40)
* start messing about with timeline manager * i have no idea what i'm doing * i continue to not know what i'm doing * it's coming along * bit more progress * update timeline with new posts as they come in * lint and fmt * Select accounts where empty string * restructure a bunch, get unfaves working * moving stuff around * federate status deletes properly * mention regex better but not 100% there * fix regex * some more hacking away at the timeline code phew * fix up some little things * i can't even * more timeline stuff * move to ulid * fiddley * some lil fixes for kibou compatibility * timelines working pretty alright! * tidy + lint
This commit is contained in:
139
internal/timeline/timeline.go
Normal file
139
internal/timeline/timeline.go
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package timeline
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
||||
)
|
||||
|
||||
// Timeline represents a timeline for one account, and contains indexed and prepared posts.
|
||||
type Timeline interface {
|
||||
/*
|
||||
RETRIEVAL FUNCTIONS
|
||||
*/
|
||||
|
||||
Get(amount int, maxID string, sinceID string, minID string) ([]*apimodel.Status, error)
|
||||
// GetXFromTop returns x amount of posts from the top of the timeline, from newest to oldest.
|
||||
GetXFromTop(amount int) ([]*apimodel.Status, error)
|
||||
// GetXBehindID returns x amount of posts from the given id onwards, from newest to oldest.
|
||||
// This will NOT include the status with the given ID.
|
||||
//
|
||||
// This corresponds to an api call to /timelines/home?max_id=WHATEVER
|
||||
GetXBehindID(amount int, fromID string) ([]*apimodel.Status, error)
|
||||
// GetXBeforeID returns x amount of posts up to the given id, from newest to oldest.
|
||||
// This will NOT include the status with the given ID.
|
||||
//
|
||||
// This corresponds to an api call to /timelines/home?since_id=WHATEVER
|
||||
GetXBeforeID(amount int, sinceID string, startFromTop bool) ([]*apimodel.Status, error)
|
||||
// GetXBetweenID returns x amount of posts from the given maxID, up to the given id, from newest to oldest.
|
||||
// This will NOT include the status with the given IDs.
|
||||
//
|
||||
// This corresponds to an api call to /timelines/home?since_id=WHATEVER&max_id=WHATEVER_ELSE
|
||||
GetXBetweenID(amount int, maxID string, sinceID string) ([]*apimodel.Status, error)
|
||||
|
||||
/*
|
||||
INDEXING FUNCTIONS
|
||||
*/
|
||||
|
||||
// IndexOne puts a status into the timeline at the appropriate place according to its 'createdAt' property.
|
||||
IndexOne(statusCreatedAt time.Time, statusID 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.
|
||||
OldestIndexedPostID() (string, error)
|
||||
|
||||
/*
|
||||
PREPARATION FUNCTIONS
|
||||
*/
|
||||
|
||||
// PrepareXFromTop instructs the timeline to prepare x amount of posts from the top of the timeline.
|
||||
PrepareFromTop(amount int) error
|
||||
// PrepareBehind instructs the timeline to prepare the next amount of entries for serialization, from position onwards.
|
||||
// If include is true, then the given status ID will also be prepared, otherwise only entries behind it will be prepared.
|
||||
PrepareBehind(statusID string, amount int) error
|
||||
// IndexOne puts a status into the timeline at the appropriate place according to its 'createdAt' property,
|
||||
// and then immediately prepares it.
|
||||
IndexAndPrepareOne(statusCreatedAt time.Time, statusID string) error
|
||||
// OldestPreparedPostID returns the id of the rearmost (ie., the oldest) prepared 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.
|
||||
OldestPreparedPostID() (string, error)
|
||||
|
||||
/*
|
||||
INFO FUNCTIONS
|
||||
*/
|
||||
|
||||
// ActualPostIndexLength returns the actual length of the post index at this point in time.
|
||||
PostIndexLength() int
|
||||
|
||||
/*
|
||||
UTILITY FUNCTIONS
|
||||
*/
|
||||
|
||||
// Reset instructs the timeline to reset to its base state -- cache only the minimum amount of posts.
|
||||
Reset() error
|
||||
// Remove removes a status from both the index and prepared posts.
|
||||
//
|
||||
// If a status has multiple entries in a timeline, they will all be removed.
|
||||
//
|
||||
// The returned int indicates the amount of entries that were removed.
|
||||
Remove(statusID string) (int, error)
|
||||
}
|
||||
|
||||
// timeline fulfils the Timeline interface
|
||||
type timeline struct {
|
||||
postIndex *postIndex
|
||||
preparedPosts *preparedPosts
|
||||
accountID string
|
||||
account *gtsmodel.Account
|
||||
db db.DB
|
||||
tc typeutils.TypeConverter
|
||||
log *logrus.Logger
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewTimeline returns a new Timeline for the given account ID
|
||||
func NewTimeline(accountID string, db db.DB, typeConverter typeutils.TypeConverter, log *logrus.Logger) Timeline {
|
||||
return &timeline{
|
||||
postIndex: &postIndex{},
|
||||
preparedPosts: &preparedPosts{},
|
||||
accountID: accountID,
|
||||
db: db,
|
||||
tc: typeConverter,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *timeline) Reset() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *timeline) PostIndexLength() int {
|
||||
if t.postIndex == nil || t.postIndex.data == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return t.postIndex.data.Len()
|
||||
}
|
Reference in New Issue
Block a user