start working on multiple tag names for tag timeline
This commit is contained in:
parent
0b978f2c56
commit
10eed3c80d
|
@ -125,10 +125,17 @@ func (m *Module) TagTimelineGETHandler(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append any additional tags
|
||||||
|
// passed as `any[]` parameter.
|
||||||
|
tagNames := append(
|
||||||
|
[]string{tagName},
|
||||||
|
c.QueryArray(apiutil.TagAnyKey)...,
|
||||||
|
)
|
||||||
|
|
||||||
resp, errWithCode := m.processor.Timeline().TagTimelineGet(
|
resp, errWithCode := m.processor.Timeline().TagTimelineGet(
|
||||||
c.Request.Context(),
|
c.Request.Context(),
|
||||||
authed.Account,
|
authed.Account,
|
||||||
tagName,
|
tagNames,
|
||||||
c.Query(apiutil.MaxIDKey),
|
c.Query(apiutil.MaxIDKey),
|
||||||
c.Query(apiutil.SinceIDKey),
|
c.Query(apiutil.SinceIDKey),
|
||||||
c.Query(apiutil.MinIDKey),
|
c.Query(apiutil.MinIDKey),
|
||||||
|
|
|
@ -54,6 +54,7 @@ const (
|
||||||
/* Tag keys */
|
/* Tag keys */
|
||||||
|
|
||||||
TagNameKey = "tag_name"
|
TagNameKey = "tag_name"
|
||||||
|
TagAnyKey = "any[]"
|
||||||
|
|
||||||
/* Web endpoint keys */
|
/* Web endpoint keys */
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ func (t *timelineDB) GetListTimeline(
|
||||||
|
|
||||||
func (t *timelineDB) GetTagTimeline(
|
func (t *timelineDB) GetTagTimeline(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
tagID string,
|
tagIDs []string,
|
||||||
maxID string,
|
maxID string,
|
||||||
sinceID string,
|
sinceID string,
|
||||||
minID string,
|
minID string,
|
||||||
|
@ -492,8 +492,8 @@ func (t *timelineDB) GetTagTimeline(
|
||||||
).
|
).
|
||||||
// Public only.
|
// Public only.
|
||||||
Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic).
|
Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic).
|
||||||
// This tag only.
|
// Provided tag IDs only.
|
||||||
Where("? = ?", bun.Ident("status_to_tag.tag_id"), tagID)
|
Where("? IN (?)", bun.Ident("status_to_tag.tag_id"), bun.In(tagIDs))
|
||||||
|
|
||||||
if maxID == "" || maxID >= id.Highest {
|
if maxID == "" || maxID >= id.Highest {
|
||||||
const future = 24 * time.Hour
|
const future = 24 * time.Hour
|
||||||
|
|
|
@ -311,7 +311,7 @@ func (suite *TimelineTestSuite) TestGetTagTimelineNoParams() {
|
||||||
tag = suite.testTags["welcome"]
|
tag = suite.testTags["welcome"]
|
||||||
)
|
)
|
||||||
|
|
||||||
s, err := suite.db.GetTagTimeline(ctx, tag.ID, "", "", "", 1)
|
s, err := suite.db.GetTagTimeline(ctx, []string{tag.ID}, "", "", "", 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
suite.FailNow(err.Error())
|
suite.FailNow(err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ type Timeline interface {
|
||||||
// Statuses should be returned in descending order of when they were created (newest first).
|
// Statuses should be returned in descending order of when they were created (newest first).
|
||||||
GetListTimeline(ctx context.Context, listID string, maxID string, sinceID string, minID string, limit int) ([]*gtsmodel.Status, error)
|
GetListTimeline(ctx context.Context, listID string, maxID string, sinceID string, minID string, limit int) ([]*gtsmodel.Status, error)
|
||||||
|
|
||||||
// GetTagTimeline returns a slice of public-visibility statuses that use the given tagID.
|
// GetTagTimeline returns a slice of public-visibility statuses that use the given tagIDs.
|
||||||
// Statuses should be returned in descending order of when they were created (newest first).
|
// Statuses should be returned in descending order of when they were created (newest first).
|
||||||
GetTagTimeline(ctx context.Context, tagID string, maxID string, sinceID string, minID string, limit int) ([]*gtsmodel.Status, error)
|
GetTagTimeline(ctx context.Context, tagIDs []string, maxID string, sinceID string, minID string, limit int) ([]*gtsmodel.Status, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,30 +32,35 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// TagTimelineGet gets a pageable timeline for the given
|
// TagTimelineGet gets a pageable timeline for the given
|
||||||
// tagName and given paging parameters. It will ensure
|
// tagNames and given paging parameters. It will ensure
|
||||||
// that each status in the timeline is actually visible
|
// that each status in the timeline is actually visible
|
||||||
// to requestingAcct before returning it.
|
// to requestingAcct before returning it.
|
||||||
func (p *Processor) TagTimelineGet(
|
func (p *Processor) TagTimelineGet(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
requestingAcct *gtsmodel.Account,
|
requestingAcct *gtsmodel.Account,
|
||||||
tagName string,
|
tagNames []string,
|
||||||
maxID string,
|
maxID string,
|
||||||
sinceID string,
|
sinceID string,
|
||||||
minID string,
|
minID string,
|
||||||
limit int,
|
limit int,
|
||||||
) (*apimodel.PageableResponse, gtserror.WithCode) {
|
) (*apimodel.PageableResponse, gtserror.WithCode) {
|
||||||
tag, errWithCode := p.getTag(ctx, tagName)
|
tagIDs := make([]string, 0, len(tagNames))
|
||||||
if errWithCode != nil {
|
for _, tagName := range tagNames {
|
||||||
return nil, errWithCode
|
tag, errWithCode := p.getTag(ctx, tagName)
|
||||||
|
if errWithCode != nil {
|
||||||
|
return nil, errWithCode
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag == nil || !*tag.Useable || !*tag.Listable {
|
||||||
|
// Obey mastodon API by returning 404 for this.
|
||||||
|
err := fmt.Errorf("tag was not found, or not useable/listable on this instance")
|
||||||
|
return nil, gtserror.NewErrorNotFound(err, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
tagIDs = append(tagIDs, tag.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tag == nil || !*tag.Useable || !*tag.Listable {
|
statuses, err := p.state.DB.GetTagTimeline(ctx, tagIDs, maxID, sinceID, minID, limit)
|
||||||
// Obey mastodon API by returning 404 for this.
|
|
||||||
err := fmt.Errorf("tag was not found, or not useable/listable on this instance")
|
|
||||||
return nil, gtserror.NewErrorNotFound(err, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
statuses, err := p.state.DB.GetTagTimeline(ctx, tag.ID, maxID, sinceID, minID, limit)
|
|
||||||
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||||
err = gtserror.Newf("db error getting statuses: %w", err)
|
err = gtserror.Newf("db error getting statuses: %w", err)
|
||||||
return nil, gtserror.NewErrorInternalError(err)
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
|
@ -66,8 +71,7 @@ func (p *Processor) TagTimelineGet(
|
||||||
requestingAcct,
|
requestingAcct,
|
||||||
statuses,
|
statuses,
|
||||||
limit,
|
limit,
|
||||||
// Use API URL for tag.
|
tagNames,
|
||||||
"/api/v1/timelines/tag/"+tagName,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +99,7 @@ func (p *Processor) packageTagResponse(
|
||||||
requestingAcct *gtsmodel.Account,
|
requestingAcct *gtsmodel.Account,
|
||||||
statuses []*gtsmodel.Status,
|
statuses []*gtsmodel.Status,
|
||||||
limit int,
|
limit int,
|
||||||
requestPath string,
|
tagNames []string,
|
||||||
) (*apimodel.PageableResponse, gtserror.WithCode) {
|
) (*apimodel.PageableResponse, gtserror.WithCode) {
|
||||||
count := len(statuses)
|
count := len(statuses)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
|
@ -131,11 +135,23 @@ func (p *Processor) packageTagResponse(
|
||||||
items = append(items, apiStatus)
|
items = append(items, apiStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use first / "primary" tag for API endpoint.
|
||||||
|
path := "/api/v1/timelines/tag/" + tagNames[0]
|
||||||
|
|
||||||
|
// Add any additional tags.
|
||||||
|
var extraQueryParams []string
|
||||||
|
if len(tagNames) > 1 {
|
||||||
|
for _, tagName := range tagNames[1:] {
|
||||||
|
extraQueryParams = append(extraQueryParams, "any[]="+tagName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return util.PackagePageableResponse(util.PageableResponseParams{
|
return util.PackagePageableResponse(util.PageableResponseParams{
|
||||||
Items: items,
|
Items: items,
|
||||||
Path: requestPath,
|
Path: path,
|
||||||
NextMaxIDValue: nextMaxIDValue,
|
NextMaxIDValue: nextMaxIDValue,
|
||||||
PrevMinIDValue: prevMinIDValue,
|
PrevMinIDValue: prevMinIDValue,
|
||||||
Limit: limit,
|
Limit: limit,
|
||||||
|
ExtraQueryParams: extraQueryParams,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue