X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fmastodon_api%2Fviews%2Faccount_view.ex;h=2d497689115c1cd85d990b95a9b00c0708464fe4;hb=86f2fbc81e5f3df6c16e05127e9e39c8fca0cde9;hp=62c516f8eb97989538a1b3e3c3b0e050574ce50d;hpb=e3534f5b3c68f9bf6a10c5fc10aa637ef66ab82e;p=akkoma diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 62c516f8e..2fe46158b 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -1,25 +1,31 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors +# Copyright © 2017-2020 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.MastodonAPI.AccountView do use Pleroma.Web, :view - alias Pleroma.HTML alias Pleroma.User + alias Pleroma.UserRelationship alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.MastodonAPI.AccountView alias Pleroma.Web.MediaProxy - def render("accounts.json", %{users: users} = opts) do + defp find_following_rel(following_relationships, follower, following) do + Enum.find(following_relationships, fn + fr -> fr.follower_id == follower.id and fr.following_id == following.id + end) + end + + def render("index.json", %{users: users} = opts) do users - |> render_many(AccountView, "account.json", opts) + |> render_many(AccountView, "show.json", opts) |> Enum.filter(&Enum.any?/1) end - def render("account.json", %{user: user} = opts) do + def render("show.json", %{user: user} = opts) do if User.visible_for?(user, opts[:for]), - do: do_render("account.json", opts), + do: do_render("show.json", opts), else: %{} end @@ -28,7 +34,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do id: to_string(user.id), acct: user.nickname, username: username_from_nickname(user.nickname), - url: user.ap_id + url: User.profile_url(user) } end @@ -36,27 +42,90 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do %{} end - def render("relationship.json", %{user: %User{} = user, target: %User{} = target}) do - follow_activity = Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(user, target) + def render( + "relationship.json", + %{user: %User{} = reading_user, target: %User{} = target} = opts + ) do + user_relationships = Map.get(opts, :user_relationships) + following_relationships = opts[:following_relationships] + + follow_state = + if following_relationships do + user_to_target_following_relation = + find_following_rel(following_relationships, reading_user, target) - requested = - if follow_activity && !User.following?(target, user) do - follow_activity.data["state"] == "pending" + User.get_follow_state(reading_user, target, user_to_target_following_relation) else - false + User.get_follow_state(reading_user, target) end + followed_by = + if following_relationships do + with %{state: "accept"} <- + find_following_rel(following_relationships, target, reading_user) do + true + else + _ -> false + end + else + User.following?(target, reading_user) + end + + # TODO: add a note on adjusting StatusView.user_relationships_opt/1 re: preloading of user relations %{ id: to_string(target.id), - following: User.following?(user, target), - followed_by: User.following?(target, user), - blocking: User.blocks?(user, target), - muting: User.mutes?(user, target), - muting_notifications: false, - subscribing: User.subscribed_to?(user, target), - requested: requested, - domain_blocking: false, - showing_reblogs: User.showing_reblogs?(user, target), + following: follow_state == "accept", + followed_by: followed_by, + blocking: + UserRelationship.exists?( + user_relationships, + :block, + reading_user, + target, + &User.blocks_user?(&1, &2) + ), + blocked_by: + UserRelationship.exists?( + user_relationships, + :block, + target, + reading_user, + &User.blocks_user?(&1, &2) + ), + muting: + UserRelationship.exists?( + user_relationships, + :mute, + reading_user, + target, + &User.mutes?(&1, &2) + ), + muting_notifications: + UserRelationship.exists?( + user_relationships, + :notification_mute, + reading_user, + target, + &User.muted_notifications?(&1, &2) + ), + subscribing: + UserRelationship.exists?( + user_relationships, + :inverse_subscription, + target, + reading_user, + &User.subscribed_to?(&2, &1) + ), + requested: follow_state == "pending", + domain_blocking: User.blocks_domain?(reading_user, target), + showing_reblogs: + not UserRelationship.exists?( + user_relationships, + :reblog_mute, + reading_user, + target, + &User.muting_reblogs?(&1, &2) + ), endorsed: false } end @@ -65,16 +134,31 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do render_many(targets, AccountView, "relationship.json", user: user, as: :target) end - defp do_render("account.json", %{user: user} = opts) do - display_name = HTML.strip_tags(user.name || user.nickname) + defp do_render("show.json", %{user: user} = opts) do + user = User.sanitize_html(user, User.html_filter_policy(opts[:for])) + display_name = user.name || user.nickname image = User.avatar_url(user) |> MediaProxy.url() header = User.banner_url(user) |> MediaProxy.url() - user_info = User.get_cached_user_info(user) - bot = (user.info.source_data["type"] || "Person") in ["Application", "Service"] + + following_count = + if !user.hide_follows_count or !user.hide_follows or opts[:for] == user do + user.following_count || 0 + else + 0 + end + + followers_count = + if !user.hide_followers_count or !user.hide_followers or opts[:for] == user do + user.follower_count || 0 + else + 0 + end + + bot = user.actor_type in ["Application", "Service"] emojis = - (user.info.source_data["tag"] || []) + (user.source_data["tag"] || []) |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end) |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} -> %{ @@ -85,57 +169,66 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do } end) - fields = - (user.info.source_data["attachment"] || []) - |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end) - |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end) - - bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for])) - - relationship = render("relationship.json", %{user: opts[:for], target: user}) + relationship = + render("relationship.json", %{ + user: opts[:for], + target: user, + user_relationships: opts[:user_relationships], + following_relationships: opts[:following_relationships] + }) %{ id: to_string(user.id), username: username_from_nickname(user.nickname), acct: user.nickname, display_name: display_name, - locked: user_info.locked, + locked: user.locked, created_at: Utils.to_masto_date(user.inserted_at), - followers_count: user_info.follower_count, - following_count: user_info.following_count, - statuses_count: user_info.note_count, - note: bio || "", - url: user.ap_id, + followers_count: followers_count, + following_count: following_count, + statuses_count: user.note_count, + note: user.bio || "", + url: User.profile_url(user), avatar: image, avatar_static: image, header: header, header_static: header, emojis: emojis, - fields: fields, + fields: user.fields, bot: bot, source: %{ - note: HTML.strip_tags((user.bio || "") |> String.replace("
", "\n")), + note: Pleroma.HTML.strip_tags((user.bio || "") |> String.replace("
", "\n")), sensitive: false, - pleroma: %{} + fields: user.raw_fields, + pleroma: %{ + discoverable: user.discoverable, + actor_type: user.actor_type + } }, # Pleroma extension pleroma: %{ - confirmation_pending: user_info.confirmation_pending, + confirmation_pending: user.confirmation_pending, tags: user.tags, - hide_followers: user.info.hide_followers, - hide_follows: user.info.hide_follows, - hide_favorites: user.info.hide_favorites, + hide_followers_count: user.hide_followers_count, + hide_follows_count: user.hide_follows_count, + hide_followers: user.hide_followers, + hide_follows: user.hide_follows, + hide_favorites: user.hide_favorites, relationship: relationship, - skip_thread_containment: user.info.skip_thread_containment, - background_image: image_url(user.info.background) |> MediaProxy.url() + skip_thread_containment: user.skip_thread_containment, + background_image: image_url(user.background) |> MediaProxy.url() } } |> maybe_put_role(user, opts[:for]) - |> maybe_put_settings(user, opts[:for], user_info) + |> maybe_put_settings(user, opts[:for], opts) |> maybe_put_notification_settings(user, opts[:for]) |> maybe_put_settings_store(user, opts[:for], opts) |> maybe_put_chat_token(user, opts[:for], opts) + |> maybe_put_activation_status(user, opts[:for]) + |> maybe_put_follow_requests_count(user, opts[:for]) + |> maybe_put_allow_following_move(user, opts[:for]) + |> maybe_put_unread_conversation_count(user, opts[:for]) end defp username_from_nickname(string) when is_binary(string) do @@ -144,25 +237,40 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do defp username_from_nickname(_), do: nil + defp maybe_put_follow_requests_count( + data, + %User{id: user_id} = user, + %User{id: user_id} + ) do + count = + User.get_follow_requests(user) + |> length() + + data + |> Kernel.put_in([:follow_requests_count], count) + end + + defp maybe_put_follow_requests_count(data, _, _), do: data + defp maybe_put_settings( data, %User{id: user_id} = user, %User{id: user_id}, - user_info + _opts ) do data - |> Kernel.put_in([:source, :privacy], user_info.default_scope) - |> Kernel.put_in([:source, :pleroma, :show_role], user.info.show_role) - |> Kernel.put_in([:source, :pleroma, :no_rich_text], user.info.no_rich_text) + |> Kernel.put_in([:source, :privacy], user.default_scope) + |> Kernel.put_in([:source, :pleroma, :show_role], user.show_role) + |> Kernel.put_in([:source, :pleroma, :no_rich_text], user.no_rich_text) end defp maybe_put_settings(data, _, _, _), do: data - defp maybe_put_settings_store(data, %User{info: info, id: id}, %User{id: id}, %{ + defp maybe_put_settings_store(data, %User{} = user, %User{}, %{ with_pleroma_settings: true }) do data - |> Kernel.put_in([:pleroma, :settings_store], info.pleroma_settings_store) + |> Kernel.put_in([:pleroma, :settings_store], user.pleroma_settings_store) end defp maybe_put_settings_store(data, _, _, _), do: data @@ -176,26 +284,48 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do defp maybe_put_chat_token(data, _, _, _), do: data - defp maybe_put_role(data, %User{info: %{show_role: true}} = user, _) do + defp maybe_put_role(data, %User{show_role: true} = user, _) do data - |> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin) - |> Kernel.put_in([:pleroma, :is_moderator], user.info.is_moderator) + |> Kernel.put_in([:pleroma, :is_admin], user.is_admin) + |> Kernel.put_in([:pleroma, :is_moderator], user.is_moderator) end defp maybe_put_role(data, %User{id: user_id} = user, %User{id: user_id}) do data - |> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin) - |> Kernel.put_in([:pleroma, :is_moderator], user.info.is_moderator) + |> Kernel.put_in([:pleroma, :is_admin], user.is_admin) + |> Kernel.put_in([:pleroma, :is_moderator], user.is_moderator) end defp maybe_put_role(data, _, _), do: data defp maybe_put_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do - Kernel.put_in(data, [:pleroma, :notification_settings], user.info.notification_settings) + Kernel.put_in(data, [:pleroma, :notification_settings], user.notification_settings) end defp maybe_put_notification_settings(data, _, _), do: data + defp maybe_put_allow_following_move(data, %User{id: user_id} = user, %User{id: user_id}) do + Kernel.put_in(data, [:pleroma, :allow_following_move], user.allow_following_move) + end + + defp maybe_put_allow_following_move(data, _, _), do: data + + defp maybe_put_activation_status(data, user, %User{is_admin: true}) do + Kernel.put_in(data, [:pleroma, :deactivated], user.deactivated) + end + + defp maybe_put_activation_status(data, _, _), do: data + + defp maybe_put_unread_conversation_count(data, %User{id: user_id} = user, %User{id: user_id}) do + data + |> Kernel.put_in( + [:pleroma, :unread_conversation_count], + user.unread_conversation_count + ) + end + + defp maybe_put_unread_conversation_count(data, _, _), do: data + defp image_url(%{"url" => [%{"href" => href} | _]}), do: href defp image_url(_), do: nil end