gtsocial-umbx

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

util.go (4646B)


      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 search
     19 
     20 import (
     21 	"context"
     22 
     23 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     24 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     25 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
     26 	"github.com/superseriousbusiness/gotosocial/internal/log"
     27 )
     28 
     29 // return true if given queryType should include accounts.
     30 func includeAccounts(queryType string) bool {
     31 	return queryType == queryTypeAny || queryType == queryTypeAccounts
     32 }
     33 
     34 // return true if given queryType should include statuses.
     35 func includeStatuses(queryType string) bool {
     36 	return queryType == queryTypeAny || queryType == queryTypeStatuses
     37 }
     38 
     39 // packageAccounts is a util function that just
     40 // converts the given accounts into an apimodel
     41 // account slice, or errors appropriately.
     42 func (p *Processor) packageAccounts(
     43 	ctx context.Context,
     44 	requestingAccount *gtsmodel.Account,
     45 	accounts []*gtsmodel.Account,
     46 ) ([]*apimodel.Account, gtserror.WithCode) {
     47 	apiAccounts := make([]*apimodel.Account, 0, len(accounts))
     48 
     49 	for _, account := range accounts {
     50 		if account.IsInstance() {
     51 			// No need to show instance accounts.
     52 			continue
     53 		}
     54 
     55 		// Ensure requester can see result account.
     56 		visible, err := p.filter.AccountVisible(ctx, requestingAccount, account)
     57 		if err != nil {
     58 			err = gtserror.Newf("error checking visibility of account %s for account %s: %w", account.ID, requestingAccount.ID, err)
     59 			return nil, gtserror.NewErrorInternalError(err)
     60 		}
     61 
     62 		if !visible {
     63 			log.Debugf(ctx, "account %s is not visible to account %s, skipping this result", account.ID, requestingAccount.ID)
     64 			continue
     65 		}
     66 
     67 		apiAccount, err := p.tc.AccountToAPIAccountPublic(ctx, account)
     68 		if err != nil {
     69 			log.Debugf(ctx, "skipping account %s because it couldn't be converted to its api representation: %s", account.ID, err)
     70 			continue
     71 		}
     72 
     73 		apiAccounts = append(apiAccounts, apiAccount)
     74 	}
     75 
     76 	return apiAccounts, nil
     77 }
     78 
     79 // packageStatuses is a util function that just
     80 // converts the given statuses into an apimodel
     81 // status slice, or errors appropriately.
     82 func (p *Processor) packageStatuses(
     83 	ctx context.Context,
     84 	requestingAccount *gtsmodel.Account,
     85 	statuses []*gtsmodel.Status,
     86 ) ([]*apimodel.Status, gtserror.WithCode) {
     87 	apiStatuses := make([]*apimodel.Status, 0, len(statuses))
     88 
     89 	for _, status := range statuses {
     90 		// Ensure requester can see result status.
     91 		visible, err := p.filter.StatusVisible(ctx, requestingAccount, status)
     92 		if err != nil {
     93 			err = gtserror.Newf("error checking visibility of status %s for account %s: %w", status.ID, requestingAccount.ID, err)
     94 			return nil, gtserror.NewErrorInternalError(err)
     95 		}
     96 
     97 		if !visible {
     98 			log.Debugf(ctx, "status %s is not visible to account %s, skipping this result", status.ID, requestingAccount.ID)
     99 			continue
    100 		}
    101 
    102 		apiStatus, err := p.tc.StatusToAPIStatus(ctx, status, requestingAccount)
    103 		if err != nil {
    104 			log.Debugf(ctx, "skipping status %s because it couldn't be converted to its api representation: %s", status.ID, err)
    105 			continue
    106 		}
    107 
    108 		apiStatuses = append(apiStatuses, apiStatus)
    109 	}
    110 
    111 	return apiStatuses, nil
    112 }
    113 
    114 // packageSearchResult wraps up the given accounts
    115 // and statuses into an apimodel SearchResult that
    116 // can be serialized to an API caller as JSON.
    117 func (p *Processor) packageSearchResult(
    118 	ctx context.Context,
    119 	requestingAccount *gtsmodel.Account,
    120 	accounts []*gtsmodel.Account,
    121 	statuses []*gtsmodel.Status,
    122 ) (*apimodel.SearchResult, gtserror.WithCode) {
    123 	apiAccounts, errWithCode := p.packageAccounts(ctx, requestingAccount, accounts)
    124 	if errWithCode != nil {
    125 		return nil, errWithCode
    126 	}
    127 
    128 	apiStatuses, errWithCode := p.packageStatuses(ctx, requestingAccount, statuses)
    129 	if errWithCode != nil {
    130 		return nil, errWithCode
    131 	}
    132 
    133 	return &apimodel.SearchResult{
    134 		Accounts: apiAccounts,
    135 		Statuses: apiStatuses,
    136 		Hashtags: make([]*apimodel.Tag, 0),
    137 	}, nil
    138 }