9fcff7851f
Too many changes in OpenAPI spec to describe each one, but basically it is tag fixes, bringing consitency to operation summaries and fixing some incorrect information.
554 lines
18 KiB
Elixir
554 lines
18 KiB
Elixir
# Pleroma: A lightweight social networking server
|
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
defmodule Pleroma.Web.ApiSpec.StatusOperation do
|
|
alias OpenApiSpex.Operation
|
|
alias OpenApiSpex.Schema
|
|
alias Pleroma.Web.ApiSpec.AccountOperation
|
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
|
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
|
|
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
|
alias Pleroma.Web.ApiSpec.Schemas.ScheduledStatus
|
|
alias Pleroma.Web.ApiSpec.Schemas.Status
|
|
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
|
|
|
|
import Pleroma.Web.ApiSpec.Helpers
|
|
|
|
def open_api_operation(action) do
|
|
operation = String.to_existing_atom("#{action}_operation")
|
|
apply(__MODULE__, operation, [])
|
|
end
|
|
|
|
def index_operation do
|
|
%Operation{
|
|
tags: ["Retrieve status information"],
|
|
summary: "Multiple statuses",
|
|
security: [%{"oAuth" => ["read:statuses"]}],
|
|
parameters: [
|
|
Operation.parameter(
|
|
:ids,
|
|
:query,
|
|
%Schema{type: :array, items: FlakeID},
|
|
"Array of status IDs"
|
|
),
|
|
Operation.parameter(
|
|
:with_muted,
|
|
:query,
|
|
BooleanLike,
|
|
"Include reactions from muted acccounts."
|
|
)
|
|
],
|
|
operationId: "StatusController.index",
|
|
responses: %{
|
|
200 => Operation.response("Array of Status", "application/json", array_of_statuses())
|
|
}
|
|
}
|
|
end
|
|
|
|
def create_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Publish new status",
|
|
security: [%{"oAuth" => ["write:statuses"]}],
|
|
description: "Post a new status",
|
|
operationId: "StatusController.create",
|
|
requestBody: request_body("Parameters", create_request(), required: true),
|
|
responses: %{
|
|
200 =>
|
|
Operation.response(
|
|
"Status. When `scheduled_at` is present, ScheduledStatus is returned instead",
|
|
"application/json",
|
|
%Schema{oneOf: [Status, ScheduledStatus]}
|
|
),
|
|
422 => Operation.response("Bad Request / MRF Rejection", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def show_operation do
|
|
%Operation{
|
|
tags: ["Retrieve status information"],
|
|
summary: "Status",
|
|
description: "View information about a status",
|
|
operationId: "StatusController.show",
|
|
security: [%{"oAuth" => ["read:statuses"]}],
|
|
parameters: [
|
|
id_param(),
|
|
Operation.parameter(
|
|
:with_muted,
|
|
:query,
|
|
BooleanLike,
|
|
"Include reactions from muted acccounts."
|
|
)
|
|
],
|
|
responses: %{
|
|
200 => status_response(),
|
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def delete_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Delete",
|
|
security: [%{"oAuth" => ["write:statuses"]}],
|
|
description: "Delete one of your own statuses",
|
|
operationId: "StatusController.delete",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response(),
|
|
403 => Operation.response("Forbidden", "application/json", ApiError),
|
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def reblog_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Reblog",
|
|
security: [%{"oAuth" => ["write:statuses"]}],
|
|
description: "Share a status",
|
|
operationId: "StatusController.reblog",
|
|
parameters: [id_param()],
|
|
requestBody:
|
|
request_body("Parameters", %Schema{
|
|
type: :object,
|
|
properties: %{
|
|
visibility: %Schema{allOf: [VisibilityScope]}
|
|
}
|
|
}),
|
|
responses: %{
|
|
200 => status_response(),
|
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def unreblog_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Undo reblog",
|
|
security: [%{"oAuth" => ["write:statuses"]}],
|
|
description: "Undo a reshare of a status",
|
|
operationId: "StatusController.unreblog",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response(),
|
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def favourite_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Favourite",
|
|
security: [%{"oAuth" => ["write:favourites"]}],
|
|
description: "Add a status to your favourites list",
|
|
operationId: "StatusController.favourite",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response(),
|
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def unfavourite_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Undo favourite",
|
|
security: [%{"oAuth" => ["write:favourites"]}],
|
|
description: "Remove a status from your favourites list",
|
|
operationId: "StatusController.unfavourite",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response(),
|
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def pin_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Pin to profile",
|
|
security: [%{"oAuth" => ["write:accounts"]}],
|
|
description: "Feature one of your own public statuses at the top of your profile",
|
|
operationId: "StatusController.pin",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response(),
|
|
400 => Operation.response("Error", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def unpin_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Unpin from profile",
|
|
security: [%{"oAuth" => ["write:accounts"]}],
|
|
description: "Unfeature a status from the top of your profile",
|
|
operationId: "StatusController.unpin",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response(),
|
|
400 => Operation.response("Error", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def bookmark_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Bookmark",
|
|
security: [%{"oAuth" => ["write:bookmarks"]}],
|
|
description: "Privately bookmark a status",
|
|
operationId: "StatusController.bookmark",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response()
|
|
}
|
|
}
|
|
end
|
|
|
|
def unbookmark_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Undo bookmark",
|
|
security: [%{"oAuth" => ["write:bookmarks"]}],
|
|
description: "Remove a status from your private bookmarks",
|
|
operationId: "StatusController.unbookmark",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response()
|
|
}
|
|
}
|
|
end
|
|
|
|
def mute_conversation_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Mute conversation",
|
|
security: [%{"oAuth" => ["write:mutes"]}],
|
|
description: "Do not receive notifications for the thread that this status is part of.",
|
|
operationId: "StatusController.mute_conversation",
|
|
requestBody:
|
|
request_body("Parameters", %Schema{
|
|
type: :object,
|
|
properties: %{
|
|
expires_in: %Schema{
|
|
type: :integer,
|
|
nullable: true,
|
|
description: "Expire the mute in `expires_in` seconds. Default 0 for infinity",
|
|
default: 0
|
|
}
|
|
}
|
|
}),
|
|
parameters: [
|
|
id_param(),
|
|
Operation.parameter(
|
|
:expires_in,
|
|
:query,
|
|
%Schema{type: :integer, default: 0},
|
|
"Expire the mute in `expires_in` seconds. Default 0 for infinity"
|
|
)
|
|
],
|
|
responses: %{
|
|
200 => status_response(),
|
|
400 => Operation.response("Error", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def unmute_conversation_operation do
|
|
%Operation{
|
|
tags: ["Status actions"],
|
|
summary: "Unmute conversation",
|
|
security: [%{"oAuth" => ["write:mutes"]}],
|
|
description:
|
|
"Start receiving notifications again for the thread that this status is part of",
|
|
operationId: "StatusController.unmute_conversation",
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => status_response(),
|
|
400 => Operation.response("Error", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def card_operation do
|
|
%Operation{
|
|
tags: ["Retrieve status information"],
|
|
deprecated: true,
|
|
summary: "Preview card",
|
|
description: "Deprecated in favor of card property inlined on Status entity",
|
|
operationId: "StatusController.card",
|
|
parameters: [id_param()],
|
|
security: [%{"oAuth" => ["read:statuses"]}],
|
|
responses: %{
|
|
200 =>
|
|
Operation.response("Card", "application/json", %Schema{
|
|
type: :object,
|
|
nullable: true,
|
|
properties: %{
|
|
type: %Schema{type: :string, enum: ["link", "photo", "video", "rich"]},
|
|
provider_name: %Schema{type: :string, nullable: true},
|
|
provider_url: %Schema{type: :string, format: :uri},
|
|
url: %Schema{type: :string, format: :uri},
|
|
image: %Schema{type: :string, nullable: true, format: :uri},
|
|
title: %Schema{type: :string},
|
|
description: %Schema{type: :string}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
end
|
|
|
|
def favourited_by_operation do
|
|
%Operation{
|
|
tags: ["Retrieve status information"],
|
|
summary: "Favourited by",
|
|
description: "View who favourited a given status",
|
|
operationId: "StatusController.favourited_by",
|
|
security: [%{"oAuth" => ["read:accounts"]}],
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 =>
|
|
Operation.response(
|
|
"Array of Accounts",
|
|
"application/json",
|
|
AccountOperation.array_of_accounts()
|
|
),
|
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def reblogged_by_operation do
|
|
%Operation{
|
|
tags: ["Retrieve status information"],
|
|
summary: "Reblogged by",
|
|
description: "View who reblogged a given status",
|
|
operationId: "StatusController.reblogged_by",
|
|
security: [%{"oAuth" => ["read:accounts"]}],
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 =>
|
|
Operation.response(
|
|
"Array of Accounts",
|
|
"application/json",
|
|
AccountOperation.array_of_accounts()
|
|
),
|
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
|
}
|
|
}
|
|
end
|
|
|
|
def context_operation do
|
|
%Operation{
|
|
tags: ["Retrieve status information"],
|
|
summary: "Parent and child statuses",
|
|
description: "View statuses above and below this status in the thread",
|
|
operationId: "StatusController.context",
|
|
security: [%{"oAuth" => ["read:statuses"]}],
|
|
parameters: [id_param()],
|
|
responses: %{
|
|
200 => Operation.response("Context", "application/json", context())
|
|
}
|
|
}
|
|
end
|
|
|
|
def favourites_operation do
|
|
%Operation{
|
|
tags: ["Timelines"],
|
|
summary: "Favourited statuses",
|
|
description:
|
|
"Statuses the user has favourited. Please note that you have to use the link headers to paginate this. You can not build the query parameters yourself.",
|
|
operationId: "StatusController.favourites",
|
|
parameters: pagination_params(),
|
|
security: [%{"oAuth" => ["read:favourites"]}],
|
|
responses: %{
|
|
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses())
|
|
}
|
|
}
|
|
end
|
|
|
|
def bookmarks_operation do
|
|
%Operation{
|
|
tags: ["Timelines"],
|
|
summary: "Bookmarked statuses",
|
|
description: "Statuses the user has bookmarked",
|
|
operationId: "StatusController.bookmarks",
|
|
parameters: pagination_params(),
|
|
security: [%{"oAuth" => ["read:bookmarks"]}],
|
|
responses: %{
|
|
200 => Operation.response("Array of Statuses", "application/json", array_of_statuses())
|
|
}
|
|
}
|
|
end
|
|
|
|
def array_of_statuses do
|
|
%Schema{type: :array, items: Status, example: [Status.schema().example]}
|
|
end
|
|
|
|
defp create_request do
|
|
%Schema{
|
|
title: "StatusCreateRequest",
|
|
type: :object,
|
|
properties: %{
|
|
status: %Schema{
|
|
type: :string,
|
|
nullable: true,
|
|
description:
|
|
"Text content of the status. If `media_ids` is provided, this becomes optional. Attaching a `poll` is optional while `status` is provided."
|
|
},
|
|
media_ids: %Schema{
|
|
nullable: true,
|
|
type: :array,
|
|
items: %Schema{type: :string},
|
|
description: "Array of Attachment ids to be attached as media."
|
|
},
|
|
poll: %Schema{
|
|
nullable: true,
|
|
type: :object,
|
|
required: [:options],
|
|
properties: %{
|
|
options: %Schema{
|
|
type: :array,
|
|
items: %Schema{type: :string},
|
|
description: "Array of possible answers. Must be provided with `poll[expires_in]`."
|
|
},
|
|
expires_in: %Schema{
|
|
type: :integer,
|
|
nullable: true,
|
|
description:
|
|
"Duration the poll should be open, in seconds. Must be provided with `poll[options]`"
|
|
},
|
|
multiple: %Schema{
|
|
allOf: [BooleanLike],
|
|
nullable: true,
|
|
description: "Allow multiple choices?"
|
|
},
|
|
hide_totals: %Schema{
|
|
allOf: [BooleanLike],
|
|
nullable: true,
|
|
description: "Hide vote counts until the poll ends?"
|
|
}
|
|
}
|
|
},
|
|
in_reply_to_id: %Schema{
|
|
nullable: true,
|
|
allOf: [FlakeID],
|
|
description: "ID of the status being replied to, if status is a reply"
|
|
},
|
|
sensitive: %Schema{
|
|
allOf: [BooleanLike],
|
|
nullable: true,
|
|
description: "Mark status and attached media as sensitive?"
|
|
},
|
|
spoiler_text: %Schema{
|
|
type: :string,
|
|
nullable: true,
|
|
description:
|
|
"Text to be shown as a warning or subject before the actual content. Statuses are generally collapsed behind this field."
|
|
},
|
|
scheduled_at: %Schema{
|
|
type: :string,
|
|
format: :"date-time",
|
|
nullable: true,
|
|
description:
|
|
"ISO 8601 Datetime at which to schedule a status. Providing this paramter will cause ScheduledStatus to be returned instead of Status. Must be at least 5 minutes in the future."
|
|
},
|
|
language: %Schema{
|
|
type: :string,
|
|
nullable: true,
|
|
description: "ISO 639 language code for this status."
|
|
},
|
|
# Pleroma-specific properties:
|
|
preview: %Schema{
|
|
allOf: [BooleanLike],
|
|
nullable: true,
|
|
description:
|
|
"If set to `true` the post won't be actually posted, but the status entitiy would still be rendered back. This could be useful for previewing rich text/custom emoji, for example"
|
|
},
|
|
content_type: %Schema{
|
|
type: :string,
|
|
nullable: true,
|
|
description:
|
|
"The MIME type of the status, it is transformed into HTML by the backend. You can get the list of the supported MIME types with the nodeinfo endpoint."
|
|
},
|
|
to: %Schema{
|
|
type: :array,
|
|
nullable: true,
|
|
items: %Schema{type: :string},
|
|
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,
|
|
description:
|
|
"The number of seconds the posted activity should expire in. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated. This needs to be longer than an hour."
|
|
},
|
|
in_reply_to_conversation_id: %Schema{
|
|
nullable: true,
|
|
type: :string,
|
|
description:
|
|
"Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`."
|
|
}
|
|
},
|
|
example: %{
|
|
"status" => "What time is it?",
|
|
"sensitive" => "false",
|
|
"poll" => %{
|
|
"options" => ["Cofe", "Adventure"],
|
|
"expires_in" => 420
|
|
}
|
|
}
|
|
}
|
|
end
|
|
|
|
def id_param do
|
|
Operation.parameter(:id, :path, FlakeID, "Status ID",
|
|
example: "9umDrYheeY451cQnEe",
|
|
required: true
|
|
)
|
|
end
|
|
|
|
defp status_response do
|
|
Operation.response("Status", "application/json", Status)
|
|
end
|
|
|
|
defp context do
|
|
%Schema{
|
|
title: "StatusContext",
|
|
description:
|
|
"Represents the tree around a given status. Used for reconstructing threads of statuses.",
|
|
type: :object,
|
|
required: [:ancestors, :descendants],
|
|
properties: %{
|
|
ancestors: array_of_statuses(),
|
|
descendants: array_of_statuses()
|
|
},
|
|
example: %{
|
|
"ancestors" => [Status.schema().example],
|
|
"descendants" => [Status.schema().example]
|
|
}
|
|
}
|
|
end
|
|
end
|