First
[anni] / lib / pleroma / web / api_spec / operations / search_operation.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ApiSpec.SearchOperation do
6   alias OpenApiSpex.Operation
7   alias OpenApiSpex.Schema
8   alias Pleroma.Web.ApiSpec.AccountOperation
9   alias Pleroma.Web.ApiSpec.Schemas.Account
10   alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
11   alias Pleroma.Web.ApiSpec.Schemas.FlakeID
12   alias Pleroma.Web.ApiSpec.Schemas.Status
13   alias Pleroma.Web.ApiSpec.Schemas.Tag
14
15   import Pleroma.Web.ApiSpec.Helpers
16
17   def open_api_operation(action) do
18     operation = String.to_existing_atom("#{action}_operation")
19     apply(__MODULE__, operation, [])
20   end
21
22   # Note: `with_relationships` param is not supported (PleromaFE uses this op for autocomplete)
23   def account_search_operation do
24     %Operation{
25       tags: ["Search"],
26       summary: "Search for matching accounts by username or display name",
27       operationId: "SearchController.account_search",
28       parameters: [
29         Operation.parameter(:q, :query, %Schema{type: :string}, "What to search for",
30           required: true
31         ),
32         Operation.parameter(
33           :limit,
34           :query,
35           %Schema{type: :integer, default: 40},
36           "Maximum number of results"
37         ),
38         Operation.parameter(
39           :resolve,
40           :query,
41           %Schema{allOf: [BooleanLike], default: false},
42           "Attempt WebFinger lookup. Use this when `q` is an exact address."
43         ),
44         Operation.parameter(
45           :following,
46           :query,
47           %Schema{allOf: [BooleanLike], default: false},
48           "Only include accounts that the user is following"
49         )
50       ],
51       responses: %{
52         200 =>
53           Operation.response(
54             "Array of Account",
55             "application/json",
56             AccountOperation.array_of_accounts()
57           )
58       }
59     }
60   end
61
62   def search_operation do
63     %Operation{
64       tags: ["Search"],
65       summary: "Search results",
66       security: [%{"oAuth" => ["read:search"]}],
67       operationId: "SearchController.search",
68       deprecated: true,
69       parameters: [
70         Operation.parameter(
71           :account_id,
72           :query,
73           FlakeID,
74           "If provided, statuses returned will be authored only by this account"
75         ),
76         Operation.parameter(
77           :type,
78           :query,
79           %Schema{type: :string, enum: ["accounts", "hashtags", "statuses"]},
80           "Search type"
81         ),
82         Operation.parameter(:q, :query, %Schema{type: :string}, "The search query", required: true),
83         Operation.parameter(
84           :resolve,
85           :query,
86           %Schema{allOf: [BooleanLike], default: false},
87           "Attempt WebFinger lookup"
88         ),
89         Operation.parameter(
90           :following,
91           :query,
92           %Schema{allOf: [BooleanLike], default: false},
93           "Only include accounts that the user is following"
94         ),
95         Operation.parameter(
96           :offset,
97           :query,
98           %Schema{type: :integer},
99           "Offset"
100         ),
101         with_relationships_param() | pagination_params()
102       ],
103       responses: %{
104         200 => Operation.response("Results", "application/json", results())
105       }
106     }
107   end
108
109   def search2_operation do
110     %Operation{
111       tags: ["Search"],
112       summary: "Search results",
113       security: [%{"oAuth" => ["read:search"]}],
114       operationId: "SearchController.search2",
115       parameters: [
116         Operation.parameter(
117           :account_id,
118           :query,
119           FlakeID,
120           "If provided, statuses returned will be authored only by this account"
121         ),
122         Operation.parameter(
123           :type,
124           :query,
125           %Schema{type: :string, enum: ["accounts", "hashtags", "statuses"]},
126           "Search type"
127         ),
128         Operation.parameter(:q, :query, %Schema{type: :string}, "What to search for",
129           required: true
130         ),
131         Operation.parameter(
132           :resolve,
133           :query,
134           %Schema{allOf: [BooleanLike], default: false},
135           "Attempt WebFinger lookup"
136         ),
137         Operation.parameter(
138           :following,
139           :query,
140           %Schema{allOf: [BooleanLike], default: false},
141           "Only include accounts that the user is following"
142         ),
143         with_relationships_param() | pagination_params()
144       ],
145       responses: %{
146         200 => Operation.response("Results", "application/json", results2())
147       }
148     }
149   end
150
151   defp results2 do
152     %Schema{
153       title: "SearchResults",
154       type: :object,
155       properties: %{
156         accounts: %Schema{
157           type: :array,
158           items: Account,
159           description: "Accounts which match the given query"
160         },
161         statuses: %Schema{
162           type: :array,
163           items: Status,
164           description: "Statuses which match the given query"
165         },
166         hashtags: %Schema{
167           type: :array,
168           items: Tag,
169           description: "Hashtags which match the given query"
170         }
171       },
172       example: %{
173         "accounts" => [Account.schema().example],
174         "statuses" => [Status.schema().example],
175         "hashtags" => [Tag.schema().example]
176       }
177     }
178   end
179
180   defp results do
181     %Schema{
182       title: "SearchResults",
183       type: :object,
184       properties: %{
185         accounts: %Schema{
186           type: :array,
187           items: Account,
188           description: "Accounts which match the given query"
189         },
190         statuses: %Schema{
191           type: :array,
192           items: Status,
193           description: "Statuses which match the given query"
194         },
195         hashtags: %Schema{
196           type: :array,
197           items: %Schema{type: :string},
198           description: "Hashtags which match the given query"
199         }
200       },
201       example: %{
202         "accounts" => [Account.schema().example],
203         "statuses" => [Status.schema().example],
204         "hashtags" => ["cofe"]
205       }
206     }
207   end
208 end