diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d42a4cfe..7d1ae3160 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -59,6 +59,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Fixed lowercase HTTP HEAD method in the Media Proxy Preview code
- Removed useless notification call on Delete activities
- Improved performance for filtering out deactivated and invisible users
+- RSS and Atom feeds for users work again
- TwitterCard meta tags conformance
### Removed
diff --git a/lib/pleroma/web/feed/feed_view.ex b/lib/pleroma/web/feed/feed_view.ex
index 35a5f9482..449659f4b 100644
--- a/lib/pleroma/web/feed/feed_view.ex
+++ b/lib/pleroma/web/feed/feed_view.ex
@@ -14,14 +14,8 @@ defmodule Pleroma.Web.Feed.FeedView do
require Pleroma.Constants
- @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}")
+ @days ~w(Mon Tue Wed Thu Fri Sat Sun)
+ @months ~w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
def prepare_activity(activity, opts \\ []) do
object = Object.normalize(activity, fetch: false)
@@ -41,13 +35,18 @@ def prepare_activity(activity, opts \\ []) do
def most_recent_update(activities) do
with %{updated_at: updated_at} <- List.first(activities) do
- NaiveDateTime.to_iso8601(updated_at)
+ to_rfc3339(updated_at)
end
end
- def most_recent_update(activities, user) do
+ def most_recent_update(activities, user, :atom) do
(List.first(activities) || user).updated_at
- |> NaiveDateTime.to_iso8601()
+ |> to_rfc3339()
+ end
+
+ def most_recent_update(activities, user, :rss) do
+ (List.first(activities) || user).updated_at
+ |> to_rfc2822()
end
def feed_logo do
@@ -61,6 +60,10 @@ def feed_logo do
|> MediaProxy.url()
end
+ def email(user) do
+ user.nickname <> "@" <> Pleroma.Web.Endpoint.host()
+ end
+
def logo(user) do
user
|> User.avatar_url()
@@ -69,18 +72,34 @@ def logo(user) do
def last_activity(activities), do: List.last(activities)
- def activity_title(%{"content" => content}, opts \\ %{}) do
- content
+ def activity_title(%{"content" => content, "summary" => summary} = data, opts \\ %{}) do
+ title =
+ cond do
+ summary != "" -> summary
+ content != "" -> activity_content(data)
+ true -> "a post"
+ end
+
+ title
|> Pleroma.Web.Metadata.Utils.scrub_html()
|> Pleroma.Emoji.Formatter.demojify()
|> Formatter.truncate(opts[:max_length], opts[:omission])
- |> escape()
+ end
+
+ def activity_description(data) do
+ content = activity_content(data)
+ summary = data["summary"]
+
+ cond do
+ content != "" -> escape(content)
+ summary != "" -> escape(summary)
+ true -> escape(data["type"])
+ end
end
def activity_content(%{"content" => content}) do
content
|> String.replace(~r/[\n\r]/, "")
- |> escape()
end
def activity_content(_), do: ""
@@ -112,4 +131,60 @@ def escape(html) do
|> html_escape()
|> safe_to_string()
end
+
+ @spec to_rfc3339(String.t() | NativeDateTime.t()) :: String.t()
+ def to_rfc3339(date) when is_binary(date) do
+ date
+ |> Timex.parse!("{ISO:Extended}")
+ |> to_rfc3339()
+ end
+
+ def to_rfc3339(nd) do
+ nd
+ |> Timex.to_datetime()
+ |> Timex.format!("{RFC3339}")
+ end
+
+ @spec to_rfc2822(String.t() | DateTime.t() | NativeDateTime.t()) :: String.t()
+ def to_rfc2822(datestr) when is_binary(datestr) do
+ datestr
+ |> Timex.parse!("{ISO:Extended}")
+ |> to_rfc2822()
+ end
+
+ def to_rfc2822(%DateTime{} = date) do
+ date
+ |> DateTime.to_naive()
+ |> NaiveDateTime.to_erl()
+ |> rfc2822_from_erl()
+ end
+
+ def to_rfc2822(nd) do
+ nd
+ |> Timex.to_datetime()
+ |> DateTime.to_naive()
+ |> NaiveDateTime.to_erl()
+ |> rfc2822_from_erl()
+ end
+
+ @doc """
+ Builds a RFC2822 timestamp from an Erlang timestamp
+ [RFC2822 3.3 - Date and Time Specification](https://tools.ietf.org/html/rfc2822#section-3.3)
+ This function always assumes the Erlang timestamp is in Universal time, not Local time
+ """
+ def rfc2822_from_erl({{year, month, day} = date, {hour, minute, second}}) do
+ day_name = Enum.at(@days, :calendar.day_of_the_week(date) - 1)
+ month_name = Enum.at(@months, month - 1)
+
+ date_part = "#{day_name}, #{day} #{month_name} #{year}"
+ time_part = "#{pad(hour)}:#{pad(minute)}:#{pad(second)}"
+
+ date_part <> " " <> time_part <> " +0000"
+ end
+
+ defp pad(num) do
+ num
+ |> Integer.to_string()
+ |> String.pad_leading(2, "0")
+ end
end
diff --git a/lib/pleroma/web/templates/feed/feed/_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
index 57bd92468..260338772 100644
--- a/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_activity.atom.eex
@@ -3,15 +3,15 @@
http://activitystrea.ms/schema/1.0/post
<%= @data["id"] %>
<%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %>
- <%= activity_content(@data) %>
- <%= @activity.data["published"] %>
- <%= @activity.data["published"] %>
+ <%= activity_description(@data) %>
+ <%= to_rfc3339(@activity.data["published"]) %>
+ <%= to_rfc3339(@activity.data["published"]) %>
<%= activity_context(@activity) %>
- <%= if @data["summary"] do %>
+ <%= if @data["summary"] != "" do %>
<%= escape(@data["summary"]) %>
<% end %>
diff --git a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
index 279f2171d..5c8f35fe4 100644
--- a/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/_activity.rss.eex
@@ -3,17 +3,12 @@
http://activitystrea.ms/schema/1.0/post
<%= @data["id"] %>
<%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %>
- <%= activity_content(@data) %>
- <%= @activity.data["published"] %>
- <%= @activity.data["published"] %>
+ <%= activity_description(@data) %>
+ <%= to_rfc2822(@activity.data["published"]) %>
<%= activity_context(@activity) %>
- <%= if @data["summary"] do %>
- <%= escape(@data["summary"]) %>
- <% end %>
-
<%= if @activity.local do %>
<%= @data["id"] %>
<% else %>
@@ -27,7 +22,7 @@
<% end %>
<%= for attachment <- @data["attachment"] || [] do %>
- <%= attachment_href(attachment) %>
+
<% end %>
<%= if @data["inReplyTo"] do %>
diff --git a/lib/pleroma/web/templates/feed/feed/_author.atom.eex b/lib/pleroma/web/templates/feed/feed/_author.atom.eex
index 25cbffada..90be8a559 100644
--- a/lib/pleroma/web/templates/feed/feed/_author.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_author.atom.eex
@@ -1,17 +1,14 @@
- <%= @user.ap_id %>
- http://activitystrea.ms/schema/1.0/person
<%= @user.ap_id %>
+ <%= @user.nickname %>
+ http://activitystrea.ms/schema/1.0/person
+ <%= @user.name %>
+ <%= User.avatar_url(@user) %>
+ <%= @user.ap_id %>
+ <%= to_rfc3339(@user.inserted_at) %>
+ <%= to_rfc3339(@user.updated_at) %>
+ <%= @user.ap_id %>
<%= @user.nickname %>
<%= @user.name %>
<%= escape(@user.bio) %>
- <%= escape(@user.bio) %>
- <%= @user.nickname %>
-
- <%= if User.banner_url(@user) do %>
-
- <% end %>
- <%= if @user.local do %>
- true
- <% end %>
diff --git a/lib/pleroma/web/templates/feed/feed/_author.rss.eex b/lib/pleroma/web/templates/feed/feed/_author.rss.eex
index 526aeddcf..22477e6b1 100644
--- a/lib/pleroma/web/templates/feed/feed/_author.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/_author.rss.eex
@@ -1,17 +1,10 @@
-
- <%= @user.ap_id %>
- http://activitystrea.ms/schema/1.0/person
- <%= @user.ap_id %>
- <%= @user.nickname %>
- <%= @user.name %>
- <%= escape(@user.bio) %>
- <%= escape(@user.bio) %>
- <%= @user.nickname %>
- <%= User.avatar_url(@user) %>
- <%= if User.banner_url(@user) do %>
- <%= User.banner_url(@user) %>
- <% end %>
- <%= if @user.local do %>
- true
- <% end %>
-
+<%= "#{email(@user)} (#{escape(@user.name)})" %>
+http://activitystrea.ms/schema/1.0/person
+<%= @user.name %>
+<%= User.avatar_url(@user) %>
+<%= @user.ap_id %>
+<%= to_rfc3339(@user.inserted_at) %>
+<%= to_rfc3339(@user.updated_at) %>
+<%= @user.nickname %>
+<%= @user.name %>
+<%= escape(@user.bio) %>
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
index 7e2e587e1..25980c1e4 100644
--- a/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.atom.eex
@@ -1,12 +1,22 @@
- http://activitystrea.ms/schema/1.0/note
- http://activitystrea.ms/schema/1.0/post
+ http://activitystrea.ms/schema/1.0/note
+ http://activitystrea.ms/schema/1.0/post
<%= render Phoenix.Controller.view_module(@conn), "_tag_author.atom", assigns %>
- <%= @data["id"] %>
- <%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %>
- <%= activity_content(@data) %>
+ <%= @data["id"] %>
+ <%= activity_title(@data, Keyword.get(@feed_config, :post_title, %{})) %>
+ <%= activity_description(@data) %>
+ <%= to_rfc3339(@activity.data["published"]) %>
+ <%= to_rfc3339(@activity.data["published"]) %>
+
+ <%= activity_context(@activity) %>
+
+
+
+ <%= if @data["summary"] != "" do %>
+ <%= @data["summary"] %>
+ <% end %>
<%= if @activity.local do %>
@@ -15,37 +25,25 @@
<% end %>
- <%= @activity.data["published"] %>
- <%= @activity.data["published"] %>
-
-
- <%= activity_context(@activity) %>
-
-
-
- <%= if @data["summary"] do %>
- <%= @data["summary"] %>
- <% end %>
-
- <%= for id <- @activity.recipients do %>
- <%= if id == Pleroma.Constants.as_public() do %>
+ <%= for id <- @activity.recipients do %>
+ <%= if id == Pleroma.Constants.as_public() do %>
+
+ <% else %>
+ <%= unless Regex.match?(~r/^#{Pleroma.Web.Endpoint.url()}.+followers$/, id) do %>
- <% else %>
- <%= unless Regex.match?(~r/^#{Pleroma.Web.Endpoint.url()}.+followers$/, id) do %>
-
- <% end %>
+ ostatus:object-type="http://activitystrea.ms/schema/1.0/person"
+ href="<%= id %>" />
<% end %>
<% end %>
+ <% end %>
- <%= for tag <- Pleroma.Object.hashtags(@object) do %>
-
- <% end %>
+ <%= for tag <- Pleroma.Object.hashtags(@object) do %>
+
+ <% end %>
- <%= for {emoji, file} <- @data["emoji"] || %{} do %>
-
- <% end %>
+ <%= for {emoji, file} <- @data["emoji"] || %{} do %>
+
+ <% end %>
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
index 2334e24a2..d582c83e8 100644
--- a/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
+++ b/lib/pleroma/web/templates/feed/feed/_tag_activity.xml.eex
@@ -4,9 +4,9 @@
<%= activity_context(@activity) %>
<%= activity_context(@activity) %>
- <%= pub_date(@activity.data["published"]) %>
+ <%= to_rfc2822(@activity.data["published"]) %>
- <%= activity_content(@data) %>
+ <%= activity_description(@data) %>
<%= for attachment <- @data["attachment"] || [] do %>
<% end %>
diff --git a/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex b/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
index 997c4936e..71c696832 100644
--- a/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/_tag_author.atom.eex
@@ -1,18 +1,14 @@
- http://activitystrea.ms/schema/1.0/person
- <%= @actor.ap_id %>
- <%= @actor.ap_id %>
- <%= @actor.nickname %>
- <%= escape(@actor.bio) %>
-
- <%= if User.banner_url(@actor) do %>
-
- <% end %>
- <%= if @actor.local do %>
- true
- <% end %>
-
- <%= @actor.nickname %>
- <%= @actor.name %>
- <%= escape(@actor.bio) %>
+ <%= @actor.ap_id %>
+ <%= @actor.nickname %>
+ http://activitystrea.ms/schema/1.0/person
+ <%= @actor.name %>
+ <%= User.avatar_url(@actor) %>
+ <%= @actor.ap_id %>
+ <%= to_rfc3339(@actor.inserted_at) %>
+ <%= to_rfc3339(@actor.updated_at) %>
+ <%= @actor.ap_id %>
+ <%= @actor.nickname %>
+ <%= @actor.name %>
+ <%= escape(@actor.bio) %>
diff --git a/lib/pleroma/web/templates/feed/feed/tag.atom.eex b/lib/pleroma/web/templates/feed/feed/tag.atom.eex
index 8c551feaf..14b0ee594 100644
--- a/lib/pleroma/web/templates/feed/feed/tag.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/tag.atom.eex
@@ -1,22 +1,20 @@
+
-
+ <%= Routes.tag_feed_url(@conn, :feed, @tag) <> ".atom" %>
+ #<%= @tag %>
+ <%= Gettext.dpgettext("static_pages", "tag feed description", "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse.", tag: @tag) %>
+ <%= feed_logo() %>
+ <%= most_recent_update(@activities) %>
+
- <%= '#{Routes.tag_feed_url(@conn, :feed, @tag)}.rss' %>
- #<%= @tag %>
-
- <%= Gettext.dpgettext("static_pages", "tag feed description", "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse.", tag: @tag) %>
- <%= feed_logo() %>
- <%= most_recent_update(@activities) %>
-
- <%= for activity <- @activities do %>
- <%= render Phoenix.Controller.view_module(@conn), "_tag_activity.atom", Map.merge(assigns, prepare_activity(activity, actor: true)) %>
- <% end %>
+ <%= for activity <- @activities do %>
+ <%= render Phoenix.Controller.view_module(@conn), "_tag_activity.atom", Map.merge(assigns, prepare_activity(activity, actor: true)) %>
+ <% end %>
diff --git a/lib/pleroma/web/templates/feed/feed/tag.rss.eex b/lib/pleroma/web/templates/feed/feed/tag.rss.eex
index 86466d367..27dde5627 100644
--- a/lib/pleroma/web/templates/feed/feed/tag.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/tag.rss.eex
@@ -1,8 +1,9 @@
-
+
-
#<%= @tag %>
<%= Gettext.dpgettext("static_pages", "tag feed description", "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse.", tag: @tag) %>
<%= '#{Routes.tag_feed_url(@conn, :feed, @tag)}.rss' %>
diff --git a/lib/pleroma/web/templates/feed/feed/user.atom.eex b/lib/pleroma/web/templates/feed/feed/user.atom.eex
index 97a7535ab..e36bfc66c 100644
--- a/lib/pleroma/web/templates/feed/feed/user.atom.eex
+++ b/lib/pleroma/web/templates/feed/feed/user.atom.eex
@@ -8,7 +8,8 @@
<%= Routes.user_feed_url(@conn, :feed, @user.nickname) <> ".atom" %>
<%= @user.nickname <> "'s timeline" %>
- <%= most_recent_update(@activities, @user) %>
+ <%= escape(@user.bio) %>
+ <%= most_recent_update(@activities, @user, :atom) %>
<%= logo(@user) %>
diff --git a/lib/pleroma/web/templates/feed/feed/user.rss.eex b/lib/pleroma/web/templates/feed/feed/user.rss.eex
index a9fee244c..fae3fcf3d 100644
--- a/lib/pleroma/web/templates/feed/feed/user.rss.eex
+++ b/lib/pleroma/web/templates/feed/feed/user.rss.eex
@@ -1,11 +1,21 @@
-
+
- <%= Routes.user_feed_url(@conn, :feed, @user.nickname) <> ".rss" %>
<%= @user.nickname <> "'s timeline" %>
- <%= most_recent_update(@activities, @user) %>
- <%= logo(@user) %>
<%= '#{Routes.user_feed_url(@conn, :feed, @user.nickname)}.rss' %>
+ "
+ rel="self" type="application/rss+xml" />
+ <%= escape(@user.bio) %>
+
+ <%= logo(@user) %>
+ <%= @user.nickname <> "'s timeline" %>
+ <%= '#{Routes.user_feed_url(@conn, :feed, @user.nickname)}.rss' %>
+
<%= render Phoenix.Controller.view_module(@conn), "_author.rss", assigns %>
diff --git a/test/pleroma/web/feed/tag_controller_test.exs b/test/pleroma/web/feed/tag_controller_test.exs
index 1bd2b157c..58ab8f137 100644
--- a/test/pleroma/web/feed/tag_controller_test.exs
+++ b/test/pleroma/web/feed/tag_controller_test.exs
@@ -63,7 +63,6 @@ test "gets a feed (ATOM)", %{conn: conn} do
]
assert xpath(xml, ~x"//feed/entry/author/name/text()"ls) == [user.nickname, user.nickname]
- assert xpath(xml, ~x"//feed/entry/author/id/text()"ls) == [user.ap_id, user.ap_id]
conn =
conn
@@ -138,8 +137,8 @@ test "gets a feed (RSS)", %{conn: conn} do
]
assert xpath(xml, ~x"//channel/item/pubDate/text()"sl) == [
- FeedView.pub_date(activity2.data["published"]),
- FeedView.pub_date(activity1.data["published"])
+ FeedView.to_rfc2822(activity2.data["published"]),
+ FeedView.to_rfc2822(activity1.data["published"])
]
assert xpath(xml, ~x"//channel/item/enclosure/@url"sl) == [
diff --git a/test/pleroma/web/feed/user_controller_test.exs b/test/pleroma/web/feed/user_controller_test.exs
index 38cde3315..de32d3d4b 100644
--- a/test/pleroma/web/feed/user_controller_test.exs
+++ b/test/pleroma/web/feed/user_controller_test.exs
@@ -74,7 +74,7 @@ test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_
|> SweetXml.parse()
|> SweetXml.xpath(~x"//entry/title/text()"l)
- assert activity_titles == ['42 & Thi...', 'This & t...']
+ assert activity_titles == ['2hu', '2hu & as']
assert resp =~ FeedView.escape(object.data["content"])
assert resp =~ FeedView.escape(object.data["summary"])
assert resp =~ FeedView.escape(object.data["context"])
@@ -90,7 +90,7 @@ test "gets an atom feed", %{conn: conn, user: user, object: object, max_id: max_
|> SweetXml.parse()
|> SweetXml.xpath(~x"//entry/title/text()"l)
- assert activity_titles == ['This & t...']
+ assert activity_titles == ['2hu & as']
end
test "gets a rss feed", %{conn: conn, user: user, object: object, max_id: max_id} do
@@ -105,7 +105,7 @@ test "gets a rss feed", %{conn: conn, user: user, object: object, max_id: max_id
|> SweetXml.parse()
|> SweetXml.xpath(~x"//item/title/text()"l)
- assert activity_titles == ['42 & Thi...', 'This & t...']
+ assert activity_titles == ['2hu', '2hu & as']
assert resp =~ FeedView.escape(object.data["content"])
assert resp =~ FeedView.escape(object.data["summary"])
assert resp =~ FeedView.escape(object.data["context"])
@@ -121,7 +121,7 @@ test "gets a rss feed", %{conn: conn, user: user, object: object, max_id: max_id
|> SweetXml.parse()
|> SweetXml.xpath(~x"//item/title/text()"l)
- assert activity_titles == ['This & t...']
+ assert activity_titles == ['2hu & as']
end
test "returns 404 for a missing feed", %{conn: conn} do