summaryrefslogtreecommitdiff
path: root/internal/processing/synchronous/status
diff options
context:
space:
mode:
Diffstat (limited to 'internal/processing/synchronous/status')
-rw-r--r--internal/processing/synchronous/status/boost.go73
-rw-r--r--internal/processing/synchronous/status/boostedby.go68
-rw-r--r--internal/processing/synchronous/status/context.go69
-rw-r--r--internal/processing/synchronous/status/create.go106
-rw-r--r--internal/processing/synchronous/status/delete.go55
-rw-r--r--internal/processing/synchronous/status/fave.go101
-rw-r--r--internal/processing/synchronous/status/favedby.go68
-rw-r--r--internal/processing/synchronous/status/get.go52
-rw-r--r--internal/processing/synchronous/status/status.go57
-rw-r--r--internal/processing/synchronous/status/unboost.go95
-rw-r--r--internal/processing/synchronous/status/unfave.go77
-rw-r--r--internal/processing/synchronous/status/util.go269
12 files changed, 0 insertions, 1090 deletions
diff --git a/internal/processing/synchronous/status/boost.go b/internal/processing/synchronous/status/boost.go
deleted file mode 100644
index 93d0f19de..000000000
--- a/internal/processing/synchronous/status/boost.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package status
-
-import (
- "errors"
- "fmt"
-
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
- "github.com/superseriousbusiness/gotosocial/internal/gtserror"
- "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 := &gtsmodel.Status{}
- if err := p.db.GetByID(targetStatusID, targetStatus); 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 := &gtsmodel.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))
- }
-
- l.Trace("going to see if status is visible")
- visible, err := p.filter.StatusVisible(targetStatus, account)
- 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"))
- }
- }
-
- // it's visible! it's boostable! so let's boost the FUCK out of it
- boostWrapperStatus, err := p.tc.StatusToBoost(targetStatus, account)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- boostWrapperStatus.CreatedWithApplicationID = application.ID
- boostWrapperStatus.GTSBoostedAccount = targetAccount
-
- // put the boost in the database
- if err := p.db.Put(boostWrapperStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // send it back to the processor for async processing
- p.fromClientAPI <- gtsmodel.FromClientAPI{
- APObjectType: gtsmodel.ActivityStreamsAnnounce,
- APActivityType: gtsmodel.ActivityStreamsCreate,
- GTSModel: boostWrapperStatus,
- OriginAccount: account,
- TargetAccount: targetAccount,
- }
-
- // return the frontend representation of the new status to the submitter
- mastoStatus, err := p.tc.StatusToMasto(boostWrapperStatus, account)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
- }
-
- return mastoStatus, nil
-}
diff --git a/internal/processing/synchronous/status/boostedby.go b/internal/processing/synchronous/status/boostedby.go
deleted file mode 100644
index b352178e3..000000000
--- a/internal/processing/synchronous/status/boostedby.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package status
-
-import (
- "errors"
- "fmt"
-
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
- "github.com/superseriousbusiness/gotosocial/internal/gtserror"
- "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 := &gtsmodel.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 := &gtsmodel.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)
- if err != nil {
- return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error seeing if status %s is visible: %s", targetStatus.ID, err))
- }
-
- if !visible {
- return nil, gtserror.NewErrorNotFound(errors.New("StatusBoostedBy: status is not visible"))
- }
-
- // get ALL accounts that faved a status -- doesn't take account of blocks and mutes and stuff
- favingAccounts, err := p.db.WhoBoostedStatus(targetStatus)
- if err != nil {
- return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error seeing who boosted status: %s", err))
- }
-
- // filter the list so the user doesn't see accounts they blocked or which blocked them
- filteredAccounts := []*gtsmodel.Account{}
- for _, acc := range favingAccounts {
- blocked, err := p.db.Blocked(account.ID, acc.ID)
- if err != nil {
- return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error checking blocks: %s", err))
- }
- if !blocked {
- filteredAccounts = append(filteredAccounts, acc)
- }
- }
-
- // 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 {
- mastoAccount, err := p.tc.AccountToMastoPublic(acc)
- if err != nil {
- return nil, gtserror.NewErrorNotFound(fmt.Errorf("StatusFavedBy: error converting account to api model: %s", err))
- }
- mastoAccounts = append(mastoAccounts, mastoAccount)
- }
-
- return mastoAccounts, nil
-}
diff --git a/internal/processing/synchronous/status/context.go b/internal/processing/synchronous/status/context.go
deleted file mode 100644
index 72b9b5623..000000000
--- a/internal/processing/synchronous/status/context.go
+++ /dev/null
@@ -1,69 +0,0 @@
-package status
-
-import (
- "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) {
-
- context := &apimodel.Context{
- Ancestors: []apimodel.Status{},
- Descendants: []apimodel.Status{},
- }
-
- targetStatus := &gtsmodel.Status{}
- if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
- if _, ok := err.(db.ErrNoEntries); ok {
- return nil, gtserror.NewErrorNotFound(err)
- }
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- visible, err := p.filter.StatusVisible(targetStatus, account)
- if err != nil {
- return nil, gtserror.NewErrorNotFound(err)
- }
- if !visible {
- return nil, gtserror.NewErrorForbidden(fmt.Errorf("account with id %s does not have permission to view status %s", account.ID, targetStatusID))
- }
-
- parents, err := p.db.StatusParents(targetStatus)
- 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 err == nil {
- context.Ancestors = append(context.Ancestors, *mastoStatus)
- }
- }
- }
-
- sort.Slice(context.Ancestors, func(i int, j int) bool {
- return context.Ancestors[i].ID < context.Ancestors[j].ID
- })
-
- children, err := p.db.StatusChildren(targetStatus)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- for _, status := range children {
- if v, err := p.filter.StatusVisible(status, account); err == nil && v {
- mastoStatus, err := p.tc.StatusToMasto(status, account)
- if err == nil {
- context.Descendants = append(context.Descendants, *mastoStatus)
- }
- }
- }
-
- return context, nil
-}
diff --git a/internal/processing/synchronous/status/create.go b/internal/processing/synchronous/status/create.go
deleted file mode 100644
index aa7468ae5..000000000
--- a/internal/processing/synchronous/status/create.go
+++ /dev/null
@@ -1,106 +0,0 @@
-package status
-
-import (
- "fmt"
- "time"
-
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
- "github.com/superseriousbusiness/gotosocial/internal/gtserror"
- "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
- "github.com/superseriousbusiness/gotosocial/internal/id"
- "github.com/superseriousbusiness/gotosocial/internal/util"
-)
-
-func (p *processor) Create(account *gtsmodel.Account, application *gtsmodel.Application, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, gtserror.WithCode) {
- uris := util.GenerateURIsForAccount(account.Username, p.config.Protocol, p.config.Host)
- thisStatusID, err := id.NewULID()
- if err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
- thisStatusURI := fmt.Sprintf("%s/%s", uris.StatusesURI, thisStatusID)
- thisStatusURL := fmt.Sprintf("%s/%s", uris.StatusesURL, thisStatusID)
-
- newStatus := &gtsmodel.Status{
- ID: thisStatusID,
- URI: thisStatusURI,
- URL: thisStatusURL,
- CreatedAt: time.Now(),
- UpdatedAt: time.Now(),
- Local: true,
- AccountID: account.ID,
- AccountURI: account.URI,
- ContentWarning: form.SpoilerText,
- ActivityStreamsType: gtsmodel.ActivityStreamsNote,
- Sensitive: form.Sensitive,
- Language: form.Language,
- CreatedWithApplicationID: application.ID,
- Text: form.Status,
- }
-
- // check if replyToID is ok
- if err := p.processReplyToID(form, account.ID, newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // check if mediaIDs are ok
- if err := p.processMediaIDs(form, account.ID, newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // check if visibility settings are ok
- if err := p.processVisibility(form, account.Privacy, newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // handle language settings
- if err := p.processLanguage(form, account.Language, newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // handle mentions
- if err := p.processMentions(form, account.ID, newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- if err := p.processTags(form, account.ID, newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- if err := p.processEmojis(form, account.ID, newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- if err := p.processContent(form, account.ID, newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // put the new status in the database, generating an ID for it in the process
- if err := p.db.Put(newStatus); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // change the status ID of the media attachments to the new status
- for _, a := range newStatus.GTSMediaAttachments {
- a.StatusID = newStatus.ID
- a.UpdatedAt = time.Now()
- if err := p.db.UpdateByID(a.ID, a); err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
- }
-
- // send it back to the processor for async processing
- p.fromClientAPI <- gtsmodel.FromClientAPI{
- APObjectType: gtsmodel.ActivityStreamsNote,
- APActivityType: gtsmodel.ActivityStreamsCreate,
- GTSModel: newStatus,
- OriginAccount: account,
- }
-
- // return the frontend representation of the new status to the submitter
- mastoStatus, err := p.tc.StatusToMasto(newStatus, account)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", newStatus.ID, err))
- }
-
- return mastoStatus, nil
-}
diff --git a/internal/processing/synchronous/status/delete.go b/internal/processing/synchronous/status/delete.go
deleted file mode 100644
index 5da196a9f..000000000
--- a/internal/processing/synchronous/status/delete.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package status
-
-import (
- "errors"
- "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 := &gtsmodel.Status{}
- if err := p.db.GetByID(targetStatusID, targetStatus); err != nil {
- if _, ok := err.(db.ErrNoEntries); !ok {
- return nil, gtserror.NewErrorNotFound(fmt.Errorf("error fetching status %s: %s", targetStatusID, err))
- }
- // status is already gone
- return nil, nil
- }
-
- if targetStatus.AccountID != account.ID {
- return nil, gtserror.NewErrorForbidden(errors.New("status doesn't belong to requesting account"))
- }
-
- var boostOfStatus *gtsmodel.Status
- if targetStatus.BoostOfID != "" {
- boostOfStatus = &gtsmodel.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)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
- }
-
- if err := p.db.DeleteByID(targetStatus.ID, &gtsmodel.Status{}); err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error deleting status from the database: %s", err))
- }
-
- // send it back to the processor for async processing
- p.fromClientAPI <- gtsmodel.FromClientAPI{
- APObjectType: gtsmodel.ActivityStreamsNote,
- APActivityType: gtsmodel.ActivityStreamsDelete,
- GTSModel: targetStatus,
- OriginAccount: account,
- }
-
- return mastoStatus, nil
-}
diff --git a/internal/processing/synchronous/status/fave.go b/internal/processing/synchronous/status/fave.go
deleted file mode 100644
index 23f0d2944..000000000
--- a/internal/processing/synchronous/status/fave.go
+++ /dev/null
@@ -1,101 +0,0 @@
-package status
-
-import (
- "errors"
- "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"
- "github.com/superseriousbusiness/gotosocial/internal/id"
- "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 := &gtsmodel.Status{}
- if err := p.db.GetByID(targetStatusID, targetStatus); 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 := &gtsmodel.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))
- }
-
- var boostOfStatus *gtsmodel.Status
- if targetStatus.BoostOfID != "" {
- boostOfStatus = &gtsmodel.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
- 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"))
- }
- }
-
- // first check if the status is already faved, if so we don't need to do anything
- newFave := true
- gtsFave := &gtsmodel.StatusFave{}
- if err := p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: account.ID}}, gtsFave); err == nil {
- // we already have a fave for this status
- newFave = false
- }
-
- if newFave {
- thisFaveID, err := id.NewRandomULID()
- if err != nil {
- return nil, gtserror.NewErrorInternalError(err)
- }
-
- // we need to create a new fave in the database
- gtsFave := &gtsmodel.StatusFave{
- ID: thisFaveID,
- AccountID: account.ID,
- TargetAccountID: targetAccount.ID,
- StatusID: targetStatus.ID,
- URI: util.GenerateURIForLike(account.Username, p.config.Protocol, p.config.Host, thisFaveID),
- GTSStatus: targetStatus,
- GTSTargetAccount: targetAccount,
- GTSFavingAccount: account,
- }
-
- if err := p.db.Put(gtsFave); err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error putting fave in database: %s", err))
- }
-
- // send it back to the processor for async processing
- p.fromClientAPI <- gtsmodel.FromClientAPI{
- APObjectType: gtsmodel.ActivityStreamsLike,
- APActivityType: gtsmodel.ActivityStreamsCreate,
- GTSModel: gtsFave,
- OriginAccount: account,
- TargetAccount: targetAccount,
- }
- }
-
- // return the mastodon representation of the target status
- mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
- }
-
- return mastoStatus, nil
-}
diff --git a/internal/processing/synchronous/status/favedby.go b/internal/processing/synchronous/status/favedby.go
deleted file mode 100644
index 5194cc258..000000000
--- a/internal/processing/synchronous/status/favedby.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package status
-
-import (
- "errors"
- "fmt"
-
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
- "github.com/superseriousbusiness/gotosocial/internal/gtserror"
- "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 := &gtsmodel.Status{}
- if err := p.db.GetByID(targetStatusID, targetStatus); 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 := &gtsmodel.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))
- }
-
- l.Trace("going to see if status is visible")
- visible, err := p.filter.StatusVisible(targetStatus, account)
- if err != nil {
- return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing if status %s is visible: %s", targetStatus.ID, err))
- }
-
- if !visible {
- return nil, gtserror.NewErrorNotFound(errors.New("status is not visible"))
- }
-
- // get ALL accounts that faved a status -- doesn't take account of blocks and mutes and stuff
- favingAccounts, err := p.db.WhoFavedStatus(targetStatus)
- if err != nil {
- return nil, gtserror.NewErrorNotFound(fmt.Errorf("error seeing who faved status: %s", err))
- }
-
- // filter the list so the user doesn't see accounts they blocked or which blocked them
- filteredAccounts := []*gtsmodel.Account{}
- for _, acc := range favingAccounts {
- blocked, err := p.db.Blocked(account.ID, acc.ID)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error checking blocks: %s", err))
- }
- if !blocked {
- filteredAccounts = append(filteredAccounts, acc)
- }
- }
-
- // 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 {
- mastoAccount, err := p.tc.AccountToMastoPublic(acc)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
- }
- mastoAccounts = append(mastoAccounts, mastoAccount)
- }
-
- return mastoAccounts, nil
-}
diff --git a/internal/processing/synchronous/status/get.go b/internal/processing/synchronous/status/get.go
deleted file mode 100644
index 9a70185b0..000000000
--- a/internal/processing/synchronous/status/get.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package status
-
-import (
- "errors"
- "fmt"
-
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
- "github.com/superseriousbusiness/gotosocial/internal/gtserror"
- "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 := &gtsmodel.Status{}
- if err := p.db.GetByID(targetStatusID, targetStatus); 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 := &gtsmodel.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))
- }
-
- 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
- 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 = &gtsmodel.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)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
- }
-
- return mastoStatus, nil
-
-}
diff --git a/internal/processing/synchronous/status/status.go b/internal/processing/synchronous/status/status.go
deleted file mode 100644
index d83c325fd..000000000
--- a/internal/processing/synchronous/status/status.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package status
-
-import (
- "github.com/sirupsen/logrus"
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
- "github.com/superseriousbusiness/gotosocial/internal/config"
- "github.com/superseriousbusiness/gotosocial/internal/db"
- "github.com/superseriousbusiness/gotosocial/internal/gtserror"
- "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
- "github.com/superseriousbusiness/gotosocial/internal/typeutils"
- "github.com/superseriousbusiness/gotosocial/internal/visibility"
-)
-
-// Processor wraps a bunch of functions for processing statuses.
-type Processor interface {
- // Create processes the given form to create a new status, returning the api model representation of that status if it's OK.
- Create(account *gtsmodel.Account, application *gtsmodel.Application, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, gtserror.WithCode)
- // Delete processes the delete of a given status, returning the deleted status if the delete goes through.
- Delete(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
- // Fave processes the faving of a given status, returning the updated status if the fave goes through.
- Fave(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
- // Boost processes the boost/reblog of a given status, returning the newly-created boost if all is well.
- Boost(account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
- // Unboost processes the unboost/unreblog of a given status, returning the status if all is well.
- Unboost(account *gtsmodel.Account, application *gtsmodel.Application, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
- // BoostedBy returns a slice of accounts that have boosted the given status, filtered according to privacy settings.
- BoostedBy(account *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode)
- // FavedBy returns a slice of accounts that have liked the given status, filtered according to privacy settings.
- FavedBy(account *gtsmodel.Account, targetStatusID string) ([]*apimodel.Account, gtserror.WithCode)
- // Get gets the given status, taking account of privacy settings and blocks etc.
- Get(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
- // Unfave processes the unfaving of a given status, returning the updated status if the fave goes through.
- Unfave(account *gtsmodel.Account, targetStatusID string) (*apimodel.Status, gtserror.WithCode)
- // Context returns the context (previous and following posts) from the given status ID
- Context(account *gtsmodel.Account, targetStatusID string) (*apimodel.Context, gtserror.WithCode)
-}
-
-type processor struct {
- tc typeutils.TypeConverter
- config *config.Config
- db db.DB
- filter visibility.Filter
- fromClientAPI chan gtsmodel.FromClientAPI
- log *logrus.Logger
-}
-
-// New returns a new status processor.
-func New(db db.DB, tc typeutils.TypeConverter, config *config.Config, fromClientAPI chan gtsmodel.FromClientAPI, log *logrus.Logger) Processor {
- return &processor{
- tc: tc,
- config: config,
- db: db,
- filter: visibility.NewFilter(db, log),
- fromClientAPI: fromClientAPI,
- log: log,
- }
-}
diff --git a/internal/processing/synchronous/status/unboost.go b/internal/processing/synchronous/status/unboost.go
deleted file mode 100644
index 2a1394695..000000000
--- a/internal/processing/synchronous/status/unboost.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package status
-
-import (
- "errors"
- "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) 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 := &gtsmodel.Status{}
- if err := p.db.GetByID(targetStatusID, targetStatus); 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 := &gtsmodel.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))
- }
-
- l.Trace("going to see if status is visible")
- visible, err := p.filter.StatusVisible(targetStatus, account)
- 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"))
- }
-
- // check if we actually have a boost for this status
- var toUnboost bool
-
- gtsBoost := &gtsmodel.Status{}
- where := []db.Where{
- {
- Key: "boost_of_id",
- Value: targetStatusID,
- },
- {
- Key: "account_id",
- Value: account.ID,
- },
- }
- err = p.db.GetWhere(where, gtsBoost)
- if err == nil {
- // we have a boost
- toUnboost = true
- }
-
- if err != nil {
- // something went wrong in the db finding the boost
- if _, ok := err.(db.ErrNoEntries); !ok {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error fetching existing boost from database: %s", err))
- }
- // we just don't have a boost
- toUnboost = false
- }
-
- if toUnboost {
- // we had a boost, so take some action to get rid of it
- if err := p.db.DeleteWhere(where, &gtsmodel.Status{}); err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error unboosting status: %s", err))
- }
-
- // pin some stuff onto the boost while we have it out of the db
- gtsBoost.GTSBoostedStatus = targetStatus
- gtsBoost.GTSBoostedStatus.GTSAuthorAccount = targetAccount
- gtsBoost.GTSBoostedAccount = targetAccount
- gtsBoost.GTSAuthorAccount = account
-
- // 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,
- }
- }
-
- mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
- }
-
- return mastoStatus, nil
-}
diff --git a/internal/processing/synchronous/status/unfave.go b/internal/processing/synchronous/status/unfave.go
deleted file mode 100644
index b51daacb9..000000000
--- a/internal/processing/synchronous/status/unfave.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package status
-
-import (
- "errors"
- "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) 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 := &gtsmodel.Status{}
- if err := p.db.GetByID(targetStatusID, targetStatus); 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 := &gtsmodel.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))
- }
-
- l.Trace("going to see if status is visible")
- visible, err := p.filter.StatusVisible(targetStatus, account)
- 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"))
- }
-
- // check if we actually have a fave for this status
- var toUnfave bool
-
- gtsFave := &gtsmodel.StatusFave{}
- err = p.db.GetWhere([]db.Where{{Key: "status_id", Value: targetStatus.ID}, {Key: "account_id", Value: account.ID}}, gtsFave)
- if err == nil {
- // we have a fave
- toUnfave = true
- }
- if err != nil {
- // something went wrong in the db finding the fave
- if _, ok := err.(db.ErrNoEntries); !ok {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error fetching existing fave from database: %s", err))
- }
- // we just don't have a fave
- toUnfave = false
- }
-
- 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 {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error unfaveing status: %s", err))
- }
-
- // send it back to the processor for async processing
- p.fromClientAPI <- gtsmodel.FromClientAPI{
- APObjectType: gtsmodel.ActivityStreamsLike,
- APActivityType: gtsmodel.ActivityStreamsUndo,
- GTSModel: gtsFave,
- OriginAccount: account,
- TargetAccount: targetAccount,
- }
- }
-
- mastoStatus, err := p.tc.StatusToMasto(targetStatus, account)
- if err != nil {
- return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status %s to frontend representation: %s", targetStatus.ID, err))
- }
-
- return mastoStatus, nil
-}
diff --git a/internal/processing/synchronous/status/util.go b/internal/processing/synchronous/status/util.go
deleted file mode 100644
index 0a023eab6..000000000
--- a/internal/processing/synchronous/status/util.go
+++ /dev/null
@@ -1,269 +0,0 @@
-package status
-
-import (
- "errors"
- "fmt"
- "strings"
-
- apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
- "github.com/superseriousbusiness/gotosocial/internal/db"
- "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
- "github.com/superseriousbusiness/gotosocial/internal/id"
- "github.com/superseriousbusiness/gotosocial/internal/util"
-)
-
-func (p *processor) processVisibility(form *apimodel.AdvancedStatusCreateForm, accountDefaultVis gtsmodel.Visibility, status *gtsmodel.Status) error {
- // by default all flags are set to true
- gtsAdvancedVis := &gtsmodel.VisibilityAdvanced{
- Federated: true,
- Boostable: true,
- Replyable: true,
- Likeable: true,
- }
-
- var gtsBasicVis gtsmodel.Visibility
- // Advanced takes priority if it's set.
- // If it's not set, take whatever masto visibility is set.
- // If *that's* not set either, then just take the account default.
- // If that's also not set, take the default for the whole instance.
- if form.VisibilityAdvanced != nil {
- gtsBasicVis = gtsmodel.Visibility(*form.VisibilityAdvanced)
- } else if form.Visibility != "" {
- gtsBasicVis = p.tc.MastoVisToVis(form.Visibility)
- } else if accountDefaultVis != "" {
- gtsBasicVis = accountDefaultVis
- } else {
- gtsBasicVis = gtsmodel.VisibilityDefault
- }
-
- switch gtsBasicVis {
- case gtsmodel.VisibilityPublic:
- // for public, there's no need to change any of the advanced flags from true regardless of what the user filled out
- break
- case gtsmodel.VisibilityUnlocked:
- // for unlocked the user can set any combination of flags they like so look at them all to see if they're set and then apply them
- if form.Federated != nil {
- gtsAdvancedVis.Federated = *form.Federated
- }
-
- if form.Boostable != nil {
- gtsAdvancedVis.Boostable = *form.Boostable
- }
-
- if form.Replyable != nil {
- gtsAdvancedVis.Replyable = *form.Replyable
- }
-
- if form.Likeable != nil {
- gtsAdvancedVis.Likeable = *form.Likeable
- }
-
- case gtsmodel.VisibilityFollowersOnly, gtsmodel.VisibilityMutualsOnly:
- // for followers or mutuals only, boostable will *always* be false, but the other fields can be set so check and apply them
- gtsAdvancedVis.Boostable = false
-
- if form.Federated != nil {
- gtsAdvancedVis.Federated = *form.Federated
- }
-
- if form.Replyable != nil {
- gtsAdvancedVis.Replyable = *form.Replyable
- }
-
- if form.Likeable != nil {
- gtsAdvancedVis.Likeable = *form.Likeable
- }
-
- case gtsmodel.VisibilityDirect:
- // direct is pretty easy: there's only one possible setting so return it
- gtsAdvancedVis.Federated = true
- gtsAdvancedVis.Boostable = false
- gtsAdvancedVis.Federated = true
- gtsAdvancedVis.Likeable = true
- }
-
- status.Visibility = gtsBasicVis
- status.VisibilityAdvanced = gtsAdvancedVis
- return nil
-}
-
-func (p *processor) processReplyToID(form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error {
- if form.InReplyToID == "" {
- return nil
- }
-
- // If this status is a reply to another status, we need to do a bit of work to establish whether or not this status can be posted:
- //
- // 1. Does the replied status exist in the database?
- // 2. Is the replied status marked as replyable?
- // 3. Does a block exist between either the current account or the account that posted the status it's replying to?
- //
- // If this is all OK, then we fetch the repliedStatus and the repliedAccount for later processing.
- repliedStatus := &gtsmodel.Status{}
- repliedAccount := &gtsmodel.Account{}
- // check replied status exists + is replyable
- if err := p.db.GetByID(form.InReplyToID, repliedStatus); err != nil {
- if _, ok := err.(db.ErrNoEntries); ok {
- return fmt.Errorf("status with id %s not replyable because it doesn't exist", form.InReplyToID)
- }
- return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err)
- }
-
- if repliedStatus.VisibilityAdvanced != nil {
- if !repliedStatus.VisibilityAdvanced.Replyable {
- return fmt.Errorf("status with id %s is marked as not replyable", form.InReplyToID)
- }
- }
-
- // check replied account is known to us
- if err := p.db.GetByID(repliedStatus.AccountID, repliedAccount); err != nil {
- if _, ok := err.(db.ErrNoEntries); ok {
- return fmt.Errorf("status with id %s not replyable because account id %s is not known", form.InReplyToID, repliedStatus.AccountID)
- }
- return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err)
- }
- // check if a block exists
- if blocked, err := p.db.Blocked(thisAccountID, repliedAccount.ID); err != nil {
- if _, ok := err.(db.ErrNoEntries); !ok {
- return fmt.Errorf("status with id %s not replyable: %s", form.InReplyToID, err)
- }
- } else if blocked {
- return fmt.Errorf("status with id %s not replyable", form.InReplyToID)
- }
- status.InReplyToID = repliedStatus.ID
- status.InReplyToAccountID = repliedAccount.ID
-
- return nil
-}
-
-func (p *processor) processMediaIDs(form *apimodel.AdvancedStatusCreateForm, thisAccountID string, status *gtsmodel.Status) error {
- if form.MediaIDs == nil {
- return nil
- }
-
- gtsMediaAttachments := []*gtsmodel.MediaAttachment{}
- attachments := []string{}
- for _, mediaID := range form.MediaIDs {
- // check these attachments exist
- a := &gtsmodel.MediaAttachment{}
- if err := p.db.GetByID(mediaID, a); err != nil {
- return fmt.Errorf("invalid media type or media not found for media id %s", mediaID)
- }
- // check they belong to the requesting account id
- if a.AccountID != thisAccountID {
- return fmt.Errorf("media with id %s does not belong to account %s", mediaID, thisAccountID)
- }
- // check they're not already used in a status
- if a.StatusID != "" || a.ScheduledStatusID != "" {
- return fmt.Errorf("media with id %s is already attached to a status", mediaID)
- }
- gtsMediaAttachments = append(gtsMediaAttachments, a)
- attachments = append(attachments, a.ID)
- }
- status.GTSMediaAttachments = gtsMediaAttachments
- status.Attachments = attachments
- return nil
-}
-
-func (p *processor) processLanguage(form *apimodel.AdvancedStatusCreateForm, accountDefaultLanguage string, status *gtsmodel.Status) error {
- if form.Language != "" {
- status.Language = form.Language
- } else {
- status.Language = accountDefaultLanguage
- }
- if status.Language == "" {
- return errors.New("no language given either in status create form or account default")
- }
- return nil
-}
-
-func (p *processor) processMentions(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
- menchies := []string{}
- gtsMenchies, err := p.db.MentionStringsToMentions(util.DeriveMentionsFromStatus(form.Status), accountID, status.ID)
- if err != nil {
- return fmt.Errorf("error generating mentions from status: %s", err)
- }
- for _, menchie := range gtsMenchies {
- menchieID, err := id.NewRandomULID()
- if err != nil {
- return err
- }
- menchie.ID = menchieID
-
- if err := p.db.Put(menchie); err != nil {
- return fmt.Errorf("error putting mentions in db: %s", err)
- }
- menchies = append(menchies, menchie.ID)
- }
- // add full populated gts menchies to the status for passing them around conveniently
- status.GTSMentions = gtsMenchies
- // add just the ids of the mentioned accounts to the status for putting in the db
- status.Mentions = menchies
- return nil
-}
-
-func (p *processor) processTags(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
- tags := []string{}
- gtsTags, err := p.db.TagStringsToTags(util.DeriveHashtagsFromStatus(form.Status), accountID, status.ID)
- if err != nil {
- return fmt.Errorf("error generating hashtags from status: %s", err)
- }
- for _, tag := range gtsTags {
- if err := p.db.Upsert(tag, "name"); err != nil {
- return fmt.Errorf("error putting tags in db: %s", err)
- }
- tags = append(tags, tag.ID)
- }
- // add full populated gts tags to the status for passing them around conveniently
- status.GTSTags = gtsTags
- // add just the ids of the used tags to the status for putting in the db
- status.Tags = tags
- return nil
-}
-
-func (p *processor) processEmojis(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
- emojis := []string{}
- gtsEmojis, err := p.db.EmojiStringsToEmojis(util.DeriveEmojisFromStatus(form.Status), accountID, status.ID)
- if err != nil {
- return fmt.Errorf("error generating emojis from status: %s", err)
- }
- for _, e := range gtsEmojis {
- emojis = append(emojis, e.ID)
- }
- // add full populated gts emojis to the status for passing them around conveniently
- status.GTSEmojis = gtsEmojis
- // add just the ids of the used emojis to the status for putting in the db
- status.Emojis = emojis
- return nil
-}
-
-func (p *processor) processContent(form *apimodel.AdvancedStatusCreateForm, accountID string, status *gtsmodel.Status) error {
- if form.Status == "" {
- status.Content = ""
- return nil
- }
-
- // surround the whole status in '<p>'
- content := fmt.Sprintf(`<p>%s</p>`, form.Status)
-
- // format mentions nicely
- for _, menchie := range status.GTSMentions {
- targetAccount := &gtsmodel.Account{}
- if err := p.db.GetByID(menchie.TargetAccountID, targetAccount); err == nil {
- mentionContent := fmt.Sprintf(`<span class="h-card"><a href="%s" class="u-url mention">@<span>%s</span></a></span>`, targetAccount.URL, targetAccount.Username)
- content = strings.ReplaceAll(content, menchie.NameString, mentionContent)
- }
- }
-
- // format tags nicely
- for _, tag := range status.GTSTags {
- tagContent := fmt.Sprintf(`<a href="%s" class="mention hashtag" rel="tag">#<span>%s</span></a>`, tag.URL, tag.Name)
- content = strings.ReplaceAll(content, fmt.Sprintf("#%s", tag.Name), tagContent)
- }
-
- // replace newlines with breaks
- content = strings.ReplaceAll(content, "\n", "<br />")
-
- status.Content = content
- return nil
-}