gtsocial-umbx

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

home.go (5028B)


      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 
     24 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     25 	"github.com/superseriousbusiness/gotosocial/internal/db"
     26 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     27 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     28 	"github.com/superseriousbusiness/gotosocial/internal/oauth"
     29 	"github.com/superseriousbusiness/gotosocial/internal/state"
     30 	"github.com/superseriousbusiness/gotosocial/internal/timeline"
     31 	"github.com/superseriousbusiness/gotosocial/internal/typeutils"
     32 	"github.com/superseriousbusiness/gotosocial/internal/util"
     33 	"github.com/superseriousbusiness/gotosocial/internal/visibility"
     34 )
     35 
     36 // HomeTimelineGrab returns a function that satisfies GrabFunction for home timelines.
     37 func HomeTimelineGrab(state *state.State) timeline.GrabFunction {
     38 	return func(ctx context.Context, accountID string, maxID string, sinceID string, minID string, limit int) ([]timeline.Timelineable, bool, error) {
     39 		statuses, err := state.DB.GetHomeTimeline(ctx, accountID, maxID, sinceID, minID, limit, false)
     40 		if err != nil && !errors.Is(err, db.ErrNoEntries) {
     41 			err = gtserror.Newf("error getting statuses from db: %w", err)
     42 			return nil, false, err
     43 		}
     44 
     45 		count := len(statuses)
     46 		if count == 0 {
     47 			// We just don't have enough statuses
     48 			// left in the db so return stop = true.
     49 			return nil, true, nil
     50 		}
     51 
     52 		items := make([]timeline.Timelineable, count)
     53 		for i, s := range statuses {
     54 			items[i] = s
     55 		}
     56 
     57 		return items, false, nil
     58 	}
     59 }
     60 
     61 // HomeTimelineFilter returns a function that satisfies FilterFunction for home timelines.
     62 func HomeTimelineFilter(state *state.State, filter *visibility.Filter) timeline.FilterFunction {
     63 	return func(ctx context.Context, accountID string, item timeline.Timelineable) (shouldIndex bool, err error) {
     64 		status, ok := item.(*gtsmodel.Status)
     65 		if !ok {
     66 			err = gtserror.New("could not convert item to *gtsmodel.Status")
     67 			return false, err
     68 		}
     69 
     70 		requestingAccount, err := state.DB.GetAccountByID(ctx, accountID)
     71 		if err != nil {
     72 			err = gtserror.Newf("error getting account with id %s: %w", accountID, err)
     73 			return false, err
     74 		}
     75 
     76 		timelineable, err := filter.StatusHomeTimelineable(ctx, requestingAccount, status)
     77 		if err != nil {
     78 			err = gtserror.Newf("error checking hometimelineability of status %s for account %s: %w", status.ID, accountID, err)
     79 			return false, err
     80 		}
     81 
     82 		return timelineable, nil
     83 	}
     84 }
     85 
     86 // HomeTimelineStatusPrepare returns a function that satisfies PrepareFunction for home timelines.
     87 func HomeTimelineStatusPrepare(state *state.State, tc typeutils.TypeConverter) timeline.PrepareFunction {
     88 	return func(ctx context.Context, accountID string, itemID string) (timeline.Preparable, error) {
     89 		status, err := state.DB.GetStatusByID(ctx, itemID)
     90 		if err != nil {
     91 			err = gtserror.Newf("error getting status with id %s: %w", itemID, err)
     92 			return nil, err
     93 		}
     94 
     95 		requestingAccount, err := state.DB.GetAccountByID(ctx, accountID)
     96 		if err != nil {
     97 			err = gtserror.Newf("error getting account with id %s: %w", accountID, err)
     98 			return nil, err
     99 		}
    100 
    101 		return tc.StatusToAPIStatus(ctx, status, requestingAccount)
    102 	}
    103 }
    104 
    105 func (p *Processor) HomeTimelineGet(ctx context.Context, authed *oauth.Auth, maxID string, sinceID string, minID string, limit int, local bool) (*apimodel.PageableResponse, gtserror.WithCode) {
    106 	statuses, err := p.state.Timelines.Home.GetTimeline(ctx, authed.Account.ID, maxID, sinceID, minID, limit, local)
    107 	if err != nil && !errors.Is(err, db.ErrNoEntries) {
    108 		err = gtserror.Newf("error getting statuses: %w", err)
    109 		return nil, gtserror.NewErrorInternalError(err)
    110 	}
    111 
    112 	count := len(statuses)
    113 	if count == 0 {
    114 		return util.EmptyPageableResponse(), nil
    115 	}
    116 
    117 	var (
    118 		items          = make([]interface{}, count)
    119 		nextMaxIDValue string
    120 		prevMinIDValue string
    121 	)
    122 
    123 	for i, item := range statuses {
    124 		if i == count-1 {
    125 			nextMaxIDValue = item.GetID()
    126 		}
    127 
    128 		if i == 0 {
    129 			prevMinIDValue = item.GetID()
    130 		}
    131 
    132 		items[i] = item
    133 	}
    134 
    135 	return util.PackagePageableResponse(util.PageableResponseParams{
    136 		Items:          items,
    137 		Path:           "api/v1/timelines/home",
    138 		NextMaxIDValue: nextMaxIDValue,
    139 		PrevMinIDValue: prevMinIDValue,
    140 		Limit:          limit,
    141 	})
    142 }