diff options
author | 2022-06-08 20:22:49 +0200 | |
---|---|---|
committer | 2022-06-08 20:22:49 +0200 | |
commit | 6f6e89e2715c9ecbadda6b8dbe5227995348dae8 (patch) | |
tree | da867633cdd72981460baf76615a81ab3390ce9c /internal/processing/statustimeline.go | |
parent | [frontend] linkify header mascot+title (#633) (diff) | |
download | gotosocial-6f6e89e2715c9ecbadda6b8dbe5227995348dae8.tar.xz |
[feature] Add paging via `Link` header for notifications and account statuses (#629)
* test link headers
* page get account statuses properly
* page get notifications
* add util func for packaging timeline responses
* return timelined stuff from accountstatusesget
* rename timeline response
* use new convenience function
* go fmt
Diffstat (limited to 'internal/processing/statustimeline.go')
-rw-r--r-- | internal/processing/statustimeline.go | 107 |
1 files changed, 46 insertions, 61 deletions
diff --git a/internal/processing/statustimeline.go b/internal/processing/statustimeline.go index d4388f381..081709302 100644 --- a/internal/processing/statustimeline.go +++ b/internal/processing/statustimeline.go @@ -22,18 +22,17 @@ import ( "context" "errors" "fmt" - "net/url" "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/oauth" "github.com/superseriousbusiness/gotosocial/internal/timeline" "github.com/superseriousbusiness/gotosocial/internal/typeutils" + "github.com/superseriousbusiness/gotosocial/internal/util" "github.com/superseriousbusiness/gotosocial/internal/visibility" ) @@ -139,114 +138,100 @@ func StatusSkipInsertFunction() timeline.SkipInsertFunction { } } -func (p *processor) packageStatusResponse(statuses []*apimodel.Status, path string, nextMaxID string, prevMinID string, limit int) (*apimodel.StatusTimelineResponse, gtserror.WithCode) { - resp := &apimodel.StatusTimelineResponse{ - Statuses: []*apimodel.Status{}, - } - resp.Statuses = statuses - - // prepare the next and previous links - if len(statuses) != 0 { - protocol := config.GetProtocol() - host := config.GetHost() - - nextLink := &url.URL{ - Scheme: protocol, - Host: host, - Path: path, - RawQuery: fmt.Sprintf("limit=%d&max_id=%s", limit, nextMaxID), - } - next := fmt.Sprintf("<%s>; rel=\"next\"", nextLink.String()) - - prevLink := &url.URL{ - Scheme: protocol, - Host: host, - Path: path, - RawQuery: fmt.Sprintf("limit=%d&min_id=%s", limit, prevMinID), - } - prev := fmt.Sprintf("<%s>; rel=\"prev\"", prevLink.String()) - resp.LinkHeader = fmt.Sprintf("%s, %s", next, prev) - } - - return resp, nil -} - -func (p *processor) HomeTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.StatusTimelineResponse, gtserror.WithCode) { +func (p *processor) HomeTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.TimelineResponse, gtserror.WithCode) { preparedItems, err := p.statusTimelines.GetTimeline(ctx, authed.Account.ID, maxID, sinceID, minID, limit, local) if err != nil { return nil, gtserror.NewErrorInternalError(err) } if len(preparedItems) == 0 { - return &apimodel.StatusTimelineResponse{ - Statuses: []*apimodel.Status{}, - }, nil + return util.EmptyTimelineResponse(), nil } - statuses := []*apimodel.Status{} + timelineables := []timeline.Timelineable{} for _, i := range preparedItems { status, ok := i.(*apimodel.Status) if !ok { return nil, gtserror.NewErrorInternalError(errors.New("error converting prepared timeline entry to api status")) } - statuses = append(statuses, status) + timelineables = append(timelineables, status) } - return p.packageStatusResponse(statuses, "api/v1/timelines/home", statuses[len(preparedItems)-1].ID, statuses[0].ID, limit) + return util.PackageTimelineableResponse(util.TimelineableResponseParams{ + Items: timelineables, + Path: "api/v1/timelines/home", + NextMaxIDValue: timelineables[len(timelineables)-1].GetID(), + PrevMinIDValue: timelineables[0].GetID(), + Limit: limit, + }) } -func (p *processor) PublicTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.StatusTimelineResponse, gtserror.WithCode) { +func (p *processor) PublicTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.TimelineResponse, gtserror.WithCode) { statuses, err := p.db.GetPublicTimeline(ctx, authed.Account.ID, maxID, sinceID, minID, limit, local) if err != nil { if err == db.ErrNoEntries { // there are just no entries left - return &apimodel.StatusTimelineResponse{ - Statuses: []*apimodel.Status{}, - }, nil + return util.EmptyTimelineResponse(), nil } // there's an actual error return nil, gtserror.NewErrorInternalError(err) } - s, err := p.filterPublicStatuses(ctx, authed, statuses) + filtered, err := p.filterPublicStatuses(ctx, authed, statuses) if err != nil { return nil, gtserror.NewErrorInternalError(err) } - if len(s) == 0 { - return &apimodel.StatusTimelineResponse{ - Statuses: []*apimodel.Status{}, - }, nil + if len(filtered) == 0 { + return util.EmptyTimelineResponse(), nil + } + + timelineables := []timeline.Timelineable{} + for _, i := range filtered { + timelineables = append(timelineables, i) } - return p.packageStatusResponse(s, "api/v1/timelines/public", s[len(s)-1].ID, s[0].ID, limit) + return util.PackageTimelineableResponse(util.TimelineableResponseParams{ + Items: timelineables, + Path: "api/v1/timelines/public", + NextMaxIDValue: timelineables[len(timelineables)-1].GetID(), + PrevMinIDValue: timelineables[0].GetID(), + Limit: limit, + }) } -func (p *processor) FavedTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, minID string, limit int) (*apimodel.StatusTimelineResponse, gtserror.WithCode) { +func (p *processor) FavedTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, minID string, limit int) (*apimodel.TimelineResponse, gtserror.WithCode) { statuses, nextMaxID, prevMinID, err := p.db.GetFavedTimeline(ctx, authed.Account.ID, maxID, minID, limit) if err != nil { if err == db.ErrNoEntries { // there are just no entries left - return &apimodel.StatusTimelineResponse{ - Statuses: []*apimodel.Status{}, - }, nil + return util.EmptyTimelineResponse(), nil } // there's an actual error return nil, gtserror.NewErrorInternalError(err) } - s, err := p.filterFavedStatuses(ctx, authed, statuses) + filtered, err := p.filterFavedStatuses(ctx, authed, statuses) if err != nil { return nil, gtserror.NewErrorInternalError(err) } - if len(s) == 0 { - return &apimodel.StatusTimelineResponse{ - Statuses: []*apimodel.Status{}, - }, nil + if len(filtered) == 0 { + return util.EmptyTimelineResponse(), nil + } + + timelineables := []timeline.Timelineable{} + for _, i := range filtered { + timelineables = append(timelineables, i) } - return p.packageStatusResponse(s, "api/v1/favourites", nextMaxID, prevMinID, limit) + return util.PackageTimelineableResponse(util.TimelineableResponseParams{ + Items: timelineables, + Path: "api/v1/favourites", + NextMaxIDValue: nextMaxID, + PrevMinIDValue: prevMinID, + Limit: limit, + }) } func (p *processor) filterPublicStatuses(ctx context.Context, authed *oauth.Auth, statuses []*gtsmodel.Status) ([]*apimodel.Status, error) { |