| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | /* | 
					
						
							|  |  |  |    GoToSocial | 
					
						
							| 
									
										
										
										
											2023-01-05 12:43:00 +01:00
										 |  |  |    Copyright (C) 2021-2023 GoToSocial Authors admin@gotosocial.org | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |    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/>. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | package bundb | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2022-12-01 16:06:09 +01:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/config" | 
					
						
							|  |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/db" | 
					
						
							|  |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/log" | 
					
						
							| 
									
										
										
										
											2022-12-08 17:35:14 +00:00
										 |  |  | 	"github.com/superseriousbusiness/gotosocial/internal/state" | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	"github.com/uptrace/bun" | 
					
						
							| 
									
										
										
										
											2022-06-10 10:56:49 +02:00
										 |  |  | 	"github.com/uptrace/bun/dialect" | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type accountDB struct { | 
					
						
							| 
									
										
										
										
											2022-12-08 17:35:14 +00:00
										 |  |  | 	conn  *DBConn | 
					
						
							|  |  |  | 	state *state.State | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | func (a *accountDB) newAccountQ(account *gtsmodel.Account) *bun.SelectQuery { | 
					
						
							|  |  |  | 	return a.conn. | 
					
						
							|  |  |  | 		NewSelect(). | 
					
						
							|  |  |  | 		Model(account). | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 		Relation("AvatarMediaAttachment"). | 
					
						
							| 
									
										
										
										
											2022-11-18 17:29:25 +00:00
										 |  |  | 		Relation("HeaderMediaAttachment") | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | func (a *accountDB) GetAccountByID(ctx context.Context, id string) (*gtsmodel.Account, db.Error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 	return a.getAccount( | 
					
						
							|  |  |  | 		ctx, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		"ID", | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		func(account *gtsmodel.Account) error { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 			return a.newAccountQ(account).Where("? = ?", bun.Ident("account.id"), id).Scan(ctx) | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		id, | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | func (a *accountDB) GetAccountByURI(ctx context.Context, uri string) (*gtsmodel.Account, db.Error) { | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 	return a.getAccount( | 
					
						
							|  |  |  | 		ctx, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		"URI", | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		func(account *gtsmodel.Account) error { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 			return a.newAccountQ(account).Where("? = ?", bun.Ident("account.uri"), uri).Scan(ctx) | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		uri, | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | func (a *accountDB) GetAccountByURL(ctx context.Context, url string) (*gtsmodel.Account, db.Error) { | 
					
						
							|  |  |  | 	return a.getAccount( | 
					
						
							|  |  |  | 		ctx, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		"URL", | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		func(account *gtsmodel.Account) error { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 			return a.newAccountQ(account).Where("? = ?", bun.Ident("account.url"), url).Scan(ctx) | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		url, | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-20 22:47:19 +02:00
										 |  |  | func (a *accountDB) GetAccountByUsernameDomain(ctx context.Context, username string, domain string) (*gtsmodel.Account, db.Error) { | 
					
						
							|  |  |  | 	return a.getAccount( | 
					
						
							|  |  |  | 		ctx, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		"Username.Domain", | 
					
						
							| 
									
										
										
										
											2022-08-20 22:47:19 +02:00
										 |  |  | 		func(account *gtsmodel.Account) error { | 
					
						
							| 
									
										
										
										
											2022-09-02 10:56:33 +01:00
										 |  |  | 			q := a.newAccountQ(account) | 
					
						
							| 
									
										
										
										
											2022-08-20 22:47:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if domain != "" { | 
					
						
							| 
									
										
										
										
											2022-12-01 16:06:09 +01:00
										 |  |  | 				q = q. | 
					
						
							|  |  |  | 					Where("LOWER(?) = ?", bun.Ident("account.username"), strings.ToLower(username)). | 
					
						
							|  |  |  | 					Where("? = ?", bun.Ident("account.domain"), domain) | 
					
						
							| 
									
										
										
										
											2022-08-20 22:47:19 +02:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2022-12-01 16:06:09 +01:00
										 |  |  | 				q = q. | 
					
						
							|  |  |  | 					Where("? = ?", bun.Ident("account.username"), strings.ToLower(username)). // usernames on our instance are always lowercase | 
					
						
							|  |  |  | 					Where("? IS NULL", bun.Ident("account.domain")) | 
					
						
							| 
									
										
										
										
											2022-08-20 22:47:19 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return q.Scan(ctx) | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		username, | 
					
						
							|  |  |  | 		domain, | 
					
						
							| 
									
										
										
										
											2022-08-20 22:47:19 +02:00
										 |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-02 10:58:42 +01:00
										 |  |  | func (a *accountDB) GetAccountByPubkeyID(ctx context.Context, id string) (*gtsmodel.Account, db.Error) { | 
					
						
							|  |  |  | 	return a.getAccount( | 
					
						
							|  |  |  | 		ctx, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		"PublicKeyURI", | 
					
						
							| 
									
										
										
										
											2022-09-02 10:58:42 +01:00
										 |  |  | 		func(account *gtsmodel.Account) error { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 			return a.newAccountQ(account).Where("? = ?", bun.Ident("account.public_key_uri"), id).Scan(ctx) | 
					
						
							| 
									
										
										
										
											2022-09-02 10:58:42 +01:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		id, | 
					
						
							| 
									
										
										
										
											2022-09-02 10:58:42 +01:00
										 |  |  | 	) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | func (a *accountDB) GetInstanceAccount(ctx context.Context, domain string) (*gtsmodel.Account, db.Error) { | 
					
						
							|  |  |  | 	var username string | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 	if domain == "" { | 
					
						
							|  |  |  | 		// I.e. our local instance account | 
					
						
							|  |  |  | 		username = config.GetHost() | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		// A remote instance account | 
					
						
							|  |  |  | 		username = domain | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return a.GetAccountByUsernameDomain(ctx, username, domain) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (a *accountDB) getAccount(ctx context.Context, lookup string, dbQuery func(*gtsmodel.Account) error, keyParts ...any) (*gtsmodel.Account, db.Error) { | 
					
						
							| 
									
										
										
										
											2022-11-18 17:29:25 +00:00
										 |  |  | 	// Fetch account from database cache with loader callback | 
					
						
							| 
									
										
										
										
											2022-12-08 17:35:14 +00:00
										 |  |  | 	account, err := a.state.Caches.GTS.Account().Load(lookup, func() (*gtsmodel.Account, error) { | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		var account gtsmodel.Account | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 		// Not cached! Perform database query | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		if err := dbQuery(&account); err != nil { | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 			return nil, a.conn.ProcessError(err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		return &account, nil | 
					
						
							|  |  |  | 	}, keyParts...) | 
					
						
							| 
									
										
										
										
											2022-11-18 17:29:25 +00:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-03 20:03:05 +00:00
										 |  |  | 	if account.AvatarMediaAttachmentID != "" { | 
					
						
							|  |  |  | 		// Set the account's related avatar | 
					
						
							|  |  |  | 		account.AvatarMediaAttachment, err = a.state.DB.GetAttachmentByID(ctx, account.AvatarMediaAttachmentID) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			log.Errorf("error getting account %s avatar: %v", account.ID, err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if account.HeaderMediaAttachmentID != "" { | 
					
						
							|  |  |  | 		// Set the account's related header | 
					
						
							|  |  |  | 		account.HeaderMediaAttachment, err = a.state.DB.GetAttachmentByID(ctx, account.HeaderMediaAttachmentID) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			log.Errorf("error getting account %s header: %v", account.ID, err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-18 17:29:25 +00:00
										 |  |  | 	if len(account.EmojiIDs) > 0 { | 
					
						
							|  |  |  | 		// Set the account's related emojis | 
					
						
							| 
									
										
										
										
											2022-12-08 17:35:14 +00:00
										 |  |  | 		account.Emojis, err = a.state.DB.GetEmojisByIDs(ctx, account.EmojiIDs) | 
					
						
							| 
									
										
										
										
											2022-11-18 17:29:25 +00:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2023-02-03 20:03:05 +00:00
										 |  |  | 			log.Errorf("error getting account %s emojis: %v", account.ID, err) | 
					
						
							| 
									
										
										
										
											2022-11-18 17:29:25 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return account, nil | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | func (a *accountDB) PutAccount(ctx context.Context, account *gtsmodel.Account) db.Error { | 
					
						
							| 
									
										
										
										
											2022-12-08 17:35:14 +00:00
										 |  |  | 	return a.state.Caches.GTS.Account().Store(account, func() error { | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		// It is safe to run this database transaction within cache.Store | 
					
						
							|  |  |  | 		// as the cache does not attempt a mutex lock until AFTER hook. | 
					
						
							|  |  |  | 		// | 
					
						
							|  |  |  | 		return a.conn.RunInTx(ctx, func(tx bun.Tx) error { | 
					
						
							|  |  |  | 			// create links between this account and any emojis it uses | 
					
						
							|  |  |  | 			for _, i := range account.EmojiIDs { | 
					
						
							|  |  |  | 				if _, err := tx.NewInsert().Model(>smodel.AccountToEmoji{ | 
					
						
							|  |  |  | 					AccountID: account.ID, | 
					
						
							|  |  |  | 					EmojiID:   i, | 
					
						
							|  |  |  | 				}).Exec(ctx); err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2022-09-26 11:56:01 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 			// insert the account | 
					
						
							|  |  |  | 			_, err := tx.NewInsert().Model(account).Exec(ctx) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-09-26 11:56:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | func (a *accountDB) UpdateAccount(ctx context.Context, account *gtsmodel.Account) db.Error { | 
					
						
							| 
									
										
										
										
											2021-09-11 13:19:06 +02:00
										 |  |  | 	// Update the account's last-updated | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	account.UpdatedAt = time.Now() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 17:35:14 +00:00
										 |  |  | 	return a.state.Caches.GTS.Account().Store(account, func() error { | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		// It is safe to run this database transaction within cache.Store | 
					
						
							|  |  |  | 		// as the cache does not attempt a mutex lock until AFTER hook. | 
					
						
							|  |  |  | 		// | 
					
						
							|  |  |  | 		return a.conn.RunInTx(ctx, func(tx bun.Tx) error { | 
					
						
							|  |  |  | 			// create links between this account and any emojis it uses | 
					
						
							|  |  |  | 			// first clear out any old emoji links | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 			if _, err := tx. | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 				NewDelete(). | 
					
						
							|  |  |  | 				TableExpr("? AS ?", bun.Ident("account_to_emojis"), bun.Ident("account_to_emoji")). | 
					
						
							|  |  |  | 				Where("? = ?", bun.Ident("account_to_emoji.account_id"), account.ID). | 
					
						
							|  |  |  | 				Exec(ctx); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-26 11:56:01 +02:00
										 |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 			// now populate new emoji links | 
					
						
							|  |  |  | 			for _, i := range account.EmojiIDs { | 
					
						
							|  |  |  | 				if _, err := tx. | 
					
						
							|  |  |  | 					NewInsert(). | 
					
						
							|  |  |  | 					Model(>smodel.AccountToEmoji{ | 
					
						
							|  |  |  | 						AccountID: account.ID, | 
					
						
							|  |  |  | 						EmojiID:   i, | 
					
						
							|  |  |  | 					}).Exec(ctx); err != nil { | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-09-01 10:08:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 			// update the account | 
					
						
							|  |  |  | 			_, err := tx.NewUpdate(). | 
					
						
							|  |  |  | 				Model(account). | 
					
						
							|  |  |  | 				Where("? = ?", bun.Ident("account.id"), account.ID). | 
					
						
							|  |  |  | 				Exec(ctx) | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | func (a *accountDB) DeleteAccount(ctx context.Context, id string) db.Error { | 
					
						
							|  |  |  | 	if err := a.conn.RunInTx(ctx, func(tx bun.Tx) error { | 
					
						
							|  |  |  | 		// clear out any emoji links | 
					
						
							|  |  |  | 		if _, err := tx. | 
					
						
							|  |  |  | 			NewDelete(). | 
					
						
							|  |  |  | 			TableExpr("? AS ?", bun.Ident("account_to_emojis"), bun.Ident("account_to_emoji")). | 
					
						
							|  |  |  | 			Where("? = ?", bun.Ident("account_to_emoji.account_id"), id). | 
					
						
							|  |  |  | 			Exec(ctx); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// delete the account | 
					
						
							|  |  |  | 		_, err := tx. | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 			NewDelete(). | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 			TableExpr("? AS ?", bun.Ident("accounts"), bun.Ident("account")). | 
					
						
							|  |  |  | 			Where("? = ?", bun.Ident("account.id"), id). | 
					
						
							|  |  |  | 			Exec(ctx) | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							| 
									
										
										
										
											2022-11-15 18:45:15 +00:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-08 17:35:14 +00:00
										 |  |  | 	a.state.Caches.GTS.Account().Invalidate("ID", id) | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-08 14:00:39 +02:00
										 |  |  | func (a *accountDB) GetAccountLastPosted(ctx context.Context, accountID string, webOnly bool) (time.Time, db.Error) { | 
					
						
							|  |  |  | 	createdAt := time.Time{} | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	q := a.conn. | 
					
						
							|  |  |  | 		NewSelect(). | 
					
						
							| 
									
										
										
										
											2022-10-08 14:00:39 +02:00
										 |  |  | 		TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")). | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		Column("status.created_at"). | 
					
						
							|  |  |  | 		Where("? = ?", bun.Ident("status.account_id"), accountID). | 
					
						
							|  |  |  | 		Order("status.id DESC"). | 
					
						
							|  |  |  | 		Limit(1) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-08 14:00:39 +02:00
										 |  |  | 	if webOnly { | 
					
						
							|  |  |  | 		q = q. | 
					
						
							|  |  |  | 			WhereGroup(" AND ", whereEmptyOrNull("status.in_reply_to_uri")). | 
					
						
							|  |  |  | 			WhereGroup(" AND ", whereEmptyOrNull("status.boost_of_id")). | 
					
						
							|  |  |  | 			Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic). | 
					
						
							|  |  |  | 			Where("? = ?", bun.Ident("status.federated"), true) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := q.Scan(ctx, &createdAt); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		return time.Time{}, a.conn.ProcessError(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-08 14:00:39 +02:00
										 |  |  | 	return createdAt, nil | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | func (a *accountDB) SetAccountHeaderOrAvatar(ctx context.Context, mediaAttachment *gtsmodel.MediaAttachment, accountID string) db.Error { | 
					
						
							| 
									
										
										
										
											2022-08-15 12:35:05 +02:00
										 |  |  | 	if *mediaAttachment.Avatar && *mediaAttachment.Header { | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 		return errors.New("one media attachment cannot be both header and avatar") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 	var column bun.Ident | 
					
						
							| 
									
										
										
										
											2021-11-22 08:46:19 +01:00
										 |  |  | 	switch { | 
					
						
							| 
									
										
										
										
											2022-08-15 12:35:05 +02:00
										 |  |  | 	case *mediaAttachment.Avatar: | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		column = bun.Ident("account.avatar_media_attachment_id") | 
					
						
							| 
									
										
										
										
											2022-08-15 12:35:05 +02:00
										 |  |  | 	case *mediaAttachment.Header: | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		column = bun.Ident("account.header_media_attachment_id") | 
					
						
							| 
									
										
										
										
											2021-11-22 08:46:19 +01:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 		return errors.New("given media attachment was neither a header nor an avatar") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TODO: there are probably more side effects here that need to be handled | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	if _, err := a.conn. | 
					
						
							|  |  |  | 		NewInsert(). | 
					
						
							|  |  |  | 		Model(mediaAttachment). | 
					
						
							|  |  |  | 		Exec(ctx); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		return a.conn.ProcessError(err) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	if _, err := a.conn. | 
					
						
							|  |  |  | 		NewUpdate(). | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		TableExpr("? AS ?", bun.Ident("accounts"), bun.Ident("account")). | 
					
						
							|  |  |  | 		Set("? = ?", column, mediaAttachment.ID). | 
					
						
							|  |  |  | 		Where("? = ?", bun.Ident("account.id"), accountID). | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 		Exec(ctx); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		return a.conn.ProcessError(err) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-12 13:14:29 +02:00
										 |  |  | func (a *accountDB) GetAccountCustomCSSByUsername(ctx context.Context, username string) (string, db.Error) { | 
					
						
							|  |  |  | 	account, err := a.GetAccountByUsernameDomain(ctx, username, "") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return account.CustomCSS, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | func (a *accountDB) GetAccountFaves(ctx context.Context, accountID string) ([]*gtsmodel.StatusFave, db.Error) { | 
					
						
							|  |  |  | 	faves := new([]*gtsmodel.StatusFave) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	if err := a.conn. | 
					
						
							|  |  |  | 		NewSelect(). | 
					
						
							|  |  |  | 		Model(faves). | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		Where("? = ?", bun.Ident("status_fave.account_id"), accountID). | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 		Scan(ctx); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		return nil, a.conn.ProcessError(err) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	return *faves, nil | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | func (a *accountDB) CountAccountStatuses(ctx context.Context, accountID string) (int, db.Error) { | 
					
						
							|  |  |  | 	return a.conn. | 
					
						
							|  |  |  | 		NewSelect(). | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")). | 
					
						
							|  |  |  | 		Where("? = ?", bun.Ident("status.account_id"), accountID). | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 		Count(ctx) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-15 14:33:01 +02:00
										 |  |  | func (a *accountDB) GetAccountStatuses(ctx context.Context, accountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]*gtsmodel.Status, db.Error) { | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	statusIDs := []string{} | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	q := a.conn. | 
					
						
							|  |  |  | 		NewSelect(). | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")). | 
					
						
							|  |  |  | 		Column("status.id"). | 
					
						
							|  |  |  | 		Order("status.id DESC") | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	if accountID != "" { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		q = q.Where("? = ?", bun.Ident("status.account_id"), accountID) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if limit != 0 { | 
					
						
							|  |  |  | 		q = q.Limit(limit) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 11:57:39 +02:00
										 |  |  | 	if excludeReplies { | 
					
						
							| 
									
										
										
										
											2022-08-27 05:35:31 -04:00
										 |  |  | 		// include self-replies (threads) | 
					
						
							|  |  |  | 		whereGroup := func(*bun.SelectQuery) *bun.SelectQuery { | 
					
						
							|  |  |  | 			return q. | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 				WhereOr("? = ?", bun.Ident("status.in_reply_to_account_id"), accountID). | 
					
						
							|  |  |  | 				WhereGroup(" OR ", whereEmptyOrNull("status.in_reply_to_uri")) | 
					
						
							| 
									
										
										
										
											2022-08-27 05:35:31 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		q = q.WhereGroup(" AND ", whereGroup) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-15 14:33:01 +02:00
										 |  |  | 	if excludeReblogs { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		q = q.WhereGroup(" AND ", whereEmptyOrNull("status.boost_of_id")) | 
					
						
							| 
									
										
										
										
											2022-04-15 14:33:01 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	if maxID != "" { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		q = q.Where("? < ?", bun.Ident("status.id"), maxID) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 11:57:39 +02:00
										 |  |  | 	if minID != "" { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		q = q.Where("? > ?", bun.Ident("status.id"), minID) | 
					
						
							| 
									
										
										
										
											2021-10-24 11:57:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if pinnedOnly { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		q = q.Where("? = ?", bun.Ident("status.pinned"), true) | 
					
						
							| 
									
										
										
										
											2021-10-24 11:57:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	if mediaOnly { | 
					
						
							| 
									
										
										
										
											2022-04-10 15:11:12 +02:00
										 |  |  | 		// attachments are stored as a json object; | 
					
						
							|  |  |  | 		// this implementation differs between sqlite and postgres, | 
					
						
							| 
									
										
										
										
											2022-06-10 10:56:49 +02:00
										 |  |  | 		// so we have to be thorough to cover all eventualities | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 		q = q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery { | 
					
						
							| 
									
										
										
										
											2022-06-10 10:56:49 +02:00
										 |  |  | 			switch a.conn.Dialect().Name() { | 
					
						
							|  |  |  | 			case dialect.PG: | 
					
						
							|  |  |  | 				return q. | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 					Where("? IS NOT NULL", bun.Ident("status.attachments")). | 
					
						
							|  |  |  | 					Where("? != '{}'", bun.Ident("status.attachments")) | 
					
						
							| 
									
										
										
										
											2022-06-10 10:56:49 +02:00
										 |  |  | 			case dialect.SQLite: | 
					
						
							|  |  |  | 				return q. | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 					Where("? IS NOT NULL", bun.Ident("status.attachments")). | 
					
						
							|  |  |  | 					Where("? != ''", bun.Ident("status.attachments")). | 
					
						
							|  |  |  | 					Where("? != 'null'", bun.Ident("status.attachments")). | 
					
						
							|  |  |  | 					Where("? != '{}'", bun.Ident("status.attachments")). | 
					
						
							|  |  |  | 					Where("? != '[]'", bun.Ident("status.attachments")) | 
					
						
							| 
									
										
										
										
											2022-06-10 10:56:49 +02:00
										 |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 				log.Panic("db dialect was neither pg nor sqlite") | 
					
						
							| 
									
										
										
										
											2022-06-10 10:56:49 +02:00
										 |  |  | 				return q | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 11:57:39 +02:00
										 |  |  | 	if publicOnly { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		q = q.Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic) | 
					
						
							| 
									
										
										
										
											2021-08-26 22:06:34 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	if err := q.Scan(ctx, &statusIDs); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		return nil, a.conn.ProcessError(err) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 09:57:47 +02:00
										 |  |  | 	return a.statusesFromIDs(ctx, statusIDs) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 09:57:47 +02:00
										 |  |  | func (a *accountDB) GetAccountWebStatuses(ctx context.Context, accountID string, limit int, maxID string) ([]*gtsmodel.Status, db.Error) { | 
					
						
							|  |  |  | 	statusIDs := []string{} | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 09:57:47 +02:00
										 |  |  | 	q := a.conn. | 
					
						
							|  |  |  | 		NewSelect(). | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")). | 
					
						
							|  |  |  | 		Column("status.id"). | 
					
						
							|  |  |  | 		Where("? = ?", bun.Ident("status.account_id"), accountID). | 
					
						
							|  |  |  | 		WhereGroup(" AND ", whereEmptyOrNull("status.in_reply_to_uri")). | 
					
						
							|  |  |  | 		WhereGroup(" AND ", whereEmptyOrNull("status.boost_of_id")). | 
					
						
							|  |  |  | 		Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic). | 
					
						
							|  |  |  | 		Where("? = ?", bun.Ident("status.federated"), true) | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-13 09:57:47 +02:00
										 |  |  | 	if maxID != "" { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		q = q.Where("? < ?", bun.Ident("status.id"), maxID) | 
					
						
							| 
									
										
										
										
											2022-07-10 16:18:21 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 	q = q.Limit(limit).Order("status.id DESC") | 
					
						
							| 
									
										
										
										
											2022-07-13 09:57:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if err := q.Scan(ctx, &statusIDs); err != nil { | 
					
						
							|  |  |  | 		return nil, a.conn.ProcessError(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return a.statusesFromIDs(ctx, statusIDs) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-09 05:37:12 -05:00
										 |  |  | func (a *accountDB) GetBookmarks(ctx context.Context, accountID string, limit int, maxID string, minID string) ([]*gtsmodel.StatusBookmark, db.Error) { | 
					
						
							|  |  |  | 	bookmarks := []*gtsmodel.StatusBookmark{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	q := a.conn. | 
					
						
							|  |  |  | 		NewSelect(). | 
					
						
							|  |  |  | 		TableExpr("? AS ?", bun.Ident("status_bookmarks"), bun.Ident("status_bookmark")). | 
					
						
							|  |  |  | 		Order("status_bookmark.id DESC"). | 
					
						
							|  |  |  | 		Where("? = ?", bun.Ident("status_bookmark.account_id"), accountID) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if accountID == "" { | 
					
						
							|  |  |  | 		return nil, errors.New("must provide an account") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if limit != 0 { | 
					
						
							|  |  |  | 		q = q.Limit(limit) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if maxID != "" { | 
					
						
							|  |  |  | 		q = q.Where("? < ?", bun.Ident("status_bookmark.id"), maxID) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if minID != "" { | 
					
						
							|  |  |  | 		q = q.Where("? > ?", bun.Ident("status_bookmark.id"), minID) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := q.Scan(ctx, &bookmarks); err != nil { | 
					
						
							|  |  |  | 		return nil, a.conn.ProcessError(err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return bookmarks, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | func (a *accountDB) GetAccountBlocks(ctx context.Context, accountID string, maxID string, sinceID string, limit int) ([]*gtsmodel.Account, string, string, db.Error) { | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	blocks := []*gtsmodel.Block{} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-25 15:34:33 +02:00
										 |  |  | 	fq := a.conn. | 
					
						
							|  |  |  | 		NewSelect(). | 
					
						
							|  |  |  | 		Model(&blocks). | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		Where("? = ?", bun.Ident("block.account_id"), accountID). | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 		Relation("TargetAccount"). | 
					
						
							|  |  |  | 		Order("block.id DESC") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if maxID != "" { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		fq = fq.Where("? < ?", bun.Ident("block.id"), maxID) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if sinceID != "" { | 
					
						
							| 
									
										
										
										
											2022-10-08 13:50:48 +02:00
										 |  |  | 		fq = fq.Where("? > ?", bun.Ident("block.id"), sinceID) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if limit > 0 { | 
					
						
							|  |  |  | 		fq = fq.Limit(limit) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-22 08:46:19 +01:00
										 |  |  | 	if err := fq.Scan(ctx); err != nil { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  | 		return nil, "", "", a.conn.ProcessError(err) | 
					
						
							| 
									
										
										
										
											2021-08-20 12:26:56 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(blocks) == 0 { | 
					
						
							|  |  |  | 		return nil, "", "", db.ErrNoEntries | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	accounts := []*gtsmodel.Account{} | 
					
						
							|  |  |  | 	for _, b := range blocks { | 
					
						
							|  |  |  | 		accounts = append(accounts, b.TargetAccount) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nextMaxID := blocks[len(blocks)-1].ID | 
					
						
							|  |  |  | 	prevMinID := blocks[0].ID | 
					
						
							|  |  |  | 	return accounts, nextMaxID, prevMinID, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-07-13 09:57:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (a *accountDB) statusesFromIDs(ctx context.Context, statusIDs []string) ([]*gtsmodel.Status, db.Error) { | 
					
						
							|  |  |  | 	// Catch case of no statuses early | 
					
						
							|  |  |  | 	if len(statusIDs) == 0 { | 
					
						
							|  |  |  | 		return nil, db.ErrNoEntries | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Allocate return slice (will be at most len statusIDS) | 
					
						
							|  |  |  | 	statuses := make([]*gtsmodel.Status, 0, len(statusIDs)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, id := range statusIDs { | 
					
						
							|  |  |  | 		// Fetch from status from database by ID | 
					
						
							| 
									
										
										
										
											2022-12-08 17:35:14 +00:00
										 |  |  | 		status, err := a.state.DB.GetStatusByID(ctx, id) | 
					
						
							| 
									
										
										
										
											2022-07-13 09:57:47 +02:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 			log.Errorf("statusesFromIDs: error getting status %q: %v", id, err) | 
					
						
							| 
									
										
										
										
											2022-07-13 09:57:47 +02:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Append to return slice | 
					
						
							|  |  |  | 		statuses = append(statuses, status) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return statuses, nil | 
					
						
							|  |  |  | } |