Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into features/remote-follow-userpage-redirect
This commit is contained in:
commit
cedee2793d
70 changed files with 4504 additions and 523 deletions
|
|
@ -52,6 +52,9 @@ defmodule Mix.Tasks.Pleroma.Config do
|
|||
|
||||
defp do_migrate_to_db(config_file) do
|
||||
if File.exists?(config_file) do
|
||||
Ecto.Adapters.SQL.query!(Repo, "TRUNCATE config;")
|
||||
Ecto.Adapters.SQL.query!(Repo, "ALTER SEQUENCE config_id_seq RESTART;")
|
||||
|
||||
custom_config =
|
||||
config_file
|
||||
|> read_file()
|
||||
|
|
|
|||
25
lib/mix/tasks/pleroma/email.ex
Normal file
25
lib/mix/tasks/pleroma/email.ex
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
defmodule Mix.Tasks.Pleroma.Email do
|
||||
use Mix.Task
|
||||
|
||||
@shortdoc "Simple Email test"
|
||||
@moduledoc File.read!("docs/administration/CLI_tasks/email.md")
|
||||
|
||||
def run(["test" | args]) do
|
||||
Mix.Pleroma.start_pleroma()
|
||||
|
||||
{options, [], []} =
|
||||
OptionParser.parse(
|
||||
args,
|
||||
strict: [
|
||||
to: :string
|
||||
]
|
||||
)
|
||||
|
||||
email = Pleroma.Emails.AdminEmail.test_email(options[:to])
|
||||
{:ok, _} = Pleroma.Emails.Mailer.deliver(email)
|
||||
|
||||
Mix.shell().info(
|
||||
"Test email has been sent to #{inspect(email.to)} from #{inspect(email.from)}"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -9,6 +9,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
|
|||
@moduledoc File.read!("docs/administration/CLI_tasks/emoji.md")
|
||||
|
||||
def run(["ls-packs" | args]) do
|
||||
Mix.Pleroma.start_pleroma()
|
||||
Application.ensure_all_started(:hackney)
|
||||
|
||||
{options, [], []} = parse_global_opts(args)
|
||||
|
|
@ -35,6 +36,7 @@ defmodule Mix.Tasks.Pleroma.Emoji do
|
|||
end
|
||||
|
||||
def run(["get-packs" | args]) do
|
||||
Mix.Pleroma.start_pleroma()
|
||||
Application.ensure_all_started(:hackney)
|
||||
|
||||
{options, pack_names, []} = parse_global_opts(args)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ defmodule Mix.Tasks.Pleroma.RobotsTxt do
|
|||
|
||||
"""
|
||||
def run(["disallow_all"]) do
|
||||
Mix.Pleroma.start_pleroma()
|
||||
static_dir = Pleroma.Config.get([:instance, :static_dir], "instance/static/")
|
||||
|
||||
if !File.exists?(static_dir) do
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ defmodule Pleroma.Activity do
|
|||
"Follow" => "follow",
|
||||
"Announce" => "reblog",
|
||||
"Like" => "favourite",
|
||||
"Move" => "move"
|
||||
"Move" => "move",
|
||||
"EmojiReaction" => "pleroma:emoji_reaction"
|
||||
}
|
||||
|
||||
@mastodon_to_ap_notification_types for {k, v} <- @mastodon_notification_types,
|
||||
|
|
|
|||
|
|
@ -236,15 +236,7 @@ defmodule Pleroma.ConfigDB do
|
|||
end
|
||||
|
||||
@spec from_string(String.t()) :: atom() | no_return()
|
||||
def from_string(":" <> entity), do: String.to_existing_atom(entity)
|
||||
|
||||
def from_string(entity) when is_binary(entity) do
|
||||
if is_module_name?(entity) do
|
||||
String.to_existing_atom("Elixir.#{entity}")
|
||||
else
|
||||
entity
|
||||
end
|
||||
end
|
||||
def from_string(string), do: do_transform_string(string)
|
||||
|
||||
@spec convert(any()) :: any()
|
||||
def convert(entity), do: do_convert(entity)
|
||||
|
|
@ -416,7 +408,7 @@ defmodule Pleroma.ConfigDB do
|
|||
|
||||
@spec is_module_name?(String.t()) :: boolean()
|
||||
def is_module_name?(string) do
|
||||
Regex.match?(~r/^(Pleroma|Phoenix|Tesla|Quack|Ueberauth)\./, string) or
|
||||
Regex.match?(~r/^(Pleroma|Phoenix|Tesla|Quack|Ueberauth|Swoosh)\./, string) or
|
||||
string in ["Oban", "Ueberauth", "ExSyslogger"]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Emails.AdminEmail do
|
|||
|
||||
import Swoosh.Email
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Web.Router.Helpers
|
||||
|
||||
defp instance_config, do: Pleroma.Config.get(:instance)
|
||||
|
|
@ -17,7 +18,20 @@ defmodule Pleroma.Emails.AdminEmail do
|
|||
end
|
||||
|
||||
defp user_url(user) do
|
||||
Helpers.feed_url(Pleroma.Web.Endpoint, :feed_redirect, user.id)
|
||||
Helpers.user_feed_url(Pleroma.Web.Endpoint, :feed_redirect, user.id)
|
||||
end
|
||||
|
||||
def test_email(mail_to \\ nil) do
|
||||
html_body = """
|
||||
<h3>Instance Test Email</h3>
|
||||
<p>A test email was requested. Hello. :)</p>
|
||||
"""
|
||||
|
||||
new()
|
||||
|> to(mail_to || Config.get([:instance, :email]))
|
||||
|> from({instance_name(), instance_notify_email()})
|
||||
|> subject("Instance Test Email")
|
||||
|> html_body(html_body)
|
||||
end
|
||||
|
||||
def report(to, reporter, account, statuses, comment) do
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ defmodule Pleroma.Notification do
|
|||
end
|
||||
|
||||
def create_notifications(%Activity{data: %{"type" => type}} = activity)
|
||||
when type in ["Like", "Announce", "Follow", "Move"] do
|
||||
when type in ["Like", "Announce", "Follow", "Move", "EmojiReaction"] do
|
||||
notifications =
|
||||
activity
|
||||
|> get_notified_from_activity()
|
||||
|
|
@ -322,7 +322,7 @@ defmodule Pleroma.Notification do
|
|||
def get_notified_from_activity(activity, local_only \\ true)
|
||||
|
||||
def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only)
|
||||
when type in ["Create", "Like", "Announce", "Follow", "Move"] do
|
||||
when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReaction"] do
|
||||
[]
|
||||
|> Utils.maybe_notify_to_recipients(activity)
|
||||
|> Utils.maybe_notify_mentioned_recipients(activity)
|
||||
|
|
|
|||
|
|
@ -117,6 +117,9 @@ defmodule Pleroma.Object.Fetcher do
|
|||
{:error, %Tesla.Mock.Error{}} ->
|
||||
nil
|
||||
|
||||
{:error, "Object has been deleted"} ->
|
||||
nil
|
||||
|
||||
e ->
|
||||
Logger.error("Error while fetching #{id}: #{inspect(e)}")
|
||||
nil
|
||||
|
|
|
|||
|
|
@ -11,11 +11,9 @@ defmodule Pleroma.Plugs.UserEnabledPlug do
|
|||
end
|
||||
|
||||
def call(%{assigns: %{user: %User{} = user}} = conn, _) do
|
||||
if User.auth_active?(user) do
|
||||
conn
|
||||
else
|
||||
conn
|
||||
|> assign(:user, nil)
|
||||
case User.account_status(user) do
|
||||
:active -> conn
|
||||
_ -> assign(conn, :user, nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ defmodule Pleroma.User do
|
|||
alias Comeonin.Pbkdf2
|
||||
alias Ecto.Multi
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Delivery
|
||||
alias Pleroma.FollowingRelationship
|
||||
|
|
@ -35,7 +36,7 @@ defmodule Pleroma.User do
|
|||
require Logger
|
||||
|
||||
@type t :: %__MODULE__{}
|
||||
|
||||
@type account_status :: :active | :deactivated | :password_reset_pending | :confirmation_pending
|
||||
@primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
|
||||
|
||||
# credo:disable-for-next-line Credo.Check.Readability.MaxLineLength
|
||||
|
|
@ -216,14 +217,21 @@ defmodule Pleroma.User do
|
|||
end
|
||||
end
|
||||
|
||||
@doc "Returns if the user should be allowed to authenticate"
|
||||
def auth_active?(%User{deactivated: true}), do: false
|
||||
@doc "Returns status account"
|
||||
@spec account_status(User.t()) :: account_status()
|
||||
def account_status(%User{deactivated: true}), do: :deactivated
|
||||
def account_status(%User{password_reset_pending: true}), do: :password_reset_pending
|
||||
|
||||
def auth_active?(%User{confirmation_pending: true}),
|
||||
do: !Pleroma.Config.get([:instance, :account_activation_required])
|
||||
def account_status(%User{confirmation_pending: true}) do
|
||||
case Config.get([:instance, :account_activation_required]) do
|
||||
true -> :confirmation_pending
|
||||
_ -> :active
|
||||
end
|
||||
end
|
||||
|
||||
def auth_active?(%User{}), do: true
|
||||
def account_status(%User{}), do: :active
|
||||
|
||||
@spec visible_for?(User.t(), User.t() | nil) :: boolean()
|
||||
def visible_for?(user, for_user \\ nil)
|
||||
|
||||
def visible_for?(%User{invisible: true}, _), do: false
|
||||
|
|
@ -231,15 +239,17 @@ defmodule Pleroma.User do
|
|||
def visible_for?(%User{id: user_id}, %User{id: for_id}) when user_id == for_id, do: true
|
||||
|
||||
def visible_for?(%User{} = user, for_user) do
|
||||
auth_active?(user) || superuser?(for_user)
|
||||
account_status(user) == :active || superuser?(for_user)
|
||||
end
|
||||
|
||||
def visible_for?(_, _), do: false
|
||||
|
||||
@spec superuser?(User.t()) :: boolean()
|
||||
def superuser?(%User{local: true, is_admin: true}), do: true
|
||||
def superuser?(%User{local: true, is_moderator: true}), do: true
|
||||
def superuser?(_), do: false
|
||||
|
||||
@spec invisible?(User.t()) :: boolean()
|
||||
def invisible?(%User{invisible: true}), do: true
|
||||
def invisible?(_), do: false
|
||||
|
||||
|
|
@ -1502,7 +1512,7 @@ defmodule Pleroma.User do
|
|||
data
|
||||
|> Map.put(:name, blank?(data[:name]) || data[:nickname])
|
||||
|> remote_user_creation()
|
||||
|> Repo.insert(on_conflict: :replace_all_except_primary_key, conflict_target: :nickname)
|
||||
|> Repo.insert(on_conflict: {:replace_all_except, [:id]}, conflict_target: :nickname)
|
||||
|> set_cache()
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ defmodule Pleroma.UserRelationship do
|
|||
target_id: target.id
|
||||
})
|
||||
|> Repo.insert(
|
||||
on_conflict: :replace_all_except_primary_key,
|
||||
on_conflict: {:replace_all_except, [:id]},
|
||||
conflict_target: [:source_id, :relationship_type, :target_id]
|
||||
)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -728,7 +728,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
params
|
||||
|> Map.put("user", reading_user)
|
||||
|> Map.put("actor_id", user.ap_id)
|
||||
|> Map.put("whole_db", true)
|
||||
|
||||
recipients =
|
||||
user_activities_recipients(%{
|
||||
|
|
@ -746,7 +745,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|> Map.put("type", ["Create", "Announce"])
|
||||
|> Map.put("user", reading_user)
|
||||
|> Map.put("actor_id", user.ap_id)
|
||||
|> Map.put("whole_db", true)
|
||||
|> Map.put("pinned_activity_ids", user.pinned_activities)
|
||||
|
||||
params =
|
||||
|
|
@ -773,7 +771,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
params
|
||||
|> Map.put("type", ["Create", "Announce"])
|
||||
|> Map.put("instance", params["instance"])
|
||||
|> Map.put("whole_db", true)
|
||||
|
||||
fetch_activities([Pleroma.Constants.as_public()], params, :offset)
|
||||
|> Enum.reverse()
|
||||
|
|
@ -1369,6 +1366,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
data <- maybe_update_follow_information(data) do
|
||||
{:ok, data}
|
||||
else
|
||||
{:error, "Object has been deleted"} = e ->
|
||||
Logger.debug("Could not decode user at fetch #{ap_id}, #{inspect(e)}")
|
||||
{:error, e}
|
||||
|
||||
e ->
|
||||
Logger.error("Could not decode user at fetch #{ap_id}, #{inspect(e)}")
|
||||
{:error, e}
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
%Activity{data: %{"content" => emoji, "actor" => actor}},
|
||||
object
|
||||
) do
|
||||
reactions = object.data["reactions"] || []
|
||||
reactions = get_cached_emoji_reactions(object)
|
||||
|
||||
new_reactions =
|
||||
case Enum.find_index(reactions, fn [candidate, _] -> emoji == candidate end) do
|
||||
|
|
@ -365,7 +365,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
%Activity{data: %{"content" => emoji, "actor" => actor}},
|
||||
object
|
||||
) do
|
||||
reactions = object.data["reactions"] || []
|
||||
reactions = get_cached_emoji_reactions(object)
|
||||
|
||||
new_reactions =
|
||||
case Enum.find_index(reactions, fn [candidate, _] -> emoji == candidate end) do
|
||||
|
|
@ -385,6 +385,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
update_element_in_object("reaction", new_reactions, object, count)
|
||||
end
|
||||
|
||||
def get_cached_emoji_reactions(object) do
|
||||
if is_list(object.data["reactions"]) do
|
||||
object.data["reactions"]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
@spec add_like_to_object(Activity.t(), Object.t()) ::
|
||||
{:ok, Object.t()} | {:error, Ecto.Changeset.t()}
|
||||
def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
|
||||
|
|
|
|||
|
|
@ -76,8 +76,7 @@ defmodule Pleroma.Web.ControllerHelper do
|
|||
end
|
||||
end
|
||||
|
||||
def try_render(conn, target, params)
|
||||
when is_binary(target) do
|
||||
def try_render(conn, target, params) when is_binary(target) do
|
||||
case render(conn, target, params) do
|
||||
nil -> render_error(conn, :not_implemented, "Can't display this activity")
|
||||
res -> res
|
||||
|
|
@ -87,4 +86,8 @@ defmodule Pleroma.Web.ControllerHelper do
|
|||
def try_render(conn, _, _) do
|
||||
render_error(conn, :not_implemented, "Can't display this activity")
|
||||
end
|
||||
|
||||
@spec put_in_if_exist(map(), atom() | String.t(), any) :: map()
|
||||
def put_in_if_exist(map, _key, nil), do: map
|
||||
def put_in_if_exist(map, key, value), do: put_in(map, key, value)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,21 +13,53 @@ defmodule Pleroma.Web.Feed.FeedView do
|
|||
|
||||
require Pleroma.Constants
|
||||
|
||||
def prepare_activity(activity) do
|
||||
@spec pub_date(String.t() | DateTime.t()) :: String.t()
|
||||
def pub_date(date) when is_binary(date) do
|
||||
date
|
||||
|> Timex.parse!("{ISO:Extended}")
|
||||
|> pub_date
|
||||
end
|
||||
|
||||
def pub_date(%DateTime{} = date), do: Timex.format!(date, "{RFC822}")
|
||||
|
||||
def prepare_activity(activity, opts \\ []) do
|
||||
object = activity_object(activity)
|
||||
|
||||
actor =
|
||||
if opts[:actor] do
|
||||
Pleroma.User.get_cached_by_ap_id(activity.actor)
|
||||
end
|
||||
|
||||
%{
|
||||
activity: activity,
|
||||
data: Map.get(object, :data),
|
||||
object: object
|
||||
object: object,
|
||||
actor: actor
|
||||
}
|
||||
end
|
||||
|
||||
def most_recent_update(activities) do
|
||||
with %{updated_at: updated_at} <- List.first(activities) do
|
||||
NaiveDateTime.to_iso8601(updated_at)
|
||||
end
|
||||
end
|
||||
|
||||
def most_recent_update(activities, user) do
|
||||
(List.first(activities) || user).updated_at
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
end
|
||||
|
||||
def feed_logo do
|
||||
case Pleroma.Config.get([:feed, :logo]) do
|
||||
nil ->
|
||||
"#{Pleroma.Web.base_url()}/static/logo.png"
|
||||
|
||||
logo ->
|
||||
"#{Pleroma.Web.base_url()}#{logo}"
|
||||
end
|
||||
|> MediaProxy.url()
|
||||
end
|
||||
|
||||
def logo(user) do
|
||||
user
|
||||
|> User.avatar_url()
|
||||
|
|
@ -40,6 +72,8 @@ defmodule Pleroma.Web.Feed.FeedView do
|
|||
|
||||
def activity_title(%{data: %{"content" => content}}, opts \\ %{}) do
|
||||
content
|
||||
|> Pleroma.Web.Metadata.Utils.scrub_html()
|
||||
|> Pleroma.Emoji.Formatter.demojify()
|
||||
|> Formatter.truncate(opts[:max_length], opts[:omission])
|
||||
|> escape()
|
||||
end
|
||||
|
|
@ -50,6 +84,8 @@ defmodule Pleroma.Web.Feed.FeedView do
|
|||
|> escape()
|
||||
end
|
||||
|
||||
def activity_content(_), do: ""
|
||||
|
||||
def activity_context(activity), do: activity.data["context"]
|
||||
|
||||
def attachment_href(attachment) do
|
||||
|
|
|
|||
41
lib/pleroma/web/feed/tag_controller.ex
Normal file
41
lib/pleroma/web/feed/tag_controller.ex
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Feed.TagController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.Feed.FeedView
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [put_in_if_exist: 3]
|
||||
|
||||
def feed(conn, %{"tag" => raw_tag} = params) do
|
||||
{format, tag} = parse_tag(raw_tag)
|
||||
|
||||
activities =
|
||||
%{"type" => ["Create"], "tag" => tag}
|
||||
|> put_in_if_exist("max_id", params["max_id"])
|
||||
|> ActivityPub.fetch_public_activities()
|
||||
|
||||
conn
|
||||
|> put_resp_content_type("application/atom+xml")
|
||||
|> put_view(FeedView)
|
||||
|> render("tag.#{format}",
|
||||
activities: activities,
|
||||
tag: tag,
|
||||
feed_config: Config.get([:feed])
|
||||
)
|
||||
end
|
||||
|
||||
@spec parse_tag(binary() | any()) :: {format :: String.t(), tag :: String.t()}
|
||||
defp parse_tag(raw_tag) when is_binary(raw_tag) do
|
||||
case Enum.reverse(String.split(raw_tag, ".")) do
|
||||
[format | tag] when format in ["atom", "rss"] -> {format, Enum.join(tag, ".")}
|
||||
_ -> {"rss", raw_tag}
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_tag(raw_tag), do: {"rss", raw_tag}
|
||||
end
|
||||
|
|
@ -2,13 +2,16 @@
|
|||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.Feed.FeedController do
|
||||
defmodule Pleroma.Web.Feed.UserController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Fallback.RedirectController
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.ActivityPubController
|
||||
alias Pleroma.Web.Feed.FeedView
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [put_in_if_exist: 3]
|
||||
|
||||
plug(Pleroma.Plugs.SetFormatPlug when action in [:feed_redirect])
|
||||
|
||||
|
|
@ -27,7 +30,7 @@ defmodule Pleroma.Web.Feed.FeedController do
|
|||
|
||||
def feed_redirect(conn, %{"nickname" => nickname}) do
|
||||
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname(nickname)} do
|
||||
redirect(conn, external: "#{feed_url(conn, :feed, user.nickname)}.atom")
|
||||
redirect(conn, external: "#{user_feed_url(conn, :feed, user.nickname)}.atom")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -36,15 +39,15 @@ defmodule Pleroma.Web.Feed.FeedController do
|
|||
activities =
|
||||
%{
|
||||
"type" => ["Create"],
|
||||
"whole_db" => true,
|
||||
"actor_id" => user.ap_id
|
||||
}
|
||||
|> Map.merge(Map.take(params, ["max_id"]))
|
||||
|> put_in_if_exist("max_id", params["max_id"])
|
||||
|> ActivityPub.fetch_public_activities()
|
||||
|
||||
conn
|
||||
|> put_resp_content_type("application/atom+xml")
|
||||
|> render("feed.xml",
|
||||
|> put_view(FeedView)
|
||||
|> render("user.xml",
|
||||
user: user,
|
||||
activities: activities,
|
||||
feed_config: Pleroma.Config.get([:feed])
|
||||
|
|
@ -7,62 +7,8 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionController do
|
|||
|
||||
require Logger
|
||||
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||
|
||||
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :index)
|
||||
|
||||
plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
|
||||
|
||||
@doc "GET /api/v1/suggestions"
|
||||
def index(%{assigns: %{user: user}} = conn, _) do
|
||||
if Config.get([:suggestions, :enabled], false) do
|
||||
with {:ok, data} <- fetch_suggestions(user) do
|
||||
limit = Config.get([:suggestions, :limit], 23)
|
||||
|
||||
data =
|
||||
data
|
||||
|> Enum.slice(0, limit)
|
||||
|> Enum.map(fn x ->
|
||||
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)
|
||||
|
||||
json(conn, data)
|
||||
end
|
||||
else
|
||||
json(conn, [])
|
||||
end
|
||||
end
|
||||
|
||||
defp fetch_suggestions(user) do
|
||||
api = Config.get([:suggestions, :third_party_engine], "")
|
||||
timeout = Config.get([:suggestions, :timeout], 5000)
|
||||
host = Config.get([Pleroma.Web.Endpoint, :url, :host])
|
||||
|
||||
url =
|
||||
api
|
||||
|> String.replace("{{host}}", host)
|
||||
|> String.replace("{{user}}", user.nickname)
|
||||
|
||||
with {:ok, %{status: 200, body: body}} <-
|
||||
Pleroma.HTTP.get(url, [], adapter: [recv_timeout: timeout, pool: :default]) do
|
||||
Jason.decode(body)
|
||||
else
|
||||
e -> Logger.error("Could not retrieve suggestions at fetch #{url}, #{inspect(e)}")
|
||||
end
|
||||
end
|
||||
|
||||
defp fetch_suggestion_id(attrs) do
|
||||
case User.get_or_fetch(attrs["acct"]) do
|
||||
{:ok, %User{id: id}} -> id
|
||||
_ -> 0
|
||||
end
|
||||
def index(conn, _) do
|
||||
json(conn, [])
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@ defmodule Pleroma.Web.MastodonAPI.AppView do
|
|||
|
||||
alias Pleroma.Web.OAuth.App
|
||||
|
||||
@vapid_key :web_push_encryption
|
||||
|> Application.get_env(:vapid_details, [])
|
||||
|> Keyword.get(:public_key)
|
||||
|
||||
def render("show.json", %{app: %App{} = app}) do
|
||||
%{
|
||||
id: app.id |> to_string,
|
||||
|
|
@ -32,8 +28,10 @@ defmodule Pleroma.Web.MastodonAPI.AppView do
|
|||
end
|
||||
|
||||
defp with_vapid_key(data) do
|
||||
if @vapid_key do
|
||||
Map.put(data, "vapid_key", @vapid_key)
|
||||
vapid_key = Application.get_env(:web_push_encryption, :vapid_details, [])[:public_key]
|
||||
|
||||
if vapid_key do
|
||||
Map.put(data, "vapid_key", vapid_key)
|
||||
else
|
||||
data
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,18 +37,37 @@ defmodule Pleroma.Web.MastodonAPI.NotificationView do
|
|||
}
|
||||
|
||||
case mastodon_type do
|
||||
"mention" -> put_status(response, activity, user)
|
||||
"favourite" -> put_status(response, parent_activity, user)
|
||||
"reblog" -> put_status(response, parent_activity, user)
|
||||
"move" -> put_target(response, activity, user)
|
||||
"follow" -> response
|
||||
_ -> nil
|
||||
"mention" ->
|
||||
put_status(response, activity, user)
|
||||
|
||||
"favourite" ->
|
||||
put_status(response, parent_activity, user)
|
||||
|
||||
"reblog" ->
|
||||
put_status(response, parent_activity, user)
|
||||
|
||||
"move" ->
|
||||
put_target(response, activity, user)
|
||||
|
||||
"follow" ->
|
||||
response
|
||||
|
||||
"pleroma:emoji_reaction" ->
|
||||
put_status(response, parent_activity, user) |> put_emoji(activity)
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
else
|
||||
_ -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp put_emoji(response, activity) do
|
||||
response
|
||||
|> Map.put(:emoji, activity.data["content"])
|
||||
end
|
||||
|
||||
defp put_status(response, activity, user) do
|
||||
Map.put(response, :status, StatusView.render("show.json", %{activity: activity, for: user}))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
emoji_reactions =
|
||||
with %{data: %{"reactions" => emoji_reactions}} <- object do
|
||||
Enum.map(emoji_reactions, fn [emoji, users] ->
|
||||
[emoji, length(users)]
|
||||
%{emoji: emoji, count: length(users)}
|
||||
end)
|
||||
else
|
||||
_ -> []
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ defmodule Pleroma.Web.Metadata.Providers.Feed do
|
|||
[
|
||||
rel: "alternate",
|
||||
type: "application/atom+xml",
|
||||
href: Helpers.feed_path(Endpoint, :feed, user.nickname) <> ".atom"
|
||||
href: Helpers.user_feed_path(Endpoint, :feed, user.nickname) <> ".atom"
|
||||
], []}
|
||||
]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,15 +21,22 @@ defmodule Pleroma.Web.Metadata.Utils do
|
|||
|
||||
def scrub_html_and_truncate(content, max_length \\ 200) when is_binary(content) do
|
||||
content
|
||||
# html content comes from DB already encoded, decode first and scrub after
|
||||
|> HtmlEntities.decode()
|
||||
|> String.replace(~r/<br\s?\/?>/, " ")
|
||||
|> HTML.strip_tags()
|
||||
|> scrub_html
|
||||
|> Emoji.Formatter.demojify()
|
||||
|> HtmlEntities.decode()
|
||||
|> Formatter.truncate(max_length)
|
||||
end
|
||||
|
||||
def scrub_html(content) when is_binary(content) do
|
||||
content
|
||||
# html content comes from DB already encoded, decode first and scrub after
|
||||
|> HtmlEntities.decode()
|
||||
|> String.replace(~r/<br\s?\/?>/, " ")
|
||||
|> HTML.strip_tags()
|
||||
end
|
||||
|
||||
def scrub_html(content), do: content
|
||||
|
||||
def attachment_url(url) do
|
||||
MediaProxy.url(url)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -69,9 +69,6 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
if Config.get([:chat, :enabled]) do
|
||||
"chat"
|
||||
end,
|
||||
if Config.get([:suggestions, :enabled]) do
|
||||
"suggestions"
|
||||
end,
|
||||
if Config.get([:instance, :allow_relay]) do
|
||||
"relay"
|
||||
end,
|
||||
|
|
@ -104,11 +101,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
nodeDescription: Config.get([:instance, :description]),
|
||||
private: !Config.get([:instance, :public], true),
|
||||
suggestions: %{
|
||||
enabled: Config.get([:suggestions, :enabled], false),
|
||||
thirdPartyEngine: Config.get([:suggestions, :third_party_engine], ""),
|
||||
timeout: Config.get([:suggestions, :timeout], 5000),
|
||||
limit: Config.get([:suggestions, :limit], 23),
|
||||
web: Config.get([:suggestions, :web], "")
|
||||
enabled: false
|
||||
},
|
||||
staffAccounts: staff_accounts,
|
||||
federation: federation_response,
|
||||
|
|
|
|||
|
|
@ -167,17 +167,37 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
|||
|
||||
defp handle_create_authorization_error(
|
||||
%Plug.Conn{} = conn,
|
||||
{:auth_active, false},
|
||||
{:account_status, :confirmation_pending},
|
||||
%{"authorization" => _} = params
|
||||
) do
|
||||
# Per https://github.com/tootsuite/mastodon/blob/
|
||||
# 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L76
|
||||
conn
|
||||
|> put_flash(:error, dgettext("errors", "Your login is missing a confirmed e-mail address"))
|
||||
|> put_status(:forbidden)
|
||||
|> authorize(params)
|
||||
end
|
||||
|
||||
defp handle_create_authorization_error(
|
||||
%Plug.Conn{} = conn,
|
||||
{:account_status, :password_reset_pending},
|
||||
%{"authorization" => _} = params
|
||||
) do
|
||||
conn
|
||||
|> put_flash(:error, dgettext("errors", "Password reset is required"))
|
||||
|> put_status(:forbidden)
|
||||
|> authorize(params)
|
||||
end
|
||||
|
||||
defp handle_create_authorization_error(
|
||||
%Plug.Conn{} = conn,
|
||||
{:account_status, :deactivated},
|
||||
%{"authorization" => _} = params
|
||||
) do
|
||||
conn
|
||||
|> put_flash(:error, dgettext("errors", "Your account is currently disabled"))
|
||||
|> put_status(:forbidden)
|
||||
|> authorize(params)
|
||||
end
|
||||
|
||||
defp handle_create_authorization_error(%Plug.Conn{} = conn, error, %{"authorization" => _}) do
|
||||
Authenticator.handle_error(conn, error)
|
||||
end
|
||||
|
|
@ -218,46 +238,14 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
|||
) do
|
||||
with {:ok, %User{} = user} <- Authenticator.get_user(conn),
|
||||
{:ok, app} <- Token.Utils.fetch_app(conn),
|
||||
{:auth_active, true} <- {:auth_active, User.auth_active?(user)},
|
||||
{:user_active, true} <- {:user_active, !user.deactivated},
|
||||
{:password_reset_pending, false} <-
|
||||
{:password_reset_pending, user.password_reset_pending},
|
||||
{:account_status, :active} <- {:account_status, User.account_status(user)},
|
||||
{:ok, scopes} <- validate_scopes(app, params),
|
||||
{:ok, auth} <- Authorization.create_authorization(app, user, scopes),
|
||||
{:ok, token} <- Token.exchange_token(app, auth) do
|
||||
json(conn, Token.Response.build(user, token))
|
||||
else
|
||||
{:auth_active, false} ->
|
||||
# Per https://github.com/tootsuite/mastodon/blob/
|
||||
# 51e154f5e87968d6bb115e053689767ab33e80cd/app/controllers/api/base_controller.rb#L76
|
||||
render_error(
|
||||
conn,
|
||||
:forbidden,
|
||||
"Your login is missing a confirmed e-mail address",
|
||||
%{},
|
||||
"missing_confirmed_email"
|
||||
)
|
||||
|
||||
{:user_active, false} ->
|
||||
render_error(
|
||||
conn,
|
||||
:forbidden,
|
||||
"Your account is currently disabled",
|
||||
%{},
|
||||
"account_is_disabled"
|
||||
)
|
||||
|
||||
{:password_reset_pending, true} ->
|
||||
render_error(
|
||||
conn,
|
||||
:forbidden,
|
||||
"Password reset is required",
|
||||
%{},
|
||||
"password_reset_required"
|
||||
)
|
||||
|
||||
_error ->
|
||||
render_invalid_credentials_error(conn)
|
||||
error ->
|
||||
handle_token_exchange_error(conn, error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -286,6 +274,43 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
|||
# Bad request
|
||||
def token_exchange(%Plug.Conn{} = conn, params), do: bad_request(conn, params)
|
||||
|
||||
defp handle_token_exchange_error(%Plug.Conn{} = conn, {:account_status, :deactivated}) do
|
||||
render_error(
|
||||
conn,
|
||||
:forbidden,
|
||||
"Your account is currently disabled",
|
||||
%{},
|
||||
"account_is_disabled"
|
||||
)
|
||||
end
|
||||
|
||||
defp handle_token_exchange_error(
|
||||
%Plug.Conn{} = conn,
|
||||
{:account_status, :password_reset_pending}
|
||||
) do
|
||||
render_error(
|
||||
conn,
|
||||
:forbidden,
|
||||
"Password reset is required",
|
||||
%{},
|
||||
"password_reset_required"
|
||||
)
|
||||
end
|
||||
|
||||
defp handle_token_exchange_error(%Plug.Conn{} = conn, {:account_status, :confirmation_pending}) do
|
||||
render_error(
|
||||
conn,
|
||||
:forbidden,
|
||||
"Your login is missing a confirmed e-mail address",
|
||||
%{},
|
||||
"missing_confirmed_email"
|
||||
)
|
||||
end
|
||||
|
||||
defp handle_token_exchange_error(%Plug.Conn{} = conn, _error) do
|
||||
render_invalid_credentials_error(conn)
|
||||
end
|
||||
|
||||
def token_revoke(%Plug.Conn{} = conn, %{"token" => _token} = params) do
|
||||
with {:ok, app} <- Token.Utils.fetch_app(conn),
|
||||
{:ok, _token} <- RevokeToken.revoke(app, params) do
|
||||
|
|
@ -472,7 +497,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
|||
%App{} = app <- Repo.get_by(App, client_id: client_id),
|
||||
true <- redirect_uri in String.split(app.redirect_uris),
|
||||
{:ok, scopes} <- validate_scopes(app, auth_attrs),
|
||||
{:auth_active, true} <- {:auth_active, User.auth_active?(user)} do
|
||||
{:account_status, :active} <- {:account_status, User.account_status(user)} do
|
||||
Authorization.create_authorization(app, user, scopes)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -49,7 +49,12 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|
|||
emoji_reactions
|
||||
|> Enum.map(fn [emoji, users] ->
|
||||
users = Enum.map(users, &User.get_cached_by_ap_id/1)
|
||||
{emoji, AccountView.render("index.json", %{users: users, for: user, as: :user})}
|
||||
|
||||
%{
|
||||
emoji: emoji,
|
||||
count: length(users),
|
||||
accounts: AccountView.render("index.json", %{users: users, for: user, as: :user})
|
||||
}
|
||||
end)
|
||||
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -48,6 +48,6 @@ defmodule Pleroma.Web.RichMedia.Parsers.MetaTagsParser do
|
|||
defp maybe_put_title(meta, _), do: meta
|
||||
|
||||
defp get_page_title(html) do
|
||||
Floki.find(html, "title") |> Floki.text()
|
||||
Floki.find(html, "title") |> List.first() |> Floki.text()
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -527,8 +527,10 @@ defmodule Pleroma.Web.Router do
|
|||
get("/notice/:id", OStatus.OStatusController, :notice)
|
||||
get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player)
|
||||
|
||||
get("/users/:nickname/feed", Feed.FeedController, :feed)
|
||||
get("/users/:nickname", Feed.FeedController, :feed_redirect)
|
||||
get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed)
|
||||
get("/users/:nickname", Feed.UserController, :feed_redirect, as: :user_feed)
|
||||
|
||||
get("/tags/:tag", Feed.TagController, :feed, as: :tag_feed)
|
||||
end
|
||||
|
||||
scope "/", Pleroma.Web do
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||
<%= activity_context(@activity) %>
|
||||
</ostatus:conversation>
|
||||
<link ref="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
|
||||
<link href="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
|
||||
|
||||
<%= if @data["summary"] do %>
|
||||
<summary><%= @data["summary"] %></summary>
|
||||
|
|
|
|||
51
lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
Normal file
51
lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<entry>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/note</activity:object-type>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
|
||||
<%= render @view_module, "_tag_author.atom", assigns %>
|
||||
|
||||
<id><%= @data["id"] %></id>
|
||||
<title><%= activity_title(@object, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
||||
<content type="html"><%= activity_content(@object) %></content>
|
||||
|
||||
<%= if @activity.local do %>
|
||||
<link type="application/atom+xml" href='<%= @data["id"] %>' rel="self"/>
|
||||
<link type="text/html" href='<%= @data["id"] %>' rel="alternate"/>
|
||||
<% else %>
|
||||
<link type="text/html" href='<%= @data["external_url"] %>' rel="alternate"/>
|
||||
<% end %>
|
||||
|
||||
<published><%= @data["published"] %></published>
|
||||
<updated><%= @data["published"] %></updated>
|
||||
|
||||
<ostatus:conversation ref="<%= activity_context(@activity) %>">
|
||||
<%= activity_context(@activity) %>
|
||||
</ostatus:conversation>
|
||||
<link href="<%= activity_context(@activity) %>" rel="ostatus:conversation"/>
|
||||
|
||||
<%= if @data["summary"] do %>
|
||||
<summary><%= @data["summary"] %></summary>
|
||||
<% end %>
|
||||
|
||||
<%= for id <- @activity.recipients do %>
|
||||
<%= if id == Pleroma.Constants.as_public() do %>
|
||||
<link rel="mentioned"
|
||||
ostatus:object-type="http://activitystrea.ms/schema/1.0/collection"
|
||||
href="http://activityschema.org/collection/public"/>
|
||||
<% else %>
|
||||
<%= unless Regex.match?(~r/^#{Pleroma.Web.base_url()}.+followers$/, id) do %>
|
||||
<link rel="mentioned"
|
||||
ostatus:object-type="http://activitystrea.ms/schema/1.0/person"
|
||||
href="<%= id %>" />
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= for tag <- @data["tag"] || [] do %>
|
||||
<category term="<%= tag %>"></category>
|
||||
<% end %>
|
||||
|
||||
<%= for {emoji, file} <- @data["emoji"] || %{} do %>
|
||||
<link name="<%= emoji %>" rel="emoji" href="<%= file %>"/>
|
||||
<% end %>
|
||||
</entry>
|
||||
15
lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
Normal file
15
lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<item>
|
||||
<title><%= activity_title(@object, Keyword.get(@feed_config, :post_title, %{})) %></title>
|
||||
|
||||
|
||||
<guid isPermalink="true"><%= activity_context(@activity) %></guid>
|
||||
<link><%= activity_context(@activity) %></link>
|
||||
<pubDate><%= pub_date(@data["published"]) %></pubDate>
|
||||
|
||||
<description><%= activity_content(@object) %></description>
|
||||
<%= for attachment <- @data["attachment"] || [] do %>
|
||||
<enclosure url="<%= attachment_href(attachment) %>" type="<%= attachment_type(attachment) %>"/>
|
||||
<% end %>
|
||||
|
||||
</item>
|
||||
|
||||
18
lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
Normal file
18
lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<author>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
|
||||
<id><%= @actor.ap_id %></id>
|
||||
<uri><%= @actor.ap_id %></uri>
|
||||
<name><%= @actor.nickname %></name>
|
||||
<summary><%= escape(@actor.bio) %></summary>
|
||||
<link rel="avatar" href="<%= User.avatar_url(@actor) %>"/>
|
||||
<%= if User.banner_url(@actor) do %>
|
||||
<link rel="header" href="<%= User.banner_url(@actor) %>"/>
|
||||
<% end %>
|
||||
<%= if @actor.local do %>
|
||||
<ap_enabled>true</ap_enabled>
|
||||
<% end %>
|
||||
|
||||
<poco:preferredUsername><%= @actor.nickname %></poco:preferredUsername>
|
||||
<poco:displayName><%= @actor.name %></poco:displayName>
|
||||
<poco:note><%= escape(@actor.bio) %></poco:note>
|
||||
</author>
|
||||
22
lib/pleroma/web/templates/feed/feed/tag.atom.eex
Normal file
22
lib/pleroma/web/templates/feed/feed/tag.atom.eex
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom"
|
||||
xmlns:thr="http://purl.org/syndication/thread/1.0"
|
||||
xmlns:georss="http://www.georss.org/georss"
|
||||
xmlns:activity="http://activitystrea.ms/spec/1.0/"
|
||||
xmlns:media="http://purl.org/syndication/atommedia"
|
||||
xmlns:poco="http://portablecontacts.net/spec/1.0"
|
||||
xmlns:ostatus="http://ostatus.org/schema/1.0"
|
||||
xmlns:statusnet="http://status.net/schema/api/1/">
|
||||
|
||||
<id><%= '#{tag_feed_url(@conn, :feed, @tag)}.rss' %></id>
|
||||
<title>#<%= @tag %></title>
|
||||
|
||||
<subtitle>These are public toots tagged with #<%= @tag %>. You can interact with them if you have an account anywhere in the fediverse.</subtitle>
|
||||
<logo><%= feed_logo() %></logo>
|
||||
<updated><%= most_recent_update(@activities) %></updated>
|
||||
<link rel="self" href="<%= '#{tag_feed_url(@conn, :feed, @tag)}.atom' %>" type="application/atom+xml"/>
|
||||
<%= for activity <- @activities do %>
|
||||
<%= render @view_module, "_tag_activity.atom", Map.merge(assigns, prepare_activity(activity, actor: true)) %>
|
||||
<% end %>
|
||||
</feed>
|
||||
15
lib/pleroma/web/templates/feed/feed/tag.rss.eex
Normal file
15
lib/pleroma/web/templates/feed/feed/tag.rss.eex
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0" xmlns:webfeeds="http://webfeeds.org/rss/1.0">
|
||||
<channel>
|
||||
|
||||
|
||||
<title>#<%= @tag %></title>
|
||||
<description>These are public toots tagged with #<%= @tag %>. You can interact with them if you have an account anywhere in the fediverse.</description>
|
||||
<link><%= '#{tag_feed_url(@conn, :feed, @tag)}.rss' %></link>
|
||||
<webfeeds:logo><%= feed_logo() %></webfeeds:logo>
|
||||
<webfeeds:accentColor>2b90d9</webfeeds:accentColor>
|
||||
<%= for activity <- @activities do %>
|
||||
<%= render @view_module, "_tag_activity.xml", Map.merge(assigns, prepare_activity(activity)) %>
|
||||
<% end %>
|
||||
</channel>
|
||||
</rss>
|
||||
|
|
@ -6,16 +6,16 @@
|
|||
xmlns:poco="http://portablecontacts.net/spec/1.0"
|
||||
xmlns:ostatus="http://ostatus.org/schema/1.0">
|
||||
|
||||
<id><%= feed_url(@conn, :feed, @user.nickname) <> ".atom" %></id>
|
||||
<id><%= user_feed_url(@conn, :feed, @user.nickname) <> ".atom" %></id>
|
||||
<title><%= @user.nickname <> "'s timeline" %></title>
|
||||
<updated><%= most_recent_update(@activities, @user) %></updated>
|
||||
<logo><%= logo(@user) %></logo>
|
||||
<link rel="self" href="<%= '#{feed_url(@conn, :feed, @user.nickname)}.atom' %>" type="application/atom+xml"/>
|
||||
<link rel="self" href="<%= '#{user_feed_url(@conn, :feed, @user.nickname)}.atom' %>" type="application/atom+xml"/>
|
||||
|
||||
<%= render @view_module, "_author.xml", assigns %>
|
||||
|
||||
<%= if last_activity(@activities) do %>
|
||||
<link rel="next" href="<%= '#{feed_url(@conn, :feed, @user.nickname)}.atom?max_id=#{last_activity(@activities).id}' %>" type="application/atom+xml"/>
|
||||
<link rel="next" href="<%= '#{user_feed_url(@conn, :feed, @user.nickname)}.atom?max_id=#{last_activity(@activities).id}' %>" type="application/atom+xml"/>
|
||||
<% end %>
|
||||
|
||||
<%= for activity <- @activities do %>
|
||||
|
|
@ -12,7 +12,10 @@ defmodule Pleroma.Workers.AttachmentsCleanupWorker do
|
|||
|
||||
@impl Oban.Worker
|
||||
def perform(
|
||||
%{"object" => %{"data" => %{"attachment" => [_ | _] = attachments, "actor" => actor}}},
|
||||
%{
|
||||
"op" => "cleanup_attachments",
|
||||
"object" => %{"data" => %{"attachment" => [_ | _] = attachments, "actor" => actor}}
|
||||
},
|
||||
_job
|
||||
) do
|
||||
hrefs =
|
||||
|
|
@ -37,7 +40,7 @@ defmodule Pleroma.Workers.AttachmentsCleanupWorker do
|
|||
)
|
||||
# The query above can be time consumptive on large instances until we
|
||||
# refactor how uploads are stored
|
||||
|> Repo.all(timout: :infinity)
|
||||
|> Repo.all(timeout: :infinity)
|
||||
# we should delete 1 object for any given attachment, but don't delete
|
||||
# files if there are more than 1 object for it
|
||||
|> Enum.reduce(%{}, fn %{
|
||||
|
|
@ -70,7 +73,11 @@ defmodule Pleroma.Workers.AttachmentsCleanupWorker do
|
|||
_ -> ""
|
||||
end
|
||||
|
||||
base_url = Pleroma.Config.get([__MODULE__, :base_url], Pleroma.Web.base_url())
|
||||
base_url =
|
||||
String.trim_trailing(
|
||||
Pleroma.Config.get([Pleroma.Upload, :base_url], Pleroma.Web.base_url()),
|
||||
"/"
|
||||
)
|
||||
|
||||
file_path = String.trim_leading(href, "#{base_url}/#{prefix}")
|
||||
|
||||
|
|
@ -84,5 +91,5 @@ defmodule Pleroma.Workers.AttachmentsCleanupWorker do
|
|||
|> Repo.delete_all()
|
||||
end
|
||||
|
||||
def perform(%{"object" => _object}, _job), do: :ok
|
||||
def perform(%{"op" => "cleanup_attachments", "object" => _object}, _job), do: :ok
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue