Merge remote-tracking branch 'origin/develop' into sixohsix/pleroma-post_expiration

This commit is contained in:
lain 2019-08-24 15:48:33 +02:00
commit cc6c0b4ba6
276 changed files with 7847 additions and 1792 deletions

View file

@ -13,10 +13,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
alias Pleroma.User
alias Pleroma.Web.CommonAPI
@spec follow(User.t(), User.t(), map) :: {:ok, User.t()} | {:error, String.t()}
def follow(follower, followed, params \\ %{}) do
options = cast_params(params)
reblogs = options[:reblogs]
result =
if not User.following?(follower, followed) do
CommonAPI.follow(follower, followed)
@ -24,19 +22,25 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
{:ok, follower, followed, nil}
end
with {:ok, follower, followed, _} <- result do
reblogs
|> case do
false -> CommonAPI.hide_reblogs(follower, followed)
_ -> CommonAPI.show_reblogs(follower, followed)
end
|> case do
with {:ok, follower, _followed, _} <- result do
options = cast_params(params)
case reblogs_visibility(options[:reblogs], result) do
{:ok, follower} -> {:ok, follower}
_ -> {:ok, follower}
end
end
end
defp reblogs_visibility(false, {:ok, follower, followed, _}) do
CommonAPI.hide_reblogs(follower, followed)
end
defp reblogs_visibility(_, {:ok, follower, followed, _}) do
CommonAPI.show_reblogs(follower, followed)
end
@spec get_followers(User.t(), map()) :: list(User.t())
def get_followers(user, params \\ %{}) do
user
|> User.get_followers_query()

View file

