Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into pleroma-instance-domain-blocks

This commit is contained in:
Lain Soykaf 2026-01-16 14:24:14 +04:00
commit 656c4368d3
288 changed files with 6024 additions and 1531 deletions

View file

@ -483,7 +483,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
security: [%{"oAuth" => ["follow", "read:mutes"]}],
parameters: [with_relationships_param() | pagination_params()],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
200 => Operation.response("Accounts", "application/json", array_of_muted_accounts())
}
}
end
@ -497,7 +497,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
security: [%{"oAuth" => ["read:blocks"]}],
parameters: [with_relationships_param() | pagination_params()],
responses: %{
200 => Operation.response("Accounts", "application/json", array_of_accounts())
200 => Operation.response("Accounts", "application/json", array_of_blocked_accounts())
}
}
end
@ -517,6 +517,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
],
responses: %{
200 => Operation.response("Account", "application/json", Account),
401 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Error", "application/json", ApiError)
}
}
@ -896,6 +897,54 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
}
end
def array_of_muted_accounts do
%Schema{
title: "ArrayOfMutedAccounts",
type: :array,
items: %Schema{
title: "MutedAccount",
description: "Response schema for a muted account",
allOf: [
Account,
%Schema{
type: :object,
properties: %{
mute_expires_at: %Schema{type: :string, format: "date-time", nullable: true}
}
}
]
},
example: [
Account.schema().example
|> Map.put("mute_expires_at", "2025-11-29T16:23:13Z")
]
}
end
def array_of_blocked_accounts do
%Schema{
title: "ArrayOfBlockedAccounts",
type: :array,
items: %Schema{
title: "BlockedAccount",
description: "Response schema for a blocked account",
allOf: [
Account,
%Schema{
type: :object,
properties: %{
block_expires_at: %Schema{type: :string, format: "date-time", nullable: true}
}
}
]
},
example: [
Account.schema().example
|> Map.put("block_expires_at", "2025-11-29T16:23:13Z")
]
}
end
defp array_of_relationships do
%Schema{
title: "ArrayOfRelationships",

View file

@ -123,7 +123,10 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
name: %Schema{type: :string, description: "Application Name"},
scopes: %Schema{type: :array, items: %Schema{type: :string}, description: "oAuth scopes"},
redirect_uris: %Schema{
type: :string,
oneOf: [
%Schema{type: :string},
%Schema{type: :array, items: %Schema{type: :string}}
],
description:
"Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter."
},
@ -141,7 +144,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
},
example: %{
"name" => "My App",
"redirect_uris" => "https://myapp.com/auth/callback",
"redirect_uris" => ["https://myapp.com/auth/callback"],
"website" => "https://myapp.com/",
"scopes" => ["read", "write"],
"trusted" => true
@ -157,7 +160,10 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
name: %Schema{type: :string, description: "Application Name"},
scopes: %Schema{type: :array, items: %Schema{type: :string}, description: "oAuth scopes"},
redirect_uris: %Schema{
type: :string,
oneOf: [
%Schema{type: :string},
%Schema{type: :array, items: %Schema{type: :string}}
],
description:
"Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter."
},
@ -175,7 +181,7 @@ defmodule Pleroma.Web.ApiSpec.Admin.OAuthAppOperation do
},
example: %{
"name" => "My App",
"redirect_uris" => "https://myapp.com/auth/callback",
"redirect_uris" => ["https://myapp.com/auth/callback"],
"website" => "https://myapp.com/",
"scopes" => ["read", "write"],
"trusted" => true

View file

@ -97,7 +97,10 @@ defmodule Pleroma.Web.ApiSpec.AppOperation do
properties: %{
client_name: %Schema{type: :string, description: "A name for your application."},
redirect_uris: %Schema{
type: :string,
oneOf: [
%Schema{type: :string},
%Schema{type: :array, items: %Schema{type: :string}}
],
description:
"Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter."
},

View file

@ -142,7 +142,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
:query,
BooleanLike.schema(),
"Include chats from muted users"
)
),
Operation.parameter(:pinned, :query, BooleanLike.schema(), "Include only pinned chats")
],
responses: %{
200 => Operation.response("The chats of the user", "application/json", chats_response())
@ -166,7 +167,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
:query,
BooleanLike.schema(),
"Include chats from muted users"
)
),
Operation.parameter(:pinned, :query, BooleanLike.schema(), "Include only pinned chats")
| pagination_params()
],
responses: %{
@ -257,6 +259,44 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
}
end
def pin_operation do
%Operation{
tags: ["Chats"],
summary: "Pin a chat",
operationId: "ChatController.pin",
parameters: [
Operation.parameter(:id, :path, :string, "The id of the chat", required: true)
],
responses: %{
200 => Operation.response("The existing chat", "application/json", Chat)
},
security: [
%{
"oAuth" => ["write:chats"]
}
]
}
end
def unpin_operation do
%Operation{
tags: ["Chats"],
summary: "Unpin a chat",
operationId: "ChatController.unpin",
parameters: [
Operation.parameter(:id, :path, :string, "The id of the chat", required: true)
],
responses: %{
200 => Operation.response("The existing chat", "application/json", Chat)
},
security: [
%{
"oAuth" => ["write:chats"]
}
]
}
end
def chats_response do
%Schema{
title: "ChatsResponse",

View file

@ -7,6 +7,7 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.Account
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.ApiNotFoundError
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
alias Pleroma.Web.ApiSpec.Schemas.Status
@ -35,7 +36,8 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
security: [%{"oAuth" => ["read:statuses"]}],
operationId: "EmojiReactionController.index",
responses: %{
200 => array_of_reactions_response()
200 => array_of_reactions_response(),
404 => Operation.response("Access denied", "application/json", ApiNotFoundError)
}
}
end
@ -54,7 +56,8 @@ defmodule Pleroma.Web.ApiSpec.EmojiReactionOperation do
operationId: "EmojiReactionController.create",
responses: %{
200 => Operation.response("Status", "application/json", Status),
400 => Operation.response("Bad Request", "application/json", ApiError)
400 => Operation.response("Bad Request", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiNotFoundError)
}
}
end

View file

@ -19,6 +19,7 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do
summary: "Retrieve follow requests",
security: [%{"oAuth" => ["read:follows", "follow"]}],
operationId: "FollowRequestController.index",
parameters: pagination_params(),
responses: %{
200 =>
Operation.response("Array of Account", "application/json", %Schema{
@ -62,4 +63,22 @@ defmodule Pleroma.Web.ApiSpec.FollowRequestOperation do
required: true
)
end
defp pagination_params do
[
Operation.parameter(:max_id, :query, :string, "Return items older than this ID"),
Operation.parameter(
:since_id,
:query,
:string,
"Return the oldest items newer than this ID"
),
Operation.parameter(
:limit,
:query,
%Schema{type: :integer, default: 20},
"Maximum number of items to return. Will be ignored if it's more than 40"
)
]
end
end

View file

@ -18,6 +18,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaFollowRequestOperation do
summary: "Retrieve outgoing follow requests",
security: [%{"oAuth" => ["read:follows", "follow"]}],
operationId: "PleromaFollowRequestController.outgoing",
parameters: pagination_params(),
responses: %{
200 =>
Operation.response("Array of Account", "application/json", %Schema{
@ -28,4 +29,22 @@ defmodule Pleroma.Web.ApiSpec.PleromaFollowRequestOperation do
}
}
end
defp pagination_params do
[
Operation.parameter(:max_id, :query, :string, "Return items older than this ID"),
Operation.parameter(
:since_id,
:query,
:string,
"Return the oldest items newer than this ID"
),
Operation.parameter(
:limit,
:query,
%Schema{type: :integer, default: 20},
"Maximum number of items to return. Will be ignored if it's more than 40"
)
]
end
end

View file

@ -0,0 +1,65 @@
defmodule Pleroma.Web.ApiSpec.PleromaFrontendSettingsOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
import Pleroma.Web.ApiSpec.Helpers
@spec open_api_operation(atom) :: Operation.t()
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def available_frontends_operation do
%Operation{
tags: ["Preferred frontends"],
summary: "Frontend settings profiles",
description: "List frontend setting profiles",
operationId: "PleromaAPI.FrontendSettingsController.available_frontends",
responses: %{
200 =>
Operation.response("Frontends", "application/json", %Schema{
type: :array,
items: %Schema{
type: :string
}
})
}
}
end
def update_preferred_frontend_operation do
%Operation{
tags: ["Preferred frontends"],
summary: "Update preferred frontend setting",
description: "Store preferred frontend in cookies",
operationId: "PleromaAPI.FrontendSettingsController.update_preferred_frontend",
requestBody:
request_body(
"Frontend",
%Schema{
type: :object,
required: [:frontend_name],
properties: %{
frontend_name: %Schema{
type: :string,
description: "Frontend name"
}
}
},
required: true
),
responses: %{
200 =>
Operation.response("Preferred frontend", "application/json", %Schema{
type: :object,
properties: %{
frontend_name: %Schema{
type: :string,
description: "Frontend name"
}
}
})
}
}
end
end

View file

@ -20,7 +20,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
%Operation{
tags: ["Scrobbles"],
summary: "Creates a new Listen activity for an account",
security: [%{"oAuth" => ["write"]}],
security: [%{"oAuth" => ["write:scrobbles"]}],
operationId: "PleromaAPI.ScrobbleController.create",
deprecated: true,
requestBody: request_body("Parameters", create_request(), required: true),
@ -39,7 +39,7 @@ defmodule Pleroma.Web.ApiSpec.PleromaScrobbleOperation do
parameters: [
%Reference{"$ref": "#/components/parameters/accountIdOrNickname"} | pagination_params()
],
security: [%{"oAuth" => ["read"]}],
security: [%{"oAuth" => ["read:scrobbles"]}],
responses: %{
200 =>
Operation.response("Array of Scrobble", "application/json", %Schema{

View file

@ -19,7 +19,8 @@ defmodule Pleroma.Web.ApiSpec.PleromaStatusOperation do
%Operation{
tags: ["Retrieve status information"],
summary: "Quoted by",
description: "View quotes for a given status",
deprecated: true,
description: "View quotes for a given status. Use /api/v1/statuses/:id/quotes instead.",
operationId: "PleromaAPI.StatusController.quotes",
parameters: [id_param() | pagination_params()],
security: [%{"oAuth" => ["read:statuses"]}],

View file

@ -7,6 +7,7 @@ defmodule Pleroma.Web.ApiSpec.ReportOperation do
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Helpers
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.ApiNotFoundError
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
def open_api_operation(action) do
@ -24,7 +25,8 @@ defmodule Pleroma.Web.ApiSpec.ReportOperation do
requestBody: Helpers.request_body("Parameters", create_request(), required: true),
responses: %{
200 => Operation.response("Report", "application/json", create_response()),
400 => Operation.response("Report", "application/json", ApiError)
400 => Operation.response("Report", "application/json", ApiError),
404 => Operation.response("Report", "application/json", ApiNotFoundError)
}
}
end

View file

@ -46,6 +46,12 @@ defmodule Pleroma.Web.ApiSpec.SearchOperation do
:query,
%Schema{allOf: [BooleanLike], default: false},
"Only include accounts that the user is following"
),
Operation.parameter(
:capabilities,
:query,
%Schema{type: :array, items: %Schema{type: :string, enum: ["accepts_chat_messages"]}},
"Only include accounts with given capabilities"
)
],
responses: %{

View file

@ -8,6 +8,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
alias Pleroma.Web.ApiSpec.AccountOperation
alias Pleroma.Web.ApiSpec.Schemas.Account
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.ApiNotFoundError
alias Pleroma.Web.ApiSpec.Schemas.Attachment
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
alias Pleroma.Web.ApiSpec.Schemas.Emoji
@ -177,6 +178,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
parameters: [id_param()],
responses: %{
200 => status_response(),
400 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
@ -242,14 +244,19 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
"error" => "You have already pinned the maximum number of statuses"
}
}),
404 =>
Operation.response("Not found", "application/json", %Schema{
allOf: [ApiError],
title: "Unprocessable Entity",
example: %{
"error" => "Record not found"
404 => Operation.response("Not found", "application/json", ApiNotFoundError),
422 =>
Operation.response(
"Unprocessable Entity",
"application/json",
%Schema{
allOf: [ApiError],
title: "Unprocessable Entity",
example: %{
"error" => "Someone else's status cannot be unpinned"
}
}
})
)
}
}
end
@ -275,7 +282,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
}
}),
responses: %{
200 => status_response()
200 => status_response(),
404 => Operation.response("Not found", "application/json", ApiNotFoundError)
}
}
end
@ -289,7 +297,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
operationId: "StatusController.unbookmark",
parameters: [id_param()],
responses: %{
200 => status_response()
200 => status_response(),
404 => Operation.response("Not found", "application/json", ApiNotFoundError)
}
}
end
@ -324,7 +333,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
],
responses: %{
200 => status_response(),
400 => Operation.response("Error", "application/json", ApiError)
400 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Not found", "application/json", ApiNotFoundError)
}
}
end
@ -340,7 +350,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
parameters: [id_param()],
responses: %{
200 => status_response(),
400 => Operation.response("Error", "application/json", ApiError)
400 => Operation.response("Error", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiNotFoundError)
}
}
end
@ -549,6 +560,27 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
}
end
def quotes_operation do
%Operation{
tags: ["Retrieve status information"],
summary: "Quoted by",
description: "View quotes for a given status",
operationId: "StatusController.quotes",
parameters: [id_param() | pagination_params()],
security: [%{"oAuth" => ["read:statuses"]}],
responses: %{
200 =>
Operation.response(
"Array of Status",
"application/json",
array_of_statuses()
),
403 => Operation.response("Forbidden", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def array_of_statuses do
%Schema{type: :array, items: Status, example: [Status.schema().example]}
end
@ -599,6 +631,20 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
nullable: true,
description: "ISO 639 language code for this status."
},
visibility: %Schema{
nullable: true,
anyOf: [
VisibilityScope,
%Schema{type: :string, description: "`list:LIST_ID`", example: "LIST:123"}
],
description:
"Visibility of the posted status. Besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`"
},
quoted_status_id: %Schema{
nullable: true,
allOf: [FlakeID],
description: "ID of the status being quoted, if any"
},
# Pleroma-specific properties:
preview: %Schema{
allOf: [BooleanLike],
@ -619,15 +665,6 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
description:
"A list of nicknames (like `lain@soykaf.club` or `lain` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for for post visibility are not affected by this and will still apply"
},
visibility: %Schema{
nullable: true,
anyOf: [
VisibilityScope,
%Schema{type: :string, description: "`list:LIST_ID`", example: "LIST:123"}
],
description:
"Visibility of the posted status. Besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`"
},
expires_in: %Schema{
nullable: true,
type: :integer,
@ -643,7 +680,8 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
quote_id: %Schema{
nullable: true,
allOf: [FlakeID],
description: "ID of the status being quoted, if any"
description: "Deprecated in favor of `quoted_status_id`",
deprecated: true
}
},
example: %{

View file

@ -33,8 +33,6 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
header: %Schema{type: :string, format: :uri},
id: FlakeID,
locked: %Schema{type: :boolean},
mute_expires_at: %Schema{type: :string, format: "date-time", nullable: true},
block_expires_at: %Schema{type: :string, format: "date-time", nullable: true},
note: %Schema{type: :string, format: :html},
statuses_count: %Schema{type: :integer},
url: %Schema{type: :string, format: :uri},

View file

@ -0,0 +1,19 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ApiSpec.Schemas.ApiNotFoundError do
alias OpenApiSpex.Schema
require OpenApiSpex
OpenApiSpex.schema(%{
title: "Not Found",
description: "Response schema for 404 API errors",
type: :object,
properties: %{error: %Schema{type: :string}},
example: %{
"error" => "Record not found"
}
})
end

View file

@ -17,7 +17,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do
account: %Schema{type: :object},
unread: %Schema{type: :integer},
last_message: ChatMessage,
updated_at: %Schema{type: :string, format: :"date-time"}
updated_at: %Schema{type: :string, format: :"date-time"},
pinned: %Schema{type: :boolean}
},
example: %{
"account" => %{
@ -69,7 +70,8 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Chat do
"id" => "1",
"unread" => 2,
"last_message" => ChatMessage.schema().example,
"updated_at" => "2020-04-21T15:06:45.000Z"
"updated_at" => "2020-04-21T15:06:45.000Z",
"pinned" => false
}
})
end

View file

@ -219,7 +219,9 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
},
quotes_count: %Schema{
type: :integer,
description: "How many statuses quoted this status"
deprecated: true,
description:
"How many statuses quoted this status. Deprecated, use `quotes_count` from parent object instead."
},
local: %Schema{
type: :boolean,
@ -259,6 +261,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
}
},
poll: %Schema{allOf: [Poll], nullable: true, description: "The poll attached to the status"},
quotes_count: %Schema{
type: :integer,
description: "How many statuses quoted this status."
},
reblog: %Schema{
allOf: [%OpenApiSpex.Reference{"$ref": "#/components/schemas/Status"}],
nullable: true,
@ -385,6 +391,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
"quotes_count" => 0
},
"poll" => nil,
"quotes_count" => 0,
"reblog" => nil,
"reblogged" => false,
"reblogs_count" => 0,