MastoAPI: Add `GET /api/v1/accounts/lookup`
[akkoma] / lib / pleroma / web / api_spec / operations / account_operation.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.ApiSpec.AccountOperation do
6 alias OpenApiSpex.Operation
7 alias OpenApiSpex.Reference
8 alias OpenApiSpex.Schema
9 alias Pleroma.Web.ApiSpec.Schemas.Account
10 alias Pleroma.Web.ApiSpec.Schemas.AccountRelationship
11 alias Pleroma.Web.ApiSpec.Schemas.ActorType
12 alias Pleroma.Web.ApiSpec.Schemas.ApiError
13 alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
14 alias Pleroma.Web.ApiSpec.Schemas.List
15 alias Pleroma.Web.ApiSpec.Schemas.Status
16 alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
17
18 import Pleroma.Web.ApiSpec.Helpers
19
20 @spec open_api_operation(atom) :: Operation.t()
21 def open_api_operation(action) do
22 operation = String.to_existing_atom("#{action}_operation")
23 apply(__MODULE__, operation, [])
24 end
25
26 @spec create_operation() :: Operation.t()
27 def create_operation do
28 %Operation{
29 tags: ["Account credentials"],
30 summary: "Register an account",
31 description:
32 "Creates a user and account records. Returns an account access token for the app that initiated the request. The app should save this token for later, and should wait for the user to confirm their account by clicking a link in their email inbox.",
33 operationId: "AccountController.create",
34 requestBody: request_body("Parameters", create_request(), required: true),
35 responses: %{
36 200 => Operation.response("Account", "application/json", create_response()),
37 400 => Operation.response("Error", "application/json", ApiError),
38 403 => Operation.response("Error", "application/json", ApiError),
39 429 => Operation.response("Error", "application/json", ApiError)
40 }
41 }
42 end
43
44 def verify_credentials_operation do
45 %Operation{
46 tags: ["Account credentials"],
47 description: "Test to make sure that the user token works.",
48 summary: "Verify account credentials",
49 operationId: "AccountController.verify_credentials",
50 security: [%{"oAuth" => ["read:accounts"]}],
51 responses: %{
52 200 => Operation.response("Account", "application/json", Account)
53 }
54 }
55 end
56
57 def update_credentials_operation do
58 %Operation{
59 tags: ["Account credentials"],
60 summary: "Update account credentials",
61 description: "Update the user's display and preferences.",
62 operationId: "AccountController.update_credentials",
63 security: [%{"oAuth" => ["write:accounts"]}],
64 requestBody: request_body("Parameters", update_credentials_request(), required: true),
65 responses: %{
66 200 => Operation.response("Account", "application/json", Account),
67 403 => Operation.response("Error", "application/json", ApiError)
68 }
69 }
70 end
71
72 def relationships_operation do
73 %Operation{
74 tags: ["Retrieve account information"],
75 summary: "Relationship with current account",
76 operationId: "AccountController.relationships",
77 description: "Find out whether a given account is followed, blocked, muted, etc.",
78 security: [%{"oAuth" => ["read:follows"]}],
79 parameters: [
80 Operation.parameter(
81 :id,
82 :query,
83 %Schema{
84 oneOf: [%Schema{type: :array, items: %Schema{type: :string}}, %Schema{type: :string}]
85 },
86 "Account IDs",
87 example: "123"
88 )
89 ],
90 responses: %{
91 200 => Operation.response("Account", "application/json", array_of_relationships())
92 }
93 }
94 end
95
96 def show_operation do
97 %Operation{
98 tags: ["Retrieve account information"],
99 summary: "Account",
100 operationId: "AccountController.show",
101 description: "View information about a profile.",
102 parameters: [
103 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
104 with_relationships_param()
105 ],
106 responses: %{
107 200 => Operation.response("Account", "application/json", Account),
108 401 => Operation.response("Error", "application/json", ApiError),
109 404 => Operation.response("Error", "application/json", ApiError)
110 }
111 }
112 end
113
114 def statuses_operation do
115 %Operation{
116 summary: "Statuses",
117 tags: ["Retrieve account information"],
118 operationId: "AccountController.statuses",
119 description:
120 "Statuses posted to the given account. Public (for public statuses only), or user token + `read:statuses` (for private statuses the user is authorized to see)",
121 parameters:
122 [
123 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
124 Operation.parameter(:pinned, :query, BooleanLike, "Include only pinned statuses"),
125 Operation.parameter(:tagged, :query, :string, "With tag"),
126 Operation.parameter(
127 :only_media,
128 :query,
129 BooleanLike,
130 "Include only statuses with media attached"
131 ),
132 Operation.parameter(
133 :with_muted,
134 :query,
135 BooleanLike,
136 "Include statuses from muted accounts."
137 ),
138 Operation.parameter(:exclude_reblogs, :query, BooleanLike, "Exclude reblogs"),
139 Operation.parameter(:exclude_replies, :query, BooleanLike, "Exclude replies"),
140 Operation.parameter(
141 :exclude_visibilities,
142 :query,
143 %Schema{type: :array, items: VisibilityScope},
144 "Exclude visibilities"
145 ),
146 Operation.parameter(
147 :with_muted,
148 :query,
149 BooleanLike,
150 "Include reactions from muted accounts."
151 )
152 ] ++ pagination_params(),
153 responses: %{
154 200 => Operation.response("Statuses", "application/json", array_of_statuses()),
155 401 => Operation.response("Error", "application/json", ApiError),
156 404 => Operation.response("Error", "application/json", ApiError)
157 }
158 }
159 end
160
161 def followers_operation do
162 %Operation{
163 tags: ["Retrieve account information"],
164 summary: "Followers",
165 operationId: "AccountController.followers",
166 security: [%{"oAuth" => ["read:accounts"]}],
167 description:
168 "Accounts which follow the given account, if network is not hidden by the account owner.",
169 parameters: [
170 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
171 Operation.parameter(:id, :query, :string, "ID of the resource owner"),
172 with_relationships_param() | pagination_params()
173 ],
174 responses: %{
175 200 => Operation.response("Accounts", "application/json", array_of_accounts())
176 }
177 }
178 end
179
180 def following_operation do
181 %Operation{
182 tags: ["Retrieve account information"],
183 summary: "Following",
184 operationId: "AccountController.following",
185 security: [%{"oAuth" => ["read:accounts"]}],
186 description:
187 "Accounts which the given account is following, if network is not hidden by the account owner.",
188 parameters: [
189 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
190 Operation.parameter(:id, :query, :string, "ID of the resource owner"),
191 with_relationships_param() | pagination_params()
192 ],
193 responses: %{200 => Operation.response("Accounts", "application/json", array_of_accounts())}
194 }
195 end
196
197 def lists_operation do
198 %Operation{
199 tags: ["Retrieve account information"],
200 summary: "Lists containing this account",
201 operationId: "AccountController.lists",
202 security: [%{"oAuth" => ["read:lists"]}],
203 description: "User lists that you have added this account to.",
204 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
205 responses: %{200 => Operation.response("Lists", "application/json", array_of_lists())}
206 }
207 end
208
209 def follow_operation do
210 %Operation{
211 tags: ["Account actions"],
212 summary: "Follow",
213 operationId: "AccountController.follow",
214 security: [%{"oAuth" => ["follow", "write:follows"]}],
215 description: "Follow the given account",
216 parameters: [
217 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
218 ],
219 requestBody:
220 request_body(
221 "Parameters",
222 %Schema{
223 type: :object,
224 properties: %{
225 reblogs: %Schema{
226 type: :boolean,
227 description: "Receive this account's reblogs in home timeline? Defaults to true.",
228 default: true
229 }
230 }
231 },
232 required: false
233 ),
234 responses: %{
235 200 => Operation.response("Relationship", "application/json", AccountRelationship),
236 400 => Operation.response("Error", "application/json", ApiError),
237 404 => Operation.response("Error", "application/json", ApiError)
238 }
239 }
240 end
241
242 def unfollow_operation do
243 %Operation{
244 tags: ["Account actions"],
245 summary: "Unfollow",
246 operationId: "AccountController.unfollow",
247 security: [%{"oAuth" => ["follow", "write:follows"]}],
248 description: "Unfollow the given account",
249 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
250 responses: %{
251 200 => Operation.response("Relationship", "application/json", AccountRelationship),
252 400 => Operation.response("Error", "application/json", ApiError),
253 404 => Operation.response("Error", "application/json", ApiError)
254 }
255 }
256 end
257
258 def mute_operation do
259 %Operation{
260 tags: ["Account actions"],
261 summary: "Mute",
262 operationId: "AccountController.mute",
263 security: [%{"oAuth" => ["follow", "write:mutes"]}],
264 requestBody: request_body("Parameters", mute_request()),
265 description:
266 "Mute the given account. Clients should filter statuses and notifications from this account, if received (e.g. due to a boost in the Home timeline).",
267 parameters: [
268 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
269 Operation.parameter(
270 :notifications,
271 :query,
272 %Schema{allOf: [BooleanLike], default: true},
273 "Mute notifications in addition to statuses? Defaults to `true`."
274 ),
275 Operation.parameter(
276 :expires_in,
277 :query,
278 %Schema{type: :integer, default: 0},
279 "Expire the mute in `expires_in` seconds. Default 0 for infinity"
280 )
281 ],
282 responses: %{
283 200 => Operation.response("Relationship", "application/json", AccountRelationship)
284 }
285 }
286 end
287
288 def unmute_operation do
289 %Operation{
290 tags: ["Account actions"],
291 summary: "Unmute",
292 operationId: "AccountController.unmute",
293 security: [%{"oAuth" => ["follow", "write:mutes"]}],
294 description: "Unmute the given account.",
295 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
296 responses: %{
297 200 => Operation.response("Relationship", "application/json", AccountRelationship)
298 }
299 }
300 end
301
302 def block_operation do
303 %Operation{
304 tags: ["Account actions"],
305 summary: "Block",
306 operationId: "AccountController.block",
307 security: [%{"oAuth" => ["follow", "write:blocks"]}],
308 description:
309 "Block the given account. Clients should filter statuses from this account if received (e.g. due to a boost in the Home timeline)",
310 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
311 responses: %{
312 200 => Operation.response("Relationship", "application/json", AccountRelationship)
313 }
314 }
315 end
316
317 def unblock_operation do
318 %Operation{
319 tags: ["Account actions"],
320 summary: "Unblock",
321 operationId: "AccountController.unblock",
322 security: [%{"oAuth" => ["follow", "write:blocks"]}],
323 description: "Unblock the given account.",
324 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
325 responses: %{
326 200 => Operation.response("Relationship", "application/json", AccountRelationship)
327 }
328 }
329 end
330
331 def follow_by_uri_operation do
332 %Operation{
333 tags: ["Account actions"],
334 summary: "Follow by URI",
335 operationId: "AccountController.follows",
336 security: [%{"oAuth" => ["follow", "write:follows"]}],
337 requestBody: request_body("Parameters", follow_by_uri_request(), required: true),
338 responses: %{
339 200 => Operation.response("Account", "application/json", AccountRelationship),
340 400 => Operation.response("Error", "application/json", ApiError),
341 404 => Operation.response("Error", "application/json", ApiError)
342 }
343 }
344 end
345
346 def mutes_operation do
347 %Operation{
348 tags: ["Blocks and mutes"],
349 summary: "Retrieve list of mutes",
350 operationId: "AccountController.mutes",
351 description: "Accounts the user has muted.",
352 security: [%{"oAuth" => ["follow", "read:mutes"]}],
353 parameters: [with_relationships_param() | pagination_params()],
354 responses: %{
355 200 => Operation.response("Accounts", "application/json", array_of_accounts())
356 }
357 }
358 end
359
360 def blocks_operation do
361 %Operation{
362 tags: ["Blocks and mutes"],
363 summary: "Retrieve list of blocks",
364 operationId: "AccountController.blocks",
365 description: "View your blocks. See also accounts/:id/{block,unblock}",
366 security: [%{"oAuth" => ["read:blocks"]}],
367 parameters: pagination_params(),
368 responses: %{
369 200 => Operation.response("Accounts", "application/json", array_of_accounts())
370 }
371 }
372 end
373
374 def lookup_operation do
375 %Operation{
376 tags: ["Account lookup"],
377 summary: "Find a user by nickname",
378 operationId: "AccountController.lookup",
379 parameters: [
380 Operation.parameter(
381 :acct,
382 :query,
383 :string,
384 "User nickname"
385 )
386 ],
387 responses: %{
388 200 => Operation.response("Account", "application/json", Account),
389 404 => Operation.response("Error", "application/json", ApiError)
390 }
391 }
392 end
393
394 def endorsements_operation do
395 %Operation{
396 tags: ["Retrieve account information"],
397 summary: "Endorsements",
398 operationId: "AccountController.endorsements",
399 description: "Not implemented",
400 security: [%{"oAuth" => ["read:accounts"]}],
401 responses: %{
402 200 => empty_array_response()
403 }
404 }
405 end
406
407 def identity_proofs_operation do
408 %Operation{
409 tags: ["Retrieve account information"],
410 summary: "Identity proofs",
411 operationId: "AccountController.identity_proofs",
412 # Validators complains about unused path params otherwise
413 parameters: [
414 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
415 ],
416 description: "Not implemented",
417 responses: %{
418 200 => empty_array_response()
419 }
420 }
421 end
422
423 defp create_request do
424 %Schema{
425 title: "AccountCreateRequest",
426 description: "POST body for creating an account",
427 type: :object,
428 required: [:username, :password, :agreement],
429 properties: %{
430 reason: %Schema{
431 type: :string,
432 nullable: true,
433 description:
434 "Text that will be reviewed by moderators if registrations require manual approval"
435 },
436 username: %Schema{type: :string, description: "The desired username for the account"},
437 email: %Schema{
438 type: :string,
439 nullable: true,
440 description:
441 "The email address to be used for login. Required when `account_activation_required` is enabled.",
442 format: :email
443 },
444 password: %Schema{
445 type: :string,
446 description: "The password to be used for login",
447 format: :password
448 },
449 agreement: %Schema{
450 allOf: [BooleanLike],
451 description:
452 "Whether the user agrees to the local rules, terms, and policies. These should be presented to the user in order to allow them to consent before setting this parameter to TRUE."
453 },
454 locale: %Schema{
455 type: :string,
456 nullable: true,
457 description: "The language of the confirmation email that will be sent"
458 },
459 # Pleroma-specific properties:
460 fullname: %Schema{type: :string, nullable: true, description: "Full name"},
461 bio: %Schema{type: :string, description: "Bio", nullable: true, default: ""},
462 captcha_solution: %Schema{
463 type: :string,
464 nullable: true,
465 description: "Provider-specific captcha solution"
466 },
467 captcha_token: %Schema{
468 type: :string,
469 nullable: true,
470 description: "Provider-specific captcha token"
471 },
472 captcha_answer_data: %Schema{
473 type: :string,
474 nullable: true,
475 description: "Provider-specific captcha data"
476 },
477 token: %Schema{
478 type: :string,
479 nullable: true,
480 description: "Invite token required when the registrations aren't public"
481 }
482 },
483 example: %{
484 "username" => "cofe",
485 "email" => "cofe@example.com",
486 "password" => "secret",
487 "agreement" => "true",
488 "bio" => "☕️"
489 }
490 }
491 end
492
493 # Note: this is a token response (if login succeeds!), but there's no oauth operation file yet.
494 defp create_response do
495 %Schema{
496 title: "AccountCreateResponse",
497 description: "Response schema for an account",
498 type: :object,
499 properties: %{
500 # The response when auto-login on create succeeds (token is issued):
501 token_type: %Schema{type: :string},
502 access_token: %Schema{type: :string},
503 refresh_token: %Schema{type: :string},
504 scope: %Schema{type: :string},
505 created_at: %Schema{type: :integer, format: :"date-time"},
506 me: %Schema{type: :string},
507 expires_in: %Schema{type: :integer},
508 #
509 # The response when registration succeeds but auto-login fails (no token):
510 identifier: %Schema{type: :string},
511 message: %Schema{type: :string}
512 },
513 # Note: example of successful registration with failed login response:
514 # example: %{
515 # "identifier" => "missing_confirmed_email",
516 # "message" => "You have been registered. Please check your email for further instructions."
517 # },
518 example: %{
519 "token_type" => "Bearer",
520 "access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
521 "refresh_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzz",
522 "created_at" => 1_585_918_714,
523 "expires_in" => 600,
524 "scope" => "read write follow push",
525 "me" => "https://gensokyo.2hu/users/raymoo"
526 }
527 }
528 end
529
530 defp update_credentials_request do
531 %Schema{
532 title: "AccountUpdateCredentialsRequest",
533 description: "POST body for creating an account",
534 type: :object,
535 properties: %{
536 bot: %Schema{
537 allOf: [BooleanLike],
538 nullable: true,
539 description: "Whether the account has a bot flag."
540 },
541 display_name: %Schema{
542 type: :string,
543 nullable: true,
544 description: "The display name to use for the profile."
545 },
546 note: %Schema{type: :string, description: "The account bio."},
547 avatar: %Schema{
548 type: :string,
549 nullable: true,
550 description: "Avatar image encoded using multipart/form-data",
551 format: :binary
552 },
553 header: %Schema{
554 type: :string,
555 nullable: true,
556 description: "Header image encoded using multipart/form-data",
557 format: :binary
558 },
559 locked: %Schema{
560 allOf: [BooleanLike],
561 nullable: true,
562 description: "Whether manual approval of follow requests is required."
563 },
564 accepts_chat_messages: %Schema{
565 allOf: [BooleanLike],
566 nullable: true,
567 description: "Whether the user accepts receiving chat messages."
568 },
569 fields_attributes: %Schema{
570 nullable: true,
571 oneOf: [
572 %Schema{type: :array, items: attribute_field()},
573 %Schema{type: :object, additionalProperties: attribute_field()}
574 ]
575 },
576 # NOTE: `source` field is not supported
577 #
578 # source: %Schema{
579 # type: :object,
580 # properties: %{
581 # privacy: %Schema{type: :string},
582 # sensitive: %Schema{type: :boolean},
583 # language: %Schema{type: :string}
584 # }
585 # },
586
587 # Pleroma-specific fields
588 no_rich_text: %Schema{
589 allOf: [BooleanLike],
590 nullable: true,
591 description: "html tags are stripped from all statuses requested from the API"
592 },
593 hide_followers: %Schema{
594 allOf: [BooleanLike],
595 nullable: true,
596 description: "user's followers will be hidden"
597 },
598 hide_follows: %Schema{
599 allOf: [BooleanLike],
600 nullable: true,
601 description: "user's follows will be hidden"
602 },
603 hide_followers_count: %Schema{
604 allOf: [BooleanLike],
605 nullable: true,
606 description: "user's follower count will be hidden"
607 },
608 hide_follows_count: %Schema{
609 allOf: [BooleanLike],
610 nullable: true,
611 description: "user's follow count will be hidden"
612 },
613 hide_favorites: %Schema{
614 allOf: [BooleanLike],
615 nullable: true,
616 description: "user's favorites timeline will be hidden"
617 },
618 show_role: %Schema{
619 allOf: [BooleanLike],
620 nullable: true,
621 description: "user's role (e.g admin, moderator) will be exposed to anyone in the
622 API"
623 },
624 default_scope: VisibilityScope,
625 pleroma_settings_store: %Schema{
626 type: :object,
627 nullable: true,
628 description: "Opaque user settings to be saved on the backend."
629 },
630 skip_thread_containment: %Schema{
631 allOf: [BooleanLike],
632 nullable: true,
633 description: "Skip filtering out broken threads"
634 },
635 allow_following_move: %Schema{
636 allOf: [BooleanLike],
637 nullable: true,
638 description: "Allows automatically follow moved following accounts"
639 },
640 also_known_as: %Schema{
641 type: :array,
642 items: %Schema{type: :string},
643 nullable: true,
644 description: "List of alternate ActivityPub IDs"
645 },
646 pleroma_background_image: %Schema{
647 type: :string,
648 nullable: true,
649 description: "Sets the background image of the user.",
650 format: :binary
651 },
652 discoverable: %Schema{
653 allOf: [BooleanLike],
654 nullable: true,
655 description:
656 "Discovery (listing, indexing) of this account by external services (search bots etc.) is allowed."
657 },
658 actor_type: ActorType
659 },
660 example: %{
661 bot: false,
662 display_name: "cofe",
663 note: "foobar",
664 fields_attributes: [%{name: "foo", value: "bar"}],
665 no_rich_text: false,
666 hide_followers: true,
667 hide_follows: false,
668 hide_followers_count: false,
669 hide_follows_count: false,
670 hide_favorites: false,
671 show_role: false,
672 default_scope: "private",
673 pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
674 skip_thread_containment: false,
675 allow_following_move: false,
676 also_known_as: ["https://foo.bar/users/foo"],
677 discoverable: false,
678 actor_type: "Person"
679 }
680 }
681 end
682
683 def array_of_accounts do
684 %Schema{
685 title: "ArrayOfAccounts",
686 type: :array,
687 items: Account,
688 example: [Account.schema().example]
689 }
690 end
691
692 defp array_of_relationships do
693 %Schema{
694 title: "ArrayOfRelationships",
695 description: "Response schema for account relationships",
696 type: :array,
697 items: AccountRelationship,
698 example: [
699 %{
700 "id" => "1",
701 "following" => true,
702 "showing_reblogs" => true,
703 "followed_by" => true,
704 "blocking" => false,
705 "blocked_by" => true,
706 "muting" => false,
707 "muting_notifications" => false,
708 "requested" => false,
709 "domain_blocking" => false,
710 "subscribing" => false,
711 "endorsed" => true
712 },
713 %{
714 "id" => "2",
715 "following" => true,
716 "showing_reblogs" => true,
717 "followed_by" => true,
718 "blocking" => false,
719 "blocked_by" => true,
720 "muting" => true,
721 "muting_notifications" => false,
722 "requested" => true,
723 "domain_blocking" => false,
724 "subscribing" => false,
725 "endorsed" => false
726 },
727 %{
728 "id" => "3",
729 "following" => true,
730 "showing_reblogs" => true,
731 "followed_by" => true,
732 "blocking" => true,
733 "blocked_by" => false,
734 "muting" => true,
735 "muting_notifications" => false,
736 "requested" => false,
737 "domain_blocking" => true,
738 "subscribing" => true,
739 "endorsed" => false
740 }
741 ]
742 }
743 end
744
745 defp follow_by_uri_request do
746 %Schema{
747 title: "AccountFollowsRequest",
748 description: "POST body for muting an account",
749 type: :object,
750 properties: %{
751 uri: %Schema{type: :string, nullable: true, format: :uri}
752 },
753 required: [:uri]
754 }
755 end
756
757 defp mute_request do
758 %Schema{
759 title: "AccountMuteRequest",
760 description: "POST body for muting an account",
761 type: :object,
762 properties: %{
763 notifications: %Schema{
764 allOf: [BooleanLike],
765 nullable: true,
766 description: "Mute notifications in addition to statuses? Defaults to true.",
767 default: true
768 },
769 expires_in: %Schema{
770 type: :integer,
771 nullable: true,
772 description: "Expire the mute in `expires_in` seconds. Default 0 for infinity",
773 default: 0
774 }
775 },
776 example: %{
777 "notifications" => true,
778 "expires_in" => 86_400
779 }
780 }
781 end
782
783 defp array_of_lists do
784 %Schema{
785 title: "ArrayOfLists",
786 description: "Response schema for lists",
787 type: :array,
788 items: List,
789 example: [
790 %{"id" => "123", "title" => "my list"},
791 %{"id" => "1337", "title" => "anotehr list"}
792 ]
793 }
794 end
795
796 defp array_of_statuses do
797 %Schema{
798 title: "ArrayOfStatuses",
799 type: :array,
800 items: Status
801 }
802 end
803
804 defp attribute_field do
805 %Schema{
806 title: "AccountAttributeField",
807 description: "Request schema for account custom fields",
808 type: :object,
809 properties: %{
810 name: %Schema{type: :string},
811 value: %Schema{type: :string}
812 },
813 required: [:name, :value],
814 example: %{
815 "name" => "Website",
816 "value" => "https://pleroma.com"
817 }
818 }
819 end
820 end