From a3322b2bf350bbb90236747813750264e5621254 Mon Sep 17 00:00:00 2001 From: tsmethurst Date: Tue, 17 Aug 2021 19:03:41 +0200 Subject: [PATCH] more fiddling --- internal/ap/extract.go | 2 +- internal/db/account.go | 18 ++++ internal/db/admin.go | 18 ++++ internal/db/basic.go | 22 +++++ internal/db/db.go | 1 + internal/db/instance.go | 18 ++++ internal/db/mention.go | 29 ++++++ internal/db/notification.go | 18 ++++ internal/db/pg/basic.go | 5 + internal/db/pg/mention.go | 77 +++++++++++++++ internal/db/pg/pg.go | 23 +++-- internal/db/pg/relationship.go | 49 +++++++--- internal/db/pg/status.go | 10 +- internal/db/pg/status_test.go | 13 ++- internal/db/relationship.go | 30 +++++- internal/db/status.go | 18 ++++ internal/db/timeline.go | 18 ++++ internal/federation/dereferencing/status.go | 12 +-- internal/gtsmodel/domainblock.go | 1 + internal/gtsmodel/emaildomainblock.go | 1 + internal/gtsmodel/emoji.go | 3 +- internal/gtsmodel/follow.go | 2 + internal/gtsmodel/followrequest.go | 6 +- internal/gtsmodel/mediaattachment.go | 1 + internal/gtsmodel/mention.go | 13 ++- internal/gtsmodel/notification.go | 20 ++-- internal/gtsmodel/status.go | 31 ++---- internal/gtsmodel/statusbookmark.go | 2 + internal/gtsmodel/statusfave.go | 2 +- internal/gtsmodel/statusmute.go | 3 + internal/gtsmodel/user.go | 6 +- internal/processing/account/createblock.go | 26 +++-- internal/processing/account/createfollow.go | 27 +++--- internal/processing/account/get.go | 2 +- internal/processing/account/getfollowers.go | 9 +- internal/processing/account/getfollowing.go | 9 +- internal/processing/account/getstatuses.go | 9 +- internal/processing/account/removeblock.go | 12 +-- internal/processing/account/removefollow.go | 2 +- internal/processing/federation.go | 10 +- internal/processing/fromclientapi.go | 4 +- internal/processing/fromcommon.go | 18 ++-- internal/processing/fromfederator.go | 4 +- internal/processing/media/getfile.go | 2 +- internal/processing/search.go | 2 +- internal/processing/status/boost.go | 31 +++--- internal/processing/status/boostedby.go | 32 +++---- internal/processing/status/context.go | 43 ++++----- internal/processing/status/create.go | 2 +- internal/processing/status/delete.go | 34 +++---- internal/processing/status/fave.go | 53 ++++------- internal/processing/status/favedby.go | 24 ++--- internal/processing/status/get.go | 31 ++---- internal/processing/status/unboost.go | 35 +++---- internal/processing/status/unfave.go | 29 +++--- internal/processing/status/util.go | 22 ++--- internal/processing/status/util_test.go | 28 +++--- internal/text/common.go | 4 +- internal/typeutils/astointernal.go | 16 ++-- internal/typeutils/internal.go | 8 +- internal/typeutils/internaltoas.go | 42 ++++---- internal/typeutils/internaltofrontend.go | 50 +++++----- internal/visibility/statusvisible.go | 12 +-- internal/visibility/util.go | 100 +++++++++++--------- testrig/testmodels.go | 16 ++-- 65 files changed, 712 insertions(+), 508 deletions(-) create mode 100644 internal/db/mention.go create mode 100644 internal/db/pg/mention.go diff --git a/internal/ap/extract.go b/internal/ap/extract.go index baffd4bf2..1ee0e008e 100644 --- a/internal/ap/extract.go +++ b/internal/ap/extract.go @@ -581,7 +581,7 @@ func ExtractMention(i Mentionable) (*gtsmodel.Mention, error) { if hrefProp == nil || !hrefProp.IsIRI() { return nil, errors.New("no href prop") } - mention.MentionedAccountURI = hrefProp.GetIRI().String() + mention.TargetAccountURI = hrefProp.GetIRI().String() return mention, nil } diff --git a/internal/db/account.go b/internal/db/account.go index 82268fe87..d30657cf9 100644 --- a/internal/db/account.go +++ b/internal/db/account.go @@ -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 . +*/ + package db import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" diff --git a/internal/db/admin.go b/internal/db/admin.go index 8e7e489d2..c9cc96117 100644 --- a/internal/db/admin.go +++ b/internal/db/admin.go @@ -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 . +*/ + package db import ( diff --git a/internal/db/basic.go b/internal/db/basic.go index 5740149c2..558bf8d91 100644 --- a/internal/db/basic.go +++ b/internal/db/basic.go @@ -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 . +*/ + package db import "context" @@ -11,6 +29,10 @@ type Basic interface { // For implementations that don't use tables, this can just return nil. DropTable(i interface{}) DBError + // RegisterTable registers a table for use in many2many relations. + // For implementations that don't use tables, or many2many relations, this can just return nil. + RegisterTable(i interface{}) DBError + // Stop should stop and close the database connection cleanly, returning an error if this is not possible. // If the database implementation doesn't need to be stopped, this can just return nil. Stop(ctx context.Context) DBError diff --git a/internal/db/db.go b/internal/db/db.go index bc55a2ca6..b3d04939b 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -35,6 +35,7 @@ type DB interface { Admin Basic Instance + Mention Notification Relationship Status diff --git a/internal/db/instance.go b/internal/db/instance.go index 152cc39b8..3268b2085 100644 --- a/internal/db/instance.go +++ b/internal/db/instance.go @@ -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 . +*/ + package db import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" diff --git a/internal/db/mention.go b/internal/db/mention.go new file mode 100644 index 000000000..0e6216508 --- /dev/null +++ b/internal/db/mention.go @@ -0,0 +1,29 @@ +/* + 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 . +*/ + +package db + +import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" + +type Mention interface { + // GetMention gets a single mention by ID + GetMention(id string) (*gtsmodel.Mention, DBError) + + // GetMentions gets multiple mentions. + GetMentions(ids []string) ([]*gtsmodel.Mention, DBError) +} diff --git a/internal/db/notification.go b/internal/db/notification.go index 7360b4080..26bcc0a79 100644 --- a/internal/db/notification.go +++ b/internal/db/notification.go @@ -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 . +*/ + package db import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" diff --git a/internal/db/pg/basic.go b/internal/db/pg/basic.go index 1debe3b74..337c6add8 100644 --- a/internal/db/pg/basic.go +++ b/internal/db/pg/basic.go @@ -185,6 +185,11 @@ func (b *basicDB) DropTable(i interface{}) db.DBError { }) } +func (b *basicDB) RegisterTable(i interface{}) db.DBError { + orm.RegisterTable(i) + return nil +} + func (b *basicDB) IsHealthy(ctx context.Context) db.DBError { return b.conn.Ping(ctx) } diff --git a/internal/db/pg/mention.go b/internal/db/pg/mention.go new file mode 100644 index 000000000..e9a27c867 --- /dev/null +++ b/internal/db/pg/mention.go @@ -0,0 +1,77 @@ +/* + 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 . +*/ + +package pg + +import ( + "context" + + "github.com/go-pg/pg/v10" + "github.com/go-pg/pg/v10/orm" + "github.com/sirupsen/logrus" + "github.com/superseriousbusiness/gotosocial/internal/config" + "github.com/superseriousbusiness/gotosocial/internal/db" + "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +) + +type mentionDB struct { + config *config.Config + conn *pg.DB + log *logrus.Logger + cancel context.CancelFunc +} + +func (m *mentionDB) newMentionQ(i interface{}) *orm.Query { + return m.conn.Model(i). + Relation("Status"). + Relation("OriginAccount"). + Relation("TargetAccount") +} + +func (m *mentionDB) processResponse(mention *gtsmodel.Mention, err error) (*gtsmodel.Mention, db.DBError) { + switch err { + case pg.ErrNoRows: + return nil, db.ErrNoEntries + case nil: + return mention, nil + default: + return nil, err + } +} + +func (m *mentionDB) GetMention(id string) (*gtsmodel.Mention, db.DBError) { + mention := >smodel.Mention{} + + q := m.newMentionQ(mention). + Where("mention.id = ?", id) + + return m.processResponse(mention, q.Select()) +} + +func (m *mentionDB) GetMentions(ids []string) ([]*gtsmodel.Mention, db.DBError) { + mentions := []*gtsmodel.Mention{} + + q := m.newMentionQ(mentions). + Where("mention.id in (?)", pg.In(ids)) + + if err := q.Select(); err != nil { + return nil, err + } + + return mentions, nil +} diff --git a/internal/db/pg/pg.go b/internal/db/pg/pg.go index a0a38038e..a851a4649 100644 --- a/internal/db/pg/pg.go +++ b/internal/db/pg/pg.go @@ -44,6 +44,7 @@ type postgresService struct { db.Admin db.Basic db.Instance + db.Mention db.Notification db.Relationship db.Status @@ -116,6 +117,12 @@ func NewPostgresService(ctx context.Context, c *config.Config, log *logrus.Logge log: log, cancel: cancel, }, + Mention: &mentionDB{ + config: c, + conn: conn, + log: log, + cancel: cancel, + }, Relationship: &relationshipDB{ config: c, conn: conn, @@ -313,14 +320,14 @@ func (ps *postgresService) MentionStringsToMentions(targetAccounts []string, ori // id, createdAt and updatedAt will be populated by the db, so we have everything we need! menchies = append(menchies, >smodel.Mention{ - StatusID: statusID, - OriginAccountID: ogAccount.ID, - OriginAccountURI: ogAccount.URI, - TargetAccountID: mentionedAccount.ID, - NameString: a, - MentionedAccountURI: mentionedAccount.URI, - MentionedAccountURL: mentionedAccount.URL, - GTSAccount: mentionedAccount, + StatusID: statusID, + OriginAccountID: ogAccount.ID, + OriginAccountURI: ogAccount.URI, + TargetAccountID: mentionedAccount.ID, + NameString: a, + TargetAccountURI: mentionedAccount.URI, + TargetAccountURL: mentionedAccount.URL, + OriginAccount: mentionedAccount, }) } return menchies, nil diff --git a/internal/db/pg/relationship.go b/internal/db/pg/relationship.go index 1835ca7a6..aa4f35104 100644 --- a/internal/db/pg/relationship.go +++ b/internal/db/pg/relationship.go @@ -23,6 +23,7 @@ import ( "fmt" "github.com/go-pg/pg/v10" + "github.com/go-pg/pg/v10/orm" "github.com/sirupsen/logrus" "github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/db" @@ -36,21 +37,41 @@ type relationshipDB struct { cancel context.CancelFunc } -func (r *relationshipDB) Blocked(account1 string, account2 string) (bool, db.DBError) { - // TODO: check domain blocks as well - var blocked bool - if err := r.conn.Model(>smodel.Block{}). - Where("account_id = ?", account1).Where("target_account_id = ?", account2). - WhereOr("target_account_id = ?", account1).Where("account_id = ?", account2). - Select(); err != nil { - if err == pg.ErrNoRows { - blocked = false - return blocked, nil - } - return blocked, err +func (r *relationshipDB) newBlockQ(block *gtsmodel.Block) *orm.Query { + return r.conn.Model(block). + Relation("Account"). + Relation("TargetAccount") +} + +func (r *relationshipDB) processResponse(block *gtsmodel.Block, err error) (*gtsmodel.Block, db.DBError) { + switch err { + case pg.ErrNoRows: + return nil, db.ErrNoEntries + case nil: + return block, nil + default: + return nil, err } - blocked = true - return blocked, nil +} + +func (r *relationshipDB) Blocked(account1 string, account2 string, eitherDirection bool) (bool, db.DBError) { + q := r.conn.Model(>smodel.Block{}).Where("account_id = ?", account1).Where("target_account_id = ?", account2) + + if eitherDirection { + q = q.WhereOr("target_account_id = ?", account1).Where("account_id = ?", account2) + } + + return q.Exists() +} + +func (r *relationshipDB) GetBlock(account1 string, account2 string) (*gtsmodel.Block, db.DBError) { + block := >smodel.Block{} + + q := r.newBlockQ(block). + Where("block.account_id = ?", account1). + Where("block.target_account_id = ?", account2) + + return r.processResponse(block, q.Select()) } func (r *relationshipDB) GetRelationship(requestingAccount string, targetAccount string) (*gtsmodel.Relationship, db.DBError) { diff --git a/internal/db/pg/status.go b/internal/db/pg/status.go index 450999b9a..5e1b55538 100644 --- a/internal/db/pg/status.go +++ b/internal/db/pg/status.go @@ -40,6 +40,10 @@ type statusDB struct { func (s *statusDB) newStatusQ(status *gtsmodel.Status) *orm.Query { return s.conn.Model(status). + Relation("Attachments"). + Relation("Tags"). + Relation("Mentions"). + Relation("Emojis"). Relation("Account"). Relation("InReplyTo"). Relation("InReplyToAccount"). @@ -48,7 +52,7 @@ func (s *statusDB) newStatusQ(status *gtsmodel.Status) *orm.Query { Relation("CreatedWithApplication") } -func (s *statusDB) processResponse(status *gtsmodel.Status, err error) (*gtsmodel.Status, db.DBError) { +func (s *statusDB) processStatusResponse(status *gtsmodel.Status, err error) (*gtsmodel.Status, db.DBError) { switch err { case pg.ErrNoRows: return nil, db.ErrNoEntries @@ -65,7 +69,7 @@ func (s *statusDB) GetStatusByID(id string) (*gtsmodel.Status, db.DBError) { q := s.newStatusQ(status). Where("status.id = ?", id) - return s.processResponse(status, q.Select()) + return s.processStatusResponse(status, q.Select()) } func (s *statusDB) GetStatusByURI(uri string) (*gtsmodel.Status, db.DBError) { @@ -74,7 +78,7 @@ func (s *statusDB) GetStatusByURI(uri string) (*gtsmodel.Status, db.DBError) { q := s.newStatusQ(status). Where("LOWER(status.uri) = LOWER(?)", uri) - return s.processResponse(status, q.Select()) + return s.processStatusResponse(status, q.Select()) } func (s *statusDB) StatusParents(status *gtsmodel.Status, onlyDirect bool) ([]*gtsmodel.Status, db.DBError) { diff --git a/internal/db/pg/status_test.go b/internal/db/pg/status_test.go index a412eb55f..eefc0bb46 100644 --- a/internal/db/pg/status_test.go +++ b/internal/db/pg/status_test.go @@ -80,7 +80,18 @@ func (suite *PGStandardTestSuite) TestGetStatusByURI() { suite.Nil(status.InReplyTo) suite.Nil(status.InReplyToAccount) } - +func (suite *PGStandardTestSuite) TestGetStatusWithExtras() { + status, err := suite.db.GetStatusByID(suite.testStatuses["admin_account_status_1"].ID) + if err != nil { + suite.FailNow(err.Error()) + } + suite.NotNil(status) + suite.NotNil(status.Account) + suite.NotNil(status.CreatedWithApplication) + suite.NotEmpty(status.Tags) + suite.NotEmpty(status.Attachments) + suite.NotEmpty(status.Emojis) +} func TestStatusTestSuite(t *testing.T) { suite.Run(t, new(PGStandardTestSuite)) } diff --git a/internal/db/relationship.go b/internal/db/relationship.go index 28c891b99..be171f9b1 100644 --- a/internal/db/relationship.go +++ b/internal/db/relationship.go @@ -1,11 +1,35 @@ +/* + 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 . +*/ + package db import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" type Relationship interface { - // Blocked checks whether a block exists in eiher direction between two accounts. - // That is, it returns true if account1 blocks account2, OR if account2 blocks account1. - Blocked(account1 string, account2 string) (bool, DBError) + // Blocked checks whether account 1 has a block in place against block2. + // If eitherDirection is true, then the function returns true if account1 blocks account2, OR if account2 blocks account1. + Blocked(account1 string, account2 string, eitherDirection bool) (bool, DBError) + + // GetBlock returns the block from account1 targeting account2, if it exists, or an error if it doesn't. + // + // Because this is slower than Blocked, only use it if you need the actual Block struct for some reason, + // not if you're just checking for the existence of a block. + GetBlock(account1 string, account2 string) (*gtsmodel.Block, DBError) // GetRelationship retrieves the relationship of the targetAccount to the requestingAccount. GetRelationship(requestingAccount string, targetAccount string) (*gtsmodel.Relationship, DBError) diff --git a/internal/db/status.go b/internal/db/status.go index 91ee54a9c..df039e0d9 100644 --- a/internal/db/status.go +++ b/internal/db/status.go @@ -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 . +*/ + package db import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" diff --git a/internal/db/timeline.go b/internal/db/timeline.go index 737a78a31..638d2d10d 100644 --- a/internal/db/timeline.go +++ b/internal/db/timeline.go @@ -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 . +*/ + package db import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" diff --git a/internal/federation/dereferencing/status.go b/internal/federation/dereferencing/status.go index c2d293329..902e9daaa 100644 --- a/internal/federation/dereferencing/status.go +++ b/internal/federation/dereferencing/status.go @@ -276,7 +276,7 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername // * the remote URL (a.RemoteURL) // This should be enough to pass along to the media processor. attachmentIDs := []string{} - for _, a := range status.GTSMediaAttachments { + for _, a := range status.Attachments { l.Tracef("dereferencing attachment: %+v", a) // it might have been processed elsewhere so check first if it's already in the database or not @@ -307,7 +307,7 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername } attachmentIDs = append(attachmentIDs, deferencedAttachment.ID) } - status.Attachments = attachmentIDs + status.AttachmentIDs = attachmentIDs // 2. Hashtags @@ -318,7 +318,7 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername // // We should dereference any accounts mentioned here which we don't have in our db yet, by their URI. mentions := []string{} - for _, m := range status.GTSMentions { + for _, m := range status.Mentions { if m.ID != "" { continue @@ -331,9 +331,9 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername } m.ID = mID - uri, err := url.Parse(m.MentionedAccountURI) + uri, err := url.Parse(m.TargetAccountURI) if err != nil { - l.Debugf("error parsing mentioned account uri %s: %s", m.MentionedAccountURI, err) + l.Debugf("error parsing mentioned account uri %s: %s", m.TargetAccountURI, err) continue } @@ -353,7 +353,7 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername } mentions = append(mentions, m.ID) } - status.Mentions = mentions + status.MentionIDs = mentions // status has replyToURI but we don't have an ID yet for the status it replies to if status.InReplyToURI != "" && status.InReplyToID == "" { diff --git a/internal/gtsmodel/domainblock.go b/internal/gtsmodel/domainblock.go index b32984e95..809250276 100644 --- a/internal/gtsmodel/domainblock.go +++ b/internal/gtsmodel/domainblock.go @@ -32,6 +32,7 @@ type DomainBlock struct { UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // Account ID of the creator of this block CreatedByAccountID string `pg:"type:CHAR(26),notnull"` + CreatedByAccount *Account `pg:"rel:belongs-to"` // Private comment on this block, viewable to admins PrivateComment string // Public comment on this block, viewable (optionally) by everyone diff --git a/internal/gtsmodel/emaildomainblock.go b/internal/gtsmodel/emaildomainblock.go index 51558550a..03618dd3a 100644 --- a/internal/gtsmodel/emaildomainblock.go +++ b/internal/gtsmodel/emaildomainblock.go @@ -32,4 +32,5 @@ type EmailDomainBlock struct { UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // Account ID of the creator of this block CreatedByAccountID string `pg:"type:CHAR(26),notnull"` + CreatedByAccount *Account `pg:"rel:belongs-to"` } diff --git a/internal/gtsmodel/emoji.go b/internal/gtsmodel/emoji.go index 2fa3b7565..f0996d1a3 100644 --- a/internal/gtsmodel/emoji.go +++ b/internal/gtsmodel/emoji.go @@ -73,5 +73,6 @@ type Emoji struct { // Is this emoji visible in the admin emoji picker? VisibleInPicker bool `pg:",notnull,default:true"` // In which emoji category is this emoji visible? - CategoryID string `pg:"type:CHAR(26)"` + CategoryID string `pg:"type:CHAR(26)"` + Status *Status `pg:"rel:belongs-to"` } diff --git a/internal/gtsmodel/follow.go b/internal/gtsmodel/follow.go index f5a170ca8..22f87768e 100644 --- a/internal/gtsmodel/follow.go +++ b/internal/gtsmodel/follow.go @@ -30,8 +30,10 @@ type Follow struct { UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // Who does this follow belong to? AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` + Account *Account `pg:"rel:belongs-to"` // Who does AccountID follow? TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` + TargetAccount *Account `pg:"rel:has-one"` // Does this follow also want to see reblogs and not just posts? ShowReblogs bool `pg:"default:true"` // What is the activitypub URI of this follow? diff --git a/internal/gtsmodel/followrequest.go b/internal/gtsmodel/followrequest.go index aabb785d2..752c7d0a2 100644 --- a/internal/gtsmodel/followrequest.go +++ b/internal/gtsmodel/followrequest.go @@ -29,9 +29,11 @@ type FollowRequest struct { // When was this follow request last updated? UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // Who does this follow request originate from? - AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` + AccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` + Account Account `pg:"rel:has-one"` // Who is the target of this follow request? - TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` + TargetAccountID string `pg:"type:CHAR(26),unique:srctarget,notnull"` + TargetAccount Account `pg:"rel:has-one"` // Does this follow also want to see reblogs and not just posts? ShowReblogs bool `pg:"default:true"` // What is the activitypub URI of this follow request? diff --git a/internal/gtsmodel/mediaattachment.go b/internal/gtsmodel/mediaattachment.go index 2aeeee962..4a8510bf4 100644 --- a/internal/gtsmodel/mediaattachment.go +++ b/internal/gtsmodel/mediaattachment.go @@ -43,6 +43,7 @@ type MediaAttachment struct { FileMeta FileMeta // To which account does this attachment belong AccountID string `pg:"type:CHAR(26),notnull"` + Account *Account `pg:"rel:belongs-to"` // Description of the attachment (for screenreaders) Description string // To which scheduled status does this attachment belong diff --git a/internal/gtsmodel/mention.go b/internal/gtsmodel/mention.go index 47c780521..5252e80d7 100644 --- a/internal/gtsmodel/mention.go +++ b/internal/gtsmodel/mention.go @@ -26,16 +26,19 @@ type Mention struct { ID string `pg:"type:CHAR(26),pk,notnull,unique"` // ID of the status this mention originates from StatusID string `pg:"type:CHAR(26),notnull"` + Status *Status `pg:"rel:belongs-to"` // When was this mention created? CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // When was this mention last updated? UpdatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // What's the internal account ID of the originator of the mention? OriginAccountID string `pg:"type:CHAR(26),notnull"` + OriginAccount *Account `pg:"rel:has-one"` // What's the AP URI of the originator of the mention? OriginAccountURI string `pg:",notnull"` // What's the internal account ID of the mention target? TargetAccountID string `pg:"type:CHAR(26),notnull"` + TargetAccount *Account `pg:"rel:has-one"` // Prevent this mention from generating a notification? Silent bool @@ -52,14 +55,14 @@ type Mention struct { // // This will not be put in the database, it's just for convenience. NameString string `pg:"-"` - // MentionedAccountURI is the AP ID (uri) of the user mentioned. + // TargetAccountURI is the AP ID (uri) of the user mentioned. // // This will not be put in the database, it's just for convenience. - MentionedAccountURI string `pg:"-"` - // MentionedAccountURL is the web url of the user mentioned. + TargetAccountURI string `pg:"-"` + // TargetAccountURL is the web url of the user mentioned. // // This will not be put in the database, it's just for convenience. - MentionedAccountURL string `pg:"-"` + TargetAccountURL string `pg:"-"` // A pointer to the gtsmodel account of the mentioned account. - GTSAccount *Account `pg:"-"` + } diff --git a/internal/gtsmodel/notification.go b/internal/gtsmodel/notification.go index efd4fe484..b85bc969e 100644 --- a/internal/gtsmodel/notification.go +++ b/internal/gtsmodel/notification.go @@ -29,24 +29,16 @@ type Notification struct { // Creation time of this notification CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // Which account does this notification target (ie., who will receive the notification?) - TargetAccountID string `pg:"type:CHAR(26),notnull"` + TargetAccountID string `pg:"type:CHAR(26),notnull"` + TargetAccount *Account `pg:"rel:has-one"` // Which account performed the action that created this notification? - OriginAccountID string `pg:"type:CHAR(26),notnull"` + OriginAccountID string `pg:"type:CHAR(26),notnull"` + OriginAccount *Account `pg:"rel:has-one"` // If the notification pertains to a status, what is the database ID of that status? - StatusID string `pg:"type:CHAR(26)"` + StatusID string `pg:"type:CHAR(26)"` + Status *Status `pg:"rel:has-one"` // Has this notification been read already? Read bool - - /* - NON-DATABASE fields - */ - - // gts model of the target account, won't be put in the database, it's just for convenience when passing the notification around. - GTSTargetAccount *Account `pg:"-"` - // gts model of the origin account, won't be put in the database, it's just for convenience when passing the notification around. - GTSOriginAccount *Account `pg:"-"` - // gts model of the relevant status, won't be put in the database, it's just for convenience when passing the notification around. - GTSStatus *Status `pg:"-"` } // NotificationType describes the reason/type of this notification. diff --git a/internal/gtsmodel/status.go b/internal/gtsmodel/status.go index 2746284a2..c722d5f42 100644 --- a/internal/gtsmodel/status.go +++ b/internal/gtsmodel/status.go @@ -33,13 +33,17 @@ type Status struct { // the html-formatted content of this status Content string // Database IDs of any media attachments associated with this status - Attachments []string `pg:",array"` + AttachmentIDs []string `pg:"attachments,array"` + Attachments []*MediaAttachment `pg:"rel:has-many"` // Database IDs of any tags used in this status - Tags []string `pg:",array"` + TagIDs []string `pg:"tags,array"` + Tags []*Tag `pg:"rel:has-many"` // Database IDs of any mentions in this status - Mentions []string `pg:",array"` + MentionIDs []string `pg:"mentions,array"` + Mentions []*Mention `pg:"rel:has-many"` // Database IDs of any emojis used in this status - Emojis []string `pg:",array"` + EmojiIDs []string `pg:"emojis,array"` + Emojis []*Emoji `pg:"rel:many2many"` // when was this status created? CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // when was this status updated? @@ -85,25 +89,6 @@ type Status struct { Text string // Has this status been pinned by its owner? Pinned bool - - /* - INTERNAL MODEL NON-DATABASE FIELDS - - These are for convenience while passing the status around internally, - but these fields should *never* be put in the db. - */ - - // Account that created this status - - // Mentions created in this status - GTSMentions []*Mention `pg:"-"` - // Hashtags used in this status - GTSTags []*Tag `pg:"-"` - // Emojis used in this status - GTSEmojis []*Emoji `pg:"-"` - // MediaAttachments used in this status - GTSMediaAttachments []*MediaAttachment `pg:"-"` - } // Visibility represents the visibility granularity of a status. diff --git a/internal/gtsmodel/statusbookmark.go b/internal/gtsmodel/statusbookmark.go index 7d95067cc..de66ebc87 100644 --- a/internal/gtsmodel/statusbookmark.go +++ b/internal/gtsmodel/statusbookmark.go @@ -28,8 +28,10 @@ type StatusBookmark struct { CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // id of the account that created ('did') the bookmarking AccountID string `pg:"type:CHAR(26),notnull"` + Account *Account `pg:"rel:belongs-to"` // id the account owning the bookmarked status TargetAccountID string `pg:"type:CHAR(26),notnull"` + TargetAccount *Account `pg:"rel:has-one"` // database id of the status that has been bookmarked StatusID string `pg:"type:CHAR(26),notnull"` } diff --git a/internal/gtsmodel/statusfave.go b/internal/gtsmodel/statusfave.go index 012360bff..6d3c5d4a9 100644 --- a/internal/gtsmodel/statusfave.go +++ b/internal/gtsmodel/statusfave.go @@ -28,7 +28,7 @@ type StatusFave struct { CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // id of the account that created ('did') the fave AccountID string `pg:"type:CHAR(26),notnull"` - Account *Account `pg:"rel:has-one"` + Account *Account `pg:"rel:belongs-to"` // id the account owning the faved status TargetAccountID string `pg:"type:CHAR(26),notnull"` TargetAccount *Account `pg:"rel:has-one"` diff --git a/internal/gtsmodel/statusmute.go b/internal/gtsmodel/statusmute.go index 6cd2b732f..4d7fa5ce2 100644 --- a/internal/gtsmodel/statusmute.go +++ b/internal/gtsmodel/statusmute.go @@ -28,8 +28,11 @@ type StatusMute struct { CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` // id of the account that created ('did') the mute AccountID string `pg:"type:CHAR(26),notnull"` + Account *Account `pg:"rel:belongs-to"` // id the account owning the muted status (can be the same as accountID) TargetAccountID string `pg:"type:CHAR(26),notnull"` + TargetAccount *Account `pg:"rel:has-one"` // database id of the status that has been muted StatusID string `pg:"type:CHAR(26),notnull"` + Status *Status `pg:"rel:has-one"` } diff --git a/internal/gtsmodel/user.go b/internal/gtsmodel/user.go index a1e912e99..fe8ebcabe 100644 --- a/internal/gtsmodel/user.go +++ b/internal/gtsmodel/user.go @@ -35,7 +35,8 @@ type User struct { // confirmed email address for this user, this should be unique -- only one email address registered per instance, multiple users per email are not supported Email string `pg:"default:null,unique"` // The id of the local gtsmodel.Account entry for this user, if it exists (unconfirmed users don't have an account yet) - AccountID string `pg:"type:CHAR(26),unique"` + AccountID string `pg:"type:CHAR(26),unique"` + Account *Account `pg:"rel:has-one"` // The encrypted password of this user, generated using https://pkg.go.dev/golang.org/x/crypto/bcrypt#GenerateFromPassword. A salt is included so we're safe against 🌈 tables EncryptedPassword string `pg:",notnull"` @@ -68,7 +69,8 @@ type User struct { // In what timezone/locale is this user located? Locale string // Which application id created this user? See gtsmodel.Application - CreatedByApplicationID string `pg:"type:CHAR(26)"` + CreatedByApplicationID string `pg:"type:CHAR(26)"` + CreatedByApplication *Application `pg:"rel:has-one"` // When did we last contact this user LastEmailedAt time.Time `pg:"type:timestamp"` diff --git a/internal/processing/account/createblock.go b/internal/processing/account/createblock.go index 798e9324f..13624c252 100644 --- a/internal/processing/account/createblock.go +++ b/internal/processing/account/createblock.go @@ -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 err == db.ErrNoEntries { - 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.Blocked(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) diff --git a/internal/processing/account/createfollow.go b/internal/processing/account/createfollow.go index 55d75fcc5..62640e03e 100644 --- a/internal/processing/account/createfollow.go +++ b/internal/processing/account/createfollow.go @@ -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.Blocked(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 { + 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.Follows(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.FollowRequested(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) } diff --git a/internal/processing/account/get.go b/internal/processing/account/get.go index 8cfd91cc2..ed6e27c94 100644 --- a/internal/processing/account/get.go +++ b/internal/processing/account/get.go @@ -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.Blocked(requestingAccount.ID, targetAccountID, true) if err != nil { return nil, fmt.Errorf("error checking account block: %s", err) } diff --git a/internal/processing/account/getfollowers.go b/internal/processing/account/getfollowers.go index 4f3617341..fddea5553 100644 --- a/internal/processing/account/getfollowers.go +++ b/internal/processing/account/getfollowers.go @@ -28,12 +28,9 @@ 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.Blocked(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")) } @@ -47,7 +44,7 @@ func (p *processor) FollowersGet(requestingAccount *gtsmodel.Account, targetAcco } for _, f := range followers { - blocked, err := p.db.Blocked(requestingAccount.ID, f.AccountID) + blocked, err := p.db.Blocked(requestingAccount.ID, f.AccountID, true) if err != nil { return nil, gtserror.NewErrorInternalError(err) } diff --git a/internal/processing/account/getfollowing.go b/internal/processing/account/getfollowing.go index 55e3e25cc..5f7693fbc 100644 --- a/internal/processing/account/getfollowing.go +++ b/internal/processing/account/getfollowing.go @@ -28,12 +28,9 @@ 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.Blocked(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")) } @@ -47,7 +44,7 @@ func (p *processor) FollowingGet(requestingAccount *gtsmodel.Account, targetAcco } for _, f := range following { - blocked, err := p.db.Blocked(requestingAccount.ID, f.AccountID) + blocked, err := p.db.Blocked(requestingAccount.ID, f.AccountID, true) if err != nil { return nil, gtserror.NewErrorInternalError(err) } diff --git a/internal/processing/account/getstatuses.go b/internal/processing/account/getstatuses.go index 64ad71a03..69a605d67 100644 --- a/internal/processing/account/getstatuses.go +++ b/internal/processing/account/getstatuses.go @@ -28,15 +28,14 @@ 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 err == db.ErrNoEntries { - return nil, gtserror.NewErrorNotFound(fmt.Errorf("no entry found for account id %s", targetAccountID)) - } + if blocked, err := p.db.Blocked(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.GetAccountStatuses(targetAccountID, limit, excludeReplies, maxID, pinnedOnly, mediaOnly) if err != nil { if err == db.ErrNoEntries { diff --git a/internal/processing/account/removeblock.go b/internal/processing/account/removeblock.go index 88a24eeef..7c1f2bc17 100644 --- a/internal/processing/account/removeblock.go +++ b/internal/processing/account/removeblock.go @@ -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 err == db.ErrNoEntries { - 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, } } diff --git a/internal/processing/account/removefollow.go b/internal/processing/account/removefollow.go index 21a0eca55..f05760c19 100644 --- a/internal/processing/account/removefollow.go +++ b/internal/processing/account/removefollow.go @@ -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.Blocked(requestingAccount.ID, targetAccountID, true) if err != nil { return nil, gtserror.NewErrorInternalError(err) } diff --git a/internal/processing/federation.go b/internal/processing/federation.go index 765fdf862..544ab3bc5 100644 --- a/internal/processing/federation.go +++ b/internal/processing/federation.go @@ -63,7 +63,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.Blocked(requestedAccount.ID, requestingAccount.ID, true) if err != nil { return nil, gtserror.NewErrorInternalError(err) } @@ -107,7 +107,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.Blocked(requestedAccount.ID, requestingAccount.ID, true) if err != nil { return nil, gtserror.NewErrorInternalError(err) } @@ -152,7 +152,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.Blocked(requestedAccount.ID, requestingAccount.ID, true) if err != nil { return nil, gtserror.NewErrorInternalError(err) } @@ -199,7 +199,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.Blocked(requestedAccount.ID, requestingAccount.ID, true) if err != nil { return nil, gtserror.NewErrorInternalError(err) } @@ -259,7 +259,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.Blocked(requestedAccount.ID, requestingAccount.ID, true) if err != nil { return nil, gtserror.NewErrorInternalError(err) } diff --git a/internal/processing/fromclientapi.go b/internal/processing/fromclientapi.go index 67db7b96a..beed283c1 100644 --- a/internal/processing/fromclientapi.go +++ b/internal/processing/fromclientapi.go @@ -192,14 +192,14 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error } // 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 } diff --git a/internal/processing/fromcommon.go b/internal/processing/fromcommon.go index a5d268613..80b18d4ac 100644 --- a/internal/processing/fromcommon.go +++ b/internal/processing/fromcommon.go @@ -30,35 +30,35 @@ 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 { + for _, m := range status.MentionIDs { 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) } - 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 { + if m.OriginAccount == nil { a := >smodel.Account{} if err := p.db.GetByID(m.TargetAccountID, a); 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.OriginAccount = a } - if m.GTSAccount.Domain != "" { + if m.OriginAccount.Domain != "" { // not a local account so skip it continue } @@ -103,7 +103,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.OriginAccount); err != nil { return fmt.Errorf("notifyStatus: error streaming notification to account: %s", err) } } diff --git a/internal/processing/fromfederator.go b/internal/processing/fromfederator.go index c75154d43..a294377ea 100644 --- a/internal/processing/fromfederator.go +++ b/internal/processing/fromfederator.go @@ -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 } diff --git a/internal/processing/media/getfile.go b/internal/processing/media/getfile.go index 1664306b8..adca406fe 100644 --- a/internal/processing/media/getfile.go +++ b/internal/processing/media/getfile.go @@ -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.Blocked(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)) } diff --git a/internal/processing/search.go b/internal/processing/search.go index c1cde8714..eb4958347 100644 --- a/internal/processing/search.go +++ b/internal/processing/search.go @@ -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.Blocked(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) diff --git a/internal/processing/status/boost.go b/internal/processing/status/boost.go index c21caf087..5f50517c9 100644 --- a/internal/processing/status/boost.go +++ b/internal/processing/status/boost.go @@ -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,13 +32,13 @@ 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.BoostOfAccount = targetAccount + boostWrapperStatus.BoostOfAccount = targetStatus.Account // put the boost in the database if err := p.db.Put(boostWrapperStatus); err != nil { @@ -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)) } diff --git a/internal/processing/status/boostedby.go b/internal/processing/status/boostedby.go index b352178e3..150e5e2b5 100644 --- a/internal/processing/status/boostedby.go +++ b/internal/processing/status/boostedby.go @@ -9,29 +9,21 @@ 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 @@ -43,7 +35,7 @@ func (p *processor) BoostedBy(account *gtsmodel.Account, targetStatusID string) // 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) + blocked, err := p.db.Blocked(requestingAccount.ID, acc.ID, true) if err != nil { return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error checking blocks: %s", err)) } diff --git a/internal/processing/status/context.go b/internal/processing/status/context.go index d342babb0..d4197f6ab 100644 --- a/internal/processing/status/context.go +++ b/internal/processing/status/context.go @@ -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 err == db.ErrNoEntries { - 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) 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) } @@ -57,8 +56,8 @@ func (p *processor) Context(account *gtsmodel.Account, targetStatusID string) (* } 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) } diff --git a/internal/processing/status/create.go b/internal/processing/status/create.go index 0e99b5f4a..30d7dcc88 100644 --- a/internal/processing/status/create.go +++ b/internal/processing/status/create.go @@ -81,7 +81,7 @@ func (p *processor) Create(account *gtsmodel.Account, application *gtsmodel.Appl } // change the status ID of the media attachments to the new status - for _, a := range newStatus.GTSMediaAttachments { + for _, a := range newStatus.Attachments { a.StatusID = newStatus.ID a.UpdatedAt = time.Now() if err := p.db.UpdateByID(a.ID, a); err != nil { diff --git a/internal/processing/status/delete.go b/internal/processing/status/delete.go index c73646af5..4c5dfd744 100644 --- a/internal/processing/status/delete.go +++ b/internal/processing/status/delete.go @@ -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 err != db.ErrNoEntries { - 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 diff --git a/internal/processing/status/fave.go b/internal/processing/status/fave.go index de789271a..7ba8c8fe8 100644 --- a/internal/processing/status/fave.go +++ b/internal/processing/status/fave.go @@ -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), - Status: targetStatus, - TargetAccount: targetAccount, - Account: 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)) } diff --git a/internal/processing/status/favedby.go b/internal/processing/status/favedby.go index 5194cc258..5ce2590ce 100644 --- a/internal/processing/status/favedby.go +++ b/internal/processing/status/favedby.go @@ -9,27 +9,19 @@ 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")) } @@ -43,7 +35,7 @@ func (p *processor) FavedBy(account *gtsmodel.Account, targetStatusID string) ([ // 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) + blocked, err := p.db.Blocked(requestingAccount.ID, acc.ID, true) if err != nil { return nil, gtserror.NewErrorInternalError(fmt.Errorf("error checking blocks: %s", err)) } @@ -52,8 +44,6 @@ func (p *processor) FavedBy(account *gtsmodel.Account, targetStatusID string) ([ } } - // 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 { diff --git a/internal/processing/status/get.go b/internal/processing/status/get.go index 9a70185b0..9d403b901 100644 --- a/internal/processing/status/get.go +++ b/internal/processing/status/get.go @@ -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 - } diff --git a/internal/processing/status/unboost.go b/internal/processing/status/unboost.go index 7a4ae5486..254cfe11f 100644 --- a/internal/processing/status/unboost.go +++ b/internal/processing/status/unboost.go @@ -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) @@ -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.Account = requestingAccount + gtsBoost.BoostOf = targetStatus - gtsBoost.BoostOf.Account = targetAccount - gtsBoost.BoostOfAccount = targetAccount - gtsBoost.Account = account + 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)) } diff --git a/internal/processing/status/unfave.go b/internal/processing/status/unfave.go index 82f43ee1f..d6e5320db 100644 --- a/internal/processing/status/unfave.go +++ b/internal/processing/status/unfave.go @@ -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,7 +31,7 @@ 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 @@ -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)) } diff --git a/internal/processing/status/util.go b/internal/processing/status/util.go index d700016e6..e26997b31 100644 --- a/internal/processing/status/util.go +++ b/internal/processing/status/util.go @@ -119,7 +119,7 @@ func (p *processor) ProcessReplyToID(form *apimodel.AdvancedStatusCreateForm, th 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 blocked, err := p.db.Blocked(thisAccountID, repliedAccount.ID, true); err != nil { if err != db.ErrNoEntries { return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err) } @@ -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) } diff --git a/internal/processing/status/util_test.go b/internal/processing/status/util_test.go index 4bf508848..9c282eb52 100644 --- a/internal/processing/status/util_test.go +++ b/internal/processing/status/util_test.go @@ -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() { diff --git a/internal/text/common.go b/internal/text/common.go index f6a5ca5f5..af77521dd 100644 --- a/internal/text/common.go +++ b/internal/text/common.go @@ -93,9 +93,9 @@ func (f *formatter) ReplaceMentions(in string, mentions []*gtsmodel.Mention) str // make sure we have a target account, either by getting one pinned on the mention, // or by pulling it from the database var targetAccount *gtsmodel.Account - if menchie.GTSAccount != nil { + if menchie.OriginAccount != nil { // got it from the mention - targetAccount = menchie.GTSAccount + targetAccount = menchie.OriginAccount } else { a := >smodel.Account{} if err := f.db.GetByID(menchie.TargetAccountID, a); err == nil { diff --git a/internal/typeutils/astointernal.go b/internal/typeutils/astointernal.go index d426b094e..4055dee2e 100644 --- a/internal/typeutils/astointernal.go +++ b/internal/typeutils/astointernal.go @@ -188,22 +188,22 @@ func (c *converter) ASStatusToStatus(statusable ap.Statusable) (*gtsmodel.Status // attachments to dereference and fetch later on (we don't do that here) if attachments, err := ap.ExtractAttachments(statusable); err == nil { - status.GTSMediaAttachments = attachments + status.Attachments = attachments } // hashtags to dereference later on if hashtags, err := ap.ExtractHashtags(statusable); err == nil { - status.GTSTags = hashtags + status.Tags = hashtags } // emojis to dereference and fetch later on if emojis, err := ap.ExtractEmojis(statusable); err == nil { - status.GTSEmojis = emojis + status.Emojis = emojis } // mentions to dereference later on if mentions, err := ap.ExtractMentions(statusable); err == nil { - status.GTSMentions = mentions + status.Mentions = mentions } // cw string for this status @@ -515,10 +515,10 @@ func (c *converter) ASAnnounceToStatus(announceable ap.Announceable) (*gtsmodel. status.AccountURI = boostingAccount.URI // these will all be wrapped in the boosted status so set them empty here - status.Attachments = []string{} - status.Tags = []string{} - status.Mentions = []string{} - status.Emojis = []string{} + status.AttachmentIDs = []string{} + status.TagIDs = []string{} + status.MentionIDs = []string{} + status.EmojiIDs = []string{} // parse the visibility from the To and CC entries var visibility gtsmodel.Visibility diff --git a/internal/typeutils/internal.go b/internal/typeutils/internal.go index ff9d60b8c..ad15ecbee 100644 --- a/internal/typeutils/internal.go +++ b/internal/typeutils/internal.go @@ -54,10 +54,10 @@ func (c *converter) StatusToBoost(s *gtsmodel.Status, boostingAccount *gtsmodel. InReplyToAccountID: "", // these will all be wrapped in the boosted status so set them empty here - Attachments: []string{}, - Tags: []string{}, - Mentions: []string{}, - Emojis: []string{}, + AttachmentIDs: []string{}, + TagIDs: []string{}, + MentionIDs: []string{}, + EmojiIDs: []string{}, // the below fields will be taken from the target status Content: s.Content, diff --git a/internal/typeutils/internaltoas.go b/internal/typeutils/internaltoas.go index 6126adedd..61ddef1c8 100644 --- a/internal/typeutils/internaltoas.go +++ b/internal/typeutils/internaltoas.go @@ -408,7 +408,7 @@ func (c *converter) StatusToAS(s *gtsmodel.Status) (vocab.ActivityStreamsNote, e tagProp := streams.NewActivityStreamsTagProperty() // tag -- mentions - for _, m := range s.GTSMentions { + for _, m := range s.Mentions { asMention, err := c.MentionToAS(m) if err != nil { return nil, fmt.Errorf("StatusToAS: error converting mention to AS mention: %s", err) @@ -441,10 +441,10 @@ func (c *converter) StatusToAS(s *gtsmodel.Status) (vocab.ActivityStreamsNote, e switch s.Visibility { case gtsmodel.VisibilityDirect: // if DIRECT, then only mentioned users should be added to TO, and nothing to CC - for _, m := range s.GTSMentions { - iri, err := url.Parse(m.GTSAccount.URI) + for _, m := range s.Mentions { + iri, err := url.Parse(m.OriginAccount.URI) if err != nil { - return nil, fmt.Errorf("StatusToAS: error parsing uri %s: %s", m.GTSAccount.URI, err) + return nil, fmt.Errorf("StatusToAS: error parsing uri %s: %s", m.OriginAccount.URI, err) } toProp.AppendIRI(iri) } @@ -453,10 +453,10 @@ func (c *converter) StatusToAS(s *gtsmodel.Status) (vocab.ActivityStreamsNote, e case gtsmodel.VisibilityFollowersOnly: // if FOLLOWERS ONLY then we want to add followers to TO, and mentions to CC toProp.AppendIRI(authorFollowersURI) - for _, m := range s.GTSMentions { - iri, err := url.Parse(m.GTSAccount.URI) + for _, m := range s.Mentions { + iri, err := url.Parse(m.OriginAccount.URI) if err != nil { - return nil, fmt.Errorf("StatusToAS: error parsing uri %s: %s", m.GTSAccount.URI, err) + return nil, fmt.Errorf("StatusToAS: error parsing uri %s: %s", m.OriginAccount.URI, err) } ccProp.AppendIRI(iri) } @@ -464,10 +464,10 @@ func (c *converter) StatusToAS(s *gtsmodel.Status) (vocab.ActivityStreamsNote, e // if UNLOCKED, we want to add followers to TO, and public and mentions to CC toProp.AppendIRI(authorFollowersURI) ccProp.AppendIRI(publicURI) - for _, m := range s.GTSMentions { - iri, err := url.Parse(m.GTSAccount.URI) + for _, m := range s.Mentions { + iri, err := url.Parse(m.OriginAccount.URI) if err != nil { - return nil, fmt.Errorf("StatusToAS: error parsing uri %s: %s", m.GTSAccount.URI, err) + return nil, fmt.Errorf("StatusToAS: error parsing uri %s: %s", m.OriginAccount.URI, err) } ccProp.AppendIRI(iri) } @@ -475,10 +475,10 @@ func (c *converter) StatusToAS(s *gtsmodel.Status) (vocab.ActivityStreamsNote, e // if PUBLIC, we want to add public to TO, and followers and mentions to CC toProp.AppendIRI(publicURI) ccProp.AppendIRI(authorFollowersURI) - for _, m := range s.GTSMentions { - iri, err := url.Parse(m.GTSAccount.URI) + for _, m := range s.Mentions { + iri, err := url.Parse(m.OriginAccount.URI) if err != nil { - return nil, fmt.Errorf("StatusToAS: error parsing uri %s: %s", m.GTSAccount.URI, err) + return nil, fmt.Errorf("StatusToAS: error parsing uri %s: %s", m.OriginAccount.URI, err) } ccProp.AppendIRI(iri) } @@ -496,7 +496,7 @@ func (c *converter) StatusToAS(s *gtsmodel.Status) (vocab.ActivityStreamsNote, e // attachment attachmentProp := streams.NewActivityStreamsAttachmentProperty() - for _, a := range s.GTSMediaAttachments { + for _, a := range s.Attachments { doc, err := c.AttachmentToAS(a) if err != nil { return nil, fmt.Errorf("StatusToAS: error converting attachment: %s", err) @@ -565,12 +565,12 @@ func (c *converter) FollowToAS(f *gtsmodel.Follow, originAccount *gtsmodel.Accou } func (c *converter) MentionToAS(m *gtsmodel.Mention) (vocab.ActivityStreamsMention, error) { - if m.GTSAccount == nil { + if m.OriginAccount == nil { a := >smodel.Account{} if err := c.db.GetWhere([]db.Where{{Key: "target_account_id", Value: m.TargetAccountID}}, a); err != nil { return nil, fmt.Errorf("MentionToAS: error getting target account from db: %s", err) } - m.GTSAccount = a + m.OriginAccount = a } // create the mention @@ -578,21 +578,21 @@ func (c *converter) MentionToAS(m *gtsmodel.Mention) (vocab.ActivityStreamsMenti // href -- this should be the URI of the mentioned user hrefProp := streams.NewActivityStreamsHrefProperty() - hrefURI, err := url.Parse(m.GTSAccount.URI) + hrefURI, err := url.Parse(m.OriginAccount.URI) if err != nil { - return nil, fmt.Errorf("MentionToAS: error parsing uri %s: %s", m.GTSAccount.URI, err) + return nil, fmt.Errorf("MentionToAS: error parsing uri %s: %s", m.OriginAccount.URI, err) } hrefProp.SetIRI(hrefURI) mention.SetActivityStreamsHref(hrefProp) // name -- this should be the namestring of the mentioned user, something like @whatever@example.org var domain string - if m.GTSAccount.Domain == "" { + if m.OriginAccount.Domain == "" { domain = c.config.AccountDomain } else { - domain = m.GTSAccount.Domain + domain = m.OriginAccount.Domain } - username := m.GTSAccount.Username + username := m.OriginAccount.Username nameString := fmt.Sprintf("@%s@%s", username, domain) nameProp := streams.NewActivityStreamsNameProperty() nameProp.AppendXMLSchemaString(nameString) diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index f8562c1ec..95bc3d3dc 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -357,8 +357,8 @@ func (c *converter) StatusToMasto(s *gtsmodel.Status, requestingAccount *gtsmode mastoAttachments := []model.Attachment{} // the status might already have some gts attachments on it if it's not been pulled directly from the database // if so, we can directly convert the gts attachments into masto ones - if s.GTSMediaAttachments != nil { - for _, gtsAttachment := range s.GTSMediaAttachments { + if s.Attachments != nil { + for _, gtsAttachment := range s.Attachments { mastoAttachment, err := c.AttachmentToMasto(gtsAttachment) if err != nil { return nil, fmt.Errorf("error converting attachment with id %s: %s", gtsAttachment.ID, err) @@ -368,7 +368,7 @@ func (c *converter) StatusToMasto(s *gtsmodel.Status, requestingAccount *gtsmode // the status doesn't have gts attachments on it, but it does have attachment IDs // in this case, we need to pull the gts attachments from the db to convert them into masto ones } else { - for _, a := range s.Attachments { + for _, a := range s.AttachmentIDs { gtsAttachment := >smodel.MediaAttachment{} if err := c.db.GetByID(a, gtsAttachment); err != nil { return nil, fmt.Errorf("error getting attachment with id %s: %s", a, err) @@ -384,8 +384,8 @@ func (c *converter) StatusToMasto(s *gtsmodel.Status, requestingAccount *gtsmode mastoMentions := []model.Mention{} // the status might already have some gts mentions on it if it's not been pulled directly from the database // if so, we can directly convert the gts mentions into masto ones - if s.GTSMentions != nil { - for _, gtsMention := range s.GTSMentions { + if s.Mentions != nil { + for _, gtsMention := range s.Mentions { mastoMention, err := c.MentionToMasto(gtsMention) if err != nil { return nil, fmt.Errorf("error converting mention with id %s: %s", gtsMention.ID, err) @@ -395,7 +395,7 @@ func (c *converter) StatusToMasto(s *gtsmodel.Status, requestingAccount *gtsmode // the status doesn't have gts mentions on it, but it does have mention IDs // in this case, we need to pull the gts mentions from the db to convert them into masto ones } else { - for _, m := range s.Mentions { + for _, m := range s.MentionIDs { gtsMention := >smodel.Mention{} if err := c.db.GetByID(m, gtsMention); err != nil { return nil, fmt.Errorf("error getting mention with id %s: %s", m, err) @@ -411,8 +411,8 @@ func (c *converter) StatusToMasto(s *gtsmodel.Status, requestingAccount *gtsmode mastoTags := []model.Tag{} // the status might already have some gts tags on it if it's not been pulled directly from the database // if so, we can directly convert the gts tags into masto ones - if s.GTSTags != nil { - for _, gtsTag := range s.GTSTags { + if s.Tags != nil { + for _, gtsTag := range s.Tags { mastoTag, err := c.TagToMasto(gtsTag) if err != nil { return nil, fmt.Errorf("error converting tag with id %s: %s", gtsTag.ID, err) @@ -422,7 +422,7 @@ func (c *converter) StatusToMasto(s *gtsmodel.Status, requestingAccount *gtsmode // the status doesn't have gts tags on it, but it does have tag IDs // in this case, we need to pull the gts tags from the db to convert them into masto ones } else { - for _, t := range s.Tags { + for _, t := range s.TagIDs { gtsTag := >smodel.Tag{} if err := c.db.GetByID(t, gtsTag); err != nil { return nil, fmt.Errorf("error getting tag with id %s: %s", t, err) @@ -438,8 +438,8 @@ func (c *converter) StatusToMasto(s *gtsmodel.Status, requestingAccount *gtsmode mastoEmojis := []model.Emoji{} // the status might already have some gts emojis on it if it's not been pulled directly from the database // if so, we can directly convert the gts emojis into masto ones - if s.GTSEmojis != nil { - for _, gtsEmoji := range s.GTSEmojis { + if s.Emojis != nil { + for _, gtsEmoji := range s.Emojis { mastoEmoji, err := c.EmojiToMasto(gtsEmoji) if err != nil { return nil, fmt.Errorf("error converting emoji with id %s: %s", gtsEmoji.ID, err) @@ -449,7 +449,7 @@ func (c *converter) StatusToMasto(s *gtsmodel.Status, requestingAccount *gtsmode // the status doesn't have gts emojis on it, but it does have emoji IDs // in this case, we need to pull the gts emojis from the db to convert them into masto ones } else { - for _, e := range s.Emojis { + for _, e := range s.EmojiIDs { gtsEmoji := >smodel.Emoji{} if err := c.db.GetByID(e, gtsEmoji); err != nil { return nil, fmt.Errorf("error getting emoji with id %s: %s", e, err) @@ -609,46 +609,46 @@ func (c *converter) RelationshipToMasto(r *gtsmodel.Relationship) (*model.Relati func (c *converter) NotificationToMasto(n *gtsmodel.Notification) (*model.Notification, error) { - if n.GTSTargetAccount == nil { + if n.TargetAccount == nil { tAccount := >smodel.Account{} if err := c.db.GetByID(n.TargetAccountID, tAccount); err != nil { return nil, fmt.Errorf("NotificationToMasto: error getting target account with id %s from the db: %s", n.TargetAccountID, err) } - n.GTSTargetAccount = tAccount + n.TargetAccount = tAccount } - if n.GTSOriginAccount == nil { + if n.OriginAccount == nil { ogAccount := >smodel.Account{} if err := c.db.GetByID(n.OriginAccountID, ogAccount); err != nil { return nil, fmt.Errorf("NotificationToMasto: error getting origin account with id %s from the db: %s", n.OriginAccountID, err) } - n.GTSOriginAccount = ogAccount + n.OriginAccount = ogAccount } - mastoAccount, err := c.AccountToMastoPublic(n.GTSOriginAccount) + mastoAccount, err := c.AccountToMastoPublic(n.OriginAccount) if err != nil { return nil, fmt.Errorf("NotificationToMasto: error converting account to masto: %s", err) } var mastoStatus *model.Status if n.StatusID != "" { - if n.GTSStatus == nil { + if n.Status == nil { status := >smodel.Status{} if err := c.db.GetByID(n.StatusID, status); err != nil { return nil, fmt.Errorf("NotificationToMasto: error getting status with id %s from the db: %s", n.StatusID, err) } - n.GTSStatus = status + n.Status = status } - if n.GTSStatus.Account == nil { - if n.GTSStatus.AccountID == n.GTSTargetAccount.ID { - n.GTSStatus.Account = n.GTSTargetAccount - } else if n.GTSStatus.AccountID == n.GTSOriginAccount.ID { - n.GTSStatus.Account = n.GTSOriginAccount + if n.Status.Account == nil { + if n.Status.AccountID == n.TargetAccount.ID { + n.Status.Account = n.TargetAccount + } else if n.Status.AccountID == n.OriginAccount.ID { + n.Status.Account = n.OriginAccount } } var err error - mastoStatus, err = c.StatusToMasto(n.GTSStatus, nil) + mastoStatus, err = c.StatusToMasto(n.Status, nil) if err != nil { return nil, fmt.Errorf("NotificationToMasto: error converting status to masto: %s", err) } diff --git a/internal/visibility/statusvisible.go b/internal/visibility/statusvisible.go index 638725e2b..1cbb1b9ca 100644 --- a/internal/visibility/statusvisible.go +++ b/internal/visibility/statusvisible.go @@ -102,7 +102,7 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount // At this point we have a populated targetAccount, targetStatus, and requestingAccount, so we can check for blocks and whathaveyou // First check if a block exists directly between the target account (which authored the status) and the requesting account. - if blocked, err := f.db.Blocked(targetAccount.ID, requestingAccount.ID); err != nil { + if blocked, err := f.db.Blocked(targetAccount.ID, requestingAccount.ID, true); err != nil { l.Debugf("something went wrong figuring out if the accounts have a block: %s", err) return false, err } else if blocked { @@ -113,7 +113,7 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount // status replies to account id if relevantAccounts.ReplyToAccount != nil && relevantAccounts.ReplyToAccount.ID != requestingAccount.ID { - if blocked, err := f.db.Blocked(relevantAccounts.ReplyToAccount.ID, requestingAccount.ID); err != nil { + if blocked, err := f.db.Blocked(relevantAccounts.ReplyToAccount.ID, requestingAccount.ID, true); err != nil { return false, err } else if blocked { l.Trace("a block exists between requesting account and reply to account") @@ -135,7 +135,7 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount // status boosts accounts id if relevantAccounts.BoostedStatusAuthor != nil { - if blocked, err := f.db.Blocked(relevantAccounts.BoostedStatusAuthor.ID, requestingAccount.ID); err != nil { + if blocked, err := f.db.Blocked(relevantAccounts.BoostedStatusAuthor.ID, requestingAccount.ID, true); err != nil { return false, err } else if blocked { l.Trace("a block exists between requesting account and boosted account") @@ -145,7 +145,7 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount // status boosts a reply to account id if relevantAccounts.BoostedReplyToAccount != nil { - if blocked, err := f.db.Blocked(relevantAccounts.BoostedReplyToAccount.ID, requestingAccount.ID); err != nil { + if blocked, err := f.db.Blocked(relevantAccounts.BoostedReplyToAccount.ID, requestingAccount.ID, true); err != nil { return false, err } else if blocked { l.Trace("a block exists between requesting account and boosted reply to account") @@ -155,7 +155,7 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount // status mentions accounts for _, a := range relevantAccounts.MentionedAccounts { - if blocked, err := f.db.Blocked(a.ID, requestingAccount.ID); err != nil { + if blocked, err := f.db.Blocked(a.ID, requestingAccount.ID, true); err != nil { return false, err } else if blocked { l.Trace("a block exists between requesting account and a mentioned account") @@ -165,7 +165,7 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount // boost mentions accounts for _, a := range relevantAccounts.BoostedMentionedAccounts { - if blocked, err := f.db.Blocked(a.ID, requestingAccount.ID); err != nil { + if blocked, err := f.db.Blocked(a.ID, requestingAccount.ID, true); err != nil { return false, err } else if blocked { l.Trace("a block exists between requesting account and a boosted mentioned account") diff --git a/internal/visibility/util.go b/internal/visibility/util.go index f004b4c23..914572446 100644 --- a/internal/visibility/util.go +++ b/internal/visibility/util.go @@ -13,28 +13,71 @@ func (f *filter) pullRelevantAccountsFromStatus(targetStatus *gtsmodel.Status) ( BoostedMentionedAccounts: []*gtsmodel.Account{}, } - // get the author account + // get the author account if it's not set on the status already if targetStatus.Account == nil { - statusAuthor := >smodel.Account{} - if err := f.db.GetByID(targetStatus.AccountID, statusAuthor); err != nil { + statusAuthor, err := f.db.GetAccountByID(targetStatus.AccountID) + if err != nil { return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting statusAuthor with id %s: %s", targetStatus.AccountID, err) } targetStatus.Account = statusAuthor } accounts.StatusAuthor = targetStatus.Account - // get the replied to account from the status and add it to the pile - if targetStatus.InReplyToAccountID != "" { - repliedToAccount := >smodel.Account{} - if err := f.db.GetByID(targetStatus.InReplyToAccountID, repliedToAccount); err != nil { + // get the replied to account if it's not set on the status already + if targetStatus.InReplyToAccountID != "" && targetStatus.InReplyToAccount == nil { + repliedToAccount, err := f.db.GetAccountByID(targetStatus.InReplyToAccountID) + if err != nil { return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting repliedToAcount with id %s: %s", targetStatus.InReplyToAccountID, err) } - accounts.ReplyToAccount = repliedToAccount + targetStatus.InReplyToAccount = repliedToAccount + } + accounts.ReplyToAccount = targetStatus.InReplyToAccount + + // get the boosted status if it's not set on the status already + if targetStatus.BoostOfID != "" && targetStatus.BoostOf == nil { + boostedStatus, err := f.db.GetStatusByID(targetStatus.BoostOfID) + if err != nil { + return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedStatus with id %s: %s", targetStatus.BoostOfID, err) + } + targetStatus.BoostOf = boostedStatus + } + + // get the boosted account if it's not set on the status already + if targetStatus.BoostOfAccountID != "" && targetStatus.BoostOfAccount == nil { + if targetStatus.BoostOf != nil && targetStatus.BoostOf.Account != nil { + targetStatus.BoostOfAccount = targetStatus.BoostOf.Account + } else { + boostedAccount, err := f.db.GetAccountByID(targetStatus.BoostOfAccountID) + if err != nil { + return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostOfAccount with id %s: %s", targetStatus.BoostOfAccountID, err) + } + targetStatus.BoostOfAccount = boostedAccount + } + } + accounts.BoostedStatusAuthor = targetStatus.BoostOfAccount + + if targetStatus.BoostOf != nil { + // the boosted status might be a reply to another account so we should get that too + if targetStatus.BoostOf.InReplyToAccountID != "" && targetStatus.BoostOf.InReplyToAccount == nil { + boostOfInReplyToAccount, err := f.db.GetAccountByID(targetStatus.BoostOf.InReplyToAccountID) + if err != nil { + return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostOfInReplyToAccount with id %s: %s", targetStatus.BoostOf.InReplyToAccountID, err) + } + targetStatus.BoostOf.InReplyToAccount = boostOfInReplyToAccount + } + + // now get all accounts with IDs that are mentioned in the status + if targetStatus.BoostOf.MentionIDs != nil && targetStatus.BoostOf.Mentions == nil { + mentions, err := f.db.GetMentions(targetStatus.BoostOf.MentionIDs) + if err != nil { + return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting mentions from boostOf status: %s", err) + } + targetStatus.BoostOf.Mentions = mentions + } } // now get all accounts with IDs that are mentioned in the status - for _, mentionID := range targetStatus.Mentions { - + for _, mentionID := range targetStatus.MentionIDs { mention := >smodel.Mention{} if err := f.db.GetByID(mentionID, mention); err != nil { return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting mention with id %s: %s", mentionID, err) @@ -47,43 +90,6 @@ func (f *filter) pullRelevantAccountsFromStatus(targetStatus *gtsmodel.Status) ( accounts.MentionedAccounts = append(accounts.MentionedAccounts, mentionedAccount) } - // get the boosted account from the status and add it to the pile - if targetStatus.BoostOfID != "" { - // retrieve the boosted status first - boostedStatus := >smodel.Status{} - if err := f.db.GetByID(targetStatus.BoostOfID, boostedStatus); err != nil { - return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedStatus with id %s: %s", targetStatus.BoostOfID, err) - } - boostedAccount := >smodel.Account{} - if err := f.db.GetByID(boostedStatus.AccountID, boostedAccount); err != nil { - return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedAccount with id %s: %s", boostedStatus.AccountID, err) - } - accounts.BoostedStatusAuthor = boostedAccount - - // the boosted status might be a reply to another account so we should get that too - if boostedStatus.InReplyToAccountID != "" { - boostedStatusRepliedToAccount := >smodel.Account{} - if err := f.db.GetByID(boostedStatus.InReplyToAccountID, boostedStatusRepliedToAccount); err != nil { - return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedStatusRepliedToAccount with id %s: %s", boostedStatus.InReplyToAccountID, err) - } - accounts.BoostedReplyToAccount = boostedStatusRepliedToAccount - } - - // now get all accounts with IDs that are mentioned in the status - for _, mentionID := range boostedStatus.Mentions { - mention := >smodel.Mention{} - if err := f.db.GetByID(mentionID, mention); err != nil { - return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boosted mention with id %s: %s", mentionID, err) - } - - mentionedAccount := >smodel.Account{} - if err := f.db.GetByID(mention.TargetAccountID, mentionedAccount); err != nil { - return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boosted mentioned account: %s", err) - } - accounts.BoostedMentionedAccounts = append(accounts.BoostedMentionedAccounts, mentionedAccount) - } - } - return accounts, nil } diff --git a/testrig/testmodels.go b/testrig/testmodels.go index 77274474c..5e1906629 100644 --- a/testrig/testmodels.go +++ b/testrig/testmodels.go @@ -793,10 +793,10 @@ func NewTestStatuses() map[string]*gtsmodel.Status { URI: "http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R", URL: "http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R", Content: "hello world! #welcome ! first post on the instance :rainbow: !", - Attachments: []string{"01F8MH6NEM8D7527KZAECTCR76"}, - Tags: []string{"01F8MHA1A2NF9MJ3WCCQ3K8BSZ"}, - Mentions: []string{}, - Emojis: []string{"01F8MH9H8E4VG3KDYJR9EGPXCQ"}, + AttachmentIDs: []string{"01F8MH6NEM8D7527KZAECTCR76"}, + TagIDs: []string{"01F8MHA1A2NF9MJ3WCCQ3K8BSZ"}, + MentionIDs: []string{}, + EmojiIDs: []string{"01F8MH9H8E4VG3KDYJR9EGPXCQ"}, CreatedAt: time.Now().Add(-71 * time.Hour), UpdatedAt: time.Now().Add(-71 * time.Hour), Local: true, @@ -917,7 +917,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { URI: "http://localhost:8080/users/the_mighty_zork/statuses/01F8MH82FYRXD2RC6108DAJ5HB", URL: "http://localhost:8080/@the_mighty_zork/statuses/01F8MH82FYRXD2RC6108DAJ5HB", Content: "here's a little gif of trent", - Attachments: []string{"01F8MH7TDVANYKWVE8VVKFPJTJ"}, + AttachmentIDs: []string{"01F8MH7TDVANYKWVE8VVKFPJTJ"}, CreatedAt: time.Now().Add(-1 * time.Hour), UpdatedAt: time.Now().Add(-1 * time.Hour), Local: true, @@ -942,7 +942,7 @@ func NewTestStatuses() map[string]*gtsmodel.Status { URI: "http://localhost:8080/users/the_mighty_zork/statuses/01FCTA44PW9H1TB328S9AQXKDS", URL: "http://localhost:8080/@the_mighty_zork/statuses/01FCTA44PW9H1TB328S9AQXKDS", Content: "hi!", - Attachments: []string{}, + AttachmentIDs: []string{}, CreatedAt: time.Now().Add(-1 * time.Minute), UpdatedAt: time.Now().Add(-1 * time.Minute), Local: true, @@ -1127,8 +1127,8 @@ func NewTestMentions() map[string]*gtsmodel.Mention { OriginAccountURI: "http://localhost:8080/users/the_mighty_zork", TargetAccountID: "01F8MH5ZK5VRH73AKHQM6Y9VNX", NameString: "@foss_satan@fossbros-anonymous.io", - MentionedAccountURI: "http://fossbros-anonymous.io/users/foss_satan", - MentionedAccountURL: "http://fossbros-anonymous.io/@foss_satan", + TargetAccountURI: "http://fossbros-anonymous.io/users/foss_satan", + TargetAccountURL: "http://fossbros-anonymous.io/@foss_satan", }, } }