2020-05-12 13:59:26 -06:00
# Pleroma: A lightweight social networking server
2021-01-12 23:49:20 -07:00
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
2020-05-12 13:59:26 -06:00
# 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
2020-05-18 10:58:59 -06:00
alias Pleroma.Web.ApiSpec.Schemas.BooleanLike
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Retrieve status information " ] ,
summary : " Multiple statuses " ,
2020-05-12 13:59:26 -06:00
security : [ %{ " oAuth " = > [ " read:statuses " ] } ] ,
parameters : [
Operation . parameter (
:ids ,
:query ,
% Schema { type : :array , items : FlakeID } ,
2020-05-12 15:09:26 -06:00
" Array of status IDs "
2020-11-16 11:23:25 -07:00
) ,
Operation . parameter (
:with_muted ,
:query ,
BooleanLike ,
" Include reactions from muted acccounts. "
2020-05-12 13:59:26 -06:00
)
] ,
operationId : " StatusController.index " ,
responses : %{
200 = > Operation . response ( " Array of Status " , " application/json " , array_of_statuses ( ) )
}
}
end
def create_operation do
% Operation {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
2020-05-12 13:59:26 -06:00
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 " ,
2021-03-05 04:51:29 -07:00
% Schema { anyOf : [ Status , ScheduledStatus ] }
2020-05-12 13:59:26 -06:00
) ,
2020-09-14 06:07:22 -06:00
422 = > Operation . response ( " Bad Request / MRF Rejection " , " application/json " , ApiError )
2020-05-12 13:59:26 -06:00
}
}
end
def show_operation do
% Operation {
2021-02-03 05:38:59 -07:00
tags : [ " Retrieve status information " ] ,
summary : " Status " ,
2020-05-12 13:59:26 -06:00
description : " View information about a status " ,
operationId : " StatusController.show " ,
security : [ %{ " oAuth " = > [ " read:statuses " ] } ] ,
2020-11-16 11:23:25 -07:00
parameters : [
id_param ( ) ,
Operation . parameter (
:with_muted ,
:query ,
BooleanLike ,
" Include reactions from muted acccounts. "
)
] ,
2020-05-12 13:59:26 -06:00
responses : %{
200 = > status_response ( ) ,
404 = > Operation . response ( " Not Found " , " application/json " , ApiError )
}
}
end
def delete_operation do
% Operation {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
summary : " Delete " ,
2020-05-12 13:59:26 -06:00
security : [ %{ " oAuth " = > [ " write:statuses " ] } ] ,
description : " Delete one of your own statuses " ,
operationId : " StatusController.delete " ,
parameters : [ id_param ( ) ] ,
responses : %{
2020-06-25 23:16:24 -06:00
200 = > status_response ( ) ,
2020-05-12 13:59:26 -06:00
403 = > Operation . response ( " Forbidden " , " application/json " , ApiError ) ,
404 = > Operation . response ( " Not Found " , " application/json " , ApiError )
}
}
end
def reblog_operation do
% Operation {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
summary : " Reblog " ,
2020-05-12 13:59:26 -06:00
security : [ %{ " oAuth " = > [ " write:statuses " ] } ] ,
2020-05-12 15:12:22 -06:00
description : " Share a status " ,
2020-05-12 13:59:26 -06:00
operationId : " StatusController.reblog " ,
parameters : [ id_param ( ) ] ,
requestBody :
request_body ( " Parameters " , % Schema {
type : :object ,
properties : %{
2021-01-18 09:15:57 -07:00
visibility : % Schema { allOf : [ VisibilityScope ] }
2020-05-12 13:59:26 -06:00
}
} ) ,
responses : %{
200 = > status_response ( ) ,
404 = > Operation . response ( " Not Found " , " application/json " , ApiError )
}
}
end
def unreblog_operation do
% Operation {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
summary : " Undo reblog " ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
summary : " Unpin from profile " ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
2020-05-12 13:59:26 -06:00
summary : " Mute conversation " ,
security : [ %{ " oAuth " = > [ " write:mutes " ] } ] ,
2020-05-12 15:59:17 -06:00
description : " Do not receive notifications for the thread that this status is part of. " ,
2020-05-12 13:59:26 -06:00
operationId : " StatusController.mute_conversation " ,
2020-09-08 06:13:50 -06:00
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 "
)
] ,
2020-05-12 13:59:26 -06:00
responses : %{
200 = > status_response ( ) ,
400 = > Operation . response ( " Error " , " application/json " , ApiError )
}
}
end
def unmute_conversation_operation do
% Operation {
2021-02-03 05:38:59 -07:00
tags : [ " Status actions " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Retrieve status information " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Retrieve status information " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Retrieve status information " ] ,
summary : " Reblogged by " ,
description : " View who reblogged a given status " ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Retrieve status information " ] ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Timelines " ] ,
2020-05-12 13:59:26 -06:00
summary : " Favourited statuses " ,
2020-06-09 02:53:40 -06:00
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. " ,
2020-05-12 13:59:26 -06:00
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 {
2021-02-03 05:38:59 -07:00
tags : [ " Timelines " ] ,
2020-05-12 13:59:26 -06:00
summary : " Bookmarked statuses " ,
description : " Statuses the user has bookmarked " ,
operationId : " StatusController.bookmarks " ,
2020-05-13 09:56:45 -06:00
parameters : pagination_params ( ) ,
2020-05-12 13:59:26 -06:00
security : [ %{ " oAuth " = > [ " read:bookmarks " ] } ] ,
responses : %{
200 = > Operation . response ( " Array of Statuses " , " application/json " , array_of_statuses ( ) )
}
}
end
2020-05-13 09:06:25 -06:00
def array_of_statuses do
2020-05-12 13:59:26 -06:00
% Schema { type : :array , items : Status , example : [ Status . schema ( ) . example ] }
end
defp create_request do
% Schema {
title : " StatusCreateRequest " ,
type : :object ,
properties : %{
status : % Schema {
type : :string ,
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
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 {
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
type : :array ,
items : % Schema { type : :string } ,
2020-05-12 15:59:17 -06:00
description : " Array of Attachment ids to be attached as media. "
2020-05-12 13:59:26 -06:00
} ,
2021-02-01 08:22:26 -07:00
poll : poll_params ( ) ,
2020-05-12 13:59:26 -06:00
in_reply_to_id : % Schema {
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
allOf : [ FlakeID ] ,
description : " ID of the status being replied to, if status is a reply "
} ,
sensitive : % Schema {
2020-05-18 10:58:59 -06:00
allOf : [ BooleanLike ] ,
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
description : " Mark status and attached media as sensitive? "
} ,
spoiler_text : % Schema {
type : :string ,
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
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. "
} ,
2020-05-15 04:55:41 -06:00
language : % Schema {
type : :string ,
nullable : true ,
description : " ISO 639 language code for this status. "
} ,
2020-05-12 13:59:26 -06:00
# Pleroma-specific properties:
preview : % Schema {
2020-05-18 10:58:59 -06:00
allOf : [ BooleanLike ] ,
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
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 ,
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
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 ,
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
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 {
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
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 {
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
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 {
2020-05-15 04:55:41 -06:00
nullable : true ,
2020-05-12 13:59:26 -06:00
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
2021-02-01 08:22:26 -07:00
def poll_params do
% Schema {
nullable : true ,
type : :object ,
required : [ :options , :expires_in ] ,
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? "
}
}
}
end
2020-05-21 04:03:38 -06:00
def id_param do
2020-05-12 13:59:26 -06:00
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