Merge branch 'develop' into documentation-migration
[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 notify: %Schema{
231 type: :boolean,
232 description:
233 "Receive notifications for all statuses posted by the account? Defaults to false.",
234 default: false
235 }
236 }
237 },
238 required: false
239 ),
240 responses: %{
241 200 => Operation.response("Relationship", "application/json", AccountRelationship),
242 400 => Operation.response("Error", "application/json", ApiError),
243 404 => Operation.response("Error", "application/json", ApiError)
244 }
245 }
246 end
247
248 def unfollow_operation do
249 %Operation{
250 tags: ["Account actions"],
251 summary: "Unfollow",
252 operationId: "AccountController.unfollow",
253 security: [%{"oAuth" => ["follow", "write:follows"]}],
254 description: "Unfollow the given account",
255 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
256 responses: %{
257 200 => Operation.response("Relationship", "application/json", AccountRelationship),
258 400 => Operation.response("Error", "application/json", ApiError),
259 404 => Operation.response("Error", "application/json", ApiError)
260 }
261 }
262 end
263
264 def mute_operation do
265 %Operation{
266 tags: ["Account actions"],
267 summary: "Mute",
268 operationId: "AccountController.mute",
269 security: [%{"oAuth" => ["follow", "write:mutes"]}],
270 requestBody: request_body("Parameters", mute_request()),
271 description:
272 "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).",
273 parameters: [
274 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
275 Operation.parameter(
276 :notifications,
277 :query,
278 %Schema{allOf: [BooleanLike], default: true},
279 "Mute notifications in addition to statuses? Defaults to `true`."
280 ),
281 Operation.parameter(
282 :expires_in,
283 :query,
284 %Schema{type: :integer, default: 0},
285 "Expire the mute in `expires_in` seconds. Default 0 for infinity"
286 )
287 ],
288 responses: %{
289 200 => Operation.response("Relationship", "application/json", AccountRelationship)
290 }
291 }
292 end
293
294 def unmute_operation do
295 %Operation{
296 tags: ["Account actions"],
297 summary: "Unmute",
298 operationId: "AccountController.unmute",
299 security: [%{"oAuth" => ["follow", "write:mutes"]}],
300 description: "Unmute the given account.",
301 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
302 responses: %{
303 200 => Operation.response("Relationship", "application/json", AccountRelationship)
304 }
305 }
306 end
307
308 def block_operation do
309 %Operation{
310 tags: ["Account actions"],
311 summary: "Block",
312 operationId: "AccountController.block",
313 security: [%{"oAuth" => ["follow", "write:blocks"]}],
314 description:
315 "Block the given account. Clients should filter statuses from this account if received (e.g. due to a boost in the Home timeline)",
316 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
317 responses: %{
318 200 => Operation.response("Relationship", "application/json", AccountRelationship)
319 }
320 }
321 end
322
323 def unblock_operation do
324 %Operation{
325 tags: ["Account actions"],
326 summary: "Unblock",
327 operationId: "AccountController.unblock",
328 security: [%{"oAuth" => ["follow", "write:blocks"]}],
329 description: "Unblock the given account.",
330 parameters: [%Reference{"$ref": "#/components/parameters/accountIdOrNickname"}],
331 responses: %{
332 200 => Operation.response("Relationship", "application/json", AccountRelationship)
333 }
334 }
335 end
336
337 def note_operation do
338 %Operation{
339 tags: ["Account actions"],
340 summary: "Set a private note about a user.",
341 operationId: "AccountController.note",
342 security: [%{"oAuth" => ["follow", "write:accounts"]}],
343 requestBody: request_body("Parameters", note_request()),
344 description: "Create a note for the given account.",
345 parameters: [
346 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
347 Operation.parameter(
348 :comment,
349 :query,
350 %Schema{type: :string},
351 "Account note body"
352 )
353 ],
354 responses: %{
355 200 => Operation.response("Relationship", "application/json", AccountRelationship)
356 }
357 }
358 end
359
360 def follow_by_uri_operation do
361 %Operation{
362 tags: ["Account actions"],
363 summary: "Follow by URI",
364 operationId: "AccountController.follows",
365 security: [%{"oAuth" => ["follow", "write:follows"]}],
366 requestBody: request_body("Parameters", follow_by_uri_request(), required: true),
367 responses: %{
368 200 => Operation.response("Account", "application/json", AccountRelationship),
369 400 => Operation.response("Error", "application/json", ApiError),
370 404 => Operation.response("Error", "application/json", ApiError)
371 }
372 }
373 end
374
375 def mutes_operation do
376 %Operation{
377 tags: ["Blocks and mutes"],
378 summary: "Retrieve list of mutes",
379 operationId: "AccountController.mutes",
380 description: "Accounts the user has muted.",
381 security: [%{"oAuth" => ["follow", "read:mutes"]}],
382 parameters: [with_relationships_param() | pagination_params()],
383 responses: %{
384 200 => Operation.response("Accounts", "application/json", array_of_accounts())
385 }
386 }
387 end
388
389 def blocks_operation do
390 %Operation{
391 tags: ["Blocks and mutes"],
392 summary: "Retrieve list of blocks",
393 operationId: "AccountController.blocks",
394 description: "View your blocks. See also accounts/:id/{block,unblock}",
395 security: [%{"oAuth" => ["read:blocks"]}],
396 parameters: pagination_params(),
397 responses: %{
398 200 => Operation.response("Accounts", "application/json", array_of_accounts())
399 }
400 }
401 end
402
403 def lookup_operation do
404 %Operation{
405 tags: ["Account lookup"],
406 summary: "Find a user by nickname",
407 operationId: "AccountController.lookup",
408 parameters: [
409 Operation.parameter(
410 :acct,
411 :query,
412 :string,
413 "User nickname"
414 )
415 ],
416 responses: %{
417 200 => Operation.response("Account", "application/json", Account),
418 404 => Operation.response("Error", "application/json", ApiError)
419 }
420 }
421 end
422
423 def endorsements_operation do
424 %Operation{
425 tags: ["Retrieve account information"],
426 summary: "Endorsements",
427 operationId: "AccountController.endorsements",
428 description: "Not implemented",
429 security: [%{"oAuth" => ["read:accounts"]}],
430 responses: %{
431 200 => empty_array_response()
432 }
433 }
434 end
435
436 def identity_proofs_operation do
437 %Operation{
438 tags: ["Retrieve account information"],
439 summary: "Identity proofs",
440 operationId: "AccountController.identity_proofs",
441 # Validators complains about unused path params otherwise
442 parameters: [
443 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
444 ],
445 description: "Not implemented",
446 responses: %{
447 200 => empty_array_response()
448 }
449 }
450 end
451
452 defp create_request do
453 %Schema{
454 title: "AccountCreateRequest",
455 description: "POST body for creating an account",
456 type: :object,
457 required: [:username, :password, :agreement],
458 properties: %{
459 reason: %Schema{
460 type: :string,
461 nullable: true,
462 description:
463 "Text that will be reviewed by moderators if registrations require manual approval"
464 },
465 username: %Schema{type: :string, description: "The desired username for the account"},
466 email: %Schema{
467 type: :string,
468 nullable: true,
469 description:
470 "The email address to be used for login. Required when `account_activation_required` is enabled.",
471 format: :email
472 },
473 password: %Schema{
474 type: :string,
475 description: "The password to be used for login",
476 format: :password
477 },
478 agreement: %Schema{
479 allOf: [BooleanLike],
480 description:
481 "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."
482 },
483 locale: %Schema{
484 type: :string,
485 nullable: true,
486 description: "The language of the confirmation email that will be sent"
487 },
488 # Pleroma-specific properties:
489 fullname: %Schema{type: :string, nullable: true, description: "Full name"},
490 bio: %Schema{type: :string, description: "Bio", nullable: true, default: ""},
491 captcha_solution: %Schema{
492 type: :string,
493 nullable: true,
494 description: "Provider-specific captcha solution"
495 },
496 captcha_token: %Schema{
497 type: :string,
498 nullable: true,
499 description: "Provider-specific captcha token"
500 },
501 captcha_answer_data: %Schema{
502 type: :string,
503 nullable: true,
504 description: "Provider-specific captcha data"
505 },
506 token: %Schema{
507 type: :string,
508 nullable: true,
509 description: "Invite token required when the registrations aren't public"
510 },
511 language: %Schema{
512 type: :string,
513 nullable: true,
514 description: "User's preferred language for emails"
515 }
516 },
517 example: %{
518 "username" => "cofe",
519 "email" => "cofe@example.com",
520 "password" => "secret",
521 "agreement" => "true",
522 "bio" => "☕️"
523 }
524 }
525 end
526
527 # Note: this is a token response (if login succeeds!), but there's no oauth operation file yet.
528 defp create_response do
529 %Schema{
530 title: "AccountCreateResponse",
531 description: "Response schema for an account",
532 type: :object,
533 properties: %{
534 # The response when auto-login on create succeeds (token is issued):
535 token_type: %Schema{type: :string},
536 access_token: %Schema{type: :string},
537 refresh_token: %Schema{type: :string},
538 scope: %Schema{type: :string},
539 created_at: %Schema{type: :integer, format: :"date-time"},
540 me: %Schema{type: :string},
541 expires_in: %Schema{type: :integer},
542 #
543 # The response when registration succeeds but auto-login fails (no token):
544 identifier: %Schema{type: :string},
545 message: %Schema{type: :string}
546 },
547 # Note: example of successful registration with failed login response:
548 # example: %{
549 # "identifier" => "missing_confirmed_email",
550 # "message" => "You have been registered. Please check your email for further instructions."
551 # },
552 example: %{
553 "token_type" => "Bearer",
554 "access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
555 "refresh_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzz",
556 "created_at" => 1_585_918_714,
557 "expires_in" => 600,
558 "scope" => "read write follow push",
559 "me" => "https://gensokyo.2hu/users/raymoo"
560 }
561 }
562 end
563
564 defp update_credentials_request do
565 %Schema{
566 title: "AccountUpdateCredentialsRequest",
567 description: "POST body for creating an account",
568 type: :object,
569 properties: %{
570 bot: %Schema{
571 allOf: [BooleanLike],
572 nullable: true,
573 description: "Whether the account has a bot flag."
574 },
575 display_name: %Schema{
576 type: :string,
577 nullable: true,
578 description: "The display name to use for the profile."
579 },
580 note: %Schema{type: :string, description: "The account bio."},
581 avatar: %Schema{
582 type: :string,
583 nullable: true,
584 description: "Avatar image encoded using multipart/form-data",
585 format: :binary
586 },
587 header: %Schema{
588 type: :string,
589 nullable: true,
590 description: "Header image encoded using multipart/form-data",
591 format: :binary
592 },
593 locked: %Schema{
594 allOf: [BooleanLike],
595 nullable: true,
596 description: "Whether manual approval of follow requests is required."
597 },
598 accepts_chat_messages: %Schema{
599 allOf: [BooleanLike],
600 nullable: true,
601 description: "Whether the user accepts receiving chat messages."
602 },
603 fields_attributes: %Schema{
604 nullable: true,
605 oneOf: [
606 %Schema{type: :array, items: attribute_field()},
607 %Schema{type: :object, additionalProperties: attribute_field()}
608 ]
609 },
610 # NOTE: `source` field is not supported
611 #
612 # source: %Schema{
613 # type: :object,
614 # properties: %{
615 # privacy: %Schema{type: :string},
616 # sensitive: %Schema{type: :boolean},
617 # language: %Schema{type: :string}
618 # }
619 # },
620
621 # Pleroma-specific fields
622 no_rich_text: %Schema{
623 allOf: [BooleanLike],
624 nullable: true,
625 description: "html tags are stripped from all statuses requested from the API"
626 },
627 hide_followers: %Schema{
628 allOf: [BooleanLike],
629 nullable: true,
630 description: "user's followers will be hidden"
631 },
632 hide_follows: %Schema{
633 allOf: [BooleanLike],
634 nullable: true,
635 description: "user's follows will be hidden"
636 },
637 hide_followers_count: %Schema{
638 allOf: [BooleanLike],
639 nullable: true,
640 description: "user's follower count will be hidden"
641 },
642 hide_follows_count: %Schema{
643 allOf: [BooleanLike],
644 nullable: true,
645 description: "user's follow count will be hidden"
646 },
647 hide_favorites: %Schema{
648 allOf: [BooleanLike],
649 nullable: true,
650 description: "user's favorites timeline will be hidden"
651 },
652 show_role: %Schema{
653 allOf: [BooleanLike],
654 nullable: true,
655 description: "user's role (e.g admin, moderator) will be exposed to anyone in the
656 API"
657 },
658 default_scope: VisibilityScope,
659 pleroma_settings_store: %Schema{
660 type: :object,
661 nullable: true,
662 description: "Opaque user settings to be saved on the backend."
663 },
664 skip_thread_containment: %Schema{
665 allOf: [BooleanLike],
666 nullable: true,
667 description: "Skip filtering out broken threads"
668 },
669 allow_following_move: %Schema{
670 allOf: [BooleanLike],
671 nullable: true,
672 description: "Allows automatically follow moved following accounts"
673 },
674 also_known_as: %Schema{
675 type: :array,
676 items: %Schema{type: :string},
677 nullable: true,
678 description: "List of alternate ActivityPub IDs"
679 },
680 pleroma_background_image: %Schema{
681 type: :string,
682 nullable: true,
683 description: "Sets the background image of the user.",
684 format: :binary
685 },
686 discoverable: %Schema{
687 allOf: [BooleanLike],
688 nullable: true,
689 description:
690 "Discovery (listing, indexing) of this account by external services (search bots etc.) is allowed."
691 },
692 actor_type: ActorType
693 },
694 example: %{
695 bot: false,
696 display_name: "cofe",
697 note: "foobar",
698 fields_attributes: [%{name: "foo", value: "bar"}],
699 no_rich_text: false,
700 hide_followers: true,
701 hide_follows: false,
702 hide_followers_count: false,
703 hide_follows_count: false,
704 hide_favorites: false,
705 show_role: false,
706 default_scope: "private",
707 pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
708 skip_thread_containment: false,
709 allow_following_move: false,
710 also_known_as: ["https://foo.bar/users/foo"],
711 discoverable: false,
712 actor_type: "Person"
713 }
714 }
715 end
716
717 def array_of_accounts do
718 %Schema{
719 title: "ArrayOfAccounts",
720 type: :array,
721 items: Account,
722 example: [Account.schema().example]
723 }
724 end
725
726 defp array_of_relationships do
727 %Schema{
728 title: "ArrayOfRelationships",
729 description: "Response schema for account relationships",
730 type: :array,
731 items: AccountRelationship,
732 example: [
733 %{
734 "id" => "1",
735 "following" => true,
736 "showing_reblogs" => true,
737 "followed_by" => true,
738 "blocking" => false,
739 "blocked_by" => true,
740 "muting" => false,
741 "muting_notifications" => false,
742 "note" => "",
743 "requested" => false,
744 "domain_blocking" => false,
745 "subscribing" => false,
746 "notifying" => false,
747 "endorsed" => true
748 },
749 %{
750 "id" => "2",
751 "following" => true,
752 "showing_reblogs" => true,
753 "followed_by" => true,
754 "blocking" => false,
755 "blocked_by" => true,
756 "muting" => true,
757 "muting_notifications" => false,
758 "note" => "",
759 "requested" => true,
760 "domain_blocking" => false,
761 "subscribing" => false,
762 "notifying" => false,
763 "endorsed" => false
764 },
765 %{
766 "id" => "3",
767 "following" => true,
768 "showing_reblogs" => true,
769 "followed_by" => true,
770 "blocking" => true,
771 "blocked_by" => false,
772 "muting" => true,
773 "muting_notifications" => false,
774 "note" => "",
775 "requested" => false,
776 "domain_blocking" => true,
777 "subscribing" => true,
778 "notifying" => true,
779 "endorsed" => false
780 }
781 ]
782 }
783 end
784
785 defp follow_by_uri_request do
786 %Schema{
787 title: "AccountFollowsRequest",
788 description: "POST body for muting an account",
789 type: :object,
790 properties: %{
791 uri: %Schema{type: :string, nullable: true, format: :uri}
792 },
793 required: [:uri]
794 }
795 end
796
797 defp mute_request do
798 %Schema{
799 title: "AccountMuteRequest",
800 description: "POST body for muting an account",
801 type: :object,
802 properties: %{
803 notifications: %Schema{
804 allOf: [BooleanLike],
805 nullable: true,
806 description: "Mute notifications in addition to statuses? Defaults to true.",
807 default: true
808 },
809 expires_in: %Schema{
810 type: :integer,
811 nullable: true,
812 description: "Expire the mute in `expires_in` seconds. Default 0 for infinity",
813 default: 0
814 }
815 },
816 example: %{
817 "notifications" => true,
818 "expires_in" => 86_400
819 }
820 }
821 end
822
823 defp note_request do
824 %Schema{
825 title: "AccountNoteRequest",
826 description: "POST body for adding a note for an account",
827 type: :object,
828 properties: %{
829 comment: %Schema{
830 type: :string,
831 description: "Account note body"
832 }
833 },
834 example: %{
835 "comment" => "Example note"
836 }
837 }
838 end
839
840 defp array_of_lists do
841 %Schema{
842 title: "ArrayOfLists",
843 description: "Response schema for lists",
844 type: :array,
845 items: List,
846 example: [
847 %{"id" => "123", "title" => "my list"},
848 %{"id" => "1337", "title" => "anotehr list"}
849 ]
850 }
851 end
852
853 defp array_of_statuses do
854 %Schema{
855 title: "ArrayOfStatuses",
856 type: :array,
857 items: Status
858 }
859 end
860
861 defp attribute_field do
862 %Schema{
863 title: "AccountAttributeField",
864 description: "Request schema for account custom fields",
865 type: :object,
866 properties: %{
867 name: %Schema{type: :string},
868 value: %Schema{type: :string}
869 },
870 required: [:name, :value],
871 example: %{
872 "name" => "Website",
873 "value" => "https://pleroma.com"
874 }
875 }
876 end
877 end