@ -4,6 +4,10 @@
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
use Pleroma.Web, :controller
import Pleroma.Web.ControllerHelper,
only: [json_response: 3, add_link_headers: 5, add_link_headers: 4, add_link_headers: 3]
alias Ecto.Changeset
alias Pleroma.Activity
alias Pleroma.Bookmark
@ -46,6 +50,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
import Ecto.Query
require Logger
require Pleroma.Constants
@rate_limited_relations_actions ~w(follow unfollow)a
@ -74,6 +79,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
plug(RateLimiter, :app_account_creation when action == :account_register)
plug(RateLimiter, :search when action in [:search, :search2, :account_search])
plug(RateLimiter, :password_reset when action == :password_reset)
plug(RateLimiter, :account_confirmation_resend when action == :account_confirmation_resend)
@local_mastodon_name "Mastodon-Local"
@ -132,7 +138,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
user_info_emojis =
((user.info.emoji || []) ++ Formatter.get_emoji_map(emojis_text))
user.info
|> Map.get(:emoji, [])
|> Enum.concat(Formatter.get_emoji_map(emojis_text))
|> Enum.dedup()
info_params =
@ -151,6 +159,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end)
end)
|> add_if_present(params, "default_scope", :default_scope)
|> add_if_present(params, "fields", :fields, fn fields ->
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
{:ok, fields}
end)
|> add_if_present(params, "fields", :raw_fields)
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
end)
@ -337,71 +351,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
json(conn, mastodon_emoji)
end
defp add_link_headers(conn, method, activities, param \\ nil, params \\ %{}) do
params =
conn.params
|> Map.drop(["since_id", "max_id", "min_id"])
|> Map.merge(params)
last = List.last(activities)
if last do
max_id = last.id
limit =
params
|> Map.get("limit", "20")
|> String.to_integer()
min_id =
if length(activities) <= limit do
activities
|> List.first()
|> Map.get(:id)
else
activities
|> Enum.at(limit * -1)
|> Map.get(:id)
end
{next_url, prev_url} =
if param do
{
mastodon_api_url(
Pleroma.Web.Endpoint,
method,
param,
Map.merge(params, %{max_id: max_id})
),
mastodon_api_url(
Pleroma.Web.Endpoint,
method,
param,
Map.merge(params, %{min_id: min_id})
)
}
else
{
mastodon_api_url(
Pleroma.Web.Endpoint,
method,
Map.merge(params, %{max_id: max_id})
),
mastodon_api_url(
Pleroma.Web.Endpoint,
method,
Map.merge(params, %{min_id: min_id})
)
}
end
conn
|> put_resp_header("link", "<#{next_url}>; rel=\"next\", <#{prev_url}>; rel=\"prev\"")
else
conn
end
end
def home_timeline(%{assigns: %{user: user}} = conn, params) do
params =
params
@ -430,6 +379,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> Map.put("local_only", local_only)
|> Map.put("blocking_user", user)
|> Map.put("muting_user", user)
|> Map.put("user", user)
|> ActivityPub.fetch_public_activities()
|> Enum.reverse()
@ -491,12 +441,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
activities <-
ActivityPub.fetch_activities_for_context(activity.data["context"], %{
"blocking_user" => user,
"user" => user
"user" => user,
"exclude_id" => activity.id
}),
activities <-
activities |> Enum.filter(fn %{id: aid} -> to_string(aid) != to_string(id) end),
activities <-
activities |> Enum.filter(fn %{data: %{"type" => type}} -> type == "Create" end),
grouped_activities <- Enum.group_by(activities, fn %{id: id} -> id < activity.id end) do
result = %{
ancestors:
@ -531,8 +478,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> put_view(StatusView)
|> try_render("poll.json", %{object: object, for: user})
else
nil -> render_error(conn, :not_found, "Record not found")
false -> render_error(conn, :not_found, "Record not found")
error when is_nil(error) or error == false ->
render_error(conn, :not_found, "Record not found")
end
end
@ -880,8 +827,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
with %Activity{data: %{"object" => object}} <- Activity.get_by_id(id),
%Object{data: %{"likes" => likes}} <- Object.normalize(object) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
%Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
q = from(u in User, where: u.ap_id in ^likes)
users =
@ -897,8 +844,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
with %Activity{data: %{"object" => object}} <- Activity.get_by_id(id),
%Object{data: %{"announcements" => announces}} <- Object.normalize(object) do
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
%Object{data: %{"announcements" => announces}} <- Object.normalize(activity) do
q = from(u in User, where: u.ap_id in ^announces)
users =
@ -939,6 +886,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> Map.put("local_only", local_only)
|> Map.put("blocking_user", user)
|> Map.put("muting_user", user)
|> Map.put("user", user)
|> Map.put("tag", tags)
|> Map.put("tag_all", tag_all)
|> Map.put("tag_reject", tag_reject)
@ -1220,10 +1168,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
recipients =
if for_user do
["https://www.w3.org/ns/activitystreams#Public"] ++
[for_user.ap_id | for_user.following]
[Pleroma.Constants.as_public()] ++ [for_user.ap_id | for_user.following]
else
["https://www.w3.org/ns/activitystreams#Public"]
[Pleroma.Constants.as_public()]
end
activities =
@ -1346,6 +1293,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
params
|> Map.put("type", "Create")
|> Map.put("blocking_user", user)
|> Map.put("user", user)
|> Map.put("muting_user", user)
# we must filter the following list for the user to avoid leaking statuses the user
@ -1686,45 +1634,35 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> String.replace("{{user}}", user)
with {:ok, %{status: 200, body: body}} <-
HTTP.get(
url,
[],
adapter: [
recv_timeout: timeout,
pool: :default
]
),
HTTP.get(url, [], adapter: [recv_timeout: timeout, pool: :default]),
{:ok, data} <- Jason.decode(body) do
data =
data
|> Enum.slice(0, limit)
|> Enum.map(fn x ->
Map.put(
x,
"id",
case User.get_or_fetch(x["acct"]) do
{:ok, %User{id: id}} -> id
_ -> 0
end
)
end)
|> Enum.map(fn x ->
Map.put(x, "avatar", MediaProxy.url(x["avatar"]))
end)
|> Enum.map(fn x ->
Map.put(x, "avatar_static", MediaProxy.url(x["avatar_static"]))
x
|> Map.put("id", fetch_suggestion_id(x))
|> Map.put("avatar", MediaProxy.url(x["avatar"]))
|> Map.put("avatar_static", MediaProxy.url(x["avatar_static"]))
end)
conn
|> json(data)
json(conn, data)
else
e -> Logger.error("Could not retrieve suggestions at fetch #{url}, #{inspect(e)}")
e ->
Logger.error("Could not retrieve suggestions at fetch #{url}, #{inspect(e)}")
end
else
json(conn, [])
end
end
defp fetch_suggestion_id(attrs) do
case User.get_or_fetch(attrs["acct"]) do
{:ok, %User{id: id}} -> id
_ -> 0
end
end
def status_card(%{assigns: %{user: user}} = conn, %{"id" => status_id}) do
with %Activity{} = activity <- Activity.get_by_id(status_id),
true <- Visibility.visible_for_user?(activity, user) do
@ -1803,7 +1741,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
conversations =
Enum.map(participations, fn participation ->
ConversationView.render("participation.json", %{participation: participation, user: user})
ConversationView.render("participation.json", %{participation: participation, for: user})
end)
conn
@ -1816,7 +1754,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
Repo.get_by(Participation, id: participation_id, user_id: user.id),
{:ok, participation} <- Participation.mark_as_read(participation) do
participation_view =
ConversationView.render("participation.json", %{participation: participation, user: user})
ConversationView.render("participation.json", %{participation: participation, for: user})
conn
|> json(participation_view)
@ -1839,6 +1777,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
def account_confirmation_resend(conn, params) do
nickname_or_email = params["email"] || params["nickname"]
with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email),
{:ok, _} <- User.try_send_confirmation_email(user) do
conn
|> json_response(:no_content, "")
end
end
def try_render(conn, target, params)
when is_binary(target) do
case render(conn, target, params) do

