gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

public.go (2871B)


      1 // GoToSocial
      2 // Copyright (C) GoToSocial Authors admin@gotosocial.org
      3 // SPDX-License-Identifier: AGPL-3.0-or-later
      4 //
      5 // This program is free software: you can redistribute it and/or modify
      6 // it under the terms of the GNU Affero General Public License as published by
      7 // the Free Software Foundation, either version 3 of the License, or
      8 // (at your option) any later version.
      9 //
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU Affero General Public License for more details.
     14 //
     15 // You should have received a copy of the GNU Affero General Public License
     16 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
     17 
     18 package timeline
     19 
     20 import (
     21 	"context"
     22 	"errors"
     23 	"fmt"
     24 
     25 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     26 	"github.com/superseriousbusiness/gotosocial/internal/db"
     27 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     28 	"github.com/superseriousbusiness/gotosocial/internal/log"
     29 	"github.com/superseriousbusiness/gotosocial/internal/oauth"
     30 	"github.com/superseriousbusiness/gotosocial/internal/util"
     31 )
     32 
     33 func (p *Processor) PublicTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.PageableResponse, gtserror.WithCode) {
     34 	statuses, err := p.state.DB.GetPublicTimeline(ctx, maxID, sinceID, minID, limit, local)
     35 	if err != nil && !errors.Is(err, db.ErrNoEntries) {
     36 		err = fmt.Errorf("PublicTimelineGet: db error getting statuses: %w", err)
     37 		return nil, gtserror.NewErrorInternalError(err)
     38 	}
     39 
     40 	count := len(statuses)
     41 	if count == 0 {
     42 		return util.EmptyPageableResponse(), nil
     43 	}
     44 
     45 	var (
     46 		items          = make([]interface{}, 0, count)
     47 		nextMaxIDValue string
     48 		prevMinIDValue string
     49 	)
     50 
     51 	for i, s := range statuses {
     52 		// Set next + prev values before filtering and API
     53 		// converting, so caller can still page properly.
     54 		if i == count-1 {
     55 			nextMaxIDValue = s.ID
     56 		}
     57 
     58 		if i == 0 {
     59 			prevMinIDValue = s.ID
     60 		}
     61 
     62 		timelineable, err := p.filter.StatusPublicTimelineable(ctx, authed.Account, s)
     63 		if err != nil {
     64 			log.Debugf(ctx, "skipping status %s because of an error checking StatusPublicTimelineable: %s", s.ID, err)
     65 			continue
     66 		}
     67 
     68 		if !timelineable {
     69 			continue
     70 		}
     71 
     72 		apiStatus, err := p.tc.StatusToAPIStatus(ctx, s, authed.Account)
     73 		if err != nil {
     74 			log.Debugf(ctx, "skipping status %s because it couldn't be converted to its api representation: %s", s.ID, err)
     75 			continue
     76 		}
     77 
     78 		items = append(items, apiStatus)
     79 	}
     80 
     81 	return util.PackagePageableResponse(util.PageableResponseParams{
     82 		Items:          items,
     83 		Path:           "api/v1/timelines/public",
     84 		NextMaxIDValue: nextMaxIDValue,
     85 		PrevMinIDValue: prevMinIDValue,
     86 		Limit:          limit,
     87 	})
     88 }