2021-06-17 18:02:33 +02:00
package visibility
import (
"fmt"
2021-07-05 13:23:03 +02:00
"github.com/superseriousbusiness/gotosocial/internal/db"
2021-06-17 18:02:33 +02:00
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)
func ( f * filter ) pullRelevantAccountsFromStatus ( targetStatus * gtsmodel . Status ) ( * relevantAccounts , error ) {
accounts := & relevantAccounts {
2021-07-05 13:23:03 +02:00
MentionedAccounts : [ ] * gtsmodel . Account { } ,
BoostedMentionedAccounts : [ ] * gtsmodel . Account { } ,
2021-06-17 18:02:33 +02:00
}
2021-08-17 19:03:41 +02:00
// get the author account if it's not set on the status already
2021-08-17 11:18:43 +02:00
if targetStatus . Account == nil {
2021-08-17 19:03:41 +02:00
statusAuthor , err := f . db . GetAccountByID ( targetStatus . AccountID )
if err != nil {
2021-06-17 18:02:33 +02:00
return accounts , fmt . Errorf ( "PullRelevantAccountsFromStatus: error getting statusAuthor with id %s: %s" , targetStatus . AccountID , err )
}
2021-08-17 11:18:43 +02:00
targetStatus . Account = statusAuthor
2021-06-17 18:02:33 +02:00
}
2021-08-17 11:18:43 +02:00
accounts . StatusAuthor = targetStatus . Account
2021-06-17 18:02:33 +02:00
2021-08-17 19:03:41 +02:00
// get the replied to account if it's not set on the status already
if targetStatus . InReplyToAccountID != "" && targetStatus . InReplyToAccount == nil {
repliedToAccount , err := f . db . GetAccountByID ( targetStatus . InReplyToAccountID )
if err != nil {
2021-06-17 18:02:33 +02:00
return accounts , fmt . Errorf ( "PullRelevantAccountsFromStatus: error getting repliedToAcount with id %s: %s" , targetStatus . InReplyToAccountID , err )
}
2021-08-17 19:03:41 +02:00
targetStatus . InReplyToAccount = repliedToAccount
2021-06-17 18:02:33 +02:00
}
2021-08-17 19:03:41 +02:00
accounts . ReplyToAccount = targetStatus . InReplyToAccount
2021-06-17 18:02:33 +02:00
2021-08-17 19:03:41 +02:00
// get the boosted status if it's not set on the status already
if targetStatus . BoostOfID != "" && targetStatus . BoostOf == nil {
boostedStatus , err := f . db . GetStatusByID ( targetStatus . BoostOfID )
if err != nil {
return accounts , fmt . Errorf ( "PullRelevantAccountsFromStatus: error getting boostedStatus with id %s: %s" , targetStatus . BoostOfID , err )
2021-07-05 13:23:03 +02:00
}
2021-08-17 19:03:41 +02:00
targetStatus . BoostOf = boostedStatus
2021-07-05 13:23:03 +02:00
}
2021-08-17 19:03:41 +02:00
// get the boosted account if it's not set on the status already
if targetStatus . BoostOfAccountID != "" && targetStatus . BoostOfAccount == nil {
if targetStatus . BoostOf != nil && targetStatus . BoostOf . Account != nil {
targetStatus . BoostOfAccount = targetStatus . BoostOf . Account
} else {
boostedAccount , err := f . db . GetAccountByID ( targetStatus . BoostOfAccountID )
if err != nil {
return accounts , fmt . Errorf ( "PullRelevantAccountsFromStatus: error getting boostOfAccount with id %s: %s" , targetStatus . BoostOfAccountID , err )
}
targetStatus . BoostOfAccount = boostedAccount
2021-06-17 18:02:33 +02:00
}
2021-08-17 19:03:41 +02:00
}
accounts . BoostedStatusAuthor = targetStatus . BoostOfAccount
2021-06-17 18:02:33 +02:00
2021-08-17 19:03:41 +02:00
if targetStatus . BoostOf != nil {
2021-06-17 18:02:33 +02:00
// the boosted status might be a reply to another account so we should get that too
2021-08-17 19:03:41 +02:00
if targetStatus . BoostOf . InReplyToAccountID != "" && targetStatus . BoostOf . InReplyToAccount == nil {
boostOfInReplyToAccount , err := f . db . GetAccountByID ( targetStatus . BoostOf . InReplyToAccountID )
if err != nil {
return accounts , fmt . Errorf ( "PullRelevantAccountsFromStatus: error getting boostOfInReplyToAccount with id %s: %s" , targetStatus . BoostOf . InReplyToAccountID , err )
2021-06-17 18:02:33 +02:00
}
2021-08-17 19:03:41 +02:00
targetStatus . BoostOf . InReplyToAccount = boostOfInReplyToAccount
2021-06-17 18:02:33 +02:00
}
2021-07-05 13:23:03 +02:00
// now get all accounts with IDs that are mentioned in the status
2021-08-17 19:03:41 +02:00
if targetStatus . BoostOf . MentionIDs != nil && targetStatus . BoostOf . Mentions == nil {
mentions , err := f . db . GetMentions ( targetStatus . BoostOf . MentionIDs )
if err != nil {
return accounts , fmt . Errorf ( "PullRelevantAccountsFromStatus: error getting mentions from boostOf status: %s" , err )
2021-07-05 13:23:03 +02:00
}
2021-08-17 19:03:41 +02:00
targetStatus . BoostOf . Mentions = mentions
}
}
2021-06-17 18:02:33 +02:00
2021-08-17 19:03:41 +02:00
// now get all accounts with IDs that are mentioned in the status
for _ , mentionID := range targetStatus . MentionIDs {
mention := & gtsmodel . Mention { }
if err := f . db . GetByID ( mentionID , mention ) ; err != nil {
return accounts , fmt . Errorf ( "PullRelevantAccountsFromStatus: error getting mention with id %s: %s" , mentionID , err )
2021-06-17 18:02:33 +02:00
}
2021-08-17 19:03:41 +02:00
mentionedAccount := & gtsmodel . Account { }
if err := f . db . GetByID ( mention . TargetAccountID , mentionedAccount ) ; err != nil {
return accounts , fmt . Errorf ( "PullRelevantAccountsFromStatus: error getting mentioned account: %s" , err )
}
accounts . MentionedAccounts = append ( accounts . MentionedAccounts , mentionedAccount )
2021-06-17 18:02:33 +02:00
}
return accounts , nil
}
// relevantAccounts denotes accounts that are replied to, boosted by, or mentioned in a status.
type relevantAccounts struct {
2021-07-05 13:23:03 +02:00
// Who wrote the status
StatusAuthor * gtsmodel . Account
// Who is the status replying to
ReplyToAccount * gtsmodel . Account
// Which accounts are mentioned (tagged) in the status
MentionedAccounts [ ] * gtsmodel . Account
// Who authed the boosted status
BoostedStatusAuthor * gtsmodel . Account
// If the boosted status replies to another account, who does it reply to?
2021-06-17 18:02:33 +02:00
BoostedReplyToAccount * gtsmodel . Account
2021-07-05 13:23:03 +02:00
// Who is mentioned (tagged) in the boosted status
BoostedMentionedAccounts [ ] * gtsmodel . Account
}
// blockedDomain checks whether the given domain is blocked by us or not
func ( f * filter ) blockedDomain ( host string ) ( bool , error ) {
b := & gtsmodel . DomainBlock { }
err := f . db . GetWhere ( [ ] db . Where { { Key : "domain" , Value : host , CaseInsensitive : true } } , b )
if err == nil {
// block exists
return true , nil
}
2021-08-17 15:23:28 +02:00
if err == db . ErrNoEntries {
2021-07-05 13:23:03 +02:00
// there are no entries so there's no block
return false , nil
}
// there's an actual error
return false , err
}
// domainBlockedRelevant checks through all relevant accounts attached to a status
// to make sure none of them are domain blocked by this instance.
//
// Will return true+nil if there's a block, false+nil if there's no block, or
// an error if something goes wrong.
func ( f * filter ) domainBlockedRelevant ( r * relevantAccounts ) ( bool , error ) {
if r . StatusAuthor != nil {
b , err := f . blockedDomain ( r . StatusAuthor . Domain )
if err != nil {
return false , err
}
if b {
return true , nil
}
}
if r . ReplyToAccount != nil {
b , err := f . blockedDomain ( r . ReplyToAccount . Domain )
if err != nil {
return false , err
}
if b {
return true , nil
}
}
for _ , a := range r . MentionedAccounts {
b , err := f . blockedDomain ( a . Domain )
if err != nil {
return false , err
}
if b {
return true , nil
}
}
if r . BoostedStatusAuthor != nil {
b , err := f . blockedDomain ( r . BoostedStatusAuthor . Domain )
if err != nil {
return false , err
}
if b {
return true , nil
}
}
if r . BoostedReplyToAccount != nil {
b , err := f . blockedDomain ( r . BoostedReplyToAccount . Domain )
if err != nil {
return false , err
}
if b {
return true , nil
}
}
for _ , a := range r . BoostedMentionedAccounts {
b , err := f . blockedDomain ( a . Domain )
if err != nil {
return false , err
}
if b {
return true , nil
}
}
return false , nil
2021-06-17 18:02:33 +02:00
}