diff options
author | 2023-02-23 23:11:10 +0100 | |
---|---|---|
committer | 2023-02-23 22:11:10 +0000 | |
commit | 689a10fe176706342704dc75e10d7c1f23d35540 (patch) | |
tree | e3540ce586c1a803c4290f3a06de631a6274e8dd /internal/processing | |
parent | [chore] improve opengraph descripiton tag (#1550) (diff) | |
download | gotosocial-689a10fe176706342704dc75e10d7c1f23d35540.tar.xz |
[bugfix] Fix deleted status causing issues when getting bookmark (#1551)
* [bugfix] Delete bookmark when status deleted
* [chore] Give bookmark processing func some love
* fix paging + embetter tests
Diffstat (limited to 'internal/processing')
-rw-r--r-- | internal/processing/account/bookmarks.go | 92 | ||||
-rw-r--r-- | internal/processing/fromcommon.go | 5 |
2 files changed, 58 insertions, 39 deletions
diff --git a/internal/processing/account/bookmarks.go b/internal/processing/account/bookmarks.go index 7551b1e0c..28688c20d 100644 --- a/internal/processing/account/bookmarks.go +++ b/internal/processing/account/bookmarks.go @@ -20,69 +20,83 @@ package account import ( "context" - "fmt" + "errors" 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/log" "github.com/superseriousbusiness/gotosocial/internal/util" ) +// BookmarksGet returns a pageable response of statuses that are bookmarked by requestingAccount. +// Paging for this response is done based on bookmark ID rather than status ID. func (p *Processor) BookmarksGet(ctx context.Context, requestingAccount *gtsmodel.Account, limit int, maxID string, minID string) (*apimodel.PageableResponse, gtserror.WithCode) { - if requestingAccount == nil { - return nil, gtserror.NewErrorForbidden(fmt.Errorf("cannot retrieve bookmarks without a requesting account")) - } - bookmarks, err := p.db.GetBookmarks(ctx, requestingAccount.ID, limit, maxID, minID) if err != nil { return nil, gtserror.NewErrorInternalError(err) } - count := len(bookmarks) - filtered := make([]*gtsmodel.Status, 0, len(bookmarks)) - nextMaxIDValue := "" - prevMinIDValue := "" - for i, b := range bookmarks { - s, err := p.db.GetStatusByID(ctx, b.StatusID) - if err != nil { - return nil, gtserror.NewErrorInternalError(err) - } - - visible, err := p.filter.StatusVisible(ctx, s, requestingAccount) - if err == nil && visible { - if i == count-1 { - nextMaxIDValue = b.ID - } + var ( + count = len(bookmarks) + items = make([]interface{}, 0, count) + nextMaxIDValue = id.Highest + prevMinIDValue = id.Lowest + ) - if i == 0 { - prevMinIDValue = b.ID + for _, bookmark := range bookmarks { + status, err := p.db.GetStatusByID(ctx, bookmark.StatusID) + if err != nil { + if errors.Is(err, db.ErrNoEntries) { + // We just don't have the status for some reason. + // Skip this one. + continue } - - filtered = append(filtered, s) + return nil, gtserror.NewErrorInternalError(err) // A real error has occurred. } - } - count = len(filtered) + visible, err := p.filter.StatusVisible(ctx, status, requestingAccount) + if err != nil { + log.Errorf(ctx, "error checking bookmarked status visibility: %s", err) + continue + } - if count == 0 { - return util.EmptyPageableResponse(), nil - } + if !visible { + continue + } - items := []interface{}{} - for _, s := range filtered { - item, err := p.tc.StatusToAPIStatus(ctx, s, requestingAccount) + // Convert the status. + item, err := p.tc.StatusToAPIStatus(ctx, status, requestingAccount) if err != nil { - return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting status to api: %s", err)) + log.Errorf(ctx, "error converting bookmarked status to api: %s", err) + continue } items = append(items, item) + + // Page based on bookmark ID, not status ID. + // Note that we only set these values here + // when we're certain that the caller is able + // to see the status, *and* we're sure that + // we can produce an api model representation. + if bookmark.ID < nextMaxIDValue { + nextMaxIDValue = bookmark.ID // Lowest ID (for paging down). + } + if bookmark.ID > prevMinIDValue { + prevMinIDValue = bookmark.ID // Highest ID (for paging up). + } + } + + if len(items) == 0 { + return util.EmptyPageableResponse(), nil } return util.PackagePageableResponse(util.PageableResponseParams{ - Items: items, - Path: "/api/v1/bookmarks", - NextMaxIDValue: nextMaxIDValue, - PrevMinIDValue: prevMinIDValue, - Limit: limit, - ExtraQueryParams: []string{}, + Items: items, + Path: "/api/v1/bookmarks", + NextMaxIDValue: nextMaxIDValue, + PrevMinIDValue: prevMinIDValue, + Limit: limit, }) } diff --git a/internal/processing/fromcommon.go b/internal/processing/fromcommon.go index a09d428e8..3e4c62c6c 100644 --- a/internal/processing/fromcommon.go +++ b/internal/processing/fromcommon.go @@ -456,6 +456,11 @@ func (p *Processor) wipeStatus(ctx context.Context, statusToDelete *gtsmodel.Sta return err } + // delete all bookmarks that point to this status + if err := p.db.DeleteWhere(ctx, []db.Where{{Key: "status_id", Value: statusToDelete.ID}}, &[]*gtsmodel.StatusBookmark{}); err != nil { + return err + } + // delete all boosts for this status + remove them from timelines if boosts, err := p.db.GetStatusReblogs(ctx, statusToDelete); err == nil { for _, b := range boosts { |