summaryrefslogtreecommitdiff
path: root/internal/processing
diff options
context:
space:
mode:
authorLibravatar Tobi Smethurst <31960611+tsmethurst@users.noreply.github.com>2021-05-31 17:36:35 +0200
committerLibravatar GitHub <noreply@github.com>2021-05-31 17:36:35 +0200
commit6ac6f8d614d17910d929981bde7d80d8ec2c0b6e (patch)
treee7a51ba572a7cc880bbc22dacb999236ac6e36e6 /internal/processing
parentMove a lot of stuff + tidy stuff (#37) (diff)
downloadgotosocial-6ac6f8d614d17910d929981bde7d80d8ec2c0b6e.tar.xz
Tidy + timeline embetterment (#38)
* tidy up timelines a bit + stub out some endpoints * who's faved and who's boosted, reblog notifs * linting * Update progress with new endpoints
Diffstat (limited to 'internal/processing')
-rw-r--r--internal/processing/fromcommon.go49
-rw-r--r--internal/processing/notification.go4
-rw-r--r--internal/processing/processor.go8
-rw-r--r--internal/processing/status.go68
-rw-r--r--internal/processing/timeline.go27
5 files changed, 151 insertions, 5 deletions
diff --git a/internal/processing/fromcommon.go b/internal/processing/fromcommon.go
index cb38d4bb4..bdb2a599b 100644
--- a/internal/processing/fromcommon.go
+++ b/internal/processing/fromcommon.go
@@ -160,5 +160,54 @@ func (p *processor) notifyFave(fave *gtsmodel.StatusFave, receivingAccount *gtsm
}
func (p *processor) notifyAnnounce(status *gtsmodel.Status) error {
+ if status.BoostOfID == "" {
+ // not a boost, nothing to do
+ return nil
+ }
+
+ boostedStatus := &gtsmodel.Status{}
+ if err := p.db.GetByID(status.BoostOfID, boostedStatus); err != nil {
+ return fmt.Errorf("notifyAnnounce: error getting status with id %s: %s", status.BoostOfID, err)
+ }
+
+ boostedAcct := &gtsmodel.Account{}
+ if err := p.db.GetByID(boostedStatus.AccountID, boostedAcct); err != nil {
+ return fmt.Errorf("notifyAnnounce: error getting account with id %s: %s", boostedStatus.AccountID, err)
+ }
+
+ if boostedAcct.Domain != "" {
+ // remote account, nothing to do
+ return nil
+ }
+
+ if boostedStatus.AccountID == status.AccountID {
+ // it's a self boost, nothing to do
+ return nil
+ }
+
+ // make sure a notif doesn't already exist for this announce
+ err := p.db.GetWhere([]db.Where{
+ {Key: "notification_type", Value: gtsmodel.NotificationReblog},
+ {Key: "target_account_id", Value: boostedAcct.ID},
+ {Key: "origin_account_id", Value: status.AccountID},
+ {Key: "status_id", Value: status.ID},
+ }, &gtsmodel.Notification{})
+ if err == nil {
+ // notification exists already so just bail
+ return nil
+ }
+
+ // now create the new reblog notification
+ notif := &gtsmodel.Notification{
+ NotificationType: gtsmodel.NotificationReblog,
+ TargetAccountID: boostedAcct.ID,
+ OriginAccountID: status.AccountID,
+ StatusID: status.ID,
+ }
+
+ if err := p.db.Put(notif); err != nil {
+ return fmt.Errorf("notifyAnnounce: error putting notification in database: %s", err)
+ }
+
return nil
}
diff --git a/internal/processing/notification.go b/internal/processing/notification.go
index 36cd81b91..44e3885b5 100644
--- a/internal/processing/notification.go
+++ b/internal/processing/notification.go
@@ -23,10 +23,10 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
-func (p *processor) NotificationsGet(authed *oauth.Auth, limit int, maxID string) ([]*apimodel.Notification, ErrorWithCode) {
+func (p *processor) NotificationsGet(authed *oauth.Auth, limit int, maxID string, sinceID string) ([]*apimodel.Notification, ErrorWithCode) {
l := p.log.WithField("func", "NotificationsGet")
- notifs, err := p.db.GetNotificationsForAccount(authed.Account.ID, limit, maxID)
+ notifs, err := p.db.GetNotificationsForAccount(authed.Account.ID, limit, maxID, sinceID)
if err != nil {
return nil, NewErrorInternalError(err)
}
diff --git a/internal/processing/processor.go b/internal/processing/processor.go
index 58b64afab..b31c37be3 100644
--- a/internal/processing/processor.go
+++ b/internal/processing/processor.go
@@ -107,7 +107,7 @@ type Processor interface {
MediaUpdate(authed *oauth.Auth, attachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, ErrorWithCode)
// NotificationsGet
- NotificationsGet(authed *oauth.Auth, limit int, maxID string) ([]*apimodel.Notification, ErrorWithCode)
+ NotificationsGet(authed *oauth.Auth, limit int, maxID string, sinceID string) ([]*apimodel.Notification, ErrorWithCode)
// SearchGet performs a search with the given params, resolving/dereferencing remotely as desired
SearchGet(authed *oauth.Auth, searchQuery *apimodel.SearchQuery) (*apimodel.SearchResult, ErrorWithCode)
@@ -120,15 +120,21 @@ type Processor interface {
StatusFave(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error)
// StatusBoost processes the boost/reblog of a given status, returning the newly-created boost if all is well.
StatusBoost(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, ErrorWithCode)
+ // StatusBoostedBy returns a slice of accounts that have boosted the given status, filtered according to privacy settings.
+ StatusBoostedBy(authed *oauth.Auth, targetStatusID string) ([]*apimodel.Account, ErrorWithCode)
// StatusFavedBy returns a slice of accounts that have liked the given status, filtered according to privacy settings.
StatusFavedBy(authed *oauth.Auth, targetStatusID string) ([]*apimodel.Account, error)
// StatusGet gets the given status, taking account of privacy settings and blocks etc.
StatusGet(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error)
// StatusUnfave processes the unfaving of a given status, returning the updated status if the fave goes through.
StatusUnfave(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error)
+ // StatusGetContext returns the context (previous and following posts) from the given status ID
+ StatusGetContext(authed *oauth.Auth, targetStatusID string) (*apimodel.Context, ErrorWithCode)
// HomeTimelineGet returns statuses from the home timeline, with the given filters/parameters.
HomeTimelineGet(authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) ([]apimodel.Status, ErrorWithCode)
+ // PublicTimelineGet returns statuses from the public/local timeline, with the given filters/parameters.
+ PublicTimelineGet(authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) ([]apimodel.Status, ErrorWithCode)
/*
FEDERATION API-FACING PROCESSING FUNCTIONS
diff --git a/internal/processing/status.go b/internal/processing/status.go
index 7530f386a..897972839 100644
--- a/internal/processing/status.go
+++ b/internal/processing/status.go
@@ -309,6 +309,70 @@ func (p *processor) StatusBoost(authed *oauth.Auth, targetStatusID string) (*api
return mastoStatus, nil
}
+func (p *processor) StatusBoostedBy(authed *oauth.Auth, targetStatusID string) ([]*apimodel.Account, ErrorWithCode) {
+ 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, 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, NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error fetching target account %s: %s", targetStatus.AccountID, err))
+ }
+
+ l.Trace("going to get relevant accounts")
+ relevantAccounts, err := p.db.PullRelevantAccountsFromStatus(targetStatus)
+ if err != nil {
+ return nil, NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error fetching related accounts for status %s: %s", targetStatusID, err))
+ }
+
+ l.Trace("going to see if status is visible")
+ visible, err := p.db.StatusVisible(targetStatus, targetAccount, authed.Account, relevantAccounts) // requestingAccount might well be nil here, but StatusVisible knows how to take care of that
+ if err != nil {
+ return nil, NewErrorNotFound(fmt.Errorf("StatusBoostedBy: error seeing if status %s is visible: %s", targetStatus.ID, err))
+ }
+
+ if !visible {
+ return nil, 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, 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(authed.Account.ID, acc.ID)
+ if err != nil {
+ return nil, 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, NewErrorNotFound(fmt.Errorf("StatusFavedBy: error converting account to api model: %s", err))
+ }
+ mastoAccounts = append(mastoAccounts, mastoAccount)
+ }
+
+ return mastoAccounts, nil
+}
+
func (p *processor) StatusFavedBy(authed *oauth.Auth, targetStatusID string) ([]*apimodel.Account, error) {
l := p.log.WithField("func", "StatusFavedBy")
@@ -479,3 +543,7 @@ func (p *processor) StatusUnfave(authed *oauth.Auth, targetStatusID string) (*ap
return mastoStatus, nil
}
+
+func (p *processor) StatusGetContext(authed *oauth.Auth, targetStatusID string) (*apimodel.Context, ErrorWithCode) {
+ return &apimodel.Context{}, nil
+}
diff --git a/internal/processing/timeline.go b/internal/processing/timeline.go
index b7c8e5dc7..7de2d63a9 100644
--- a/internal/processing/timeline.go
+++ b/internal/processing/timeline.go
@@ -28,13 +28,36 @@ import (
)
func (p *processor) HomeTimelineGet(authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) ([]apimodel.Status, ErrorWithCode) {
- l := p.log.WithField("func", "HomeTimelineGet")
-
statuses, err := p.db.GetHomeTimelineForAccount(authed.Account.ID, maxID, sinceID, minID, limit, local)
if err != nil {
return nil, NewErrorInternalError(err)
}
+ s, err := p.filterStatuses(authed, statuses)
+ if err != nil {
+ return nil, NewErrorInternalError(err)
+ }
+
+ return s, nil
+}
+
+func (p *processor) PublicTimelineGet(authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) ([]apimodel.Status, ErrorWithCode) {
+ statuses, err := p.db.GetPublicTimelineForAccount(authed.Account.ID, maxID, sinceID, minID, limit, local)
+ if err != nil {
+ return nil, NewErrorInternalError(err)
+ }
+
+ s, err := p.filterStatuses(authed, statuses)
+ if err != nil {
+ return nil, NewErrorInternalError(err)
+ }
+
+ return s, nil
+}
+
+func (p *processor) filterStatuses(authed *oauth.Auth, statuses []*gtsmodel.Status) ([]apimodel.Status, error) {
+ l := p.log.WithField("func", "filterStatuses")
+
apiStatuses := []apimodel.Status{}
for _, s := range statuses {
targetAccount := &gtsmodel.Account{}