View file

@ -28,7 +28,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
@ -37,11 +37,11 @@ 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)
follow_state = User.get_cached_follow_state(user, target)
requested =
if follow_activity && !User.following?(target, user) do
follow_activity.data["state"] == "pending"
if follow_state && !User.following?(user, target) do
follow_state == "pending"
else
false
end
@ -50,13 +50,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
id: to_string(target.id),
following: User.following?(user, target),
followed_by: User.following?(target, user),
blocking: User.blocks?(user, target),
blocked_by: User.blocks?(target, user),
blocking: User.blocks_ap_id?(user, target),
blocked_by: User.blocks_ap_id?(target, user),
muting: User.mutes?(user, target),
muting_notifications: User.muted_notifications?(user, target),
subscribing: User.subscribed_to?(user, target),
requested: requested,
domain_blocking: false,
domain_blocking: User.blocks_domain?(user, target),
showing_reblogs: User.showing_reblogs?(user, target),
endorsed: false
}
@ -72,6 +72,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
image = User.avatar_url(user) |> MediaProxy.url()
header = User.banner_url(user) |> MediaProxy.url()
user_info = User.get_cached_user_info(user)
following_count =
((!user.info.hide_follows or opts[:for] == user) && user_info.following_count) || 0
followers_count =
((!user.info.hide_followers or opts[:for] == user) && user_info.follower_count) || 0
bot = (user.info.source_data["type"] || "Person") in ["Application", "Service"]
emojis =
@ -87,12 +94,18 @@ 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)
user.info
|> User.Info.fields()
|> Enum.map(fn %{"name" => name, "value" => value} ->
%{
"name" => Pleroma.HTML.strip_tags(name),
"value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
}
end)
raw_fields = Map.get(user.info, :raw_fields, [])
bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for]))
relationship = render("relationship.json", %{user: opts[:for], target: user})
%{
@ -102,11 +115,11 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
display_name: display_name,
locked: user_info.locked,
created_at: Utils.to_masto_date(user.inserted_at),
followers_count: user_info.follower_count,
following_count: user_info.following_count,
followers_count: followers_count,
following_count: following_count,
statuses_count: user_info.note_count,
note: bio || "",
url: user.ap_id,
url: User.profile_url(user),
avatar: image,
avatar_static: image,
header: header,
@ -117,6 +130,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
source: %{
note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
sensitive: false,
fields: raw_fields,
pleroma: %{}
},

View file

@ -11,8 +11,8 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.StatusView
def render("participation.json", %{participation: participation, user: user}) do
participation = Repo.preload(participation, conversation: :users)
def render("participation.json", %{participation: participation, for: user}) do
participation = Repo.preload(participation, conversation: [], recipients: [])
last_activity_id =
with nil <- participation.last_activity_id do
@ -28,7 +28,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do
# Conversations return all users except the current user.
users =
participation.conversation.users
participation.recipients
|> Enum.reject(&(&1.id == user.id))
accounts =

View file

@ -5,8 +5,12 @@
defmodule Pleroma.Web.MastodonAPI.StatusView do
use Pleroma.Web, :view
require Pleroma.Constants
alias Pleroma.Activity
alias Pleroma.ActivityExpiration
alias Pleroma.Conversation
alias Pleroma.Conversation.Participation
alias Pleroma.HTML
alias Pleroma.Object
alias Pleroma.Repo
@ -25,19 +29,19 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
defp get_replied_to_activities(activities) do
activities
|> Enum.map(fn
%{data: %{"type" => "Create", "object" => object}} ->
object = Object.normalize(object)
object.data["inReplyTo"] != "" && object.data["inReplyTo"]
%{data: %{"type" => "Create"}} = activity ->
object = Object.normalize(activity)
object && object.data["inReplyTo"] != "" && object.data["inReplyTo"]
_ ->
nil
end)
|> Enum.filter(& &1)
|> Activity.create_by_object_ap_id()
|> Activity.create_by_object_ap_id_with_object()
|> Repo.all()
|> Enum.reduce(%{}, fn activity, acc ->
object = Object.normalize(activity)
Map.put(acc, object.data["id"], activity)
if object, do: Map.put(acc, object.data["id"], activity), else: acc
end)
end
@ -69,12 +73,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
def render("index.json", opts) do
replied_to_activities = get_replied_to_activities(opts.activities)
parallel = unless is_nil(opts[:parallel]), do: opts[:parallel], else: true
opts.activities
|> safe_render_many(
StatusView,
"status.json",
Map.put(opts, :replied_to_activities, replied_to_activities)
Map.put(opts, :replied_to_activities, replied_to_activities),
parallel
)
end
@ -89,6 +95,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
reblogged_activity =
Activity.create_by_object_ap_id(activity_object.data["id"])
|> Activity.with_preloaded_bookmark(opts[:for])
|> Activity.with_set_thread_muted_field(opts[:for])
|> Repo.one()
reblogged = render("status.json", Map.put(opts, :activity, reblogged_activity))
@ -143,6 +150,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
object = Object.normalize(activity)
user = get_user(activity.data["actor"])
user_follower_address = user.follower_address
like_count = object.data["like_count"] || 0
announcement_count = object.data["announcement_count"] || 0
@ -158,7 +166,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
mentions =
(object.data["to"] ++ tag_mentions)
|> Enum.uniq()
|> Enum.map(fn ap_id -> User.get_cached_by_ap_id(ap_id) end)
|> Enum.map(fn
Pleroma.Constants.as_public() -> nil
^user_follower_address -> nil
ap_id -> User.get_cached_by_ap_id(ap_id)
end)
|> Enum.filter(& &1)
|> Enum.map(fn user -> AccountView.render("mention.json", %{user: user}) end)
@ -178,7 +190,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
thread_muted? =
case activity.thread_muted? do
thread_muted? when is_boolean(thread_muted?) -> thread_muted?
nil -> CommonAPI.thread_muted?(user, activity)
nil -> (opts[:for] && CommonAPI.thread_muted?(opts[:for], activity)) || false
end
attachment_data = object.data["attachment"] || []
@ -232,7 +244,20 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
if user.local do
Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, activity)
else
object.data["external_url"] || object.data["id"]
object.data["url"] || object.data["external_url"] || object.data["id"]
end
direct_conversation_id =
with {_, true} <- {:include_id, opts[:with_direct_conversation_id]},
{_, %User{} = for_user} <- {:for_user, opts[:for]},
%{data: %{"context" => context}} when is_binary(context) <- activity,
%Conversation{} = conversation <- Conversation.get_for_ap_id(context),
%Participation{id: participation_id} <-
Participation.for_user_and_conversation(for_user, conversation) do
participation_id
else
_e ->
nil
end
%{
@ -273,7 +298,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
in_reply_to_account_acct: reply_to_user && reply_to_user.nickname,
content: %{"text/plain" => content_plaintext},
spoiler_text: %{"text/plain" => summary_plaintext},
expires_at: expires_at
expires_at: expires_at,
direct_conversation_id: direct_conversation_id
}
}
end