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