First
[anni] / lib / pleroma / web / mastodon_api / views / instance_view.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.MastodonAPI.InstanceView do
6   use Pleroma.Web, :view
7
8   alias Pleroma.Config
9   alias Pleroma.Web.ActivityPub.MRF
10
11   @mastodon_api_level "2.7.2"
12
13   def render("show.json", _) do
14     instance = Config.get(:instance)
15
16     %{
17       uri: Pleroma.Web.Endpoint.url(),
18       title: Keyword.get(instance, :name),
19       description: Keyword.get(instance, :description),
20       short_description: Keyword.get(instance, :short_description),
21       version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})",
22       email: Keyword.get(instance, :email),
23       urls: %{
24         streaming_api: Pleroma.Web.Endpoint.websocket_url()
25       },
26       stats: Pleroma.Stats.get_stats(),
27       thumbnail:
28         URI.merge(Pleroma.Web.Endpoint.url(), Keyword.get(instance, :instance_thumbnail))
29         |> to_string,
30       languages: Keyword.get(instance, :languages, ["en"]),
31       registrations: Keyword.get(instance, :registrations_open),
32       approval_required: Keyword.get(instance, :account_approval_required),
33       # Extra (not present in Mastodon):
34       max_toot_chars: Keyword.get(instance, :limit),
35       max_media_attachments: Keyword.get(instance, :max_media_attachments),
36       poll_limits: Keyword.get(instance, :poll_limits),
37       upload_limit: Keyword.get(instance, :upload_limit),
38       avatar_upload_limit: Keyword.get(instance, :avatar_upload_limit),
39       background_upload_limit: Keyword.get(instance, :background_upload_limit),
40       banner_upload_limit: Keyword.get(instance, :banner_upload_limit),
41       background_image: Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image),
42       shout_limit: Config.get([:shout, :limit]),
43       description_limit: Keyword.get(instance, :description_limit),
44       pleroma: %{
45         metadata: %{
46           account_activation_required: Keyword.get(instance, :account_activation_required),
47           features: features(),
48           federation: federation(),
49           fields_limits: fields_limits(),
50           post_formats: Config.get([:instance, :allowed_post_formats]),
51           birthday_required: Config.get([:instance, :birthday_required]),
52           birthday_min_age: Config.get([:instance, :birthday_min_age])
53         },
54         stats: %{mau: Pleroma.User.active_user_count()},
55         vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
56       }
57     }
58   end
59
60   def features do
61     [
62       "pleroma_api",
63       "mastodon_api",
64       "mastodon_api_streaming",
65       "polls",
66       "v2_suggestions",
67       "pleroma_explicit_addressing",
68       "shareable_emoji_packs",
69       "multifetch",
70       "pleroma:api/v1/notifications:include_types_filter",
71       "editing",
72       if Config.get([:activitypub, :blockers_visible]) do
73         "blockers_visible"
74       end,
75       if Config.get([:media_proxy, :enabled]) do
76         "media_proxy"
77       end,
78       if Config.get([:gopher, :enabled]) do
79         "gopher"
80       end,
81       # backwards compat
82       if Config.get([:shout, :enabled]) do
83         "chat"
84       end,
85       if Config.get([:shout, :enabled]) do
86         "shout"
87       end,
88       if Config.get([:instance, :allow_relay]) do
89         "relay"
90       end,
91       if Config.get([:instance, :safe_dm_mentions]) do
92         "safe_dm_mentions"
93       end,
94       "pleroma_emoji_reactions",
95       "pleroma_chat_messages",
96       if Config.get([:instance, :show_reactions]) do
97         "exposable_reactions"
98       end,
99       if Config.get([:instance, :profile_directory]) do
100         "profile_directory"
101       end,
102       "pleroma:get:main/ostatus"
103     ]
104     |> Enum.filter(& &1)
105   end
106
107   def federation do
108     quarantined = Config.get([:instance, :quarantined_instances], [])
109
110     if Config.get([:mrf, :transparency]) do
111       {:ok, data} = MRF.describe()
112
113       data
114       |> Map.put(
115         :quarantined_instances,
116         Enum.map(quarantined, fn {instance, _reason} -> instance end)
117       )
118       # This is for backwards compatibility. We originally didn't sent
119       # extra info like a reason why an instance was rejected/quarantined/etc.
120       # Because we didn't want to break backwards compatibility it was decided
121       # to add an extra "info" key.
122       |> Map.put(:quarantined_instances_info, %{
123         "quarantined_instances" =>
124           quarantined
125           |> Enum.map(fn {instance, reason} -> {instance, %{"reason" => reason}} end)
126           |> Map.new()
127       })
128     else
129       %{}
130     end
131     |> Map.put(:enabled, Config.get([:instance, :federating]))
132   end
133
134   def fields_limits do
135     %{
136       max_fields: Config.get([:instance, :max_account_fields]),
137       max_remote_fields: Config.get([:instance, :max_remote_account_fields]),
138       name_length: Config.get([:instance, :account_field_name_length]),
139       value_length: Config.get([:instance, :account_field_value_length])
140     }
141   end
142 end