gtsocial-umbx

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

searchget.go (7316B)


      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 	"net/http"
     22 
     23 	"github.com/gin-gonic/gin"
     24 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
     25 	apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
     26 	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
     27 	"github.com/superseriousbusiness/gotosocial/internal/oauth"
     28 )
     29 
     30 // SearchGETHandler swagger:operation GET /api/v1/search searchGet
     31 //
     32 // Search for statuses, accounts, or hashtags, on this instance or elsewhere.
     33 //
     34 // If statuses are in the result, they will be returned in descending chronological order (newest first), with sequential IDs (bigger = newer).
     35 //
     36 //	---
     37 //	tags:
     38 //	- search
     39 //
     40 //	produces:
     41 //	- application/json
     42 //
     43 //	parameters:
     44 //	-
     45 //		name: max_id
     46 //		type: string
     47 //		description: >-
     48 //			Return only items *OLDER* than the given max ID.
     49 //			The item with the specified ID will not be included in the response.
     50 //			Currently only used if 'type' is set to a specific type.
     51 //		in: query
     52 //		required: false
     53 //	-
     54 //		name: min_id
     55 //		type: string
     56 //		description: >-
     57 //			Return only items *immediately newer* than the given min ID.
     58 //			The item with the specified ID will not be included in the response.
     59 //			Currently only used if 'type' is set to a specific type.
     60 //		in: query
     61 //		required: false
     62 //	-
     63 //		name: limit
     64 //		type: integer
     65 //		description: Number of each type of item to return.
     66 //		default: 20
     67 //		maximum: 40
     68 //		minimum: 1
     69 //		in: query
     70 //		required: false
     71 //	-
     72 //		name: offset
     73 //		type: integer
     74 //		description: >-
     75 //			Page number of results to return (starts at 0).
     76 //			This parameter is currently not used, page by selecting
     77 //			a specific query type and using maxID and minID instead.
     78 //		default: 0
     79 //		maximum: 10
     80 //		minimum: 0
     81 //		in: query
     82 //		required: false
     83 //	-
     84 //		name: q
     85 //		type: string
     86 //		description: |-
     87 //			Query string to search for. This can be in the following forms:
     88 //			- `@[username]` -- search for an account with the given username on any domain. Can return multiple results.
     89 //			- @[username]@[domain]` -- search for a remote account with exact username and domain. Will only ever return 1 result at most.
     90 //			- `https://example.org/some/arbitrary/url` -- search for an account OR a status with the given URL. Will only ever return 1 result at most.
     91 //			- any arbitrary string -- search for accounts or statuses containing the given string. Can return multiple results.
     92 //		in: query
     93 //		required: true
     94 //	-
     95 //		name: type
     96 //		type: string
     97 //		description: |-
     98 //			Type of item to return. One of:
     99 //			- `` -- empty string; return any/all results.
    100 //			- `accounts` -- return account(s).
    101 //			- `statuses` -- return status(es).
    102 //			- `hashtags` -- return hashtag(s).
    103 //			If `type` is specified, paging can be performed using max_id and min_id parameters.
    104 //			If `type` is not specified, see the `offset` parameter for paging.
    105 //		in: query
    106 //	-
    107 //		name: resolve
    108 //		type: boolean
    109 //		description: >-
    110 //			If searching query is for `@[username]@[domain]`, or a URL, allow the GoToSocial
    111 //			instance to resolve the search by making calls to remote instances (webfinger, ActivityPub, etc).
    112 //		default: false
    113 //		in: query
    114 //	-
    115 //		name: following
    116 //		type: boolean
    117 //		description: >-
    118 //			If search type includes accounts, and search query is an arbitrary string, show only accounts
    119 //			that the requesting account follows. If this is set to `true`, then the GoToSocial instance will
    120 //			enhance the search by also searching within account notes, not just in usernames and display names.
    121 //		default: false
    122 //		in: query
    123 //	-
    124 //		name: exclude_unreviewed
    125 //		type: boolean
    126 //		description: >-
    127 //			If searching for hashtags, exclude those not yet approved by instance admin.
    128 //			Currently this parameter is unused.
    129 //		default: false
    130 //		in: query
    131 //
    132 //	security:
    133 //	- OAuth2 Bearer:
    134 //		- read:search
    135 //
    136 //	responses:
    137 //		'200':
    138 //			name: search results
    139 //			description: Results of the search.
    140 //			schema:
    141 //				type: array
    142 //				items:
    143 //					"$ref": "#/definitions/searchResult"
    144 //		'400':
    145 //			description: bad request
    146 //		'401':
    147 //			description: unauthorized
    148 //		'404':
    149 //			description: not found
    150 //		'406':
    151 //			description: not acceptable
    152 //		'500':
    153 //			description: internal server error
    154 func (m *Module) SearchGETHandler(c *gin.Context) {
    155 	authed, err := oauth.Authed(c, true, true, true, true)
    156 	if err != nil {
    157 		apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1)
    158 		return
    159 	}
    160 
    161 	if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil {
    162 		apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
    163 		return
    164 	}
    165 
    166 	limit, errWithCode := apiutil.ParseLimit(c.Query(apiutil.LimitKey), 20, 40, 1)
    167 	if errWithCode != nil {
    168 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
    169 		return
    170 	}
    171 
    172 	offset, errWithCode := apiutil.ParseSearchOffset(c.Query(apiutil.SearchOffsetKey), 0, 10, 0)
    173 	if errWithCode != nil {
    174 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
    175 		return
    176 	}
    177 
    178 	query, errWithCode := apiutil.ParseSearchQuery(c.Query(apiutil.SearchQueryKey))
    179 	if errWithCode != nil {
    180 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
    181 		return
    182 	}
    183 
    184 	resolve, errWithCode := apiutil.ParseSearchResolve(c.Query(apiutil.SearchResolveKey), false)
    185 	if errWithCode != nil {
    186 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
    187 		return
    188 	}
    189 
    190 	following, errWithCode := apiutil.ParseSearchFollowing(c.Query(apiutil.SearchFollowingKey), false)
    191 	if errWithCode != nil {
    192 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
    193 		return
    194 	}
    195 
    196 	excludeUnreviewed, errWithCode := apiutil.ParseSearchExcludeUnreviewed(c.Query(apiutil.SearchExcludeUnreviewedKey), false)
    197 	if errWithCode != nil {
    198 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
    199 		return
    200 	}
    201 
    202 	searchRequest := &apimodel.SearchRequest{
    203 		MaxID:             c.Query(apiutil.MaxIDKey),
    204 		MinID:             c.Query(apiutil.MinIDKey),
    205 		Limit:             limit,
    206 		Offset:            offset,
    207 		Query:             query,
    208 		QueryType:         c.Query(apiutil.SearchTypeKey),
    209 		Resolve:           resolve,
    210 		Following:         following,
    211 		ExcludeUnreviewed: excludeUnreviewed,
    212 	}
    213 
    214 	results, errWithCode := m.processor.Search().Get(c.Request.Context(), authed.Account, searchRequest)
    215 	if errWithCode != nil {
    216 		apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)
    217 		return
    218 	}
    219 
    220 	c.JSON(http.StatusOK, results)
    221 }