mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
Database updates (#144)
* start moving some database stuff around * continue moving db stuff around * more fiddling * more updates * and some more * and yet more * i broke SOMETHING but what, it's a mystery * tidy up * vendor ttlcache * use ttlcache * fix up some tests * rename some stuff * little reminder * some more updates
This commit is contained in:
@ -31,24 +31,20 @@ import (
|
||||
|
||||
func (p *processor) BlockCreate(requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) {
|
||||
// make sure the target account actually exists in our db
|
||||
targetAcct := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetAccountID, targetAcct); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("BlockCreate: account %s not found in the db: %s", targetAccountID, err))
|
||||
}
|
||||
targetAccount, err := p.db.GetAccountByID(targetAccountID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("BlockCreate: error getting account %s from the db: %s", targetAccountID, err))
|
||||
}
|
||||
|
||||
// if requestingAccount already blocks target account, we don't need to do anything
|
||||
block := >smodel.Block{}
|
||||
if err := p.db.GetWhere([]db.Where{
|
||||
{Key: "account_id", Value: requestingAccount.ID},
|
||||
{Key: "target_account_id", Value: targetAccountID},
|
||||
}, block); err == nil {
|
||||
// block already exists, just return relationship
|
||||
if blocked, err := p.db.IsBlocked(requestingAccount.ID, targetAccountID, false); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("BlockCreate: error checking existence of block: %s", err))
|
||||
} else if blocked {
|
||||
return p.RelationshipGet(requestingAccount, targetAccountID)
|
||||
}
|
||||
|
||||
// make the block
|
||||
block := >smodel.Block{}
|
||||
newBlockID, err := id.NewULID()
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
@ -57,7 +53,7 @@ func (p *processor) BlockCreate(requestingAccount *gtsmodel.Account, targetAccou
|
||||
block.AccountID = requestingAccount.ID
|
||||
block.Account = requestingAccount
|
||||
block.TargetAccountID = targetAccountID
|
||||
block.TargetAccount = targetAcct
|
||||
block.TargetAccount = targetAccount
|
||||
block.URI = util.GenerateURIForBlock(requestingAccount.Username, p.config.Protocol, p.config.Host, newBlockID)
|
||||
|
||||
// whack it in the database
|
||||
@ -123,7 +119,7 @@ func (p *processor) BlockCreate(requestingAccount *gtsmodel.Account, targetAccou
|
||||
URI: frURI,
|
||||
},
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAcct,
|
||||
TargetAccount: targetAccount,
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +134,7 @@ func (p *processor) BlockCreate(requestingAccount *gtsmodel.Account, targetAccou
|
||||
URI: fURI,
|
||||
},
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAcct,
|
||||
TargetAccount: targetAccount,
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,7 +144,7 @@ func (p *processor) BlockCreate(requestingAccount *gtsmodel.Account, targetAccou
|
||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||
GTSModel: block,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAcct,
|
||||
TargetAccount: targetAccount,
|
||||
}
|
||||
|
||||
return p.RelationshipGet(requestingAccount, targetAccountID)
|
||||
|
@ -31,38 +31,33 @@ import (
|
||||
|
||||
func (p *processor) FollowCreate(requestingAccount *gtsmodel.Account, form *apimodel.AccountFollowRequest) (*apimodel.Relationship, gtserror.WithCode) {
|
||||
// if there's a block between the accounts we shouldn't create the request ofc
|
||||
blocked, err := p.db.Blocked(requestingAccount.ID, form.ID)
|
||||
if err != nil {
|
||||
if blocked, err := p.db.IsBlocked(requestingAccount.ID, form.ID, true); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
if blocked {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("accountfollowcreate: block exists between accounts"))
|
||||
} else if blocked {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("block exists between accounts"))
|
||||
}
|
||||
|
||||
// make sure the target account actually exists in our db
|
||||
targetAcct := >smodel.Account{}
|
||||
if err := p.db.GetByID(form.ID, targetAcct); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
targetAcct, err := p.db.GetAccountByID(form.ID)
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("accountfollowcreate: account %s not found in the db: %s", form.ID, err))
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// check if a follow exists already
|
||||
follows, err := p.db.Follows(requestingAccount, targetAcct)
|
||||
if err != nil {
|
||||
if follows, err := p.db.IsFollowing(requestingAccount, targetAcct); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("accountfollowcreate: error checking follow in db: %s", err))
|
||||
}
|
||||
if follows {
|
||||
} else if follows {
|
||||
// already follows so just return the relationship
|
||||
return p.RelationshipGet(requestingAccount, form.ID)
|
||||
}
|
||||
|
||||
// check if a follow exists already
|
||||
followRequested, err := p.db.FollowRequested(requestingAccount, targetAcct)
|
||||
if err != nil {
|
||||
// check if a follow request exists already
|
||||
if followRequested, err := p.db.IsFollowRequested(requestingAccount, targetAcct); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("accountfollowcreate: error checking follow request in db: %s", err))
|
||||
}
|
||||
if followRequested {
|
||||
} else if followRequested {
|
||||
// already follow requested so just return the relationship
|
||||
return p.RelationshipGet(requestingAccount, form.ID)
|
||||
}
|
||||
|
@ -133,9 +133,9 @@ func (p *processor) Delete(account *gtsmodel.Account, origin string) error {
|
||||
var maxID string
|
||||
selectStatusesLoop:
|
||||
for {
|
||||
statuses, err := p.db.GetStatusesForAccount(account.ID, 20, false, maxID, false, false)
|
||||
statuses, err := p.db.GetAccountStatuses(account.ID, 20, false, maxID, false, false)
|
||||
if err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// no statuses left for this instance so we're done
|
||||
l.Infof("Delete: done iterating through statuses for account %s", account.Username)
|
||||
break selectStatusesLoop
|
||||
@ -147,7 +147,7 @@ selectStatusesLoop:
|
||||
|
||||
for i, s := range statuses {
|
||||
// pass the status delete through the client api channel for processing
|
||||
s.GTSAuthorAccount = account
|
||||
s.Account = account
|
||||
l.Debug("putting status in the client api channel")
|
||||
p.fromClientAPI <- gtsmodel.FromClientAPI{
|
||||
APObjectType: gtsmodel.ActivityStreamsNote,
|
||||
@ -158,7 +158,7 @@ selectStatusesLoop:
|
||||
}
|
||||
|
||||
if err := p.db.DeleteByID(s.ID, s); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// actual error has occurred
|
||||
l.Errorf("Delete: db error status %s for account %s: %s", s.ID, account.Username, err)
|
||||
break selectStatusesLoop
|
||||
@ -168,7 +168,7 @@ selectStatusesLoop:
|
||||
// if there are any boosts of this status, delete them as well
|
||||
boosts := []*gtsmodel.Status{}
|
||||
if err := p.db.GetWhere([]db.Where{{Key: "boost_of_id", Value: s.ID}}, &boosts); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// an actual error has occurred
|
||||
l.Errorf("Delete: db error selecting boosts of status %s for account %s: %s", s.ID, account.Username, err)
|
||||
break selectStatusesLoop
|
||||
@ -190,7 +190,7 @@ selectStatusesLoop:
|
||||
}
|
||||
|
||||
if err := p.db.DeleteByID(b.ID, b); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// actual error has occurred
|
||||
l.Errorf("Delete: db error deleting boost with id %s: %s", b.ID, err)
|
||||
break selectStatusesLoop
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
func (p *processor) Get(requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Account, error) {
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetAccountID, targetAccount); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
return nil, errors.New("account not found")
|
||||
}
|
||||
return nil, fmt.Errorf("db error: %s", err)
|
||||
@ -39,7 +39,7 @@ func (p *processor) Get(requestingAccount *gtsmodel.Account, targetAccountID str
|
||||
var blocked bool
|
||||
var err error
|
||||
if requestingAccount != nil {
|
||||
blocked, err = p.db.Blocked(requestingAccount.ID, targetAccountID)
|
||||
blocked, err = p.db.IsBlocked(requestingAccount.ID, targetAccountID, true)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error checking account block: %s", err)
|
||||
}
|
||||
|
@ -28,26 +28,23 @@ import (
|
||||
)
|
||||
|
||||
func (p *processor) FollowersGet(requestingAccount *gtsmodel.Account, targetAccountID string) ([]apimodel.Account, gtserror.WithCode) {
|
||||
blocked, err := p.db.Blocked(requestingAccount.ID, targetAccountID)
|
||||
if err != nil {
|
||||
if blocked, err := p.db.IsBlocked(requestingAccount.ID, targetAccountID, true); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if blocked {
|
||||
} else if blocked {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("block exists between accounts"))
|
||||
}
|
||||
|
||||
followers := []gtsmodel.Follow{}
|
||||
accounts := []apimodel.Account{}
|
||||
if err := p.db.GetFollowersByAccountID(targetAccountID, &followers, false); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
follows, err := p.db.GetAccountFollowedBy(targetAccountID, false)
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
return accounts, nil
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
for _, f := range followers {
|
||||
blocked, err := p.db.Blocked(requestingAccount.ID, f.AccountID)
|
||||
for _, f := range follows {
|
||||
blocked, err := p.db.IsBlocked(requestingAccount.ID, f.AccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -55,15 +52,18 @@ func (p *processor) FollowersGet(requestingAccount *gtsmodel.Account, targetAcco
|
||||
continue
|
||||
}
|
||||
|
||||
a := >smodel.Account{}
|
||||
if err := p.db.GetByID(f.AccountID, a); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
continue
|
||||
if f.Account == nil {
|
||||
a, err := p.db.GetAccountByID(f.AccountID)
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
continue
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
f.Account = a
|
||||
}
|
||||
|
||||
account, err := p.tc.AccountToMastoPublic(a)
|
||||
account, err := p.tc.AccountToMastoPublic(f.Account)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
@ -28,26 +28,23 @@ import (
|
||||
)
|
||||
|
||||
func (p *processor) FollowingGet(requestingAccount *gtsmodel.Account, targetAccountID string) ([]apimodel.Account, gtserror.WithCode) {
|
||||
blocked, err := p.db.Blocked(requestingAccount.ID, targetAccountID)
|
||||
if err != nil {
|
||||
if blocked, err := p.db.IsBlocked(requestingAccount.ID, targetAccountID, true); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
if blocked {
|
||||
} else if blocked {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("block exists between accounts"))
|
||||
}
|
||||
|
||||
following := []gtsmodel.Follow{}
|
||||
accounts := []apimodel.Account{}
|
||||
if err := p.db.GetFollowingByAccountID(targetAccountID, &following); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
follows, err := p.db.GetAccountFollows(targetAccountID)
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
return accounts, nil
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
for _, f := range following {
|
||||
blocked, err := p.db.Blocked(requestingAccount.ID, f.AccountID)
|
||||
for _, f := range follows {
|
||||
blocked, err := p.db.IsBlocked(requestingAccount.ID, f.AccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -55,15 +52,18 @@ func (p *processor) FollowingGet(requestingAccount *gtsmodel.Account, targetAcco
|
||||
continue
|
||||
}
|
||||
|
||||
a := >smodel.Account{}
|
||||
if err := p.db.GetByID(f.TargetAccountID, a); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
continue
|
||||
if f.TargetAccount == nil {
|
||||
a, err := p.db.GetAccountByID(f.TargetAccountID)
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
continue
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
f.TargetAccount = a
|
||||
}
|
||||
|
||||
account, err := p.tc.AccountToMastoPublic(a)
|
||||
account, err := p.tc.AccountToMastoPublic(f.TargetAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
@ -28,18 +28,17 @@ import (
|
||||
)
|
||||
|
||||
func (p *processor) StatusesGet(requestingAccount *gtsmodel.Account, targetAccountID string, limit int, excludeReplies bool, maxID string, pinnedOnly bool, mediaOnly bool) ([]apimodel.Status, gtserror.WithCode) {
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetAccountID, targetAccount); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no entry found for account id %s", targetAccountID))
|
||||
}
|
||||
if blocked, err := p.db.IsBlocked(requestingAccount.ID, targetAccountID, true); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
} else if blocked {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("block exists between accounts"))
|
||||
}
|
||||
|
||||
apiStatuses := []apimodel.Status{}
|
||||
statuses, err := p.db.GetStatusesForAccount(targetAccountID, limit, excludeReplies, maxID, pinnedOnly, mediaOnly)
|
||||
|
||||
statuses, err := p.db.GetAccountStatuses(targetAccountID, limit, excludeReplies, maxID, pinnedOnly, mediaOnly)
|
||||
if err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
return apiStatuses, nil
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
|
@ -29,11 +29,9 @@ import (
|
||||
|
||||
func (p *processor) BlockRemove(requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) {
|
||||
// make sure the target account actually exists in our db
|
||||
targetAcct := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetAccountID, targetAcct); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("BlockRemove: account %s not found in the db: %s", targetAccountID, err))
|
||||
}
|
||||
targetAccount, err := p.db.GetAccountByID(targetAccountID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("BlockCreate: error getting account %s from the db: %s", targetAccountID, err))
|
||||
}
|
||||
|
||||
// check if a block exists, and remove it if it does (storing the URI for later)
|
||||
@ -44,7 +42,7 @@ func (p *processor) BlockRemove(requestingAccount *gtsmodel.Account, targetAccou
|
||||
{Key: "target_account_id", Value: targetAccountID},
|
||||
}, block); err == nil {
|
||||
block.Account = requestingAccount
|
||||
block.TargetAccount = targetAcct
|
||||
block.TargetAccount = targetAccount
|
||||
if err := p.db.DeleteByID(block.ID, >smodel.Block{}); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("BlockRemove: error removing block from db: %s", err))
|
||||
}
|
||||
@ -58,7 +56,7 @@ func (p *processor) BlockRemove(requestingAccount *gtsmodel.Account, targetAccou
|
||||
APActivityType: gtsmodel.ActivityStreamsUndo,
|
||||
GTSModel: block,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetAcct,
|
||||
TargetAccount: targetAccount,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ import (
|
||||
|
||||
func (p *processor) FollowRemove(requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Relationship, gtserror.WithCode) {
|
||||
// if there's a block between the accounts we shouldn't do anything
|
||||
blocked, err := p.db.Blocked(requestingAccount.ID, targetAccountID)
|
||||
blocked, err := p.db.IsBlocked(requestingAccount.ID, targetAccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -40,7 +40,7 @@ func (p *processor) FollowRemove(requestingAccount *gtsmodel.Account, targetAcco
|
||||
// make sure the target account actually exists in our db
|
||||
targetAcct := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetAccountID, targetAcct); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("AccountFollowRemove: account %s not found in the db: %s", targetAccountID, err))
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ func (p *processor) DomainBlockCreate(account *gtsmodel.Account, domain string,
|
||||
domainBlock := >smodel.DomainBlock{}
|
||||
err := p.db.GetWhere([]db.Where{{Key: "domain", Value: domain, CaseInsensitive: true}}, domainBlock)
|
||||
if err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// something went wrong in the DB
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("DomainBlockCreate: db error checking for existence of domain block %s: %s", domain, err))
|
||||
}
|
||||
@ -60,7 +60,7 @@ func (p *processor) DomainBlockCreate(account *gtsmodel.Account, domain string,
|
||||
|
||||
// put the new block in the database
|
||||
if err := p.db.Put(domainBlock); err != nil {
|
||||
if _, ok := err.(db.ErrAlreadyExists); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// there's a real error creating the block
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("DomainBlockCreate: db error putting new domain block %s: %s", domain, err))
|
||||
}
|
||||
@ -123,9 +123,9 @@ func (p *processor) initiateDomainBlockSideEffects(account *gtsmodel.Account, bl
|
||||
|
||||
selectAccountsLoop:
|
||||
for {
|
||||
accounts, err := p.db.GetAccountsForInstance(block.Domain, maxID, limit)
|
||||
accounts, err := p.db.GetInstanceAccounts(block.Domain, maxID, limit)
|
||||
if err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// no accounts left for this instance so we're done
|
||||
l.Infof("domainBlockProcessSideEffects: done iterating through accounts for domain %s", block.Domain)
|
||||
break selectAccountsLoop
|
||||
|
@ -32,7 +32,7 @@ func (p *processor) DomainBlockDelete(account *gtsmodel.Account, id string) (*ap
|
||||
domainBlock := >smodel.DomainBlock{}
|
||||
|
||||
if err := p.db.GetByID(id, domainBlock); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// something has gone really wrong
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ func (p *processor) DomainBlockGet(account *gtsmodel.Account, id string, export
|
||||
domainBlock := >smodel.DomainBlock{}
|
||||
|
||||
if err := p.db.GetByID(id, domainBlock); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// something has gone really wrong
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ func (p *processor) DomainBlocksGet(account *gtsmodel.Account, export bool) ([]*
|
||||
domainBlocks := []*gtsmodel.DomainBlock{}
|
||||
|
||||
if err := p.db.GetAll(&domainBlocks); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// something has gone really wrong
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
@ -29,9 +29,9 @@ import (
|
||||
)
|
||||
|
||||
func (p *processor) BlocksGet(authed *oauth.Auth, maxID string, sinceID string, limit int) (*apimodel.BlocksResponse, gtserror.WithCode) {
|
||||
accounts, nextMaxID, prevMinID, err := p.db.GetBlocksForAccount(authed.Account.ID, maxID, sinceID, limit)
|
||||
accounts, nextMaxID, prevMinID, err := p.db.GetAccountBlocks(authed.Account.ID, maxID, sinceID, limit)
|
||||
if err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are just no entries
|
||||
return &apimodel.BlocksResponse{
|
||||
Accounts: []*apimodel.Account{},
|
||||
|
@ -36,13 +36,12 @@ import (
|
||||
|
||||
func (p *processor) GetFediUser(ctx context.Context, requestedUsername string, requestURL *url.URL) (interface{}, gtserror.WithCode) {
|
||||
// get the account the request is referring to
|
||||
requestedAccount := >smodel.Account{}
|
||||
if err := p.db.GetLocalAccountByUsername(requestedUsername, requestedAccount); err != nil {
|
||||
requestedAccount, err := p.db.GetLocalAccountByUsername(requestedUsername)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting account with username %s: %s", requestedUsername, err))
|
||||
}
|
||||
|
||||
var requestedPerson vocab.ActivityStreamsPerson
|
||||
var err error
|
||||
if util.IsPublicKeyPath(requestURL) {
|
||||
// if it's a public key path, we don't need to authenticate but we'll only serve the bare minimum user profile needed for the public key
|
||||
requestedPerson, err = p.tc.AccountToASMinimal(requestedAccount)
|
||||
@ -63,7 +62,7 @@ func (p *processor) GetFediUser(ctx context.Context, requestedUsername string, r
|
||||
return nil, gtserror.NewErrorNotAuthorized(err)
|
||||
}
|
||||
|
||||
blocked, err := p.db.Blocked(requestedAccount.ID, requestingAccount.ID)
|
||||
blocked, err := p.db.IsBlocked(requestedAccount.ID, requestingAccount.ID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -91,8 +90,8 @@ func (p *processor) GetFediUser(ctx context.Context, requestedUsername string, r
|
||||
|
||||
func (p *processor) GetFediFollowers(ctx context.Context, requestedUsername string, requestURL *url.URL) (interface{}, gtserror.WithCode) {
|
||||
// get the account the request is referring to
|
||||
requestedAccount := >smodel.Account{}
|
||||
if err := p.db.GetLocalAccountByUsername(requestedUsername, requestedAccount); err != nil {
|
||||
requestedAccount, err := p.db.GetLocalAccountByUsername(requestedUsername)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting account with username %s: %s", requestedUsername, err))
|
||||
}
|
||||
|
||||
@ -107,7 +106,7 @@ func (p *processor) GetFediFollowers(ctx context.Context, requestedUsername stri
|
||||
return nil, gtserror.NewErrorNotAuthorized(err)
|
||||
}
|
||||
|
||||
blocked, err := p.db.Blocked(requestedAccount.ID, requestingAccount.ID)
|
||||
blocked, err := p.db.IsBlocked(requestedAccount.ID, requestingAccount.ID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -136,8 +135,8 @@ func (p *processor) GetFediFollowers(ctx context.Context, requestedUsername stri
|
||||
|
||||
func (p *processor) GetFediFollowing(ctx context.Context, requestedUsername string, requestURL *url.URL) (interface{}, gtserror.WithCode) {
|
||||
// get the account the request is referring to
|
||||
requestedAccount := >smodel.Account{}
|
||||
if err := p.db.GetLocalAccountByUsername(requestedUsername, requestedAccount); err != nil {
|
||||
requestedAccount, err := p.db.GetLocalAccountByUsername(requestedUsername)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting account with username %s: %s", requestedUsername, err))
|
||||
}
|
||||
|
||||
@ -152,7 +151,7 @@ func (p *processor) GetFediFollowing(ctx context.Context, requestedUsername stri
|
||||
return nil, gtserror.NewErrorNotAuthorized(err)
|
||||
}
|
||||
|
||||
blocked, err := p.db.Blocked(requestedAccount.ID, requestingAccount.ID)
|
||||
blocked, err := p.db.IsBlocked(requestedAccount.ID, requestingAccount.ID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -181,8 +180,8 @@ func (p *processor) GetFediFollowing(ctx context.Context, requestedUsername stri
|
||||
|
||||
func (p *processor) GetFediStatus(ctx context.Context, requestedUsername string, requestedStatusID string, requestURL *url.URL) (interface{}, gtserror.WithCode) {
|
||||
// get the account the request is referring to
|
||||
requestedAccount := >smodel.Account{}
|
||||
if err := p.db.GetLocalAccountByUsername(requestedUsername, requestedAccount); err != nil {
|
||||
requestedAccount, err := p.db.GetLocalAccountByUsername(requestedUsername)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting account with username %s: %s", requestedUsername, err))
|
||||
}
|
||||
|
||||
@ -199,7 +198,7 @@ func (p *processor) GetFediStatus(ctx context.Context, requestedUsername string,
|
||||
|
||||
// authorize the request:
|
||||
// 1. check if a block exists between the requester and the requestee
|
||||
blocked, err := p.db.Blocked(requestedAccount.ID, requestingAccount.ID)
|
||||
blocked, err := p.db.IsBlocked(requestedAccount.ID, requestingAccount.ID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -241,8 +240,8 @@ func (p *processor) GetFediStatus(ctx context.Context, requestedUsername string,
|
||||
|
||||
func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername string, requestedStatusID string, page bool, onlyOtherAccounts bool, minID string, requestURL *url.URL) (interface{}, gtserror.WithCode) {
|
||||
// get the account the request is referring to
|
||||
requestedAccount := >smodel.Account{}
|
||||
if err := p.db.GetLocalAccountByUsername(requestedUsername, requestedAccount); err != nil {
|
||||
requestedAccount, err := p.db.GetLocalAccountByUsername(requestedUsername)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting account with username %s: %s", requestedUsername, err))
|
||||
}
|
||||
|
||||
@ -259,7 +258,7 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
||||
|
||||
// authorize the request:
|
||||
// 1. check if a block exists between the requester and the requestee
|
||||
blocked, err := p.db.Blocked(requestedAccount.ID, requestingAccount.ID)
|
||||
blocked, err := p.db.IsBlocked(requestedAccount.ID, requestingAccount.ID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -321,7 +320,7 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
||||
} else {
|
||||
// scenario 3
|
||||
// get immediate children
|
||||
replies, err := p.db.StatusChildren(s, true, minID)
|
||||
replies, err := p.db.GetStatusChildren(s, true, minID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -374,8 +373,8 @@ func (p *processor) GetFediStatusReplies(ctx context.Context, requestedUsername
|
||||
|
||||
func (p *processor) GetWebfingerAccount(ctx context.Context, requestedUsername string, requestURL *url.URL) (*apimodel.WellKnownResponse, gtserror.WithCode) {
|
||||
// get the account the request is referring to
|
||||
requestedAccount := >smodel.Account{}
|
||||
if err := p.db.GetLocalAccountByUsername(requestedUsername, requestedAccount); err != nil {
|
||||
requestedAccount, err := p.db.GetLocalAccountByUsername(requestedUsername)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("database error getting account with username %s: %s", requestedUsername, err))
|
||||
}
|
||||
|
||||
|
@ -27,9 +27,9 @@ import (
|
||||
)
|
||||
|
||||
func (p *processor) FollowRequestsGet(auth *oauth.Auth) ([]apimodel.Account, gtserror.WithCode) {
|
||||
frs := []gtsmodel.FollowRequest{}
|
||||
if err := p.db.GetFollowRequestsForAccountID(auth.Account.ID, &frs); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
frs, err := p.db.GetAccountFollowRequests(auth.Account.ID)
|
||||
if err != nil {
|
||||
if err != db.ErrNoEntries {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
}
|
||||
|
@ -187,19 +187,19 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error
|
||||
return errors.New("note was not parseable as *gtsmodel.Status")
|
||||
}
|
||||
|
||||
if statusToDelete.GTSAuthorAccount == nil {
|
||||
statusToDelete.GTSAuthorAccount = clientMsg.OriginAccount
|
||||
if statusToDelete.Account == nil {
|
||||
statusToDelete.Account = clientMsg.OriginAccount
|
||||
}
|
||||
|
||||
// delete all attachments for this status
|
||||
for _, a := range statusToDelete.Attachments {
|
||||
for _, a := range statusToDelete.AttachmentIDs {
|
||||
if err := p.mediaProcessor.Delete(a); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// delete all mentions for this status
|
||||
for _, m := range statusToDelete.Mentions {
|
||||
for _, m := range statusToDelete.MentionIDs {
|
||||
if err := p.db.DeleteByID(m, >smodel.Mention{}); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -237,16 +237,16 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error
|
||||
// TODO: move all the below functions into federation.Federator
|
||||
|
||||
func (p *processor) federateStatus(status *gtsmodel.Status) error {
|
||||
if status.GTSAuthorAccount == nil {
|
||||
if status.Account == nil {
|
||||
a := >smodel.Account{}
|
||||
if err := p.db.GetByID(status.AccountID, a); err != nil {
|
||||
return fmt.Errorf("federateStatus: error fetching status author account: %s", err)
|
||||
}
|
||||
status.GTSAuthorAccount = a
|
||||
status.Account = a
|
||||
}
|
||||
|
||||
// do nothing if this isn't our status
|
||||
if status.GTSAuthorAccount.Domain != "" {
|
||||
if status.Account.Domain != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -255,9 +255,9 @@ func (p *processor) federateStatus(status *gtsmodel.Status) error {
|
||||
return fmt.Errorf("federateStatus: error converting status to as format: %s", err)
|
||||
}
|
||||
|
||||
outboxIRI, err := url.Parse(status.GTSAuthorAccount.OutboxURI)
|
||||
outboxIRI, err := url.Parse(status.Account.OutboxURI)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateStatus: error parsing outboxURI %s: %s", status.GTSAuthorAccount.OutboxURI, err)
|
||||
return fmt.Errorf("federateStatus: error parsing outboxURI %s: %s", status.Account.OutboxURI, err)
|
||||
}
|
||||
|
||||
_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, asStatus)
|
||||
@ -265,16 +265,16 @@ func (p *processor) federateStatus(status *gtsmodel.Status) error {
|
||||
}
|
||||
|
||||
func (p *processor) federateStatusDelete(status *gtsmodel.Status) error {
|
||||
if status.GTSAuthorAccount == nil {
|
||||
if status.Account == nil {
|
||||
a := >smodel.Account{}
|
||||
if err := p.db.GetByID(status.AccountID, a); err != nil {
|
||||
return fmt.Errorf("federateStatus: error fetching status author account: %s", err)
|
||||
}
|
||||
status.GTSAuthorAccount = a
|
||||
status.Account = a
|
||||
}
|
||||
|
||||
// do nothing if this isn't our status
|
||||
if status.GTSAuthorAccount.Domain != "" {
|
||||
if status.Account.Domain != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -283,14 +283,14 @@ func (p *processor) federateStatusDelete(status *gtsmodel.Status) error {
|
||||
return fmt.Errorf("federateStatusDelete: error converting status to as format: %s", err)
|
||||
}
|
||||
|
||||
outboxIRI, err := url.Parse(status.GTSAuthorAccount.OutboxURI)
|
||||
outboxIRI, err := url.Parse(status.Account.OutboxURI)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateStatusDelete: error parsing outboxURI %s: %s", status.GTSAuthorAccount.OutboxURI, err)
|
||||
return fmt.Errorf("federateStatusDelete: error parsing outboxURI %s: %s", status.Account.OutboxURI, err)
|
||||
}
|
||||
|
||||
actorIRI, err := url.Parse(status.GTSAuthorAccount.URI)
|
||||
actorIRI, err := url.Parse(status.Account.URI)
|
||||
if err != nil {
|
||||
return fmt.Errorf("federateStatusDelete: error parsing actorIRI %s: %s", status.GTSAuthorAccount.URI, err)
|
||||
return fmt.Errorf("federateStatusDelete: error parsing actorIRI %s: %s", status.Account.URI, err)
|
||||
}
|
||||
|
||||
// create a delete and set the appropriate actor on it
|
||||
|
@ -30,35 +30,31 @@ import (
|
||||
|
||||
func (p *processor) notifyStatus(status *gtsmodel.Status) error {
|
||||
// if there are no mentions in this status then just bail
|
||||
if len(status.Mentions) == 0 {
|
||||
if len(status.MentionIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if status.GTSMentions == nil {
|
||||
if status.Mentions == nil {
|
||||
// there are mentions but they're not fully populated on the status yet so do this
|
||||
menchies := []*gtsmodel.Mention{}
|
||||
for _, m := range status.Mentions {
|
||||
gtsm := >smodel.Mention{}
|
||||
if err := p.db.GetByID(m, gtsm); err != nil {
|
||||
return fmt.Errorf("notifyStatus: error getting mention with id %s from the db: %s", m, err)
|
||||
}
|
||||
menchies = append(menchies, gtsm)
|
||||
menchies, err := p.db.GetMentions(status.MentionIDs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notifyStatus: error getting mentions for status %s from the db: %s", status.ID, err)
|
||||
}
|
||||
status.GTSMentions = menchies
|
||||
status.Mentions = menchies
|
||||
}
|
||||
|
||||
// now we have mentions as full gtsmodel.Mention structs on the status we can continue
|
||||
for _, m := range status.GTSMentions {
|
||||
for _, m := range status.Mentions {
|
||||
// make sure this is a local account, otherwise we don't need to create a notification for it
|
||||
if m.GTSAccount == nil {
|
||||
a := >smodel.Account{}
|
||||
if err := p.db.GetByID(m.TargetAccountID, a); err != nil {
|
||||
if m.TargetAccount == nil {
|
||||
a, err := p.db.GetAccountByID(m.TargetAccountID)
|
||||
if err != nil {
|
||||
// we don't have the account or there's been an error
|
||||
return fmt.Errorf("notifyStatus: error getting account with id %s from the db: %s", m.TargetAccountID, err)
|
||||
}
|
||||
m.GTSAccount = a
|
||||
m.TargetAccount = a
|
||||
}
|
||||
if m.GTSAccount.Domain != "" {
|
||||
if m.TargetAccount.Domain != "" {
|
||||
// not a local account so skip it
|
||||
continue
|
||||
}
|
||||
@ -74,7 +70,7 @@ func (p *processor) notifyStatus(status *gtsmodel.Status) error {
|
||||
// notification exists already so just continue
|
||||
continue
|
||||
}
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// there's a real error in the db
|
||||
return fmt.Errorf("notifyStatus: error checking existence of notification for mention with id %s : %s", m.ID, err)
|
||||
}
|
||||
@ -89,8 +85,11 @@ func (p *processor) notifyStatus(status *gtsmodel.Status) error {
|
||||
ID: notifID,
|
||||
NotificationType: gtsmodel.NotificationMention,
|
||||
TargetAccountID: m.TargetAccountID,
|
||||
TargetAccount: m.TargetAccount,
|
||||
OriginAccountID: status.AccountID,
|
||||
OriginAccount: status.Account,
|
||||
StatusID: status.ID,
|
||||
Status: status,
|
||||
}
|
||||
|
||||
if err := p.db.Put(notif); err != nil {
|
||||
@ -103,7 +102,7 @@ func (p *processor) notifyStatus(status *gtsmodel.Status) error {
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
||||
if err := p.streamingProcessor.StreamNotificationToAccount(mastoNotif, m.GTSAccount); err != nil {
|
||||
if err := p.streamingProcessor.StreamNotificationToAccount(mastoNotif, m.TargetAccount); err != nil {
|
||||
return fmt.Errorf("notifyStatus: error streaming notification to account: %s", err)
|
||||
}
|
||||
}
|
||||
@ -146,9 +145,9 @@ func (p *processor) notifyFollowRequest(followRequest *gtsmodel.FollowRequest, r
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) notifyFollow(follow *gtsmodel.Follow, receivingAccount *gtsmodel.Account) error {
|
||||
func (p *processor) notifyFollow(follow *gtsmodel.Follow, targetAccount *gtsmodel.Account) error {
|
||||
// return if this isn't a local account
|
||||
if receivingAccount.Domain != "" {
|
||||
if targetAccount.Domain != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -171,7 +170,9 @@ func (p *processor) notifyFollow(follow *gtsmodel.Follow, receivingAccount *gtsm
|
||||
ID: notifID,
|
||||
NotificationType: gtsmodel.NotificationFollow,
|
||||
TargetAccountID: follow.TargetAccountID,
|
||||
TargetAccount: follow.TargetAccount,
|
||||
OriginAccountID: follow.AccountID,
|
||||
OriginAccount: follow.Account,
|
||||
}
|
||||
if err := p.db.Put(notif); err != nil {
|
||||
return fmt.Errorf("notifyFollow: error putting notification in database: %s", err)
|
||||
@ -183,16 +184,16 @@ func (p *processor) notifyFollow(follow *gtsmodel.Follow, receivingAccount *gtsm
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
||||
if err := p.streamingProcessor.StreamNotificationToAccount(mastoNotif, receivingAccount); err != nil {
|
||||
if err := p.streamingProcessor.StreamNotificationToAccount(mastoNotif, targetAccount); err != nil {
|
||||
return fmt.Errorf("notifyStatus: error streaming notification to account: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *processor) notifyFave(fave *gtsmodel.StatusFave, receivingAccount *gtsmodel.Account) error {
|
||||
func (p *processor) notifyFave(fave *gtsmodel.StatusFave, targetAccount *gtsmodel.Account) error {
|
||||
// return if this isn't a local account
|
||||
if receivingAccount.Domain != "" {
|
||||
if targetAccount.Domain != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -205,8 +206,11 @@ func (p *processor) notifyFave(fave *gtsmodel.StatusFave, receivingAccount *gtsm
|
||||
ID: notifID,
|
||||
NotificationType: gtsmodel.NotificationFave,
|
||||
TargetAccountID: fave.TargetAccountID,
|
||||
TargetAccount: fave.TargetAccount,
|
||||
OriginAccountID: fave.AccountID,
|
||||
OriginAccount: fave.Account,
|
||||
StatusID: fave.StatusID,
|
||||
Status: fave.Status,
|
||||
}
|
||||
|
||||
if err := p.db.Put(notif); err != nil {
|
||||
@ -219,7 +223,7 @@ func (p *processor) notifyFave(fave *gtsmodel.StatusFave, receivingAccount *gtsm
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
||||
if err := p.streamingProcessor.StreamNotificationToAccount(mastoNotif, receivingAccount); err != nil {
|
||||
if err := p.streamingProcessor.StreamNotificationToAccount(mastoNotif, targetAccount); err != nil {
|
||||
return fmt.Errorf("notifyStatus: error streaming notification to account: %s", err)
|
||||
}
|
||||
|
||||
@ -232,22 +236,29 @@ func (p *processor) notifyAnnounce(status *gtsmodel.Status) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
boostedStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(status.BoostOfID, boostedStatus); err != nil {
|
||||
return fmt.Errorf("notifyAnnounce: error getting status with id %s: %s", status.BoostOfID, err)
|
||||
if status.BoostOf == nil {
|
||||
boostedStatus, err := p.db.GetStatusByID(status.BoostOfID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notifyAnnounce: error getting status with id %s: %s", status.BoostOfID, err)
|
||||
}
|
||||
status.BoostOf = boostedStatus
|
||||
}
|
||||
|
||||
boostedAcct := >smodel.Account{}
|
||||
if err := p.db.GetByID(boostedStatus.AccountID, boostedAcct); err != nil {
|
||||
return fmt.Errorf("notifyAnnounce: error getting account with id %s: %s", boostedStatus.AccountID, err)
|
||||
if status.BoostOfAccount == nil {
|
||||
boostedAcct, err := p.db.GetAccountByID(status.BoostOfAccountID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notifyAnnounce: error getting account with id %s: %s", status.BoostOfAccountID, err)
|
||||
}
|
||||
status.BoostOf.Account = boostedAcct
|
||||
status.BoostOfAccount = boostedAcct
|
||||
}
|
||||
|
||||
if boostedAcct.Domain != "" {
|
||||
if status.BoostOfAccount.Domain == "" {
|
||||
// remote account, nothing to do
|
||||
return nil
|
||||
}
|
||||
|
||||
if boostedStatus.AccountID == status.AccountID {
|
||||
if status.BoostOfAccountID == status.AccountID {
|
||||
// it's a self boost, nothing to do
|
||||
return nil
|
||||
}
|
||||
@ -255,7 +266,7 @@ func (p *processor) notifyAnnounce(status *gtsmodel.Status) error {
|
||||
// make sure a notif doesn't already exist for this announce
|
||||
err := p.db.GetWhere([]db.Where{
|
||||
{Key: "notification_type", Value: gtsmodel.NotificationReblog},
|
||||
{Key: "target_account_id", Value: boostedAcct.ID},
|
||||
{Key: "target_account_id", Value: status.BoostOfAccountID},
|
||||
{Key: "origin_account_id", Value: status.AccountID},
|
||||
{Key: "status_id", Value: status.ID},
|
||||
}, >smodel.Notification{})
|
||||
@ -273,9 +284,12 @@ func (p *processor) notifyAnnounce(status *gtsmodel.Status) error {
|
||||
notif := >smodel.Notification{
|
||||
ID: notifID,
|
||||
NotificationType: gtsmodel.NotificationReblog,
|
||||
TargetAccountID: boostedAcct.ID,
|
||||
TargetAccountID: status.BoostOfAccountID,
|
||||
TargetAccount: status.BoostOfAccount,
|
||||
OriginAccountID: status.AccountID,
|
||||
OriginAccount: status.Account,
|
||||
StatusID: status.ID,
|
||||
Status: status,
|
||||
}
|
||||
|
||||
if err := p.db.Put(notif); err != nil {
|
||||
@ -288,7 +302,7 @@ func (p *processor) notifyAnnounce(status *gtsmodel.Status) error {
|
||||
return fmt.Errorf("notifyStatus: error converting notification to masto representation: %s", err)
|
||||
}
|
||||
|
||||
if err := p.streamingProcessor.StreamNotificationToAccount(mastoNotif, boostedAcct); err != nil {
|
||||
if err := p.streamingProcessor.StreamNotificationToAccount(mastoNotif, status.BoostOfAccount); err != nil {
|
||||
return fmt.Errorf("notifyStatus: error streaming notification to account: %s", err)
|
||||
}
|
||||
|
||||
@ -297,32 +311,33 @@ func (p *processor) notifyAnnounce(status *gtsmodel.Status) error {
|
||||
|
||||
func (p *processor) timelineStatus(status *gtsmodel.Status) error {
|
||||
// make sure the author account is pinned onto the status
|
||||
if status.GTSAuthorAccount == nil {
|
||||
a := >smodel.Account{}
|
||||
if err := p.db.GetByID(status.AccountID, a); err != nil {
|
||||
if status.Account == nil {
|
||||
a, err := p.db.GetAccountByID(status.AccountID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("timelineStatus: error getting author account with id %s: %s", status.AccountID, err)
|
||||
}
|
||||
status.GTSAuthorAccount = a
|
||||
status.Account = a
|
||||
}
|
||||
|
||||
// get local followers of the account that posted the status
|
||||
followers := []gtsmodel.Follow{}
|
||||
if err := p.db.GetFollowersByAccountID(status.AccountID, &followers, true); err != nil {
|
||||
follows, err := p.db.GetAccountFollowedBy(status.AccountID, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("timelineStatus: error getting followers for account id %s: %s", status.AccountID, err)
|
||||
}
|
||||
|
||||
// if the poster is local, add a fake entry for them to the followers list so they can see their own status in their timeline
|
||||
if status.GTSAuthorAccount.Domain == "" {
|
||||
followers = append(followers, gtsmodel.Follow{
|
||||
if status.Account.Domain == "" {
|
||||
follows = append(follows, >smodel.Follow{
|
||||
AccountID: status.AccountID,
|
||||
Account: status.Account,
|
||||
})
|
||||
}
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(len(followers))
|
||||
errors := make(chan error, len(followers))
|
||||
wg.Add(len(follows))
|
||||
errors := make(chan error, len(follows))
|
||||
|
||||
for _, f := range followers {
|
||||
for _, f := range follows {
|
||||
go p.timelineStatusForAccount(status, f.AccountID, errors, &wg)
|
||||
}
|
||||
|
||||
@ -354,8 +369,8 @@ func (p *processor) timelineStatusForAccount(status *gtsmodel.Status, accountID
|
||||
defer wg.Done()
|
||||
|
||||
// get the timeline owner account
|
||||
timelineAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(accountID, timelineAccount); err != nil {
|
||||
timelineAccount, err := p.db.GetAccountByID(accountID)
|
||||
if err != nil {
|
||||
errors <- fmt.Errorf("timelineStatusForAccount: error getting account for timeline with id %s: %s", accountID, err)
|
||||
return
|
||||
}
|
||||
|
@ -100,8 +100,8 @@ func (p *processor) processFromFederator(federatorMsg gtsmodel.FromFederator) er
|
||||
}
|
||||
incomingAnnounce.ID = incomingAnnounceID
|
||||
|
||||
if err := p.db.Put(incomingAnnounce); err != nil {
|
||||
if _, ok := err.(db.ErrAlreadyExists); !ok {
|
||||
if err := p.db.PutStatus(incomingAnnounce); err != nil {
|
||||
if err != db.ErrNoEntries {
|
||||
return fmt.Errorf("error adding dereferenced announce to the db: %s", err)
|
||||
}
|
||||
}
|
||||
@ -164,14 +164,14 @@ func (p *processor) processFromFederator(federatorMsg gtsmodel.FromFederator) er
|
||||
}
|
||||
|
||||
// delete all attachments for this status
|
||||
for _, a := range statusToDelete.Attachments {
|
||||
for _, a := range statusToDelete.AttachmentIDs {
|
||||
if err := p.mediaProcessor.Delete(a); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// delete all mentions for this status
|
||||
for _, m := range statusToDelete.Mentions {
|
||||
for _, m := range statusToDelete.MentionIDs {
|
||||
if err := p.db.DeleteByID(m, >smodel.Mention{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -51,8 +51,8 @@ func (p *processor) InstancePatch(form *apimodel.InstanceSettingsUpdateRequest)
|
||||
}
|
||||
|
||||
// fetch the instance account from the db for processing
|
||||
ia := >smodel.Account{}
|
||||
if err := p.db.GetLocalAccountByUsername(p.config.Host, ia); err != nil {
|
||||
ia, err := p.db.GetInstanceAccount("")
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error fetching instance account %s: %s", p.config.Host, err))
|
||||
}
|
||||
|
||||
@ -67,8 +67,8 @@ func (p *processor) InstancePatch(form *apimodel.InstanceSettingsUpdateRequest)
|
||||
// validate & update site contact account if it's set on the form
|
||||
if form.ContactUsername != nil {
|
||||
// make sure the account with the given username exists in the db
|
||||
contactAccount := >smodel.Account{}
|
||||
if err := p.db.GetLocalAccountByUsername(*form.ContactUsername, contactAccount); err != nil {
|
||||
contactAccount, err := p.db.GetLocalAccountByUsername(*form.ContactUsername)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorBadRequest(err, fmt.Sprintf("account with username %s not retrievable", *form.ContactUsername))
|
||||
}
|
||||
// make sure it has a user associated with it
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
func (p *processor) Delete(mediaAttachmentID string) gtserror.WithCode {
|
||||
a := >smodel.MediaAttachment{}
|
||||
if err := p.db.GetByID(mediaAttachmentID, a); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// attachment already gone
|
||||
return nil
|
||||
}
|
||||
@ -38,7 +38,7 @@ func (p *processor) Delete(mediaAttachmentID string) gtserror.WithCode {
|
||||
|
||||
// delete the attachment
|
||||
if err := p.db.DeleteByID(mediaAttachmentID, a); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
errs = append(errs, fmt.Sprintf("remove attachment: %s", err))
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContent
|
||||
|
||||
// make sure the requesting account and the media account don't block each other
|
||||
if account != nil {
|
||||
blocked, err := p.db.Blocked(account.ID, form.AccountID)
|
||||
blocked, err := p.db.IsBlocked(account.ID, form.AccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("block status could not be established between accounts %s and %s: %s", form.AccountID, account.ID, err))
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ import (
|
||||
func (p *processor) GetMedia(account *gtsmodel.Account, mediaAttachmentID string) (*apimodel.Attachment, gtserror.WithCode) {
|
||||
attachment := >smodel.MediaAttachment{}
|
||||
if err := p.db.GetByID(mediaAttachmentID, attachment); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// attachment doesn't exist
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("attachment doesn't exist in the db"))
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import (
|
||||
func (p *processor) Update(account *gtsmodel.Account, mediaAttachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, gtserror.WithCode) {
|
||||
attachment := >smodel.MediaAttachment{}
|
||||
if err := p.db.GetByID(mediaAttachmentID, attachment); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// attachment doesn't exist
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("attachment doesn't exist in the db"))
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import (
|
||||
func (p *processor) NotificationsGet(authed *oauth.Auth, limit int, maxID string, sinceID string) ([]*apimodel.Notification, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "NotificationsGet")
|
||||
|
||||
notifs, err := p.db.GetNotificationsForAccount(authed.Account.ID, limit, maxID, sinceID)
|
||||
notifs, err := p.db.GetNotifications(authed.Account.ID, limit, maxID, sinceID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ func (p *processor) SearchGet(authed *oauth.Auth, searchQuery *apimodel.SearchQu
|
||||
*/
|
||||
for _, foundAccount := range foundAccounts {
|
||||
// make sure there's no block in either direction between the account and the requester
|
||||
if blocked, err := p.db.Blocked(authed.Account.ID, foundAccount.ID); err == nil && !blocked {
|
||||
if blocked, err := p.db.IsBlocked(authed.Account.ID, foundAccount.ID, true); err == nil && !blocked {
|
||||
// all good, convert it and add it to the results
|
||||
if acctMasto, err := p.tc.AccountToMastoPublic(foundAccount); err == nil && acctMasto != nil {
|
||||
results.Accounts = append(results.Accounts, *acctMasto)
|
||||
@ -99,11 +99,6 @@ func (p *processor) SearchGet(authed *oauth.Auth, searchQuery *apimodel.SearchQu
|
||||
}
|
||||
|
||||
for _, foundStatus := range foundStatuses {
|
||||
statusOwner := >smodel.Account{}
|
||||
if err := p.db.GetByID(foundStatus.AccountID, statusOwner); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if visible, err := p.filter.StatusVisible(foundStatus, authed.Account); !visible || err != nil {
|
||||
continue
|
||||
}
|
||||
@ -126,12 +121,9 @@ func (p *processor) searchStatusByURI(authed *oauth.Auth, uri *url.URL, resolve
|
||||
"resolve": resolve,
|
||||
})
|
||||
|
||||
maybeStatus := >smodel.Status{}
|
||||
if err := p.db.GetWhere([]db.Where{{Key: "uri", Value: uri.String(), CaseInsensitive: true}}, maybeStatus); err == nil {
|
||||
// we have it and it's a status
|
||||
if maybeStatus, err := p.db.GetStatusByURI(uri.String()); err == nil {
|
||||
return maybeStatus, nil
|
||||
} else if err := p.db.GetWhere([]db.Where{{Key: "url", Value: uri.String(), CaseInsensitive: true}}, maybeStatus); err == nil {
|
||||
// we have it and it's a status
|
||||
} else if maybeStatus, err := p.db.GetStatusByURL(uri.String()); err == nil {
|
||||
return maybeStatus, nil
|
||||
}
|
||||
|
||||
@ -150,14 +142,12 @@ func (p *processor) searchStatusByURI(authed *oauth.Auth, uri *url.URL, resolve
|
||||
}
|
||||
|
||||
func (p *processor) searchAccountByURI(authed *oauth.Auth, uri *url.URL, resolve bool) (*gtsmodel.Account, error) {
|
||||
maybeAccount := >smodel.Account{}
|
||||
if err := p.db.GetWhere([]db.Where{{Key: "uri", Value: uri.String(), CaseInsensitive: true}}, maybeAccount); err == nil {
|
||||
// we have it and it's an account
|
||||
if maybeAccount, err := p.db.GetAccountByURI(uri.String()); err == nil {
|
||||
return maybeAccount, nil
|
||||
} else if err = p.db.GetWhere([]db.Where{{Key: "url", Value: uri.String(), CaseInsensitive: true}}, maybeAccount); err == nil {
|
||||
// we have it and it's an account
|
||||
} else if maybeAccount, err := p.db.GetAccountByURL(uri.String()); err == nil {
|
||||
return maybeAccount, nil
|
||||
}
|
||||
|
||||
if resolve {
|
||||
// we don't have it locally so try and dereference it
|
||||
account, _, err := p.federator.GetRemoteAccount(authed.Account.Username, uri, true)
|
||||
@ -179,7 +169,8 @@ func (p *processor) searchAccountByMention(authed *oauth.Auth, mention string, r
|
||||
// if it's a local account we can skip a whole bunch of stuff
|
||||
maybeAcct := >smodel.Account{}
|
||||
if domain == p.config.Host {
|
||||
if err = p.db.GetLocalAccountByUsername(username, maybeAcct); err != nil {
|
||||
maybeAcct, err = p.db.GetLocalAccountByUsername(username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("searchAccountByMention: error getting local account by username: %s", err)
|
||||
}
|
||||
return maybeAcct, nil
|
||||
@ -196,7 +187,7 @@ func (p *processor) searchAccountByMention(authed *oauth.Auth, mention string, r
|
||||
return maybeAcct, nil
|
||||
}
|
||||
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// if it's not errNoEntries there's been a real database error so bail at this point
|
||||
return nil, fmt.Errorf("searchAccountByMention: database error: %s", err)
|
||||
}
|
||||
|
@ -9,31 +9,22 @@ import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Boost(account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "StatusBoost")
|
||||
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
func (p *processor) Boost(requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account)
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
if targetStatus.VisibilityAdvanced != nil {
|
||||
if !targetStatus.VisibilityAdvanced.Boostable {
|
||||
return nil, gtserror.NewErrorForbidden(errors.New("status is not boostable"))
|
||||
@ -41,16 +32,16 @@ func (p *processor) Boost(account *gtsmodel.Account, application *gtsmodel.Appli
|
||||
}
|
||||
|
||||
// it's visible! it's boostable! so let's boost the FUCK out of it
|
||||
boostWrapperStatus, err := p.tc.StatusToBoost(targetStatus, account)
|
||||
boostWrapperStatus, err := p.tc.StatusToBoost(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
boostWrapperStatus.CreatedWithApplicationID = application.ID
|
||||
boostWrapperStatus.GTSBoostedAccount = targetAccount
|
||||
boostWrapperStatus.BoostOfAccount = targetStatus.Account
|
||||
|
||||
// put the boost in the database
|
||||
if err := p.db.Put(boostWrapperStatus); err != nil {
|
||||
if err := p.db.PutStatus(boostWrapperStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
@ -59,12 +50,12 @@ func (p *processor) Boost(account *gtsmodel.Account, application *gtsmodel.Appli
|
||||
APObjectType: gtsmodel.ActivityStreamsAnnounce,
|
||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||
GTSModel: boostWrapperStatus,
|
||||
OriginAccount: account,
|
||||
TargetAccount: targetAccount,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetStatus.Account,
|
||||
}
|
||||
|
||||
// return the frontend representation of the new status to the submitter
|
||||
mastoStatus, err := p.tc.StatusToMasto(boostWrapperStatus, account)
|
||||
mastoStatus, err := p.tc.StatusToMasto(boostWrapperStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
@ -9,46 +9,37 @@ import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) BoostedBy(account *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "StatusBoostedBy")
|
||||
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account)
|
||||
func (p *processor) BoostedBy(requestingAccount *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("StatusBoostedBy: status is not visible"))
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
// get ALL accounts that faved a status -- doesn't take account of blocks and mutes and stuff
|
||||
favingAccounts, err := p.db.WhoBoostedStatus(targetStatus)
|
||||
statusReblogs, err := p.db.GetStatusReblogs(targetStatus)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error seeing who boosted status: %s", err))
|
||||
}
|
||||
|
||||
// filter the list so the user doesn't see accounts they blocked or which blocked them
|
||||
filteredAccounts := []*gtsmodel.Account{}
|
||||
for _, acc := range favingAccounts {
|
||||
blocked, err := p.db.Blocked(account.ID, acc.ID)
|
||||
for _, s := range statusReblogs {
|
||||
blocked, err := p.db.IsBlocked(requestingAccount.ID, s.AccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error checking blocks: %s", err))
|
||||
}
|
||||
if !blocked {
|
||||
filteredAccounts = append(filteredAccounts, acc)
|
||||
filteredAccounts = append(filteredAccounts, s.Account)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,46 +1,45 @@
|
||||
package status
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Context(account *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode) {
|
||||
func (p *processor) Context(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
context := &apimodel.Context{
|
||||
Ancestors: []apimodel.Status{},
|
||||
Descendants: []apimodel.Status{},
|
||||
}
|
||||
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
return nil, gtserror.NewErrorNotFound(err)
|
||||
}
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(err)
|
||||
}
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorForbidden(fmt.Errorf("account with id %s does not have permission to view status %s", account.ID, targetStatusID))
|
||||
}
|
||||
|
||||
parents, err := p.db.StatusParents(targetStatus, false)
|
||||
parents, err := p.db.GetStatusParents(targetStatus, false)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
for _, status := range parents {
|
||||
if v, err := p.filter.StatusVisible(status, account); err == nil && v {
|
||||
mastoStatus, err := p.tc.StatusToMasto(status, account)
|
||||
if v, err := p.filter.StatusVisible(status, requestingAccount); err == nil && v {
|
||||
mastoStatus, err := p.tc.StatusToMasto(status, requestingAccount)
|
||||
if err == nil {
|
||||
context.Ancestors = append(context.Ancestors, *mastoStatus)
|
||||
}
|
||||
@ -51,14 +50,14 @@ func (p *processor) Context(account *gtsmodel.Account, targetStatusID string) (*
|
||||
return context.Ancestors[i].ID < context.Ancestors[j].ID
|
||||
})
|
||||
|
||||
children, err := p.db.StatusChildren(targetStatus, false, "")
|
||||
children, err := p.db.GetStatusChildren(targetStatus, false, "")
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
for _, status := range children {
|
||||
if v, err := p.filter.StatusVisible(status, account); err == nil && v {
|
||||
mastoStatus, err := p.tc.StatusToMasto(status, account)
|
||||
if v, err := p.filter.StatusVisible(status, requestingAccount); err == nil && v {
|
||||
mastoStatus, err := p.tc.StatusToMasto(status, requestingAccount)
|
||||
if err == nil {
|
||||
context.Descendants = append(context.Descendants, *mastoStatus)
|
||||
}
|
||||
|
@ -38,27 +38,22 @@ func (p *processor) Create(account *gtsmodel.Account, application *gtsmodel.Appl
|
||||
Text: form.Status,
|
||||
}
|
||||
|
||||
// check if replyToID is ok
|
||||
if err := p.ProcessReplyToID(form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// check if mediaIDs are ok
|
||||
if err := p.ProcessMediaIDs(form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// check if visibility settings are ok
|
||||
if err := p.ProcessVisibility(form, account.Privacy, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// handle language settings
|
||||
if err := p.ProcessLanguage(form, account.Language, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// handle mentions
|
||||
if err := p.ProcessMentions(form, account.ID, newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
@ -75,20 +70,11 @@ func (p *processor) Create(account *gtsmodel.Account, application *gtsmodel.Appl
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// put the new status in the database, generating an ID for it in the process
|
||||
if err := p.db.Put(newStatus); err != nil {
|
||||
// put the new status in the database
|
||||
if err := p.db.PutStatus(newStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// change the status ID of the media attachments to the new status
|
||||
for _, a := range newStatus.GTSMediaAttachments {
|
||||
a.StatusID = newStatus.ID
|
||||
a.UpdatedAt = time.Now()
|
||||
if err := p.db.UpdateByID(a.ID, a); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// send it back to the processor for async processing
|
||||
p.fromClientAPI <- gtsmodel.FromClientAPI{
|
||||
APObjectType: gtsmodel.ActivityStreamsNote,
|
||||
|
@ -5,36 +5,24 @@ import (
|
||||
"fmt"
|
||||
|
||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Delete(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "StatusDelete")
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
// status is already gone
|
||||
return nil, nil
|
||||
func (p *processor) Delete(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
if targetStatus.AccountID != account.ID {
|
||||
if targetStatus.AccountID != requestingAccount.ID {
|
||||
return nil, gtserror.NewErrorForbidden(errors.New("status doesn't belong to requesting account"))
|
||||
}
|
||||
|
||||
var boostOfStatus *gtsmodel.Status
|
||||
if targetStatus.BoostOfID != "" {
|
||||
boostOfStatus = >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatus.BoostOfID, boostOfStatus); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching boosted status %s: %s", targetStatus.BoostOfID, err))
|
||||
}
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
@ -48,8 +36,8 @@ func (p *processor) Delete(account *gtsmodel.Account, targetStatusID string) (*a
|
||||
APObjectType: gtsmodel.ActivityStreamsNote,
|
||||
APActivityType: gtsmodel.ActivityStreamsDelete,
|
||||
GTSModel: targetStatus,
|
||||
OriginAccount: account,
|
||||
TargetAccount: account,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: requestingAccount,
|
||||
}
|
||||
|
||||
return mastoStatus, nil
|
||||
|
@ -12,39 +12,22 @@ import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
|
||||
func (p *processor) Fave(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "StatusFave")
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
func (p *processor) Fave(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
var boostOfStatus *gtsmodel.Status
|
||||
if targetStatus.BoostOfID != "" {
|
||||
boostOfStatus = >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatus.BoostOfID, boostOfStatus); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching boosted status %s: %s", targetStatus.BoostOfID, err))
|
||||
}
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account) // requestingAccount might well be nil here, but StatusVisible knows how to take care of that
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
// is the status faveable?
|
||||
if targetStatus.VisibilityAdvanced != nil {
|
||||
if !targetStatus.VisibilityAdvanced.Likeable {
|
||||
return nil, gtserror.NewErrorForbidden(errors.New("status is not faveable"))
|
||||
@ -54,7 +37,7 @@ func (p *processor) Fave(account *gtsmodel.Account, targetStatusID string) (*api
|
||||
// first check if the status is already faved, if so we don't need to do anything
|
||||
newFave := true
|
||||
gtsFave := >smodel.StatusFave{}
|
||||
if err := p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: account.ID}}, gtsFave); err == nil {
|
||||
if err := p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave); err == nil {
|
||||
// we already have a fave for this status
|
||||
newFave = false
|
||||
}
|
||||
@ -67,14 +50,14 @@ func (p *processor) Fave(account *gtsmodel.Account, targetStatusID string) (*api
|
||||
|
||||
// we need to create a new fave in the database
|
||||
gtsFave := >smodel.StatusFave{
|
||||
ID: thisFaveID,
|
||||
AccountID: account.ID,
|
||||
TargetAccountID: targetAccount.ID,
|
||||
StatusID: targetStatus.ID,
|
||||
URI: util.GenerateURIForLike(account.Username, p.config.Protocol, p.config.Host, thisFaveID),
|
||||
GTSStatus: targetStatus,
|
||||
GTSTargetAccount: targetAccount,
|
||||
GTSFavingAccount: account,
|
||||
ID: thisFaveID,
|
||||
AccountID: requestingAccount.ID,
|
||||
Account: requestingAccount,
|
||||
TargetAccountID: targetStatus.AccountID,
|
||||
TargetAccount: targetStatus.Account,
|
||||
StatusID: targetStatus.ID,
|
||||
Status: targetStatus,
|
||||
URI: util.GenerateURIForLike(requestingAccount.Username, p.config.Protocol, p.config.Host, thisFaveID),
|
||||
}
|
||||
|
||||
if err := p.db.Put(gtsFave); err != nil {
|
||||
@ -86,13 +69,13 @@ func (p *processor) Fave(account *gtsmodel.Account, targetStatusID string) (*api
|
||||
APObjectType: gtsmodel.ActivityStreamsLike,
|
||||
APActivityType: gtsmodel.ActivityStreamsCreate,
|
||||
GTSModel: gtsFave,
|
||||
OriginAccount: account,
|
||||
TargetAccount: targetAccount,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetStatus.Account,
|
||||
}
|
||||
}
|
||||
|
||||
// return the mastodon representation of the target status
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
@ -9,51 +9,40 @@ import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) FavedBy(account *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "StatusFavedBy")
|
||||
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
func (p *processor) FavedBy(requestingAccount *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account)
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
// get ALL accounts that faved a status -- doesn't take account of blocks and mutes and stuff
|
||||
favingAccounts, err := p.db.WhoFavedStatus(targetStatus)
|
||||
statusFaves, err := p.db.GetStatusFaves(targetStatus)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing who faved status: %s", err))
|
||||
}
|
||||
|
||||
// filter the list so the user doesn't see accounts they blocked or which blocked them
|
||||
filteredAccounts := []*gtsmodel.Account{}
|
||||
for _, acc := range favingAccounts {
|
||||
blocked, err := p.db.Blocked(account.ID, acc.ID)
|
||||
for _, fave := range statusFaves {
|
||||
blocked, err := p.db.IsBlocked(requestingAccount.ID, fave.AccountID, true)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error checking blocks: %s", err))
|
||||
}
|
||||
if !blocked {
|
||||
filteredAccounts = append(filteredAccounts, acc)
|
||||
filteredAccounts = append(filteredAccounts, fave.Account)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: filter other things here? suspended? muted? silenced?
|
||||
|
||||
// now we can return the masto representation of those accounts
|
||||
mastoAccounts := []*apimodel.Account{}
|
||||
for _, acc := range filteredAccounts {
|
||||
|
@ -9,44 +9,27 @@ import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Get(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "StatusGet")
|
||||
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
func (p *processor) Get(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account) // requestingAccount might well be nil here, but StatusVisible knows how to take care of that
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
var boostOfStatus *gtsmodel.Status
|
||||
if targetStatus.BoostOfID != "" {
|
||||
boostOfStatus = >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatus.BoostOfID, boostOfStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error fetching boosted status %s: %s", targetStatus.BoostOfID, err))
|
||||
}
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
return mastoStatus, nil
|
||||
|
||||
}
|
||||
|
@ -10,27 +10,19 @@ import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Unboost(account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "Unboost")
|
||||
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
func (p *processor) Unboost(requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account)
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
@ -46,7 +38,7 @@ func (p *processor) Unboost(account *gtsmodel.Account, application *gtsmodel.App
|
||||
},
|
||||
{
|
||||
Key: "account_id",
|
||||
Value: account.ID,
|
||||
Value: requestingAccount.ID,
|
||||
},
|
||||
}
|
||||
err = p.db.GetWhere(where, gtsBoost)
|
||||
@ -57,7 +49,7 @@ func (p *processor) Unboost(account *gtsmodel.Account, application *gtsmodel.App
|
||||
|
||||
if err != nil {
|
||||
// something went wrong in the db finding the boost
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error fetching existing boost from database: %s", err))
|
||||
}
|
||||
// we just don't have a boost
|
||||
@ -71,22 +63,23 @@ func (p *processor) Unboost(account *gtsmodel.Account, application *gtsmodel.App
|
||||
}
|
||||
|
||||
// pin some stuff onto the boost while we have it out of the db
|
||||
gtsBoost.GTSBoostedStatus = targetStatus
|
||||
gtsBoost.GTSBoostedStatus.GTSAuthorAccount = targetAccount
|
||||
gtsBoost.GTSBoostedAccount = targetAccount
|
||||
gtsBoost.GTSAuthorAccount = account
|
||||
gtsBoost.Account = requestingAccount
|
||||
|
||||
gtsBoost.BoostOf = targetStatus
|
||||
gtsBoost.BoostOfAccount = targetStatus.Account
|
||||
gtsBoost.BoostOf.Account = targetStatus.Account
|
||||
|
||||
// send it back to the processor for async processing
|
||||
p.fromClientAPI <- gtsmodel.FromClientAPI{
|
||||
APObjectType: gtsmodel.ActivityStreamsAnnounce,
|
||||
APActivityType: gtsmodel.ActivityStreamsUndo,
|
||||
GTSModel: gtsBoost,
|
||||
OriginAccount: account,
|
||||
TargetAccount: targetAccount,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetStatus.Account,
|
||||
}
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
@ -10,26 +10,19 @@ import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Unfave(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "StatusUnfave")
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
func (p *processor) Unfave(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account)
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
@ -38,14 +31,14 @@ func (p *processor) Unfave(account *gtsmodel.Account, targetStatusID string) (*a
|
||||
var toUnfave bool
|
||||
|
||||
gtsFave := >smodel.StatusFave{}
|
||||
err = p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: account.ID}}, gtsFave)
|
||||
err = p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave)
|
||||
if err == nil {
|
||||
// we have a fave
|
||||
toUnfave = true
|
||||
}
|
||||
if err != nil {
|
||||
// something went wrong in the db finding the fave
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error fetching existing fave from database: %s", err))
|
||||
}
|
||||
// we just don't have a fave
|
||||
@ -54,7 +47,7 @@ func (p *processor) Unfave(account *gtsmodel.Account, targetStatusID string) (*a
|
||||
|
||||
if toUnfave {
|
||||
// we had a fave, so take some action to get rid of it
|
||||
if err := p.db.DeleteWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: account.ID}}, gtsFave); err != nil {
|
||||
if err := p.db.DeleteWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: requestingAccount.ID}}, gtsFave); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error unfaveing status: %s", err))
|
||||
}
|
||||
|
||||
@ -63,12 +56,12 @@ func (p *processor) Unfave(account *gtsmodel.Account, targetStatusID string) (*a
|
||||
APObjectType: gtsmodel.ActivityStreamsLike,
|
||||
APActivityType: gtsmodel.ActivityStreamsUndo,
|
||||
GTSModel: gtsFave,
|
||||
OriginAccount: account,
|
||||
TargetAccount: targetAccount,
|
||||
OriginAccount: requestingAccount,
|
||||
TargetAccount: targetStatus.Account,
|
||||
}
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ func (p *processor) ProcessReplyToID(form *apimodel.AdvancedStatusCreateForm, th
|
||||
repliedAccount := >smodel.Account{}
|
||||
// check replied status exists + is replyable
|
||||
if err := p.db.GetByID(form.InReplyToID, repliedStatus); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
return fmt.Errorf("status with id %s not replyable because it doesn't exist", form.InReplyToID)
|
||||
}
|
||||
return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err)
|
||||
@ -113,14 +113,14 @@ func (p *processor) ProcessReplyToID(form *apimodel.AdvancedStatusCreateForm, th
|
||||
|
||||
// check replied account is known to us
|
||||
if err := p.db.GetByID(repliedStatus.AccountID, repliedAccount); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
return fmt.Errorf("status with id %s not replyable because account id %s is not known", form.InReplyToID, repliedStatus.AccountID)
|
||||
}
|
||||
return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err)
|
||||
}
|
||||
// check if a block exists
|
||||
if blocked, err := p.db.Blocked(thisAccountID, repliedAccount.ID); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if blocked, err := p.db.IsBlocked(thisAccountID, repliedAccount.ID, true); err != nil {
|
||||
if err != db.ErrNoEntries {
|
||||
return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err)
|
||||
}
|
||||
} else if blocked {
|
||||
@ -156,8 +156,8 @@ func (p *processor) ProcessMediaIDs(form *apimodel.AdvancedStatusCreateForm, thi
|
||||
gtsMediaAttachments = append(gtsMediaAttachments, a)
|
||||
attachments = append(attachments, a.ID)
|
||||
}
|
||||
status.GTSMediaAttachments = gtsMediaAttachments
|
||||
status.Attachments = attachments
|
||||
status.Attachments = gtsMediaAttachments
|
||||
status.AttachmentIDs = attachments
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -192,9 +192,9 @@ func (p *processor) ProcessMentions(form *apimodel.AdvancedStatusCreateForm, acc
|
||||
menchies = append(menchies, menchie.ID)
|
||||
}
|
||||
// add full populated gts menchies to the status for passing them around conveniently
|
||||
status.GTSMentions = gtsMenchies
|
||||
status.Mentions = gtsMenchies
|
||||
// add just the ids of the mentioned accounts to the status for putting in the db
|
||||
status.Mentions = menchies
|
||||
status.MentionIDs = menchies
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -211,9 +211,9 @@ func (p *processor) ProcessTags(form *apimodel.AdvancedStatusCreateForm, account
|
||||
tags = append(tags, tag.ID)
|
||||
}
|
||||
// add full populated gts tags to the status for passing them around conveniently
|
||||
status.GTSTags = gtsTags
|
||||
status.Tags = gtsTags
|
||||
// add just the ids of the used tags to the status for putting in the db
|
||||
status.Tags = tags
|
||||
status.TagIDs = tags
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -227,9 +227,9 @@ func (p *processor) ProcessEmojis(form *apimodel.AdvancedStatusCreateForm, accou
|
||||
emojis = append(emojis, e.ID)
|
||||
}
|
||||
// add full populated gts emojis to the status for passing them around conveniently
|
||||
status.GTSEmojis = gtsEmojis
|
||||
status.Emojis = gtsEmojis
|
||||
// add just the ids of the used emojis to the status for putting in the db
|
||||
status.Emojis = emojis
|
||||
status.EmojiIDs = emojis
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -252,9 +252,9 @@ func (p *processor) ProcessContent(form *apimodel.AdvancedStatusCreateForm, acco
|
||||
var formatted string
|
||||
switch form.Format {
|
||||
case apimodel.StatusFormatPlain:
|
||||
formatted = p.formatter.FromPlain(content, status.GTSMentions, status.GTSTags)
|
||||
formatted = p.formatter.FromPlain(content, status.Mentions, status.Tags)
|
||||
case apimodel.StatusFormatMarkdown:
|
||||
formatted = p.formatter.FromMarkdown(content, status.GTSMentions, status.GTSTags)
|
||||
formatted = p.formatter.FromMarkdown(content, status.Mentions, status.Tags)
|
||||
default:
|
||||
return fmt.Errorf("format %s not recognised as a valid status format", form.Format)
|
||||
}
|
||||
|
@ -91,19 +91,19 @@ func (suite *UtilTestSuite) TestProcessMentions1() {
|
||||
err := suite.status.ProcessMentions(form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
assert.Len(suite.T(), status.GTSMentions, 1)
|
||||
newMention := status.GTSMentions[0]
|
||||
assert.Len(suite.T(), status.Mentions, 1)
|
||||
newMention := status.Mentions[0]
|
||||
assert.Equal(suite.T(), mentionedAccount.ID, newMention.TargetAccountID)
|
||||
assert.Equal(suite.T(), creatingAccount.ID, newMention.OriginAccountID)
|
||||
assert.Equal(suite.T(), creatingAccount.URI, newMention.OriginAccountURI)
|
||||
assert.Equal(suite.T(), status.ID, newMention.StatusID)
|
||||
assert.Equal(suite.T(), fmt.Sprintf("@%s@%s", mentionedAccount.Username, mentionedAccount.Domain), newMention.NameString)
|
||||
assert.Equal(suite.T(), mentionedAccount.URI, newMention.MentionedAccountURI)
|
||||
assert.Equal(suite.T(), mentionedAccount.URL, newMention.MentionedAccountURL)
|
||||
assert.NotNil(suite.T(), newMention.GTSAccount)
|
||||
assert.Equal(suite.T(), mentionedAccount.URI, newMention.TargetAccountURI)
|
||||
assert.Equal(suite.T(), mentionedAccount.URL, newMention.TargetAccountURL)
|
||||
assert.NotNil(suite.T(), newMention.OriginAccount)
|
||||
|
||||
assert.Len(suite.T(), status.Mentions, 1)
|
||||
assert.Equal(suite.T(), newMention.ID, status.Mentions[0])
|
||||
assert.Len(suite.T(), status.MentionIDs, 1)
|
||||
assert.Equal(suite.T(), newMention.ID, status.MentionIDs[0])
|
||||
}
|
||||
|
||||
func (suite *UtilTestSuite) TestProcessContentFull1() {
|
||||
@ -232,19 +232,19 @@ func (suite *UtilTestSuite) TestProcessMentions2() {
|
||||
err := suite.status.ProcessMentions(form, creatingAccount.ID, status)
|
||||
assert.NoError(suite.T(), err)
|
||||
|
||||
assert.Len(suite.T(), status.GTSMentions, 1)
|
||||
newMention := status.GTSMentions[0]
|
||||
assert.Len(suite.T(), status.Mentions, 1)
|
||||
newMention := status.Mentions[0]
|
||||
assert.Equal(suite.T(), mentionedAccount.ID, newMention.TargetAccountID)
|
||||
assert.Equal(suite.T(), creatingAccount.ID, newMention.OriginAccountID)
|
||||
assert.Equal(suite.T(), creatingAccount.URI, newMention.OriginAccountURI)
|
||||
assert.Equal(suite.T(), status.ID, newMention.StatusID)
|
||||
assert.Equal(suite.T(), fmt.Sprintf("@%s@%s", mentionedAccount.Username, mentionedAccount.Domain), newMention.NameString)
|
||||
assert.Equal(suite.T(), mentionedAccount.URI, newMention.MentionedAccountURI)
|
||||
assert.Equal(suite.T(), mentionedAccount.URL, newMention.MentionedAccountURL)
|
||||
assert.NotNil(suite.T(), newMention.GTSAccount)
|
||||
assert.Equal(suite.T(), mentionedAccount.URI, newMention.TargetAccountURI)
|
||||
assert.Equal(suite.T(), mentionedAccount.URL, newMention.TargetAccountURL)
|
||||
assert.NotNil(suite.T(), newMention.OriginAccount)
|
||||
|
||||
assert.Len(suite.T(), status.Mentions, 1)
|
||||
assert.Equal(suite.T(), newMention.ID, status.Mentions[0])
|
||||
assert.Len(suite.T(), status.MentionIDs, 1)
|
||||
assert.Equal(suite.T(), newMention.ID, status.MentionIDs[0])
|
||||
}
|
||||
|
||||
func (suite *UtilTestSuite) TestProcessContentFull2() {
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
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 processing
|
||||
|
||||
import (
|
||||
|
@ -74,9 +74,9 @@ func (p *processor) HomeTimelineGet(authed *oauth.Auth, maxID string, sinceID st
|
||||
}
|
||||
|
||||
func (p *processor) PublicTimelineGet(authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.StatusTimelineResponse, gtserror.WithCode) {
|
||||
statuses, err := p.db.GetPublicTimelineForAccount(authed.Account.ID, maxID, sinceID, minID, limit, local)
|
||||
statuses, err := p.db.GetPublicTimeline(authed.Account.ID, maxID, sinceID, minID, limit, local)
|
||||
if err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are just no entries left
|
||||
return &apimodel.StatusTimelineResponse{
|
||||
Statuses: []*apimodel.Status{},
|
||||
@ -95,9 +95,9 @@ func (p *processor) PublicTimelineGet(authed *oauth.Auth, maxID string, sinceID
|
||||
}
|
||||
|
||||
func (p *processor) FavedTimelineGet(authed *oauth.Auth, maxID string, minID string, limit int) (*apimodel.StatusTimelineResponse, gtserror.WithCode) {
|
||||
statuses, nextMaxID, prevMinID, err := p.db.GetFavedTimelineForAccount(authed.Account.ID, maxID, minID, limit)
|
||||
statuses, nextMaxID, prevMinID, err := p.db.GetFavedTimeline(authed.Account.ID, maxID, minID, limit)
|
||||
if err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are just no entries left
|
||||
return &apimodel.StatusTimelineResponse{
|
||||
Statuses: []*apimodel.Status{},
|
||||
@ -122,7 +122,7 @@ func (p *processor) filterPublicStatuses(authed *oauth.Auth, statuses []*gtsmode
|
||||
for _, s := range statuses {
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(s.AccountID, targetAccount); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
l.Debugf("filterPublicStatuses: skipping status %s because account %s can't be found in the db", s.ID, s.AccountID)
|
||||
continue
|
||||
}
|
||||
@ -157,7 +157,7 @@ func (p *processor) filterFavedStatuses(authed *oauth.Auth, statuses []*gtsmodel
|
||||
for _, s := range statuses {
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(s.AccountID, targetAccount); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
l.Debugf("filterFavedStatuses: skipping status %s because account %s can't be found in the db", s.ID, s.AccountID)
|
||||
continue
|
||||
}
|
||||
|
Reference in New Issue
Block a user