gtsocial-umbx

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

get.go (4886B)


      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 list
     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/gtscontext"
     28 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     29 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     30 	"github.com/superseriousbusiness/gotosocial/internal/log"
     31 	"github.com/superseriousbusiness/gotosocial/internal/util"
     32 )
     33 
     34 // Get returns the api model of one list with the given ID.
     35 func (p *Processor) Get(ctx context.Context, account *gtsmodel.Account, id string) (*apimodel.List, gtserror.WithCode) {
     36 	list, errWithCode := p.getList(
     37 		// Use barebones ctx; no embedded
     38 		// structs necessary for this call.
     39 		gtscontext.SetBarebones(ctx),
     40 		account.ID,
     41 		id,
     42 	)
     43 	if errWithCode != nil {
     44 		return nil, errWithCode
     45 	}
     46 
     47 	return p.apiList(ctx, list)
     48 }
     49 
     50 // GetMultiple returns multiple lists created by the given account, sorted by list ID DESC (newest first).
     51 func (p *Processor) GetAll(ctx context.Context, account *gtsmodel.Account) ([]*apimodel.List, gtserror.WithCode) {
     52 	lists, err := p.state.DB.GetListsForAccountID(
     53 		// Use barebones ctx; no embedded
     54 		// structs necessary for simple GET.
     55 		gtscontext.SetBarebones(ctx),
     56 		account.ID,
     57 	)
     58 	if err != nil {
     59 		if errors.Is(err, db.ErrNoEntries) {
     60 			return nil, nil
     61 		}
     62 		return nil, gtserror.NewErrorInternalError(err)
     63 	}
     64 
     65 	apiLists := make([]*apimodel.List, 0, len(lists))
     66 	for _, list := range lists {
     67 		apiList, errWithCode := p.apiList(ctx, list)
     68 		if errWithCode != nil {
     69 			return nil, errWithCode
     70 		}
     71 
     72 		apiLists = append(apiLists, apiList)
     73 	}
     74 
     75 	return apiLists, nil
     76 }
     77 
     78 // GetListAccounts returns accounts that are in the given list, owned by the given account.
     79 // The additional parameters can be used for paging.
     80 func (p *Processor) GetListAccounts(
     81 	ctx context.Context,
     82 	account *gtsmodel.Account,
     83 	listID string,
     84 	maxID string,
     85 	sinceID string,
     86 	minID string,
     87 	limit int,
     88 ) (*apimodel.PageableResponse, gtserror.WithCode) {
     89 	// Ensure list exists + is owned by requesting account.
     90 	if _, errWithCode := p.getList(ctx, account.ID, listID); errWithCode != nil {
     91 		return nil, errWithCode
     92 	}
     93 
     94 	// To know which accounts are in the list,
     95 	// we need to first get requested list entries.
     96 	listEntries, err := p.state.DB.GetListEntries(ctx, listID, maxID, sinceID, minID, limit)
     97 	if err != nil && !errors.Is(err, db.ErrNoEntries) {
     98 		err = fmt.Errorf("GetListAccounts: error getting list entries: %w", err)
     99 		return nil, gtserror.NewErrorInternalError(err)
    100 	}
    101 
    102 	count := len(listEntries)
    103 	if count == 0 {
    104 		// No list entries means no accounts.
    105 		return util.EmptyPageableResponse(), nil
    106 	}
    107 
    108 	var (
    109 		items          = make([]interface{}, count)
    110 		nextMaxIDValue string
    111 		prevMinIDValue string
    112 	)
    113 
    114 	// For each list entry, we want the account it points to.
    115 	// To get this, we need to first get the follow that the
    116 	// list entry pertains to, then extract the target account
    117 	// from that follow.
    118 	//
    119 	// We do paging not by account ID, but by list entry ID.
    120 	for i, listEntry := range listEntries {
    121 		if i == count-1 {
    122 			nextMaxIDValue = listEntry.ID
    123 		}
    124 
    125 		if i == 0 {
    126 			prevMinIDValue = listEntry.ID
    127 		}
    128 
    129 		if err := p.state.DB.PopulateListEntry(ctx, listEntry); err != nil {
    130 			log.Debugf(ctx, "skipping list entry because of error populating it: %q", err)
    131 			continue
    132 		}
    133 
    134 		if err := p.state.DB.PopulateFollow(ctx, listEntry.Follow); err != nil {
    135 			log.Debugf(ctx, "skipping list entry because of error populating follow: %q", err)
    136 			continue
    137 		}
    138 
    139 		apiAccount, err := p.tc.AccountToAPIAccountPublic(ctx, listEntry.Follow.TargetAccount)
    140 		if err != nil {
    141 			log.Debugf(ctx, "skipping list entry because of error converting follow target account: %q", err)
    142 			continue
    143 		}
    144 
    145 		items[i] = apiAccount
    146 	}
    147 
    148 	return util.PackagePageableResponse(util.PageableResponseParams{
    149 		Items:          items,
    150 		Path:           "api/v1/lists/" + listID + "/accounts",
    151 		NextMaxIDValue: nextMaxIDValue,
    152 		PrevMinIDValue: prevMinIDValue,
    153 		Limit:          limit,
    154 	})
    155 }