Merge branch 'log-slow-queries' into 'develop'
[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 endorsements_operation do
404 %Operation{
405 tags: ["Retrieve account information"],
406 summary: "Endorsements",
407 operationId: "AccountController.endorsements",
408 description: "Not implemented",
409 security: [%{"oAuth" => ["read:accounts"]}],
410 responses: %{
411 200 => empty_array_response()
412 }
413 }
414 end
415
416 def identity_proofs_operation do
417 %Operation{
418 tags: ["Retrieve account information"],
419 summary: "Identity proofs",
420 operationId: "AccountController.identity_proofs",
421 # Validators complains about unused path params otherwise
422 parameters: [
423 %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
424 ],
425 description: "Not implemented",
426 responses: %{
427 200 => empty_array_response()
428 }
429 }
430 end
431
432 defp create_request do
433 %Schema{
434 title: "AccountCreateRequest",
435 description: "POST body for creating an account",
436 type: :object,
437 required: [:username, :password, :agreement],
438 properties: %{
439 reason: %Schema{
440 type: :string,
441 nullable: true,
442 description:
443 "Text that will be reviewed by moderators if registrations require manual approval"
444 },
445 username: %Schema{type: :string, description: "The desired username for the account"},
446 email: %Schema{
447 type: :string,
448 nullable: true,
449 description:
450 "The email address to be used for login. Required when `account_activation_required` is enabled.",
451 format: :email
452 },
453 password: %Schema{
454 type: :string,
455 description: "The password to be used for login",
456 format: :password
457 },
458 agreement: %Schema{
459 allOf: [BooleanLike],
460 description:
461 "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."
462 },
463 locale: %Schema{
464 type: :string,
465 nullable: true,
466 description: "The language of the confirmation email that will be sent"
467 },
468 # Pleroma-specific properties:
469 fullname: %Schema{type: :string, nullable: true, description: "Full name"},
470 bio: %Schema{type: :string, description: "Bio", nullable: true, default: ""},
471 captcha_solution: %Schema{
472 type: :string,
473 nullable: true,
474 description: "Provider-specific captcha solution"
475 },
476 captcha_token: %Schema{
477 type: :string,
478 nullable: true,
479 description: "Provider-specific captcha token"
480 },
481 captcha_answer_data: %Schema{
482 type: :string,
483 nullable: true,
484 description: "Provider-specific captcha data"
485 },
486 token: %Schema{
487 type: :string,
488 nullable: true,
489 description: "Invite token required when the registrations aren't public"
490 }
491 },
492 example: %{
493 "username" => "cofe",
494 "email" => "cofe@example.com",
495 "password" => "secret",
496 "agreement" => "true",
497 "bio" => "☕️"
498 }
499 }
500 end
501
502 # Note: this is a token response (if login succeeds!), but there's no oauth operation file yet.
503 defp create_response do
504 %Schema{
505 title: "AccountCreateResponse",
506 description: "Response schema for an account",
507 type: :object,
508 properties: %{
509 # The response when auto-login on create succeeds (token is issued):
510 token_type: %Schema{type: :string},
511 access_token: %Schema{type: :string},
512 refresh_token: %Schema{type: :string},
513 scope: %Schema{type: :string},
514 created_at: %Schema{type: :integer, format: :"date-time"},
515 me: %Schema{type: :string},
516 expires_in: %Schema{type: :integer},
517 #
518 # The response when registration succeeds but auto-login fails (no token):
519 identifier: %Schema{type: :string},
520 message: %Schema{type: :string}
521 },
522 # Note: example of successful registration with failed login response:
523 # example: %{
524 # "identifier" => "missing_confirmed_email",
525 # "message" => "You have been registered. Please check your email for further instructions."
526 # },
527 example: %{
528 "token_type" => "Bearer",
529 "access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
530 "refresh_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzz",
531 "created_at" => 1_585_918_714,
532 "expires_in" => 600,
533 "scope" => "read write follow push",
534 "me" => "https://gensokyo.2hu/users/raymoo"
535 }
536 }
537 end
538
539 defp update_credentials_request do
540 %Schema{
541 title: "AccountUpdateCredentialsRequest",
542 description: "POST body for creating an account",
543 type: :object,
544 properties: %{
545 bot: %Schema{
546 allOf: [BooleanLike],
547 nullable: true,
548 description: "Whether the account has a bot flag."
549 },
550 display_name: %Schema{
551 type: :string,
552 nullable: true,
553 description: "The display name to use for the profile."
554 },
555 note: %Schema{type: :string, description: "The account bio."},
556 avatar: %Schema{
557 type: :string,
558 nullable: true,
559 description: "Avatar image encoded using multipart/form-data",
560 format: :binary
561 },
562 header: %Schema{
563 type: :string,
564 nullable: true,
565 description: "Header image encoded using multipart/form-data",
566 format: :binary
567 },
568 locked: %Schema{
569 allOf: [BooleanLike],
570 nullable: true,
571 description: "Whether manual approval of follow requests is required."
572 },
573 accepts_chat_messages: %Schema{
574 allOf: [BooleanLike],
575 nullable: true,
576 description: "Whether the user accepts receiving chat messages."
577 },
578 fields_attributes: %Schema{
579 nullable: true,
580 oneOf: [
581 %Schema{type: :array, items: attribute_field()},
582 %Schema{type: :object, additionalProperties: attribute_field()}
583 ]
584 },
585 # NOTE: `source` field is not supported
586 #
587 # source: %Schema{
588 # type: :object,
589 # properties: %{
590 # privacy: %Schema{type: :string},
591 # sensitive: %Schema{type: :boolean},
592 # language: %Schema{type: :string}
593 # }
594 # },
595
596 # Pleroma-specific fields
597 no_rich_text: %Schema{
598 allOf: [BooleanLike],
599 nullable: true,
600 description: "html tags are stripped from all statuses requested from the API"
601 },
602 hide_followers: %Schema{
603 allOf: [BooleanLike],
604 nullable: true,
605 description: "user's followers will be hidden"
606 },
607 hide_follows: %Schema{
608 allOf: [BooleanLike],
609 nullable: true,
610 description: "user's follows will be hidden"
611 },
612 hide_followers_count: %Schema{
613 allOf: [BooleanLike],
614 nullable: true,
615 description: "user's follower count will be hidden"
616 },
617 hide_follows_count: %Schema{
618 allOf: [BooleanLike],
619 nullable: true,
620 description: "user's follow count will be hidden"
621 },
622 hide_favorites: %Schema{
623 allOf: [BooleanLike],
624 nullable: true,
625 description: "user's favorites timeline will be hidden"
626 },
627 show_role: %Schema{
628 allOf: [BooleanLike],
629 nullable: true,
630 description: "user's role (e.g admin, moderator) will be exposed to anyone in the
631 API"
632 },
633 default_scope: VisibilityScope,
634 pleroma_settings_store: %Schema{
635 type: :object,
636 nullable: true,
637 description: "Opaque user settings to be saved on the backend."
638 },
639 skip_thread_containment: %Schema{
640 allOf: [BooleanLike],
641 nullable: true,
642 description: "Skip filtering out broken threads"
643 },
644 allow_following_move: %Schema{
645 allOf: [BooleanLike],
646 nullable: true,
647 description: "Allows automatically follow moved following accounts"
648 },
649 also_known_as: %Schema{
650 type: :array,
651 items: %Schema{type: :string},
652 nullable: true,
653 description: "List of alternate ActivityPub IDs"
654 },
655 pleroma_background_image: %Schema{
656 type: :string,
657 nullable: true,
658 description: "Sets the background image of the user.",
659 format: :binary
660 },
661 discoverable: %Schema{
662 allOf: [BooleanLike],
663 nullable: true,
664 description:
665 "Discovery (listing, indexing) of this account by external services (search bots etc.) is allowed."
666 },
667 actor_type: ActorType
668 },
669 example: %{
670 bot: false,
671 display_name: "cofe",
672 note: "foobar",
673 fields_attributes: [%{name: "foo", value: "bar"}],
674 no_rich_text: false,
675 hide_followers: true,
676 hide_follows: false,
677 hide_followers_count: false,
678 hide_follows_count: false,
679 hide_favorites: false,
680 show_role: false,
681 default_scope: "private",
682 pleroma_settings_store: %{"pleroma-fe" => %{"key" => "val"}},
683 skip_thread_containment: false,
684 allow_following_move: false,
685 also_known_as: ["https://foo.bar/users/foo"],
686 discoverable: false,
687 actor_type: "Person"
688 }
689 }
690 end
691
692 def array_of_accounts do
693 %Schema{
694 title: "ArrayOfAccounts",
695 type: :array,
696 items: Account,
697 example: [Account.schema().example]
698 }
699 end
700
701 defp array_of_relationships do
702 %Schema{
703 title: "ArrayOfRelationships",
704 description: "Response schema for account relationships",
705 type: :array,
706 items: AccountRelationship,
707 example: [
708 %{
709 "id" => "1",
710 "following" => true,
711 "showing_reblogs" => true,
712 "followed_by" => true,
713 "blocking" => false,
714 "blocked_by" => true,
715 "muting" => false,
716 "muting_notifications" => false,
717 "note" => "",
718 "requested" => false,
719 "domain_blocking" => false,
720 "subscribing" => false,
721 "notifying" => false,
722 "endorsed" => true
723 },
724 %{
725 "id" => "2",
726 "following" => true,
727 "showing_reblogs" => true,
728 "followed_by" => true,
729 "blocking" => false,
730 "blocked_by" => true,
731 "muting" => true,
732 "muting_notifications" => false,
733 "note" => "",
734 "requested" => true,
735 "domain_blocking" => false,
736 "subscribing" => false,
737 "notifying" => false,
738 "endorsed" => false
739 },
740 %{
741 "id" => "3",
742 "following" => true,
743 "showing_reblogs" => true,
744 "followed_by" => true,
745 "blocking" => true,
746 "blocked_by" => false,
747 "muting" => true,
748 "muting_notifications" => false,
749 "note" => "",
750 "requested" => false,
751 "domain_blocking" => true,
752 "subscribing" => true,
753 "notifying" => true,
754 "endorsed" => false
755 }
756 ]
757 }
758 end
759
760 defp follow_by_uri_request do
761 %Schema{
762 title: "AccountFollowsRequest",
763 description: "POST body for muting an account",
764 type: :object,
765 properties: %{
766 uri: %Schema{type: :string, nullable: true, format: :uri}
767 },
768 required: [:uri]
769 }
770 end
771
772 defp mute_request do
773 %Schema{
774 title: "AccountMuteRequest",
775 description: "POST body for muting an account",
776 type: :object,
777 properties: %{
778 notifications: %Schema{
779 allOf: [BooleanLike],
780 nullable: true,
781 description: "Mute notifications in addition to statuses? Defaults to true.",
782 default: true
783 },
784 expires_in: %Schema{
785 type: :integer,
786 nullable: true,
787 description: "Expire the mute in `expires_in` seconds. Default 0 for infinity",
788 default: 0
789 }
790 },
791 example: %{
792 "notifications" => true,
793 "expires_in" => 86_400
794 }
795 }
796 end
797
798 defp note_request do
799 %Schema{
800 title: "AccountNoteRequest",
801 description: "POST body for adding a note for an account",
802 type: :object,
803 properties: %{
804 comment: %Schema{
805 type: :string,
806 description: "Account note body"
807 }
808 },
809 example: %{
810 "comment" => "Example note"
811 }
812 }
813 end
814
815 defp array_of_lists do
816 %Schema{
817 title: "ArrayOfLists",
818 description: "Response schema for lists",
819 type: :array,
820 items: List,
821 example: [
822 %{"id" => "123", "title" => "my list"},
823 %{"id" => "1337", "title" => "anotehr list"}
824 ]
825 }
826 end
827
828 defp array_of_statuses do
829 %Schema{
830 title: "ArrayOfStatuses",
831 type: :array,
832 items: Status
833 }
834 end
835
836 defp attribute_field do
837 %Schema{
838 title: "AccountAttributeField",
839 description: "Request schema for account custom fields",
840 type: :object,
841 properties: %{
842 name: %Schema{type: :string},
843 value: %Schema{type: :string}
844 },
845 required: [:name, :value],
846 example: %{
847 "name" => "Website",
848 "value" => "https://pleroma.com"
849 }
850 }
851 end
852 end