2019-10-07 12:20:41 +00:00
|
|
|
# Pleroma: A lightweight social networking server
|
2023-01-02 20:38:50 +00:00
|
|
|
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
2019-10-07 12:20:41 +00:00
|
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
|
|
|
defmodule Pleroma.Web.Feed.FeedView do
|
|
|
|
use Phoenix.HTML
|
|
|
|
use Pleroma.Web, :view
|
|
|
|
|
2019-11-08 06:23:24 +00:00
|
|
|
alias Pleroma.Formatter
|
2019-10-07 12:20:41 +00:00
|
|
|
alias Pleroma.Object
|
|
|
|
alias Pleroma.User
|
2022-02-28 06:13:39 +00:00
|
|
|
alias Pleroma.Web.Gettext
|
2019-10-07 12:20:41 +00:00
|
|
|
alias Pleroma.Web.MediaProxy
|
|
|
|
|
|
|
|
require Pleroma.Constants
|
|
|
|
|
2022-11-15 16:45:32 +00:00
|
|
|
@days ~w(Mon Tue Wed Thu Fri Sat Sun)
|
|
|
|
@months ~w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
|
|
|
|
|
2020-01-24 19:08:10 +00:00
|
|
|
def prepare_activity(activity, opts \\ []) do
|
2021-01-04 12:38:31 +00:00
|
|
|
object = Object.normalize(activity, fetch: false)
|
2019-11-08 06:23:24 +00:00
|
|
|
|
2020-01-24 19:08:10 +00:00
|
|
|
actor =
|
|
|
|
if opts[:actor] do
|
|
|
|
Pleroma.User.get_cached_by_ap_id(activity.actor)
|
|
|
|
end
|
|
|
|
|
2019-11-08 06:23:24 +00:00
|
|
|
%{
|
|
|
|
activity: activity,
|
2020-12-21 19:54:26 +00:00
|
|
|
object: object,
|
2019-11-08 06:23:24 +00:00
|
|
|
data: Map.get(object, :data),
|
2020-01-24 19:08:10 +00:00
|
|
|
actor: actor
|
2019-11-08 06:23:24 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2020-01-24 19:08:10 +00:00
|
|
|
def most_recent_update(activities) do
|
|
|
|
with %{updated_at: updated_at} <- List.first(activities) do
|
2022-11-13 20:50:52 +00:00
|
|
|
to_rfc3339(updated_at)
|
2020-01-24 19:08:10 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-11-13 20:50:52 +00:00
|
|
|
def most_recent_update(activities, user, :atom) do
|
2019-10-07 12:20:41 +00:00
|
|
|
(List.first(activities) || user).updated_at
|
2022-11-13 20:50:52 +00:00
|
|
|
|> to_rfc3339()
|
|
|
|
end
|
|
|
|
|
|
|
|
def most_recent_update(activities, user, :rss) do
|
|
|
|
(List.first(activities) || user).updated_at
|
2022-11-15 16:45:32 +00:00
|
|
|
|> to_rfc2822()
|
2019-10-07 12:20:41 +00:00
|
|
|
end
|
|
|
|
|
2019-12-17 19:13:45 +00:00
|
|
|
def feed_logo do
|
|
|
|
case Pleroma.Config.get([:feed, :logo]) do
|
|
|
|
nil ->
|
2021-05-31 20:09:11 +00:00
|
|
|
"#{Pleroma.Web.Endpoint.url()}/static/logo.svg"
|
2019-12-17 19:13:45 +00:00
|
|
|
|
|
|
|
logo ->
|
2021-05-31 20:09:11 +00:00
|
|
|
"#{Pleroma.Web.Endpoint.url()}#{logo}"
|
2019-12-17 19:13:45 +00:00
|
|
|
end
|
|
|
|
|> MediaProxy.url()
|
|
|
|
end
|
|
|
|
|
2022-11-13 20:50:52 +00:00
|
|
|
def email(user) do
|
|
|
|
user.nickname <> "@" <> Pleroma.Web.Endpoint.host()
|
|
|
|
end
|
|
|
|
|
2019-10-07 12:20:41 +00:00
|
|
|
def logo(user) do
|
|
|
|
user
|
|
|
|
|> User.avatar_url()
|
|
|
|
|> MediaProxy.url()
|
|
|
|
end
|
|
|
|
|
2019-11-08 06:23:24 +00:00
|
|
|
def last_activity(activities), do: List.last(activities)
|
2019-10-07 12:20:41 +00:00
|
|
|
|
2023-03-05 19:20:54 +00:00
|
|
|
def activity_title(%{"content" => content} = data, opts \\ %{}) do
|
|
|
|
summary = Map.get(data, "summary", "")
|
2023-03-05 20:16:24 +00:00
|
|
|
|
2022-11-13 20:50:52 +00:00
|
|
|
title =
|
|
|
|
cond do
|
|
|
|
summary != "" -> summary
|
|
|
|
content != "" -> activity_content(data)
|
|
|
|
true -> "a post"
|
|
|
|
end
|
|
|
|
|
|
|
|
title
|
2019-12-17 19:13:45 +00:00
|
|
|
|> Pleroma.Web.Metadata.Utils.scrub_html()
|
|
|
|
|> Pleroma.Emoji.Formatter.demojify()
|
2019-11-08 06:23:24 +00:00
|
|
|
|> Formatter.truncate(opts[:max_length], opts[:omission])
|
2019-10-07 12:20:41 +00:00
|
|
|
end
|
|
|
|
|
2022-11-13 20:50:52 +00:00
|
|
|
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
|
|
|
|
|
2020-04-16 15:05:36 +00:00
|
|
|
def activity_content(%{"content" => content}) do
|
2019-10-07 12:20:41 +00:00
|
|
|
content
|
|
|
|
|> String.replace(~r/[\n\r]/, "")
|
|
|
|
end
|
|
|
|
|
2019-12-17 19:13:45 +00:00
|
|
|
def activity_content(_), do: ""
|
|
|
|
|
2020-11-10 07:44:22 +00:00
|
|
|
def activity_context(activity), do: escape(activity.data["context"])
|
2019-10-07 12:20:41 +00:00
|
|
|
|
|
|
|
def attachment_href(attachment) do
|
|
|
|
attachment["url"]
|
|
|
|
|> hd()
|
|
|
|
|> Map.get("href")
|
|
|
|
end
|
|
|
|
|
|
|
|
def attachment_type(attachment) do
|
|
|
|
attachment["url"]
|
|
|
|
|> hd()
|
|
|
|
|> Map.get("mediaType")
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_href(id) do
|
|
|
|
with %Object{data: %{"external_url" => external_url}} <- Object.get_cached_by_ap_id(id) do
|
|
|
|
external_url
|
|
|
|
else
|
|
|
|
_e -> id
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def escape(html) do
|
|
|
|
html
|
|
|
|
|> html_escape()
|
|
|
|
|> safe_to_string()
|
|
|
|
end
|
2022-11-13 20:50:52 +00:00
|
|
|
|
|
|
|
@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
|
|
|
|
|
2022-11-15 16:45:32 +00:00
|
|
|
@spec to_rfc2822(String.t() | DateTime.t() | NativeDateTime.t()) :: String.t()
|
|
|
|
def to_rfc2822(datestr) when is_binary(datestr) do
|
2022-11-13 20:50:52 +00:00
|
|
|
datestr
|
|
|
|
|> Timex.parse!("{ISO:Extended}")
|
2022-11-15 16:45:32 +00:00
|
|
|
|> to_rfc2822()
|
2022-11-13 20:50:52 +00:00
|
|
|
end
|
|
|
|
|
2022-11-15 16:45:32 +00:00
|
|
|
def to_rfc2822(%DateTime{} = date) do
|
2022-11-13 20:50:52 +00:00
|
|
|
date
|
2022-11-15 16:45:32 +00:00
|
|
|
|> DateTime.to_naive()
|
|
|
|
|> NaiveDateTime.to_erl()
|
|
|
|
|> rfc2822_from_erl()
|
2022-11-13 20:50:52 +00:00
|
|
|
end
|
|
|
|
|
2022-11-15 16:45:32 +00:00
|
|
|
def to_rfc2822(nd) do
|
2022-11-13 20:50:52 +00:00
|
|
|
nd
|
|
|
|
|> Timex.to_datetime()
|
2022-11-15 16:45:32 +00:00
|
|
|
|> 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")
|
2022-11-13 20:50:52 +00:00
|
|
|
end
|
2019-10-07 12:20:41 +00:00
|
|
|
end
|