aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mix/tasks/pleroma/config.ex3
-rw-r--r--lib/mix/tasks/pleroma/email.ex25
-rw-r--r--lib/mix/tasks/pleroma/emoji.ex2
-rw-r--r--lib/mix/tasks/pleroma/robotstxt.ex1
-rw-r--r--lib/pleroma/activity.ex3
-rw-r--r--lib/pleroma/config/config_db.ex12
-rw-r--r--lib/pleroma/emails/admin_email.ex16
-rw-r--r--lib/pleroma/notification.ex4
-rw-r--r--lib/pleroma/object/fetcher.ex3
-rw-r--r--lib/pleroma/plugs/user_enabled_plug.ex8
-rw-r--r--lib/pleroma/user.ex26
-rw-r--r--lib/pleroma/user_relationship.ex2
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex7
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex12
-rw-r--r--lib/pleroma/web/controller_helper.ex7
-rw-r--r--lib/pleroma/web/feed/feed_view.ex40
-rw-r--r--lib/pleroma/web/feed/tag_controller.ex41
-rw-r--r--lib/pleroma/web/feed/user_controller.ex (renamed from lib/pleroma/web/feed/feed_controller.ex)13
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex58
-rw-r--r--lib/pleroma/web/mastodon_api/views/app_view.ex10
-rw-r--r--lib/pleroma/web/mastodon_api/views/notification_view.ex31
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex2
-rw-r--r--lib/pleroma/web/metadata/feed.ex2
-rw-r--r--lib/pleroma/web/metadata/utils.ex13
-rw-r--r--lib/pleroma/web/nodeinfo/nodeinfo_controller.ex9
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex103
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex7
-rw-r--r--lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex2
-rw-r--r--lib/pleroma/web/router.ex6
-rw-r--r--lib/pleroma/web/templates/feed/feed/_activity.xml.eex2
-rw-r--r--lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex51
-rw-r--r--lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex15
-rw-r--r--lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex18
-rw-r--r--lib/pleroma/web/templates/feed/feed/tag.atom.eex22
-rw-r--r--lib/pleroma/web/templates/feed/feed/tag.rss.eex15
-rw-r--r--lib/pleroma/web/templates/feed/feed/user.xml.eex (renamed from lib/pleroma/web/templates/feed/feed/feed.xml.eex)6
-rw-r--r--lib/pleroma/workers/attachments_cleanup_worker.ex15
37 files changed, 438 insertions, 174 deletions
diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex
index 861832451..3e76d2c97 100644
--- a/lib/mix/tasks/pleroma/config.ex
+++ b/lib/mix/tasks/pleroma/config.ex
@@ -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()
diff --git a/lib/mix/tasks/pleroma/email.ex b/lib/mix/tasks/pleroma/email.ex
new file mode 100644
index 000000000..2c3801429
--- /dev/null
+++ b/lib/mix/tasks/pleroma/email.ex
@@ -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
diff --git a/lib/mix/tasks/pleroma/emoji.ex b/lib/mix/tasks/pleroma/emoji.ex
index 35669af27..24d999707 100644
--- a/lib/mix/tasks/pleroma/emoji.ex
+++ b/lib/mix/tasks/pleroma/emoji.ex
@@ -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)
diff --git a/lib/mix/tasks/pleroma/robotstxt.ex b/lib/mix/tasks/pleroma/robotstxt.ex
index 2128e1cd6..e99dd8502 100644
--- a/lib/mix/tasks/pleroma/robotstxt.ex
+++ b/lib/mix/tasks/pleroma/robotstxt.ex
@@ -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
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex
index 896cbb3c5..0f8fce774 100644
--- a/lib/pleroma/activity.ex
+++ b/lib/pleroma/activity.ex
@@ -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,
diff --git a/lib/pleroma/config/config_db.ex b/lib/pleroma/config/config_db.ex
index 91a1aa0cc..119251bee 100644
--- a/lib/pleroma/config/config_db.ex
+++ b/lib/pleroma/config/config_db.ex
@@ -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
diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex
index b15e4041b..5f23345f7 100644
--- a/lib/pleroma/emails/admin_email.ex
+++ b/lib/pleroma/emails/admin_email.ex
@@ -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
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 8f3e46af9..d04a65a1e 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -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)
diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex
index a1bde90f1..037c42339 100644
--- a/lib/pleroma/object/fetcher.ex
+++ b/lib/pleroma/object/fetcher.ex
@@ -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
diff --git a/lib/pleroma/plugs/user_enabled_plug.ex b/lib/pleroma/plugs/user_enabled_plug.ex
index 8d102ee5b..7b304eebc 100644
--- a/lib/pleroma/plugs/user_enabled_plug.ex
+++ b/lib/pleroma/plugs/user_enabled_plug.ex
@@ -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
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 430f04ae9..3c86cdb38 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -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
diff --git a/lib/pleroma/user_relationship.ex b/lib/pleroma/user_relationship.ex
index 24c724549..3149e10e9 100644
--- a/lib/pleroma/user_relationship.ex
+++ b/lib/pleroma/user_relationship.ex
@@ -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
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 60c9e7e64..1ac67b618 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -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}
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 4def431f1..4f7fdaf38 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -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
diff --git a/lib/pleroma/web/controller_helper.ex b/lib/pleroma/web/controller_helper.ex
index 9a4e322c9..e3d7a465b 100644
--- a/lib/pleroma/web/controller_helper.ex
+++ b/lib/pleroma/web/controller_helper.ex
@@ -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
diff --git a/lib/pleroma/web/feed/feed_view.ex b/lib/pleroma/web/feed/feed_view.ex
index bb1332fd3..334802e0a 100644
--- a/lib/pleroma/web/feed/feed_view.ex
+++ b/lib/pleroma/web/feed/feed_view.ex
@@ -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
diff --git a/lib/pleroma/web/feed/tag_controller.ex b/lib/pleroma/web/feed/tag_controller.ex
new file mode 100644
index 000000000..9accd0872
--- /dev/null
+++ b/lib/pleroma/web/feed/tag_controller.ex
@@ -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
diff --git a/lib/pleroma/web/feed/feed_controller.ex b/lib/pleroma/web/feed/user_controller.ex
index d0e23007d..f5096834b 100644
--- a/lib/pleroma/web/feed/feed_controller.ex
+++ b/lib/pleroma/web/feed/user_controller.ex
@@ -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])
diff --git a/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex b/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex
index fe71c36af..b9cc8f104 100644
--- a/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex
@@ -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
diff --git a/lib/pleroma/web/mastodon_api/views/app_view.ex b/lib/pleroma/web/mastodon_api/views/app_view.ex
index f52b693a6..beba89edb 100644
--- a/lib/pleroma/web/mastodon_api/views/app_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/app_view.ex
@@ -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
diff --git a/lib/pleroma/web/mastodon_api/views/notification_view.ex b/lib/pleroma/web/mastodon_api/views/notification_view.ex
index ddd7f5318..360ec10f0 100644
--- a/lib/pleroma/web/mastodon_api/views/notification_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/notification_view.ex
@@ -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
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index 64a97896a..e60ef709b 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -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
_ -> []
diff --git a/lib/pleroma/web/metadata/feed.ex b/lib/pleroma/web/metadata/feed.ex
index 8043e6c54..ee48913a7 100644
--- a/lib/pleroma/web/metadata/feed.ex
+++ b/lib/pleroma/web/metadata/feed.ex
@@ -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
diff --git a/lib/pleroma/web/metadata/utils.ex b/lib/pleroma/web/metadata/utils.ex
index 589d11901..000bd9f66 100644
--- a/lib/pleroma/web/metadata/utils.ex
+++ b/lib/pleroma/web/metadata/utils.ex
@@ -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
+ |> 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()
- |> Emoji.Formatter.demojify()
- |> HtmlEntities.decode()
- |> Formatter.truncate(max_length)
end
+ def scrub_html(content), do: content
+
def attachment_url(url) do
MediaProxy.url(url)
end
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
index abcf46034..03c35cc2a 100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
@@ -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,
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index 5292aedf2..528f08574 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -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
diff --git a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
index bb19836ae..cd1c0764f 100644
--- a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
@@ -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
diff --git a/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex b/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
index 913975616..c2a3c07a2 100644
--- a/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
+++ b/lib/pleroma/web/rich_media/parsers/meta_tags_parser.ex
@@ -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
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index ef6e5a565..b5c1d85c7 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -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
diff --git a/lib/pleroma/web/templates/feed/feed/_activity.xml.eex b/lib/pleroma/web/templates/feed/feed/_activity.xml.eex
index 514eacaed..ac8a75009 100644
--- a/lib/pleroma/web/templates/feed/feed/_activity.xml.eex
+++ b/lib/pleroma/web/templates/feed/feed/_activity.xml.eex
@@ -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>
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
new file mode 100644
index 000000000..da4fa6d6c
--- /dev/null
+++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
@@ -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>
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
new file mode 100644
index 000000000..295574df1
--- /dev/null
+++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
@@ -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>
+
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex b/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
new file mode 100644
index 000000000..997c4936e
--- /dev/null
+++ b/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
@@ -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>
diff --git a/lib/pleroma/web/templates/feed/feed/tag.atom.eex b/lib/pleroma/web/templates/feed/feed/tag.atom.eex
new file mode 100644
index 000000000..a288539ed
--- /dev/null
+++ b/lib/pleroma/web/templates/feed/feed/tag.atom.eex
@@ -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>
diff --git a/lib/pleroma/web/templates/feed/feed/tag.rss.eex b/lib/pleroma/web/templates/feed/feed/tag.rss.eex
new file mode 100644
index 000000000..eeda01a04
--- /dev/null
+++ b/lib/pleroma/web/templates/feed/feed/tag.rss.eex
@@ -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>
diff --git a/lib/pleroma/web/templates/feed/feed/feed.xml.eex b/lib/pleroma/web/templates/feed/feed/user.xml.eex
index 5ae36d345..d274c08ae 100644
--- a/lib/pleroma/web/templates/feed/feed/feed.xml.eex
+++ b/lib/pleroma/web/templates/feed/feed/user.xml.eex
@@ -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 %>
diff --git a/lib/pleroma/workers/attachments_cleanup_worker.ex b/lib/pleroma/workers/attachments_cleanup_worker.ex
index 3f421db40..2cbc6b64d 100644
--- a/lib/pleroma/workers/attachments_cleanup_worker.ex
+++ b/lib/pleroma/workers/attachments_cleanup_worker.ex
@@ -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