mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-30 00:26:15 -06:00
more updates
This commit is contained in:
parent
a3322b2bf3
commit
81ea286254
30 changed files with 290 additions and 251 deletions
|
|
@ -18,14 +18,13 @@
|
|||
|
||||
package db
|
||||
|
||||
import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
type Account interface {
|
||||
// GetAccountByUserID is a shortcut for the common action of fetching an account corresponding to a user ID.
|
||||
// The given account pointer will be set to the result of the query, whatever it is.
|
||||
// In case of no entries, a 'no entries' error will be returned
|
||||
GetAccountByUserID(userID string, account *gtsmodel.Account) DBError
|
||||
|
||||
// GetAccountByID returns one account with the given ID, or an error if something goes wrong.
|
||||
GetAccountByID(id string) (*gtsmodel.Account, DBError)
|
||||
|
||||
|
|
@ -75,10 +74,10 @@ type Account interface {
|
|||
|
||||
GetAccountBlocks(accountID string, maxID string, sinceID string, limit int) ([]*gtsmodel.Account, string, string, DBError)
|
||||
|
||||
// GetAccountLastStatus simply gets the most recent status by the given account.
|
||||
// The given slice 'status' pointer will be set to the result of the query, whatever it is.
|
||||
// In case of no entries, a 'no entries' error will be returned
|
||||
GetAccountLastStatus(accountID string, status *gtsmodel.Status) DBError
|
||||
// GetAccountLastPosted simply gets the timestamp of the most recent post by the account.
|
||||
//
|
||||
// The returned time will be zero if account has never posted anything.
|
||||
GetAccountLastPosted(accountID string) (time.Time, DBError)
|
||||
|
||||
// SetAccountHeaderOrAvatar sets the header or avatar for the given accountID to the given media attachment.
|
||||
SetAccountHeaderOrAvatar(mediaAttachment *gtsmodel.MediaAttachment, accountID string) DBError
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ import "fmt"
|
|||
type DBError error
|
||||
|
||||
var (
|
||||
ErrNoEntries DBError = fmt.Errorf("no entries")
|
||||
ErrAlreadyExists DBError = fmt.Errorf("already exists")
|
||||
ErrUnknown DBError = fmt.Errorf("unknown error")
|
||||
ErrNoEntries DBError = fmt.Errorf("no entries")
|
||||
ErrMultipleEntries DBError = fmt.Errorf("multiple entries")
|
||||
ErrAlreadyExists DBError = fmt.Errorf("already exists")
|
||||
ErrUnknown DBError = fmt.Errorf("unknown error")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
|
|
@ -44,24 +45,15 @@ func (a *accountDB) newAccountQ(account *gtsmodel.Account) *orm.Query {
|
|||
Relation("HeaderMediaAttachment")
|
||||
}
|
||||
|
||||
func (a *accountDB) processResponse(account *gtsmodel.Account, err error) (*gtsmodel.Account, db.DBError) {
|
||||
switch err {
|
||||
case pg.ErrNoRows:
|
||||
return nil, db.ErrNoEntries
|
||||
case nil:
|
||||
return account, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountByID(id string) (*gtsmodel.Account, db.DBError) {
|
||||
account := >smodel.Account{}
|
||||
|
||||
q := a.newAccountQ(account).
|
||||
Where("account.id = ?", id)
|
||||
|
||||
return a.processResponse(account, q.Select())
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
return account, err
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountByURI(uri string) (*gtsmodel.Account, db.DBError) {
|
||||
|
|
@ -70,7 +62,9 @@ func (a *accountDB) GetAccountByURI(uri string) (*gtsmodel.Account, db.DBError)
|
|||
q := a.newAccountQ(account).
|
||||
Where("account.uri = ?", uri)
|
||||
|
||||
return a.processResponse(account, q.Select())
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
return account, err
|
||||
}
|
||||
|
||||
func (a *accountDB) GetInstanceAccount(domain string) (*gtsmodel.Account, db.DBError) {
|
||||
|
|
@ -88,18 +82,23 @@ func (a *accountDB) GetInstanceAccount(domain string) (*gtsmodel.Account, db.DBE
|
|||
Where("? IS NULL", pg.Ident("domain"))
|
||||
}
|
||||
|
||||
return a.processResponse(account, q.Select())
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
return account, err
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountLastStatus(accountID string, status *gtsmodel.Status) db.DBError {
|
||||
if err := a.conn.Model(status).Order("created_at DESC").Limit(1).Where("account_id = ?", accountID).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
return db.ErrNoEntries
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
func (a *accountDB) GetAccountLastPosted(accountID string) (time.Time, db.DBError) {
|
||||
status := >smodel.Status{}
|
||||
|
||||
q := a.conn.Model(status).
|
||||
Order("id DESC").
|
||||
Limit(1).
|
||||
Where("account_id = ?", accountID).
|
||||
Column("created_at")
|
||||
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
return status.CreatedAt, err
|
||||
}
|
||||
|
||||
func (a *accountDB) SetAccountHeaderOrAvatar(mediaAttachment *gtsmodel.MediaAttachment, accountID string) db.DBError {
|
||||
|
|
@ -127,25 +126,6 @@ func (a *accountDB) SetAccountHeaderOrAvatar(mediaAttachment *gtsmodel.MediaAtta
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountByUserID(userID string, account *gtsmodel.Account) db.DBError {
|
||||
user := >smodel.User{
|
||||
ID: userID,
|
||||
}
|
||||
if err := a.conn.Model(user).Where("id = ?", userID).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
return db.ErrNoEntries
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err := a.conn.Model(account).Where("id = ?", user.AccountID).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
return db.ErrNoEntries
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *accountDB) GetLocalAccountByUsername(username string, account *gtsmodel.Account) db.DBError {
|
||||
if err := a.conn.Model(account).Where("username = ?", username).Where("? IS NULL", pg.Ident("domain")).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import (
|
|||
|
||||
"github.com/go-pg/pg/extra/pgdebug"
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
|
|
@ -38,6 +39,11 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||
)
|
||||
|
||||
var registerTables []interface{} = []interface{}{
|
||||
>smodel.StatusToEmoji{},
|
||||
>smodel.StatusToTag{},
|
||||
}
|
||||
|
||||
// postgresService satisfies the DB interface
|
||||
type postgresService struct {
|
||||
db.Account
|
||||
|
|
@ -58,6 +64,11 @@ type postgresService struct {
|
|||
// NewPostgresService returns a postgresService derived from the provided config, which implements the go-fed DB interface.
|
||||
// Under the hood, it uses https://github.com/go-pg/pg to create and maintain a database connection.
|
||||
func NewPostgresService(ctx context.Context, c *config.Config, log *logrus.Logger) (db.DB, error) {
|
||||
for _, t := range registerTables {
|
||||
// https://pg.uptrace.dev/orm/many-to-many-relation/
|
||||
orm.RegisterTable(t)
|
||||
}
|
||||
|
||||
opts, err := derivePGOptions(c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create postgres service: %s", err)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"container/list"
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
|
|
@ -38,7 +39,7 @@ type statusDB struct {
|
|||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (s *statusDB) newStatusQ(status *gtsmodel.Status) *orm.Query {
|
||||
func (s *statusDB) newStatusQ(status interface{}) *orm.Query {
|
||||
return s.conn.Model(status).
|
||||
Relation("Attachments").
|
||||
Relation("Tags").
|
||||
|
|
@ -52,15 +53,11 @@ func (s *statusDB) newStatusQ(status *gtsmodel.Status) *orm.Query {
|
|||
Relation("CreatedWithApplication")
|
||||
}
|
||||
|
||||
func (s *statusDB) processStatusResponse(status *gtsmodel.Status, err error) (*gtsmodel.Status, db.DBError) {
|
||||
switch err {
|
||||
case pg.ErrNoRows:
|
||||
return nil, db.ErrNoEntries
|
||||
case nil:
|
||||
return status, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
func (s *statusDB) newFaveQ(faves interface{}) *orm.Query {
|
||||
return s.conn.Model(faves).
|
||||
Relation("Account").
|
||||
Relation("TargetAccount").
|
||||
Relation("Status")
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusByID(id string) (*gtsmodel.Status, db.DBError) {
|
||||
|
|
@ -69,7 +66,9 @@ func (s *statusDB) GetStatusByID(id string) (*gtsmodel.Status, db.DBError) {
|
|||
q := s.newStatusQ(status).
|
||||
Where("status.id = ?", id)
|
||||
|
||||
return s.processStatusResponse(status, q.Select())
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
return status, err
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusByURI(uri string) (*gtsmodel.Status, db.DBError) {
|
||||
|
|
@ -78,10 +77,52 @@ func (s *statusDB) GetStatusByURI(uri string) (*gtsmodel.Status, db.DBError) {
|
|||
q := s.newStatusQ(status).
|
||||
Where("LOWER(status.uri) = LOWER(?)", uri)
|
||||
|
||||
return s.processStatusResponse(status, q.Select())
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
return status, err
|
||||
}
|
||||
|
||||
func (s *statusDB) StatusParents(status *gtsmodel.Status, onlyDirect bool) ([]*gtsmodel.Status, db.DBError) {
|
||||
func (s *statusDB) PutStatus(status *gtsmodel.Status) db.DBError {
|
||||
transaction := func(tx *pg.Tx) error {
|
||||
// create links between this status and any emojis it uses
|
||||
for _, i := range status.EmojiIDs {
|
||||
if _, err := tx.Model(>smodel.StatusToEmoji{
|
||||
StatusID: status.ID,
|
||||
EmojiID: i,
|
||||
}).Insert(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// create links between this status and any tags it uses
|
||||
for _, i := range status.TagIDs {
|
||||
if _, err := tx.Model(>smodel.StatusToTag{
|
||||
StatusID: status.ID,
|
||||
TagID: i,
|
||||
}).Insert(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// change the status ID of the media attachments to the new status
|
||||
for _, a := range status.Attachments {
|
||||
a.StatusID = status.ID
|
||||
a.UpdatedAt = time.Now()
|
||||
if _, err := s.conn.Model(a).
|
||||
Where("id = ?", a.ID).
|
||||
Update(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err := tx.Model(status).Insert()
|
||||
return err
|
||||
}
|
||||
|
||||
return processErrorResponse(s.conn.RunInTransaction(context.Background(), transaction))
|
||||
}
|
||||
|
||||
func (s *statusDB) GetStatusParents(status *gtsmodel.Status, onlyDirect bool) ([]*gtsmodel.Status, db.DBError) {
|
||||
parents := []*gtsmodel.Status{}
|
||||
s.statusParent(status, &parents, onlyDirect)
|
||||
|
||||
|
|
@ -93,18 +134,19 @@ func (s *statusDB) statusParent(status *gtsmodel.Status, foundStatuses *[]*gtsmo
|
|||
return
|
||||
}
|
||||
|
||||
parentStatus := >smodel.Status{}
|
||||
if err := s.conn.Model(parentStatus).Where("id = ?", status.InReplyToID).Select(); err == nil {
|
||||
parentStatus, err := s.GetStatusByID(status.InReplyToID)
|
||||
if err == nil {
|
||||
*foundStatuses = append(*foundStatuses, parentStatus)
|
||||
}
|
||||
|
||||
if onlyDirect {
|
||||
return
|
||||
}
|
||||
|
||||
s.statusParent(parentStatus, foundStatuses, false)
|
||||
}
|
||||
|
||||
func (s *statusDB) StatusChildren(status *gtsmodel.Status, onlyDirect bool, minID string) ([]*gtsmodel.Status, db.DBError) {
|
||||
func (s *statusDB) GetStatusChildren(status *gtsmodel.Status, onlyDirect bool, minID string) ([]*gtsmodel.Status, db.DBError) {
|
||||
foundStatuses := &list.List{}
|
||||
foundStatuses.PushFront(status)
|
||||
s.statusChildren(status, foundStatuses, onlyDirect, minID)
|
||||
|
|
@ -159,78 +201,52 @@ func (s *statusDB) statusChildren(status *gtsmodel.Status, foundStatuses *list.L
|
|||
}
|
||||
}
|
||||
|
||||
func (s *statusDB) GetReplyCountForStatus(status *gtsmodel.Status) (int, db.DBError) {
|
||||
func (s *statusDB) CountStatusReplies(status *gtsmodel.Status) (int, db.DBError) {
|
||||
return s.conn.Model(>smodel.Status{}).Where("in_reply_to_id = ?", status.ID).Count()
|
||||
}
|
||||
|
||||
func (s *statusDB) GetReblogCountForStatus(status *gtsmodel.Status) (int, db.DBError) {
|
||||
func (s *statusDB) CountStatusReblogs(status *gtsmodel.Status) (int, db.DBError) {
|
||||
return s.conn.Model(>smodel.Status{}).Where("boost_of_id = ?", status.ID).Count()
|
||||
}
|
||||
|
||||
func (s *statusDB) GetFaveCountForStatus(status *gtsmodel.Status) (int, db.DBError) {
|
||||
func (s *statusDB) CountStatusFaves(status *gtsmodel.Status) (int, db.DBError) {
|
||||
return s.conn.Model(>smodel.StatusFave{}).Where("status_id = ?", status.ID).Count()
|
||||
}
|
||||
|
||||
func (s *statusDB) StatusFavedBy(status *gtsmodel.Status, accountID string) (bool, db.DBError) {
|
||||
func (s *statusDB) IsStatusFavedBy(status *gtsmodel.Status, accountID string) (bool, db.DBError) {
|
||||
return s.conn.Model(>smodel.StatusFave{}).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||
}
|
||||
|
||||
func (s *statusDB) StatusRebloggedBy(status *gtsmodel.Status, accountID string) (bool, db.DBError) {
|
||||
func (s *statusDB) IsStatusRebloggedBy(status *gtsmodel.Status, accountID string) (bool, db.DBError) {
|
||||
return s.conn.Model(>smodel.Status{}).Where("boost_of_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||
}
|
||||
|
||||
func (s *statusDB) StatusMutedBy(status *gtsmodel.Status, accountID string) (bool, db.DBError) {
|
||||
func (s *statusDB) IsStatusMutedBy(status *gtsmodel.Status, accountID string) (bool, db.DBError) {
|
||||
return s.conn.Model(>smodel.StatusMute{}).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||
}
|
||||
|
||||
func (s *statusDB) StatusBookmarkedBy(status *gtsmodel.Status, accountID string) (bool, db.DBError) {
|
||||
func (s *statusDB) IsStatusBookmarkedBy(status *gtsmodel.Status, accountID string) (bool, db.DBError) {
|
||||
return s.conn.Model(>smodel.StatusBookmark{}).Where("status_id = ?", status.ID).Where("account_id = ?", accountID).Exists()
|
||||
}
|
||||
|
||||
func (s *statusDB) WhoFavedStatus(status *gtsmodel.Status) ([]*gtsmodel.Account, db.DBError) {
|
||||
accounts := []*gtsmodel.Account{}
|
||||
|
||||
func (s *statusDB) GetStatusFaves(status *gtsmodel.Status) ([]*gtsmodel.StatusFave, db.DBError) {
|
||||
faves := []*gtsmodel.StatusFave{}
|
||||
if err := s.conn.Model(&faves).Where("status_id = ?", status.ID).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
return accounts, nil // no rows just means nobody has faved this status, so that's fine
|
||||
}
|
||||
return nil, err // an actual error has occurred
|
||||
}
|
||||
|
||||
for _, f := range faves {
|
||||
acc := >smodel.Account{}
|
||||
if err := s.conn.Model(acc).Where("id = ?", f.AccountID).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
continue // the account doesn't exist for some reason??? but this isn't the place to worry about that so just skip it
|
||||
}
|
||||
return nil, err // an actual error has occurred
|
||||
}
|
||||
accounts = append(accounts, acc)
|
||||
}
|
||||
return accounts, nil
|
||||
q := s.newFaveQ(&faves).
|
||||
Where("status_id = ?", status.ID)
|
||||
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
return faves, err
|
||||
}
|
||||
|
||||
func (s *statusDB) WhoBoostedStatus(status *gtsmodel.Status) ([]*gtsmodel.Account, db.DBError) {
|
||||
accounts := []*gtsmodel.Account{}
|
||||
func (s *statusDB) GetStatusReblogs(status *gtsmodel.Status) ([]*gtsmodel.Status, db.DBError) {
|
||||
reblogs := []*gtsmodel.Status{}
|
||||
|
||||
boosts := []*gtsmodel.Status{}
|
||||
if err := s.conn.Model(&boosts).Where("boost_of_id = ?", status.ID).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
return accounts, nil // no rows just means nobody has boosted this status, so that's fine
|
||||
}
|
||||
return nil, err // an actual error has occurred
|
||||
}
|
||||
q := s.newStatusQ(&reblogs).
|
||||
Where("boost_of_id = ?", status.ID)
|
||||
|
||||
for _, f := range boosts {
|
||||
acc := >smodel.Account{}
|
||||
if err := s.conn.Model(acc).Where("id = ?", f.AccountID).Select(); err != nil {
|
||||
if err == pg.ErrNoRows {
|
||||
continue // the account doesn't exist for some reason??? but this isn't the place to worry about that so just skip it
|
||||
}
|
||||
return nil, err // an actual error has occurred
|
||||
}
|
||||
accounts = append(accounts, acc)
|
||||
}
|
||||
return accounts, nil
|
||||
err := processErrorResponse(q.Select())
|
||||
|
||||
return reblogs, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ func (suite *PGStandardTestSuite) TestGetStatusByURI() {
|
|||
suite.Nil(status.InReplyTo)
|
||||
suite.Nil(status.InReplyToAccount)
|
||||
}
|
||||
|
||||
func (suite *PGStandardTestSuite) TestGetStatusWithExtras() {
|
||||
status, err := suite.db.GetStatusByID(suite.testStatuses["admin_account_status_1"].ID)
|
||||
if err != nil {
|
||||
|
|
@ -92,6 +93,7 @@ func (suite *PGStandardTestSuite) TestGetStatusWithExtras() {
|
|||
suite.NotEmpty(status.Attachments)
|
||||
suite.NotEmpty(status.Emojis)
|
||||
}
|
||||
|
||||
func TestStatusTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(PGStandardTestSuite))
|
||||
}
|
||||
|
|
|
|||
25
internal/db/pg/util.go
Normal file
25
internal/db/pg/util.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package pg
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
)
|
||||
|
||||
// processErrorResponse parses the given error and returns an appropriate DBError.
|
||||
func processErrorResponse(err error) db.DBError {
|
||||
switch err {
|
||||
case nil:
|
||||
return nil
|
||||
case pg.ErrNoRows:
|
||||
return db.ErrNoEntries
|
||||
case pg.ErrMultiRows:
|
||||
return db.ErrMultipleEntries
|
||||
default:
|
||||
if strings.Contains(err.Error(), "duplicate key value violates unique constraint") {
|
||||
return db.ErrAlreadyExists
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -27,42 +27,45 @@ type Status interface {
|
|||
// GetStatusByURI returns one status from the database, with all rel fields populated (if possible).
|
||||
GetStatusByURI(uri string) (*gtsmodel.Status, DBError)
|
||||
|
||||
// GetReplyCountForStatus returns the amount of replies recorded for a status, or an error if something goes wrong
|
||||
GetReplyCountForStatus(status *gtsmodel.Status) (int, DBError)
|
||||
// PutStatus stores one status in the database.
|
||||
PutStatus(status *gtsmodel.Status) DBError
|
||||
|
||||
// GetReblogCountForStatus returns the amount of reblogs/boosts recorded for a status, or an error if something goes wrong
|
||||
GetReblogCountForStatus(status *gtsmodel.Status) (int, DBError)
|
||||
// CountStatusReplies returns the amount of replies recorded for a status, or an error if something goes wrong
|
||||
CountStatusReplies(status *gtsmodel.Status) (int, DBError)
|
||||
|
||||
// GetFaveCountForStatus returns the amount of faves/likes recorded for a status, or an error if something goes wrong
|
||||
GetFaveCountForStatus(status *gtsmodel.Status) (int, DBError)
|
||||
// CountStatusReblogs returns the amount of reblogs/boosts recorded for a status, or an error if something goes wrong
|
||||
CountStatusReblogs(status *gtsmodel.Status) (int, DBError)
|
||||
|
||||
// StatusParents get the parent statuses of a given status.
|
||||
// CountStatusFaves returns the amount of faves/likes recorded for a status, or an error if something goes wrong
|
||||
CountStatusFaves(status *gtsmodel.Status) (int, DBError)
|
||||
|
||||
// GetStatusParents get the parent statuses of a given status.
|
||||
//
|
||||
// If onlyDirect is true, only the immediate parent will be returned.
|
||||
StatusParents(status *gtsmodel.Status, onlyDirect bool) ([]*gtsmodel.Status, DBError)
|
||||
GetStatusParents(status *gtsmodel.Status, onlyDirect bool) ([]*gtsmodel.Status, DBError)
|
||||
|
||||
// StatusChildren gets the child statuses of a given status.
|
||||
// GetStatusChildren gets the child statuses of a given status.
|
||||
//
|
||||
// If onlyDirect is true, only the immediate children will be returned.
|
||||
StatusChildren(status *gtsmodel.Status, onlyDirect bool, minID string) ([]*gtsmodel.Status, DBError)
|
||||
GetStatusChildren(status *gtsmodel.Status, onlyDirect bool, minID string) ([]*gtsmodel.Status, DBError)
|
||||
|
||||
// StatusFavedBy checks if a given status has been faved by a given account ID
|
||||
StatusFavedBy(status *gtsmodel.Status, accountID string) (bool, DBError)
|
||||
// IsStatusFavedBy checks if a given status has been faved by a given account ID
|
||||
IsStatusFavedBy(status *gtsmodel.Status, accountID string) (bool, DBError)
|
||||
|
||||
// StatusRebloggedBy checks if a given status has been reblogged/boosted by a given account ID
|
||||
StatusRebloggedBy(status *gtsmodel.Status, accountID string) (bool, DBError)
|
||||
// IsStatusRebloggedBy checks if a given status has been reblogged/boosted by a given account ID
|
||||
IsStatusRebloggedBy(status *gtsmodel.Status, accountID string) (bool, DBError)
|
||||
|
||||
// StatusMutedBy checks if a given status has been muted by a given account ID
|
||||
StatusMutedBy(status *gtsmodel.Status, accountID string) (bool, DBError)
|
||||
// IsStatusMutedBy checks if a given status has been muted by a given account ID
|
||||
IsStatusMutedBy(status *gtsmodel.Status, accountID string) (bool, DBError)
|
||||
|
||||
// StatusBookmarkedBy checks if a given status has been bookmarked by a given account ID
|
||||
StatusBookmarkedBy(status *gtsmodel.Status, accountID string) (bool, DBError)
|
||||
// IsStatusBookmarkedBy checks if a given status has been bookmarked by a given account ID
|
||||
IsStatusBookmarkedBy(status *gtsmodel.Status, accountID string) (bool, DBError)
|
||||
|
||||
// WhoFavedStatus returns a slice of accounts who faved the given status.
|
||||
// GetStatusFaves returns a slice of faves/likes of the given status.
|
||||
// This slice will be unfiltered, not taking account of blocks and whatnot, so filter it before serving it back to a user.
|
||||
WhoFavedStatus(status *gtsmodel.Status) ([]*gtsmodel.Account, DBError)
|
||||
GetStatusFaves(status *gtsmodel.Status) ([]*gtsmodel.StatusFave, DBError)
|
||||
|
||||
// WhoBoostedStatus returns a slice of accounts who boosted the given status.
|
||||
// GetStatusReblogs returns a slice of statuses that are a boost/reblog of the given status.
|
||||
// This slice will be unfiltered, not taking account of blocks and whatnot, so filter it before serving it back to a user.
|
||||
WhoBoostedStatus(status *gtsmodel.Status) ([]*gtsmodel.Account, DBError)
|
||||
GetStatusReblogs(status *gtsmodel.Status) ([]*gtsmodel.Status, DBError)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue