mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-29 17:46:15 -06:00
more fiddling
This commit is contained in:
parent
15153ee0c8
commit
a3322b2bf3
65 changed files with 712 additions and 508 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package db
|
||||
|
||||
import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package 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
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ type DB interface {
|
|||
Admin
|
||||
Basic
|
||||
Instance
|
||||
Mention
|
||||
Notification
|
||||
Relationship
|
||||
Status
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package db
|
||||
|
||||
import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
|
|
|
|||
29
internal/db/mention.go
Normal file
29
internal/db/mention.go
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package db
|
||||
|
||||
import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
77
internal/db/pg/mention.go
Normal file
77
internal/db/pg/mention.go
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package db
|
||||
|
||||
import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package db
|
||||
|
||||
import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
|
|
|
|||
|
|
@ -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 == "" {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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?
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:"-"`
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -9,44 +9,27 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Get(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "StatusGet")
|
||||
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
func (p *processor) Get(requestingAccount *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account) // requestingAccount might well be nil here, but StatusVisible knows how to take care of that
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
||||
var boostOfStatus *gtsmodel.Status
|
||||
if targetStatus.BoostOfID != "" {
|
||||
boostOfStatus = >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatus.BoostOfID, boostOfStatus); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error fetching boosted status %s: %s", targetStatus.BoostOfID, err))
|
||||
}
|
||||
}
|
||||
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
|
||||
mastoStatus, err := p.tc.StatusToMasto(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
return mastoStatus, nil
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,27 +10,19 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (p *processor) Unboost(account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
l := p.log.WithField("func", "Unboost")
|
||||
|
||||
l.Tracef("going to search for target status %s", targetStatusID)
|
||||
targetStatus := >smodel.Status{}
|
||||
if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
|
||||
func (p *processor) Unboost(requestingAccount *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode) {
|
||||
targetStatus, err := p.db.GetStatusByID(targetStatusID)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
|
||||
}
|
||||
|
||||
l.Tracef("going to search for target account %s", targetStatus.AccountID)
|
||||
targetAccount := >smodel.Account{}
|
||||
if err := p.db.GetByID(targetStatus.AccountID, targetAccount); err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching target account %s: %s", targetStatus.AccountID, err))
|
||||
if targetStatus.Account == nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no status owner for status %s", targetStatusID))
|
||||
}
|
||||
|
||||
l.Trace("going to see if status is visible")
|
||||
visible, err := p.filter.StatusVisible(targetStatus, account)
|
||||
visible, err := p.filter.StatusVisible(targetStatus, requestingAccount)
|
||||
if err != nil {
|
||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
|
||||
}
|
||||
|
||||
if !visible {
|
||||
return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
|
||||
}
|
||||
|
|
@ -46,7 +38,7 @@ func (p *processor) Unboost(account *gtsmodel.Account, application *gtsmodel.App
|
|||
},
|
||||
{
|
||||
Key: "account_id",
|
||||
Value: account.ID,
|
||||
Value: requestingAccount.ID,
|
||||
},
|
||||
}
|
||||
err = p.db.GetWhere(where, gtsBoost)
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue