mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-16 15:33:02 -06:00
improve blocking stuff
This commit is contained in:
parent
861cc1dff1
commit
f4dc4d0aa0
19 changed files with 270 additions and 22 deletions
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||
)
|
||||
|
||||
// AccountBlockPOSTHandler handles the creation of a block from the authed account targeting the given account ID.
|
||||
func (m *Module) AccountBlockPOSTHandler(c *gin.Context) {
|
||||
authed, err := oauth.Authed(c, true, true, true, true)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||
)
|
||||
|
||||
// AccountUnblockPOSTHandler handles the removal of a block from the authed account targeting the given account ID.
|
||||
func (m *Module) AccountUnblockPOSTHandler(c *gin.Context) {
|
||||
authed, err := oauth.Authed(c, true, true, true, true)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -393,6 +393,7 @@ func (f *federator) DereferenceAnnounce(announce *gtsmodel.Status, requestingUse
|
|||
announce.Language = boostedStatus.Language
|
||||
announce.Text = boostedStatus.Text
|
||||
announce.BoostOfID = boostedStatus.ID
|
||||
announce.BoostOfAccountID = boostedStatus.AccountID
|
||||
announce.Visibility = boostedStatus.Visibility
|
||||
announce.VisibilityAdvanced = boostedStatus.VisibilityAdvanced
|
||||
announce.GTSBoostedStatus = boostedStatus
|
||||
|
|
@ -477,6 +478,7 @@ func (f *federator) DereferenceAnnounce(announce *gtsmodel.Status, requestingUse
|
|||
announce.Language = boostedStatus.Language
|
||||
announce.Text = boostedStatus.Text
|
||||
announce.BoostOfID = boostedStatus.ID
|
||||
announce.BoostOfAccountID = boostedStatus.AccountID
|
||||
announce.Visibility = boostedStatus.Visibility
|
||||
announce.VisibilityAdvanced = boostedStatus.VisibilityAdvanced
|
||||
announce.GTSBoostedStatus = boostedStatus
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ type Status struct {
|
|||
InReplyToAccountID string `pg:"type:CHAR(26)"`
|
||||
// id of the status this status is a boost of
|
||||
BoostOfID string `pg:"type:CHAR(26)"`
|
||||
// id of the account that owns the boosted status
|
||||
BoostOfAccountID string `pg:"type:CHAR(26)"`
|
||||
// cw string for this status
|
||||
ContentWarning string
|
||||
// visibility entry for this status
|
||||
|
|
|
|||
|
|
@ -45,9 +45,19 @@ func (p *processor) Get(requestingAccount *gtsmodel.Account, targetAccountID str
|
|||
p.log.WithField("func", "AccountGet").Debugf("dereferencing account: %s", err)
|
||||
}
|
||||
|
||||
var mastoAccount *apimodel.Account
|
||||
var blocked bool
|
||||
var err error
|
||||
if requestingAccount != nil && targetAccount.ID == requestingAccount.ID {
|
||||
if requestingAccount != nil {
|
||||
blocked, err = p.db.Blocked(requestingAccount.ID, targetAccountID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error checking account block: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
var mastoAccount *apimodel.Account
|
||||
if blocked {
|
||||
mastoAccount, err = p.tc.AccountToMastoBlocked(targetAccount)
|
||||
} else if requestingAccount != nil && targetAccount.ID == requestingAccount.ID {
|
||||
mastoAccount, err = p.tc.AccountToMastoSensitive(targetAccount)
|
||||
} else {
|
||||
mastoAccount, err = p.tc.AccountToMastoPublic(targetAccount)
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func (p *processor) BlocksGet(authed *oauth.Auth, maxID string, sinceID string,
|
|||
|
||||
apiAccounts := []*apimodel.Account{}
|
||||
for _, a := range accounts {
|
||||
apiAccount, err := p.tc.AccountToMastoPublic(a)
|
||||
apiAccount, err := p.tc.AccountToMastoBlocked(a)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,7 +99,14 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error
|
|||
return errors.New("block was not parseable as *gtsmodel.Block")
|
||||
}
|
||||
|
||||
// TODO: remove any of the blocking account's statuses from the blocked account's timeline
|
||||
// remove any of the blocking account's statuses from the blocked account's timeline, and vice versa
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(block.AccountID, block.TargetAccountID); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(block.TargetAccountID, block.AccountID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: same with notifications
|
||||
// TODO: same with bookmarks
|
||||
|
||||
|
|
|
|||
|
|
@ -129,8 +129,18 @@ func (p *processor) processFromFederator(federatorMsg gtsmodel.FromFederator) er
|
|||
}
|
||||
case gtsmodel.ActivityStreamsBlock:
|
||||
// CREATE A BLOCK
|
||||
block, ok := federatorMsg.GTSModel.(*gtsmodel.Block)
|
||||
if !ok {
|
||||
return errors.New("block was not parseable as *gtsmodel.Block")
|
||||
}
|
||||
|
||||
// TODO: remove any of the blocking account's statuses from the blocked account's timeline
|
||||
// remove any of the blocking account's statuses from the blocked account's timeline, and vice versa
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(block.AccountID, block.TargetAccountID); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.timelineManager.WipeStatusesFromAccountID(block.TargetAccountID, block.AccountID); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: same with notifications
|
||||
// TODO: same with bookmarks
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 timeline
|
||||
|
||||
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 timeline
|
||||
|
||||
import (
|
||||
|
|
@ -44,7 +62,7 @@ grabloop:
|
|||
}
|
||||
|
||||
for _, s := range filtered {
|
||||
if _, err := t.IndexOne(s.CreatedAt, s.ID, s.BoostOfID); err != nil {
|
||||
if _, err := t.IndexOne(s.CreatedAt, s.ID, s.BoostOfID, s.AccountID, s.BoostOfAccountID); err != nil {
|
||||
return fmt.Errorf("IndexBefore: error indexing status with id %s: %s", s.ID, err)
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +97,7 @@ grabloop:
|
|||
}
|
||||
|
||||
for _, s := range filtered {
|
||||
if _, err := t.IndexOne(s.CreatedAt, s.ID, s.BoostOfID); err != nil {
|
||||
if _, err := t.IndexOne(s.CreatedAt, s.ID, s.BoostOfID, s.AccountID, s.BoostOfAccountID); err != nil {
|
||||
return fmt.Errorf("IndexBehind: error indexing status with id %s: %s", s.ID, err)
|
||||
}
|
||||
}
|
||||
|
|
@ -91,24 +109,29 @@ func (t *timeline) IndexOneByID(statusID string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (t *timeline) IndexOne(statusCreatedAt time.Time, statusID string, boostOfID string) (bool, error) {
|
||||
func (t *timeline) IndexOne(statusCreatedAt time.Time, statusID string, boostOfID string, accountID string, boostOfAccountID string) (bool, error) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
postIndexEntry := &postIndexEntry{
|
||||
statusID: statusID,
|
||||
boostOfID: boostOfID,
|
||||
accountID: accountID,
|
||||
boostOfAccountID: boostOfAccountID,
|
||||
}
|
||||
|
||||
return t.postIndex.insertIndexed(postIndexEntry)
|
||||
}
|
||||
|
||||
func (t *timeline) IndexAndPrepareOne(statusCreatedAt time.Time, statusID string) (bool, error) {
|
||||
func (t *timeline) IndexAndPrepareOne(statusCreatedAt time.Time, statusID string, boostOfID string, accountID string, boostOfAccountID string) (bool, error) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
postIndexEntry := &postIndexEntry{
|
||||
statusID: statusID,
|
||||
boostOfID: boostOfID,
|
||||
accountID: accountID,
|
||||
boostOfAccountID: boostOfAccountID,
|
||||
}
|
||||
|
||||
inserted, err := t.postIndex.insertIndexed(postIndexEntry)
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ type Manager interface {
|
|||
Remove(statusID string, timelineAccountID string) (int, error)
|
||||
// WipeStatusFromAllTimelines removes one status from the index and prepared posts of all timelines
|
||||
WipeStatusFromAllTimelines(statusID string) error
|
||||
// WipeStatusesFromAccountID removes all statuses by the given accountID from the timelineAccountID's timelines.
|
||||
WipeStatusesFromAccountID(accountID string, timelineAccountID string) error
|
||||
}
|
||||
|
||||
// NewManager returns a new timeline manager with the given database, typeconverter, config, and log.
|
||||
|
|
@ -112,7 +114,7 @@ func (m *manager) Ingest(status *gtsmodel.Status, timelineAccountID string) (boo
|
|||
}
|
||||
|
||||
l.Trace("ingesting status")
|
||||
return t.IndexOne(status.CreatedAt, status.ID, status.BoostOfID)
|
||||
return t.IndexOne(status.CreatedAt, status.ID, status.BoostOfID, status.AccountID, status.BoostOfAccountID)
|
||||
}
|
||||
|
||||
func (m *manager) IngestAndPrepare(status *gtsmodel.Status, timelineAccountID string) (bool, error) {
|
||||
|
|
@ -128,7 +130,7 @@ func (m *manager) IngestAndPrepare(status *gtsmodel.Status, timelineAccountID st
|
|||
}
|
||||
|
||||
l.Trace("ingesting status")
|
||||
return t.IndexAndPrepareOne(status.CreatedAt, status.ID)
|
||||
return t.IndexAndPrepareOne(status.CreatedAt, status.ID, status.BoostOfID, status.AccountID, status.BoostOfAccountID)
|
||||
}
|
||||
|
||||
func (m *manager) Remove(statusID string, timelineAccountID string) (int, error) {
|
||||
|
|
@ -219,6 +221,16 @@ func (m *manager) WipeStatusFromAllTimelines(statusID string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (m *manager) WipeStatusesFromAccountID(accountID string, timelineAccountID string) error {
|
||||
t, err := m.getOrCreateTimeline(timelineAccountID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = t.RemoveAllBy(accountID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *manager) getOrCreateTimeline(timelineAccountID string) (Timeline, error) {
|
||||
var t Timeline
|
||||
i, ok := m.accountTimelines.Load(timelineAccountID)
|
||||
|
|
|
|||
|
|
@ -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 timeline
|
||||
|
||||
import (
|
||||
|
|
@ -12,6 +30,8 @@ type postIndex struct {
|
|||
type postIndexEntry struct {
|
||||
statusID string
|
||||
boostOfID string
|
||||
accountID string
|
||||
boostOfAccountID string
|
||||
}
|
||||
|
||||
func (p *postIndex) insertIndexed(i *postIndexEntry) (bool, error) {
|
||||
|
|
|
|||
|
|
@ -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 timeline
|
||||
|
||||
import (
|
||||
|
|
@ -207,7 +225,10 @@ func (t *timeline) prepare(statusID string) error {
|
|||
|
||||
// shove it in prepared posts as a prepared posts entry
|
||||
preparedPostsEntry := &preparedPostsEntry{
|
||||
statusID: statusID,
|
||||
statusID: gtsStatus.ID,
|
||||
boostOfID: gtsStatus.BoostOfID,
|
||||
accountID: gtsStatus.AccountID,
|
||||
boostOfAccountID: gtsStatus.BoostOfAccountID,
|
||||
prepared: apiModelStatus,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 timeline
|
||||
|
||||
import (
|
||||
|
|
@ -13,6 +31,9 @@ type preparedPosts struct {
|
|||
|
||||
type preparedPostsEntry struct {
|
||||
statusID string
|
||||
boostOfID string
|
||||
accountID string
|
||||
boostOfAccountID string
|
||||
prepared *apimodel.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 timeline
|
||||
|
||||
import (
|
||||
|
|
@ -58,3 +76,55 @@ func (t *timeline) Remove(statusID string) (int, error) {
|
|||
l.Debugf("removed %d entries", removed)
|
||||
return removed, nil
|
||||
}
|
||||
|
||||
func (t *timeline) RemoveAllBy(accountID string) (int, error) {
|
||||
l := t.log.WithFields(logrus.Fields{
|
||||
"func": "RemoveAllBy",
|
||||
"accountTimeline": t.accountID,
|
||||
"accountID": accountID,
|
||||
})
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
var removed int
|
||||
|
||||
// remove entr(ies) from the post index
|
||||
removeIndexes := []*list.Element{}
|
||||
if t.postIndex != nil && t.postIndex.data != nil {
|
||||
for e := t.postIndex.data.Front(); e != nil; e = e.Next() {
|
||||
entry, ok := e.Value.(*postIndexEntry)
|
||||
if !ok {
|
||||
return removed, errors.New("Remove: could not parse e as a postIndexEntry")
|
||||
}
|
||||
if entry.accountID == accountID || entry.boostOfAccountID == accountID {
|
||||
l.Debug("found status in postIndex")
|
||||
removeIndexes = append(removeIndexes, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, e := range removeIndexes {
|
||||
t.postIndex.data.Remove(e)
|
||||
removed = removed + 1
|
||||
}
|
||||
|
||||
// remove entr(ies) from prepared posts
|
||||
removePrepared := []*list.Element{}
|
||||
if t.preparedPosts != nil && t.preparedPosts.data != nil {
|
||||
for e := t.preparedPosts.data.Front(); e != nil; e = e.Next() {
|
||||
entry, ok := e.Value.(*preparedPostsEntry)
|
||||
if !ok {
|
||||
return removed, errors.New("Remove: could not parse e as a preparedPostsEntry")
|
||||
}
|
||||
if entry.accountID == accountID || entry.boostOfAccountID == accountID {
|
||||
l.Debug("found status in preparedPosts")
|
||||
removePrepared = append(removePrepared, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, e := range removePrepared {
|
||||
t.preparedPosts.data.Remove(e)
|
||||
removed = removed + 1
|
||||
}
|
||||
|
||||
l.Debugf("removed %d entries", removed)
|
||||
return removed, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ type Timeline interface {
|
|||
//
|
||||
// The returned bool indicates whether or not the status was actually inserted into the timeline. This will be false
|
||||
// if the status is a boost and the original post or another boost of it already exists < boostReinsertionDepth back in the timeline.
|
||||
IndexOne(statusCreatedAt time.Time, statusID string, boostOfID string) (bool, error)
|
||||
IndexOne(statusCreatedAt time.Time, statusID string, boostOfID string, accountID string, boostOfAccountID string) (bool, error)
|
||||
|
||||
// OldestIndexedPostID returns the id of the rearmost (ie., the oldest) indexed post, or an error if something goes wrong.
|
||||
// If nothing goes wrong but there's no oldest post, an empty string will be returned so make sure to check for this.
|
||||
|
|
@ -85,7 +85,7 @@ type Timeline interface {
|
|||
//
|
||||
// The returned bool indicates whether or not the status was actually inserted into the timeline. This will be false
|
||||
// if the status is a boost and the original post or another boost of it already exists < boostReinsertionDepth back in the timeline.
|
||||
IndexAndPrepareOne(statusCreatedAt time.Time, statusID string) (bool, error)
|
||||
IndexAndPrepareOne(statusCreatedAt time.Time, statusID string, boostOfID string, accountID string, boostOfAccountID string) (bool, error)
|
||||
// OldestPreparedPostID returns the id of the rearmost (ie., the oldest) prepared post, or an error if something goes wrong.
|
||||
// If nothing goes wrong but there's no oldest post, an empty string will be returned so make sure to check for this.
|
||||
OldestPreparedPostID() (string, error)
|
||||
|
|
@ -109,6 +109,10 @@ type Timeline interface {
|
|||
//
|
||||
// The returned int indicates the amount of entries that were removed.
|
||||
Remove(statusID string) (int, error)
|
||||
// RemoveAllBy removes all statuses by the given accountID, from both the index and prepared posts.
|
||||
//
|
||||
// The returned int indicates the amount of entries that were removed.
|
||||
RemoveAllBy(accountID string) (int, error)
|
||||
}
|
||||
|
||||
// timeline fulfils the Timeline interface
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ type TypeConverter interface {
|
|||
// if something goes wrong. The returned account should be ready to serialize on an API level, and may NOT have sensitive fields.
|
||||
// In other words, this is the public record that the server has of an account.
|
||||
AccountToMastoPublic(account *gtsmodel.Account) (*model.Account, error)
|
||||
// AccountToMastoBlocked takes a db model account as a param, and returns a mastotype account, or an error if
|
||||
// something goes wrong. The returned account will be a bare minimum representation of the account. This function should be used
|
||||
// when someone wants to view an account they've blocked.
|
||||
AccountToMastoBlocked(account *gtsmodel.Account) (*model.Account, error)
|
||||
// AppToMastoSensitive takes a db model application as a param, and returns a populated mastotype application, or an error
|
||||
// if something goes wrong. The returned application should be ready to serialize on an API level, and may have sensitive fields
|
||||
// (such as client id and client secret), so serve it only to an authorized user who should have permission to see it.
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ func (c *converter) StatusToBoost(s *gtsmodel.Status, boostingAccount *gtsmodel.
|
|||
Language: s.Language,
|
||||
Text: s.Text,
|
||||
BoostOfID: s.ID,
|
||||
BoostOfAccountID: s.AccountID,
|
||||
Visibility: s.Visibility,
|
||||
VisibilityAdvanced: s.VisibilityAdvanced,
|
||||
|
||||
|
|
|
|||
|
|
@ -173,6 +173,27 @@ func (c *converter) AccountToMastoPublic(a *gtsmodel.Account) (*model.Account, e
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (c *converter) AccountToMastoBlocked(a *gtsmodel.Account) (*model.Account, error) {
|
||||
var acct string
|
||||
if a.Domain != "" {
|
||||
// this is a remote user
|
||||
acct = fmt.Sprintf("%s@%s", a.Username, a.Domain)
|
||||
} else {
|
||||
// this is a local user
|
||||
acct = a.Username
|
||||
}
|
||||
|
||||
return &model.Account{
|
||||
ID: a.ID,
|
||||
Username: a.Username,
|
||||
Acct: acct,
|
||||
DisplayName: a.Username,
|
||||
Bot: a.Bot,
|
||||
CreatedAt: a.CreatedAt.Format(time.RFC3339),
|
||||
URL: a.URL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *converter) AppToMastoSensitive(a *gtsmodel.Application) (*model.Application, error) {
|
||||
return &model.Application{
|
||||
ID: a.ID,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue