total rebase
[anni] / lib / pleroma / web / static_fe / static_fe_controller.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.StaticFE.StaticFEController do
6   use Pleroma.Web, :controller
7
8   alias Pleroma.Activity
9   alias Pleroma.Object
10   alias Pleroma.User
11   alias Pleroma.Web.ActivityPub.ActivityPub
12   alias Pleroma.Web.ActivityPub.Visibility
13   alias Pleroma.Web.Metadata
14   alias Pleroma.Web.Router.Helpers
15
16   plug(:assign_id)
17
18   @page_keys ["max_id", "min_id", "limit", "since_id", "order"]
19
20   @doc "Renders requested local public activity or public activities of requested user"
21   def show(%{assigns: %{notice_id: notice_id}} = conn, _params) do
22     with %Activity{local: true} = activity <-
23            Activity.get_by_id_with_object(notice_id),
24          true <- Visibility.public?(activity.object),
25          {_, true} <- {:visible?, Visibility.visible_for_user?(activity, _reading_user = nil)},
26          %User{} = user <- User.get_by_ap_id(activity.object.data["actor"]) do
27       url = Helpers.url(conn) <> conn.request_path
28
29       meta =
30         Metadata.build_tags(%{
31           activity_id: notice_id,
32           object: activity.object,
33           user: user,
34           url: url
35         })
36
37       timeline =
38         activity.object.data["context"]
39         |> ActivityPub.fetch_activities_for_context(%{})
40         |> Enum.reverse()
41         |> Enum.map(&represent(&1, &1.object.id == activity.object.id))
42
43       render(conn, "conversation.html", %{activities: timeline, meta: meta})
44     else
45       %Activity{object: %Object{data: data}} ->
46         conn
47         |> put_status(:found)
48         |> redirect(external: data["url"] || data["external_url"] || data["id"])
49
50       _ ->
51         not_found(conn, "Post not found.")
52     end
53   end
54
55   def show(%{assigns: %{username_or_id: username_or_id}} = conn, params) do
56     with {_, %User{local: true} = user} <-
57            {:fetch_user, User.get_cached_by_nickname_or_id(username_or_id)},
58          {_, :visible} <- {:visibility, User.visible_for(user, _reading_user = nil)} do
59       meta = Metadata.build_tags(%{user: user})
60
61       params =
62         params
63         |> Map.take(@page_keys)
64         |> Map.new(fn {k, v} -> {String.to_existing_atom(k), v} end)
65
66       timeline =
67         user
68         |> ActivityPub.fetch_user_activities(_reading_user = nil, params)
69         |> Enum.map(&represent/1)
70
71       prev_page_id =
72         (params["min_id"] || params["max_id"]) &&
73           List.first(timeline) && List.first(timeline).id
74
75       next_page_id = List.last(timeline) && List.last(timeline).id
76
77       render(conn, "profile.html", %{
78         user: User.sanitize_html(user),
79         timeline: timeline,
80         prev_page_id: prev_page_id,
81         next_page_id: next_page_id,
82         meta: meta
83       })
84     else
85       _ ->
86         not_found(conn, "User not found.")
87     end
88   end
89
90   def show(%{assigns: %{object_id: _}} = conn, _params) do
91     url = Helpers.url(conn) <> conn.request_path
92
93     case Activity.get_create_by_object_ap_id_with_object(url) do
94       %Activity{} = activity ->
95         to = Helpers.o_status_path(Pleroma.Web.Endpoint, :notice, activity)
96         redirect(conn, to: to)
97
98       _ ->
99         not_found(conn, "Post not found.")
100     end
101   end
102
103   def show(%{assigns: %{activity_id: _}} = conn, _params) do
104     url = Helpers.url(conn) <> conn.request_path
105
106     case Activity.get_by_ap_id(url) do
107       %Activity{} = activity ->
108         to = Helpers.o_status_path(Pleroma.Web.Endpoint, :notice, activity)
109         redirect(conn, to: to)
110
111       _ ->
112         not_found(conn, "Post not found.")
113     end
114   end
115
116   defp get_title(%Object{data: %{"name" => name}}) when is_binary(name),
117     do: name
118
119   defp get_title(%Object{data: %{"summary" => summary}}) when is_binary(summary),
120     do: summary
121
122   defp get_title(_), do: nil
123
124   defp not_found(conn, message) do
125     conn
126     |> put_status(404)
127     |> render("error.html", %{message: message, meta: ""})
128   end
129
130   defp get_counts(%Activity{} = activity) do
131     %Object{data: data} = Object.normalize(activity, fetch: false)
132
133     %{
134       likes: data["like_count"] || 0,
135       replies: data["repliesCount"] || 0,
136       announces: data["announcement_count"] || 0
137     }
138   end
139
140   defp represent(%Activity{} = activity), do: represent(activity, false)
141
142   defp represent(%Activity{object: %Object{data: data}} = activity, selected) do
143     {:ok, user} = User.get_or_fetch(activity.object.data["actor"])
144
145     link =
146       case user.local do
147         true -> Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, activity)
148         _ -> data["url"] || data["external_url"] || data["id"]
149       end
150
151     content =
152       if data["content"] do
153         data["content"]
154         |> Pleroma.HTML.filter_tags()
155         |> Pleroma.Emoji.Formatter.emojify(Map.get(data, "emoji", %{}))
156       else
157         nil
158       end
159
160     %{
161       user: User.sanitize_html(user),
162       title: get_title(activity.object),
163       content: content,
164       attachment: data["attachment"],
165       link: link,
166       published: data["published"],
167       sensitive: data["sensitive"],
168       selected: selected,
169       counts: get_counts(activity),
170       id: activity.id
171     }
172   end
173
174   defp assign_id(%{path_info: ["notice", notice_id]} = conn, _opts),
175     do: assign(conn, :notice_id, notice_id)
176
177   defp assign_id(%{path_info: ["users", user_id]} = conn, _opts),
178     do: assign(conn, :username_or_id, user_id)
179
180   defp assign_id(%{path_info: ["objects", object_id]} = conn, _opts),
181     do: assign(conn, :object_id, object_id)
182
183   defp assign_id(%{path_info: ["activities", activity_id]} = conn, _opts),
184     do: assign(conn, :activity_id, activity_id)
185
186   defp assign_id(conn, _opts), do: conn
187 end