mirror of
https://git.pleroma.social/pleroma/pleroma.git
synced 2024-12-23 00:26:30 +00:00
Merge branch 'instance-v2' into 'develop'
Implement api/v2/instance route See merge request pleroma/pleroma!3939
This commit is contained in:
commit
bd50892c25
7 changed files with 296 additions and 23 deletions
1
changelog.d/instance-v2.add
Normal file
1
changelog.d/instance-v2.add
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Implement /api/v2/instance route
|
|
@ -23,6 +23,18 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show2_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Instance misc"],
|
||||||
|
summary: "Retrieve instance information",
|
||||||
|
description: "Information about the server",
|
||||||
|
operationId: "InstanceController.show2",
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Instance", "application/json", instance2())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def peers_operation do
|
def peers_operation do
|
||||||
%Operation{
|
%Operation{
|
||||||
tags: ["Instance misc"],
|
tags: ["Instance misc"],
|
||||||
|
@ -165,6 +177,166 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp instance2 do
|
||||||
|
%Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
domain: %Schema{type: :string, description: "The domain name of the instance"},
|
||||||
|
title: %Schema{type: :string, description: "The title of the website"},
|
||||||
|
version: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "The version of Pleroma installed on the instance"
|
||||||
|
},
|
||||||
|
source_url: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "The version of Pleroma installed on the instance"
|
||||||
|
},
|
||||||
|
description: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Admin-defined description of the Pleroma site"
|
||||||
|
},
|
||||||
|
usage: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "Instance usage statistics",
|
||||||
|
properties: %{
|
||||||
|
users: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "User count statistics",
|
||||||
|
properties: %{
|
||||||
|
active_month: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Monthly active users"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
email: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "An email that may be contacted for any inquiries",
|
||||||
|
format: :email
|
||||||
|
},
|
||||||
|
urls: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "URLs of interest for clients apps",
|
||||||
|
properties: %{}
|
||||||
|
},
|
||||||
|
stats: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "Statistics about how much information the instance contains",
|
||||||
|
properties: %{
|
||||||
|
user_count: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Users registered on this instance"
|
||||||
|
},
|
||||||
|
status_count: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Statuses authored by users on instance"
|
||||||
|
},
|
||||||
|
domain_count: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Domains federated with this instance"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
thumbnail: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
url: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Banner image for the website",
|
||||||
|
nullable: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
languages: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string},
|
||||||
|
description: "Primary langauges of the website and its staff"
|
||||||
|
},
|
||||||
|
registrations: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "Registrations-related configuration",
|
||||||
|
properties: %{
|
||||||
|
enabled: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "Whether registrations are enabled"
|
||||||
|
},
|
||||||
|
approval_required: %Schema{
|
||||||
|
type: :boolean,
|
||||||
|
description: "Whether users need to be manually approved by admin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
configuration: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "Instance configuration",
|
||||||
|
properties: %{
|
||||||
|
urls: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
streaming: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Websockets address for push streaming"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
statuses: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "A map with poll limits for local statuses",
|
||||||
|
properties: %{
|
||||||
|
max_characters: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Posts character limit (CW/Subject included in the counter)"
|
||||||
|
},
|
||||||
|
max_media_attachments: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Media attachment limit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
media_attachments: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "A map with poll limits for media attachments",
|
||||||
|
properties: %{
|
||||||
|
image_size_limit: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "File size limit of uploaded images"
|
||||||
|
},
|
||||||
|
video_size_limit: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "File size limit of uploaded videos"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
polls: %Schema{
|
||||||
|
type: :object,
|
||||||
|
description: "A map with poll limits for local polls",
|
||||||
|
properties: %{
|
||||||
|
max_options: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Maximum number of options."
|
||||||
|
},
|
||||||
|
max_characters_per_option: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Maximum number of characters per option."
|
||||||
|
},
|
||||||
|
min_expiration: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Minimum expiration time (in seconds)."
|
||||||
|
},
|
||||||
|
max_expiration: %Schema{
|
||||||
|
type: :integer,
|
||||||
|
description: "Maximum expiration time (in seconds)."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
defp array_of_domains do
|
defp array_of_domains do
|
||||||
%Schema{
|
%Schema{
|
||||||
type: :array,
|
type: :array,
|
||||||
|
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceController do
|
||||||
|
|
||||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||||
|
|
||||||
plug(:skip_auth when action in [:show, :peers])
|
plug(:skip_auth when action in [:show, :show2, :peers])
|
||||||
|
|
||||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.InstanceOperation
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.InstanceOperation
|
||||||
|
|
||||||
|
@ -16,6 +16,11 @@ defmodule Pleroma.Web.MastodonAPI.InstanceController do
|
||||||
render(conn, "show.json")
|
render(conn, "show.json")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v2/instance"
|
||||||
|
def show2(conn, _params) do
|
||||||
|
render(conn, "show2.json")
|
||||||
|
end
|
||||||
|
|
||||||
@doc "GET /api/v1/instance/peers"
|
@doc "GET /api/v1/instance/peers"
|
||||||
def peers(conn, _params) do
|
def peers(conn, _params) do
|
||||||
json(conn, Pleroma.Stats.get_peers())
|
json(conn, Pleroma.Stats.get_peers())
|
||||||
|
|
|
@ -13,12 +13,11 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
||||||
def render("show.json", _) do
|
def render("show.json", _) do
|
||||||
instance = Config.get(:instance)
|
instance = Config.get(:instance)
|
||||||
|
|
||||||
%{
|
common_information(instance)
|
||||||
uri: Pleroma.Web.Endpoint.url(),
|
|> Map.merge(%{
|
||||||
title: Keyword.get(instance, :name),
|
uri: Pleroma.Web.WebFinger.host(),
|
||||||
description: Keyword.get(instance, :description),
|
description: Keyword.get(instance, :description),
|
||||||
short_description: Keyword.get(instance, :short_description),
|
short_description: Keyword.get(instance, :short_description),
|
||||||
version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})",
|
|
||||||
email: Keyword.get(instance, :email),
|
email: Keyword.get(instance, :email),
|
||||||
urls: %{
|
urls: %{
|
||||||
streaming_api: Pleroma.Web.Endpoint.websocket_url()
|
streaming_api: Pleroma.Web.Endpoint.websocket_url()
|
||||||
|
@ -27,9 +26,9 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
||||||
thumbnail:
|
thumbnail:
|
||||||
URI.merge(Pleroma.Web.Endpoint.url(), Keyword.get(instance, :instance_thumbnail))
|
URI.merge(Pleroma.Web.Endpoint.url(), Keyword.get(instance, :instance_thumbnail))
|
||||||
|> to_string,
|
|> to_string,
|
||||||
languages: Keyword.get(instance, :languages, ["en"]),
|
|
||||||
registrations: Keyword.get(instance, :registrations_open),
|
registrations: Keyword.get(instance, :registrations_open),
|
||||||
approval_required: Keyword.get(instance, :account_approval_required),
|
approval_required: Keyword.get(instance, :account_approval_required),
|
||||||
|
configuration: configuration(),
|
||||||
# Extra (not present in Mastodon):
|
# Extra (not present in Mastodon):
|
||||||
max_toot_chars: Keyword.get(instance, :limit),
|
max_toot_chars: Keyword.get(instance, :limit),
|
||||||
max_media_attachments: Keyword.get(instance, :max_media_attachments),
|
max_media_attachments: Keyword.get(instance, :max_media_attachments),
|
||||||
|
@ -41,19 +40,44 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
||||||
background_image: Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image),
|
background_image: Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image),
|
||||||
shout_limit: Config.get([:shout, :limit]),
|
shout_limit: Config.get([:shout, :limit]),
|
||||||
description_limit: Keyword.get(instance, :description_limit),
|
description_limit: Keyword.get(instance, :description_limit),
|
||||||
pleroma: %{
|
pleroma: pleroma_configuration(instance)
|
||||||
metadata: %{
|
})
|
||||||
account_activation_required: Keyword.get(instance, :account_activation_required),
|
end
|
||||||
features: features(),
|
|
||||||
federation: federation(),
|
def render("show2.json", _) do
|
||||||
fields_limits: fields_limits(),
|
instance = Config.get(:instance)
|
||||||
post_formats: Config.get([:instance, :allowed_post_formats]),
|
|
||||||
birthday_required: Config.get([:instance, :birthday_required]),
|
common_information(instance)
|
||||||
birthday_min_age: Config.get([:instance, :birthday_min_age])
|
|> Map.merge(%{
|
||||||
},
|
domain: Pleroma.Web.WebFinger.host(),
|
||||||
stats: %{mau: Pleroma.User.active_user_count()},
|
source_url: Pleroma.Application.repository(),
|
||||||
vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
|
description: Keyword.get(instance, :short_description),
|
||||||
}
|
usage: %{users: %{active_month: Pleroma.User.active_user_count()}},
|
||||||
|
thumbnail: %{
|
||||||
|
url:
|
||||||
|
URI.merge(Pleroma.Web.Endpoint.url(), Keyword.get(instance, :instance_thumbnail))
|
||||||
|
|> to_string
|
||||||
|
},
|
||||||
|
configuration: configuration2(),
|
||||||
|
registrations: %{
|
||||||
|
enabled: Keyword.get(instance, :registrations_open),
|
||||||
|
approval_required: Keyword.get(instance, :account_approval_required),
|
||||||
|
message: nil
|
||||||
|
},
|
||||||
|
contact: %{
|
||||||
|
email: Keyword.get(instance, :email),
|
||||||
|
account: nil
|
||||||
|
},
|
||||||
|
# Extra (not present in Mastodon):
|
||||||
|
pleroma: pleroma_configuration2(instance)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp common_information(instance) do
|
||||||
|
%{
|
||||||
|
title: Keyword.get(instance, :name),
|
||||||
|
version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})",
|
||||||
|
languages: Keyword.get(instance, :languages, ["en"])
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -133,7 +157,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
||||||
|> Map.put(:enabled, Config.get([:instance, :federating]))
|
|> Map.put(:enabled, Config.get([:instance, :federating]))
|
||||||
end
|
end
|
||||||
|
|
||||||
def fields_limits do
|
defp fields_limits do
|
||||||
%{
|
%{
|
||||||
max_fields: Config.get([:instance, :max_account_fields]),
|
max_fields: Config.get([:instance, :max_account_fields]),
|
||||||
max_remote_fields: Config.get([:instance, :max_remote_account_fields]),
|
max_remote_fields: Config.get([:instance, :max_remote_account_fields]),
|
||||||
|
@ -141,4 +165,65 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
||||||
value_length: Config.get([:instance, :account_field_value_length])
|
value_length: Config.get([:instance, :account_field_value_length])
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp configuration do
|
||||||
|
%{
|
||||||
|
statuses: %{
|
||||||
|
max_characters: Config.get([:instance, :limit]),
|
||||||
|
max_media_attachments: Config.get([:instance, :max_media_attachments])
|
||||||
|
},
|
||||||
|
media_attachments: %{
|
||||||
|
image_size_limit: Config.get([:instance, :upload_limit]),
|
||||||
|
video_size_limit: Config.get([:instance, :upload_limit])
|
||||||
|
},
|
||||||
|
polls: %{
|
||||||
|
max_options: Config.get([:instance, :poll_limits, :max_options]),
|
||||||
|
max_characters_per_option: Config.get([:instance, :poll_limits, :max_option_chars]),
|
||||||
|
min_expiration: Config.get([:instance, :poll_limits, :min_expiration]),
|
||||||
|
max_expiration: Config.get([:instance, :poll_limits, :max_expiration])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp configuration2 do
|
||||||
|
configuration()
|
||||||
|
|> Map.merge(%{
|
||||||
|
urls: %{streaming: Pleroma.Web.Endpoint.websocket_url()}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp pleroma_configuration(instance) do
|
||||||
|
%{
|
||||||
|
metadata: %{
|
||||||
|
account_activation_required: Keyword.get(instance, :account_activation_required),
|
||||||
|
features: features(),
|
||||||
|
federation: federation(),
|
||||||
|
fields_limits: fields_limits(),
|
||||||
|
post_formats: Config.get([:instance, :allowed_post_formats]),
|
||||||
|
birthday_required: Config.get([:instance, :birthday_required]),
|
||||||
|
birthday_min_age: Config.get([:instance, :birthday_min_age])
|
||||||
|
},
|
||||||
|
stats: %{mau: Pleroma.User.active_user_count()},
|
||||||
|
vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp pleroma_configuration2(instance) do
|
||||||
|
configuration = pleroma_configuration(instance)
|
||||||
|
|
||||||
|
configuration
|
||||||
|
|> Map.merge(%{
|
||||||
|
metadata:
|
||||||
|
configuration.metadata
|
||||||
|
|> Map.merge(%{
|
||||||
|
avatar_upload_limit: Keyword.get(instance, :avatar_upload_limit),
|
||||||
|
background_upload_limit: Keyword.get(instance, :background_upload_limit),
|
||||||
|
banner_upload_limit: Keyword.get(instance, :banner_upload_limit),
|
||||||
|
background_image:
|
||||||
|
Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image),
|
||||||
|
description_limit: Keyword.get(instance, :description_limit),
|
||||||
|
shout_limit: Config.get([:shout, :limit])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -783,11 +783,14 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
scope "/api/v2", Pleroma.Web.MastodonAPI do
|
scope "/api/v2", Pleroma.Web.MastodonAPI do
|
||||||
pipe_through(:api)
|
pipe_through(:api)
|
||||||
|
|
||||||
get("/search", SearchController, :search2)
|
get("/search", SearchController, :search2)
|
||||||
|
|
||||||
post("/media", MediaController, :create2)
|
post("/media", MediaController, :create2)
|
||||||
|
|
||||||
get("/suggestions", SuggestionController, :index2)
|
get("/suggestions", SuggestionController, :index2)
|
||||||
|
|
||||||
|
get("/instance", InstanceController, :show2)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api", Pleroma.Web do
|
scope "/api", Pleroma.Web do
|
||||||
|
|
|
@ -70,7 +70,7 @@ defmodule Pleroma.Web.WebFinger do
|
||||||
|
|
||||||
def represent_user(user, "JSON") do
|
def represent_user(user, "JSON") do
|
||||||
%{
|
%{
|
||||||
"subject" => "acct:#{user.nickname}@#{domain()}",
|
"subject" => "acct:#{user.nickname}@#{host()}",
|
||||||
"aliases" => gather_aliases(user),
|
"aliases" => gather_aliases(user),
|
||||||
"links" => gather_links(user)
|
"links" => gather_links(user)
|
||||||
}
|
}
|
||||||
|
@ -90,13 +90,13 @@ defmodule Pleroma.Web.WebFinger do
|
||||||
:XRD,
|
:XRD,
|
||||||
%{xmlns: "http://docs.oasis-open.org/ns/xri/xrd-1.0"},
|
%{xmlns: "http://docs.oasis-open.org/ns/xri/xrd-1.0"},
|
||||||
[
|
[
|
||||||
{:Subject, "acct:#{user.nickname}@#{domain()}"}
|
{:Subject, "acct:#{user.nickname}@#{host()}"}
|
||||||
] ++ aliases ++ links
|
] ++ aliases ++ links
|
||||||
}
|
}
|
||||||
|> XmlBuilder.to_doc()
|
|> XmlBuilder.to_doc()
|
||||||
end
|
end
|
||||||
|
|
||||||
defp domain do
|
def host do
|
||||||
Pleroma.Config.get([__MODULE__, :domain]) || Pleroma.Web.Endpoint.host()
|
Pleroma.Config.get([__MODULE__, :domain]) || Pleroma.Web.Endpoint.host()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -106,4 +106,11 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
|
||||||
|> get("/api/v1/instance")
|
|> get("/api/v1/instance")
|
||||||
|> json_response_and_validate_schema(200)
|
|> json_response_and_validate_schema(200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "get instance information v2", %{conn: conn} do
|
||||||
|
clear_config([:auth, :oauth_consumer_strategies], [])
|
||||||
|
|
||||||
|
assert get(conn, "/api/v2/instance")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue