Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into develop
commit
94076a23e4
@ -0,0 +1,122 @@
|
|||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Plugs.Cache do
|
||||||
|
@moduledoc """
|
||||||
|
Caches successful GET responses.
|
||||||
|
|
||||||
|
To enable the cache add the plug to a router pipeline or controller:
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.Cache)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
To configure the plug you need to pass settings as the second argument to the `plug/2` macro:
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.Cache, [ttl: nil, query_params: true])
|
||||||
|
|
||||||
|
Available options:
|
||||||
|
|
||||||
|
- `ttl`: An expiration time (time-to-live). This value should be in milliseconds or `nil` to disable expiration. Defaults to `nil`.
|
||||||
|
- `query_params`: Take URL query string into account (`true`), ignore it (`false`) or limit to specific params only (list). Defaults to `true`.
|
||||||
|
|
||||||
|
Additionally, you can overwrite the TTL inside a controller action by assigning `cache_ttl` to the connection struct:
|
||||||
|
|
||||||
|
def index(conn, _params) do
|
||||||
|
ttl = 60_000 # one minute
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:cache_ttl, ttl)
|
||||||
|
|> render("index.html")
|
||||||
|
end
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import Phoenix.Controller, only: [current_path: 1, json: 2]
|
||||||
|
import Plug.Conn
|
||||||
|
|
||||||
|
@behaviour Plug
|
||||||
|
|
||||||
|
@defaults %{ttl: nil, query_params: true}
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def init([]), do: @defaults
|
||||||
|
|
||||||
|
def init(opts) do
|
||||||
|
opts = Map.new(opts)
|
||||||
|
Map.merge(@defaults, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def call(%{method: "GET"} = conn, opts) do
|
||||||
|
key = cache_key(conn, opts)
|
||||||
|
|
||||||
|
case Cachex.get(:web_resp_cache, key) do
|
||||||
|
{:ok, nil} ->
|
||||||
|
cache_resp(conn, opts)
|
||||||
|
|
||||||
|
{:ok, record} ->
|
||||||
|
send_cached(conn, record)
|
||||||
|
|
||||||
|
{atom, message} when atom in [:ignore, :error] ->
|
||||||
|
render_error(conn, message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(conn, _), do: conn
|
||||||
|
|
||||||
|
# full path including query params
|
||||||
|
defp cache_key(conn, %{query_params: true}), do: current_path(conn)
|
||||||
|
|
||||||
|
# request path without query params
|
||||||
|
defp cache_key(conn, %{query_params: false}), do: conn.request_path
|
||||||
|
|
||||||
|
# request path with specific query params
|
||||||
|
defp cache_key(conn, %{query_params: query_params}) when is_list(query_params) do
|
||||||
|
query_string =
|
||||||
|
conn.params
|
||||||
|
|> Map.take(query_params)
|
||||||
|
|> URI.encode_query()
|
||||||
|
|
||||||
|
conn.request_path <> "?" <> query_string
|
||||||
|
end
|
||||||
|
|
||||||
|
defp cache_resp(conn, opts) do
|
||||||
|
register_before_send(conn, fn
|
||||||
|
%{status: 200, resp_body: body} = conn ->
|
||||||
|
ttl = Map.get(conn.assigns, :cache_ttl, opts.ttl)
|
||||||
|
key = cache_key(conn, opts)
|
||||||
|
content_type = content_type(conn)
|
||||||
|
record = {content_type, body}
|
||||||
|
|
||||||
|
Cachex.put(:web_resp_cache, key, record, ttl: ttl)
|
||||||
|
|
||||||
|
put_resp_header(conn, "x-cache", "MISS from Pleroma")
|
||||||
|
|
||||||
|
conn ->
|
||||||
|
conn
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp content_type(conn) do
|
||||||
|
conn
|
||||||
|
|> Plug.Conn.get_resp_header("content-type")
|
||||||
|
|> hd()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp send_cached(conn, {content_type, body}) do
|
||||||
|
conn
|
||||||
|
|> put_resp_content_type(content_type, nil)
|
||||||
|
|> put_resp_header("x-cache", "HIT from Pleroma")
|
||||||
|
|> send_resp(:ok, body)
|
||||||
|
|> halt()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp render_error(conn, message) do
|
||||||
|
conn
|
||||||
|
|> put_status(:internal_server_error)
|
||||||
|
|> json(%{error: message})
|
||||||
|
|> halt()
|
||||||
|
end
|
||||||
|
end
|
@ -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.Plugs.TrailingFormatPlug do
|
||||||
|
@moduledoc "Calls TrailingFormatPlug for specific paths. Ideally we would just do this in the router, but TrailingFormatPlug needs to be called before Plug.Parsers."
|
||||||
|
|
||||||
|
@behaviour Plug
|
||||||
|
@paths [
|
||||||
|
"/api/statusnet",
|
||||||
|
"/api/statuses",
|
||||||
|
"/api/qvitter",
|
||||||
|
"/api/search",
|
||||||
|
"/api/account",
|
||||||
|
"/api/friends",
|
||||||
|
"/api/mutes",
|
||||||
|
"/api/media",
|
||||||
|
"/api/favorites",
|
||||||
|
"/api/blocks",
|
||||||
|
"/api/friendships",
|
||||||
|
"/api/users",
|
||||||
|
"/users",
|
||||||
|
"/nodeinfo",
|
||||||
|
"/api/help",
|
||||||
|
"/api/externalprofile",
|
||||||
|
"/notice",
|
||||||
|
"/api/pleroma/emoji"
|
||||||
|
]
|
||||||
|
|
||||||
|
def init(opts) do
|
||||||
|
TrailingFormatPlug.init(opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
for path <- @paths do
|
||||||
|
def call(%{request_path: unquote(path) <> _} = conn, opts) do
|
||||||
|
TrailingFormatPlug.call(conn, opts)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(conn, _opts), do: conn
|
||||||
|
end
|
@ -1,38 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.Representers.BaseRepresenter do
|
|
||||||
defmacro __using__(_opts) do
|
|
||||||
quote do
|
|
||||||
def to_json(object) do
|
|
||||||
to_json(object, %{})
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_json(object, options) do
|
|
||||||
object
|
|
||||||
|> to_map(options)
|
|
||||||
|> Jason.encode!()
|
|
||||||
end
|
|
||||||
|
|
||||||
def enum_to_list(enum, options) do
|
|
||||||
mapping = fn el -> to_map(el, options) end
|
|
||||||
Enum.map(enum, mapping)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_map(object) do
|
|
||||||
to_map(object, %{})
|
|
||||||
end
|
|
||||||
|
|
||||||
def enum_to_json(enum) do
|
|
||||||
enum_to_json(enum, %{})
|
|
||||||
end
|
|
||||||
|
|
||||||
def enum_to_json(enum, options) do
|
|
||||||
enum
|
|
||||||
|> enum_to_list(options)
|
|
||||||
|> Jason.encode!()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,39 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter do
|
|
||||||
use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter
|
|
||||||
alias Pleroma.Object
|
|
||||||
|
|
||||||
def to_map(%Object{data: %{"url" => [url | _]}} = object, _opts) do
|
|
||||||
data = object.data
|
|
||||||
|
|
||||||
%{
|
|
||||||
url: url["href"] |> Pleroma.Web.MediaProxy.url(),
|
|
||||||
mimetype: url["mediaType"] || url["mimeType"],
|
|
||||||
id: data["uuid"],
|
|
||||||
oembed: false,
|
|
||||||
description: data["name"]
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_map(%Object{data: %{"url" => url} = data}, _opts) when is_binary(url) do
|
|
||||||
%{
|
|
||||||
url: url |> Pleroma.Web.MediaProxy.url(),
|
|
||||||
mimetype: data["mediaType"] || data["mimeType"],
|
|
||||||
id: data["uuid"],
|
|
||||||
oembed: false,
|
|
||||||
description: data["name"]
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_map(%Object{}, _opts) do
|
|
||||||
%{}
|
|
||||||
end
|
|
||||||
|
|
||||||
# If we only get the naked data, wrap in an object
|
|
||||||
def to_map(%{} = data, opts) do
|
|
||||||
to_map(%Object{data: data}, opts)
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,366 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.ActivityView do
|
|
||||||
use Pleroma.Web, :view
|
|
||||||
alias Pleroma.Activity
|
|
||||||
alias Pleroma.Formatter
|
|
||||||
alias Pleroma.HTML
|
|
||||||
alias Pleroma.Object
|
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web.CommonAPI
|
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
|
||||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
|
||||||
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
|
||||||
alias Pleroma.Web.TwitterAPI.UserView
|
|
||||||
|
|
||||||
import Ecto.Query
|
|
||||||
require Logger
|
|
||||||
require Pleroma.Constants
|
|
||||||
|
|
||||||
defp query_context_ids([]), do: []
|
|
||||||
|
|
||||||
defp query_context_ids(contexts) do
|
|
||||||
query = from(o in Object, where: fragment("(?)->>'id' = ANY(?)", o.data, ^contexts))
|
|
||||||
|
|
||||||
Repo.all(query)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp query_users([]), do: []
|
|
||||||
|
|
||||||
defp query_users(user_ids) do
|
|
||||||
query = from(user in User, where: user.ap_id in ^user_ids)
|
|
||||||
|
|
||||||
Repo.all(query)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp collect_context_ids(activities) do
|
|
||||||
_contexts =
|
|
||||||
activities
|
|
||||||
|> Enum.reject(& &1.data["context_id"])
|
|
||||||
|> Enum.map(fn %{data: data} ->
|
|
||||||
data["context"]
|
|
||||||
end)
|
|
||||||
|> Enum.filter(& &1)
|
|
||||||
|> query_context_ids()
|
|
||||||
|> Enum.reduce(%{}, fn %{data: %{"id" => ap_id}, id: id}, acc ->
|
|
||||||
Map.put(acc, ap_id, id)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp collect_users(activities) do
|
|
||||||
activities
|
|
||||||
|> Enum.map(fn activity ->
|
|
||||||
case activity.data do
|
|
||||||
data = %{"type" => "Follow"} ->
|
|
||||||
[data["actor"], data["object"]]
|
|
||||||
|
|
||||||
data ->
|
|
||||||
[data["actor"]]
|
|
||||||
end ++ activity.recipients
|
|
||||||
end)
|
|
||||||
|> List.flatten()
|
|
||||||
|> Enum.uniq()
|
|
||||||
|> query_users()
|
|
||||||
|> Enum.reduce(%{}, fn user, acc ->
|
|
||||||
Map.put(acc, user.ap_id, user)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_context_id(%{data: %{"context_id" => context_id}}, _) when not is_nil(context_id),
|
|
||||||
do: context_id
|
|
||||||
|
|
||||||
defp get_context_id(%{data: %{"context" => nil}}, _), do: nil
|
|
||||||
|
|
||||||
defp get_context_id(%{data: %{"context" => context}}, options) do
|
|
||||||
cond do
|
|
||||||
id = options[:context_ids][context] -> id
|
|
||||||
true -> Utils.context_to_conversation_id(context)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_context_id(_, _), do: nil
|
|
||||||
|
|
||||||
defp get_user(ap_id, opts) do
|
|
||||||
cond do
|
|
||||||
user = opts[:users][ap_id] ->
|
|
||||||
user
|
|
||||||
|
|
||||||
String.ends_with?(ap_id, "/followers") ->
|
|
||||||
nil
|
|
||||||
|
|
||||||
ap_id == Pleroma.Constants.as_public() ->
|
|
||||||
nil
|
|
||||||
|
|
||||||
user = User.get_cached_by_ap_id(ap_id) ->
|
|
||||||
user
|
|
||||||
|
|
||||||
user = User.get_by_guessed_nickname(ap_id) ->
|
|
||||||
user
|
|
||||||
|
|
||||||
true ->
|
|
||||||
User.error_user(ap_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("index.json", opts) do
|
|
||||||
context_ids = collect_context_ids(opts.activities)
|
|
||||||
users = collect_users(opts.activities)
|
|
||||||
|
|
||||||
opts =
|
|
||||||
opts
|
|
||||||
|> Map.put(:context_ids, context_ids)
|
|
||||||
|> Map.put(:users, users)
|
|
||||||
|
|
||||||
safe_render_many(
|
|
||||||
opts.activities,
|
|
||||||
ActivityView,
|
|
||||||
"activity.json",
|
|
||||||
opts
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("activity.json", %{activity: %{data: %{"type" => "Delete"}} = activity} = opts) do
|
|
||||||
user = get_user(activity.data["actor"], opts)
|
|
||||||
created_at = activity.data["published"] |> Utils.date_to_asctime()
|
|
||||||
|
|
||||||
%{
|
|
||||||
"id" => activity.id,
|
|
||||||
"uri" => activity.data["object"],
|
|
||||||
"user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
|
|
||||||
"attentions" => [],
|
|
||||||
"statusnet_html" => "deleted notice {{tag",
|
|
||||||
"text" => "deleted notice {{tag",
|
|
||||||
"is_local" => activity.local,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"created_at" => created_at,
|
|
||||||
"in_reply_to_status_id" => nil,
|
|
||||||
"external_url" => activity.data["id"],
|
|
||||||
"activity_type" => "delete"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("activity.json", %{activity: %{data: %{"type" => "Follow"}} = activity} = opts) do
|
|
||||||
user = get_user(activity.data["actor"], opts)
|
|
||||||
created_at = activity.data["published"] || DateTime.to_iso8601(activity.inserted_at)
|
|
||||||
created_at = created_at |> Utils.date_to_asctime()
|
|
||||||
|
|
||||||
followed = get_user(activity.data["object"], opts)
|
|
||||||
text = "#{user.nickname} started following #{followed.nickname}"
|
|
||||||
|
|
||||||
%{
|
|
||||||
"id" => activity.id,
|
|
||||||
"user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
|
|
||||||
"attentions" => [],
|
|
||||||
"statusnet_html" => text,
|
|
||||||
"text" => text,
|
|
||||||
"is_local" => activity.local,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"created_at" => created_at,
|
|
||||||
"in_reply_to_status_id" => nil,
|
|
||||||
"external_url" => activity.data["id"],
|
|
||||||
"activity_type" => "follow"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("activity.json", %{activity: %{data: %{"type" => "Announce"}} = activity} = opts) do
|
|
||||||
user = get_user(activity.data["actor"], opts)
|
|
||||||
created_at = activity.data["published"] |> Utils.date_to_asctime()
|
|
||||||
announced_activity = Activity.get_create_by_object_ap_id(activity.data["object"])
|
|
||||||
|
|
||||||
text = "#{user.nickname} repeated a status."
|
|
||||||
|
|
||||||
retweeted_status = render("activity.json", Map.merge(opts, %{activity: announced_activity}))
|
|
||||||
|
|
||||||
%{
|
|
||||||
"id" => activity.id,
|
|
||||||
"user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
|
|
||||||
"statusnet_html" => text,
|
|
||||||
"text" => text,
|
|
||||||
"is_local" => activity.local,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"uri" => "tag:#{activity.data["id"]}:objectType=note",
|
|
||||||
"created_at" => created_at,
|
|
||||||
"retweeted_status" => retweeted_status,
|
|
||||||
"statusnet_conversation_id" => get_context_id(announced_activity, opts),
|
|
||||||
"external_url" => activity.data["id"],
|
|
||||||
"activity_type" => "repeat"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("activity.json", %{activity: %{data: %{"type" => "Like"}} = activity} = opts) do
|
|
||||||
user = get_user(activity.data["actor"], opts)
|
|
||||||
liked_activity = Activity.get_create_by_object_ap_id(activity.data["object"])
|
|
||||||
liked_activity_id = if liked_activity, do: liked_activity.id, else: nil
|
|
||||||
|
|
||||||
created_at =
|
|
||||||
activity.data["published"]
|
|
||||||
|> Utils.date_to_asctime()
|
|
||||||
|
|
||||||
text = "#{user.nickname} favorited a status."
|
|
||||||
|
|
||||||
favorited_status =
|
|
||||||
if liked_activity,
|
|
||||||
do: render("activity.json", Map.merge(opts, %{activity: liked_activity})),
|
|
||||||
else: nil
|
|
||||||
|
|
||||||
%{
|
|
||||||
"id" => activity.id,
|
|
||||||
"user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
|
|
||||||
"statusnet_html" => text,
|
|
||||||
"text" => text,
|
|
||||||
"is_local" => activity.local,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"uri" => "tag:#{activity.data["id"]}:objectType=Favourite",
|
|
||||||
"created_at" => created_at,
|
|
||||||
"favorited_status" => favorited_status,
|
|
||||||
"in_reply_to_status_id" => liked_activity_id,
|
|
||||||
"external_url" => activity.data["id"],
|
|
||||||
"activity_type" => "like"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render(
|
|
||||||
"activity.json",
|
|
||||||
%{activity: %{data: %{"type" => "Create", "object" => object_id}} = activity} = opts
|
|
||||||
) do
|
|
||||||
user = get_user(activity.data["actor"], opts)
|
|
||||||
|
|
||||||
object = Object.normalize(object_id)
|
|
||||||
|
|
||||||
created_at = object.data["published"] |> Utils.date_to_asctime()
|
|
||||||
like_count = object.data["like_count"] || 0
|
|
||||||
announcement_count = object.data["announcement_count"] || 0
|
|
||||||
favorited = opts[:for] && opts[:for].ap_id in (object.data["likes"] || [])
|
|
||||||
repeated = opts[:for] && opts[:for].ap_id in (object.data["announcements"] || [])
|
|
||||||
pinned = activity.id in user.info.pinned_activities
|
|
||||||
|
|
||||||
attentions =
|
|
||||||
[]
|
|
||||||
|> Utils.maybe_notify_to_recipients(activity)
|
|
||||||
|> Utils.maybe_notify_mentioned_recipients(activity)
|
|
||||||
|> Enum.map(fn ap_id -> get_user(ap_id, opts) end)
|
|
||||||
|> Enum.filter(& &1)
|
|
||||||
|> Enum.map(fn user -> UserView.render("show.json", %{user: user, for: opts[:for]}) end)
|
|
||||||
|
|
||||||
conversation_id = get_context_id(activity, opts)
|
|
||||||
|
|
||||||
tags = object.data["tag"] || []
|
|
||||||
possibly_sensitive = object.data["sensitive"] || Enum.member?(tags, "nsfw")
|
|
||||||
|
|
||||||
tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags
|
|
||||||
|
|
||||||
{summary, content} = render_content(object.data)
|
|
||||||
|
|
||||||
html =
|
|
||||||
content
|
|
||||||
|> HTML.get_cached_scrubbed_html_for_activity(
|
|
||||||
User.html_filter_policy(opts[:for]),
|
|
||||||
activity,
|
|
||||||
"twitterapi:content"
|
|
||||||
)
|
|
||||||
|> Formatter.emojify(object.data["emoji"])
|
|
||||||
|
|
||||||
text =
|
|
||||||
if content do
|
|
||||||
content
|
|
||||||
|> String.replace(~r/<br\s?\/?>/, "\n")
|
|
||||||
|> HTML.get_cached_stripped_html_for_activity(activity, "twitterapi:content")
|
|
||||||
else
|
|
||||||
""
|
|
||||||
end
|
|
||||||
|
|
||||||
reply_parent = Activity.get_in_reply_to_activity(activity)
|
|
||||||
|
|
||||||
reply_user = reply_parent && User.get_cached_by_ap_id(reply_parent.actor)
|
|
||||||
|
|
||||||
summary = HTML.strip_tags(summary)
|
|
||||||
|
|
||||||
card =
|
|
||||||
StatusView.render(
|
|
||||||
"card.json",
|
|
||||||
Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
|
|
||||||
)
|
|
||||||
|
|
||||||
thread_muted? =
|
|
||||||
case activity.thread_muted? do
|
|
||||||
thread_muted? when is_boolean(thread_muted?) -> thread_muted?
|
|
||||||
nil -> CommonAPI.thread_muted?(user, activity)
|
|
||||||
end
|
|
||||||
|
|
||||||
%{
|
|
||||||
"id" => activity.id,
|
|
||||||
"uri" => object.data["id"],
|
|
||||||
"user" => UserView.render("show.json", %{user: user, for: opts[:for]}),
|
|
||||||
"statusnet_html" => html,
|
|
||||||
"text" => text,
|
|
||||||
"is_local" => activity.local,
|
|
||||||
"is_post_verb" => true,
|
|
||||||
"created_at" => created_at,
|
|
||||||
"in_reply_to_status_id" => reply_parent && reply_parent.id,
|
|
||||||
"in_reply_to_screen_name" => reply_user && reply_user.nickname,
|
|
||||||
"in_reply_to_profileurl" => User.profile_url(reply_user),
|
|
||||||
"in_reply_to_ostatus_uri" => reply_user && reply_user.ap_id,
|
|
||||||
"in_reply_to_user_id" => reply_user && reply_user.id,
|
|
||||||
"statusnet_conversation_id" => conversation_id,
|
|
||||||
"attachments" => (object.data["attachment"] || []) |> ObjectRepresenter.enum_to_list(opts),
|
|
||||||
"attentions" => attentions,
|
|
||||||
"fave_num" => like_count,
|
|
||||||
"repeat_num" => announcement_count,
|
|
||||||
"favorited" => !!favorited,
|
|
||||||
"repeated" => !!repeated,
|
|
||||||
"pinned" => pinned,
|
|
||||||
"external_url" => object.data["external_url"] || object.data["id"],
|
|
||||||
"tags" => tags,
|
|
||||||
"activity_type" => "post",
|
|
||||||
"possibly_sensitive" => possibly_sensitive,
|
|
||||||
"visibility" => Pleroma.Web.ActivityPub.Visibility.get_visibility(object),
|
|
||||||
"summary" => summary,
|
|
||||||
"summary_html" => summary |> Formatter.emojify(object.data["emoji"]),
|
|
||||||
"card" => card,
|
|
||||||
"muted" => thread_muted? || User.mutes?(opts[:for], user)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("activity.json", %{activity: unhandled_activity}) do
|
|
||||||
Logger.warn("#{__MODULE__} unhandled activity: #{inspect(unhandled_activity)}")
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_content(%{"type" => "Note"} = object) do
|
|
||||||
summary = object["summary"]
|
|
||||||
|
|
||||||
content =
|
|
||||||
if !!summary and summary != "" do
|
|
||||||
"<p>#{summary}</p>#{object["content"]}"
|
|
||||||
else
|
|
||||||
object["content"]
|
|
||||||
end
|
|
||||||
|
|
||||||
{summary, content}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_content(%{"type" => object_type} = object)
|
|
||||||
when object_type in ["Article", "Page", "Video"] do
|
|
||||||
summary = object["name"] || object["summary"]
|
|
||||||
|
|
||||||
content =
|
|
||||||
if !!summary and summary != "" and is_bitstring(object["url"]) do
|
|
||||||
"<p><a href=\"#{object["url"]}\">#{summary}</a></p>#{object["content"]}"
|
|
||||||
else
|
|
||||||
object["content"]
|
|
||||||
end
|
|
||||||
|
|
||||||
{summary, content}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_content(object) do
|
|
||||||
summary = object["summary"] || "Unhandled activity type: #{object["type"]}"
|
|
||||||
content = "<p>#{summary}</p>#{object["content"]}"
|
|
||||||
|
|
||||||
{summary, content}
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,71 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.NotificationView do
|
|
||||||
use Pleroma.Web, :view
|
|
||||||
alias Pleroma.Notification
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
|
||||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
|
||||||
alias Pleroma.Web.TwitterAPI.UserView
|
|
||||||
|
|
||||||
require Pleroma.Constants
|
|
||||||
|
|
||||||
defp get_user(ap_id, opts) do
|
|
||||||
cond do
|
|
||||||
user = opts[:users][ap_id] ->
|
|
||||||
user
|
|
||||||
|
|
||||||
String.ends_with?(ap_id, "/followers") ->
|
|
||||||
nil
|
|
||||||
|
|
||||||
ap_id == Pleroma.Constants.as_public() ->
|
|
||||||
nil
|
|
||||||
|
|
||||||
true ->
|
|
||||||
User.get_cached_by_ap_id(ap_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("notification.json", %{notifications: notifications, for: user}) do
|
|
||||||
render_many(
|
|
||||||
notifications,
|
|
||||||
Pleroma.Web.TwitterAPI.NotificationView,
|
|
||||||
"notification.json",
|
|
||||||
for: user
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def render(
|
|
||||||
"notification.json",
|
|
||||||
%{
|
|
||||||
notification: %Notification{
|
|
||||||
id: id,
|
|
||||||
seen: seen,
|
|
||||||
activity: activity,
|
|
||||||
inserted_at: created_at
|
|
||||||
},
|
|
||||||
for: user
|
|
||||||
} = opts
|
|
||||||
) do
|
|
||||||
ntype =
|
|
||||||
case activity.data["type"] do
|
|
||||||
"Create" -> "mention"
|
|
||||||
"Like" -> "like"
|
|
||||||
"Announce" -> "repeat"
|
|
||||||
"Follow" -> "follow"
|
|
||||||
end
|
|
||||||
|
|
||||||
from = get_user(activity.data["actor"], opts)
|
|
||||||
|
|
||||||
%{
|
|
||||||
"id" => id,
|
|
||||||
"ntype" => ntype,
|
|
||||||
"notice" => ActivityView.render("activity.json", %{activity: activity, for: user}),
|
|
||||||
"from_profile" => UserView.render("show.json", %{user: from, for: user}),
|
|
||||||
"is_seen" => if(seen, do: 1, else: 0),
|
|
||||||
"created_at" => created_at |> Utils.format_naive_asctime()
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,191 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.UserView do
|
|
||||||
use Pleroma.Web, :view
|
|
||||||
alias Pleroma.Formatter
|
|
||||||
alias Pleroma.HTML
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
|
||||||
alias Pleroma.Web.MediaProxy
|
|
||||||
|
|
||||||
def render("show.json", %{user: user = %User{}} = assigns) do
|
|
||||||
render_one(user, Pleroma.Web.TwitterAPI.UserView, "user.json", assigns)
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("index.json", %{users: users, for: user}) do
|
|
||||||
users
|
|
||||||
|> render_many(Pleroma.Web.TwitterAPI.UserView, "user.json", for: user)
|
|
||||||
|> Enum.filter(&Enum.any?/1)
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("user.json", %{user: user = %User{}} = assigns) do
|
|
||||||
if User.visible_for?(user, assigns[:for]),
|
|
||||||
do: do_render("user.json", assigns),
|
|
||||||
else: %{}
|
|
||||||
end
|
|
||||||
|
|
||||||
def render("short.json", %{
|
|
||||||
user: %User{
|
|
||||||
nickname: nickname,
|
|
||||||
id: id,
|
|
||||||
ap_id: ap_id,
|
|
||||||
name: name
|
|
||||||
}
|
|
||||||
}) do
|
|
||||||
%{
|
|
||||||
"fullname" => name,
|
|
||||||
"id" => id,
|
|
||||||
"ostatus_uri" => ap_id,
|
|
||||||
"profile_url" => ap_id,
|
|
||||||
"screen_name" => nickname
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp do_render("user.json", %{user: user = %User{}} = assigns) do
|
|
||||||
for_user = assigns[:for]
|
|
||||||
image = User.avatar_url(user) |> MediaProxy.url()
|
|
||||||
|
|
||||||
{following, follows_you, statusnet_blocking} =
|
|
||||||
if for_user do
|
|
||||||
{
|
|
||||||
User.following?(for_user, user),
|
|
||||||
User.following?(user, for_user),
|
|
||||||
User.blocks?(for_user, user)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{false, false, false}
|
|
||||||
end
|
|
||||||
|
|
||||||
user_info = User.get_cached_user_info(user)
|
|
||||||
|
|
||||||
emoji =
|
|
||||||
(user.info.source_data["tag"] || [])
|
|
||||||
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|
|
||||||
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
|
|
||||||
{String.trim(name, ":"), url}
|
|
||||||
end)
|
|
||||||
|
|
||||||
emoji = Enum.dedup(emoji ++ user.info.emoji)
|
|
||||||
|
|
||||||
description_html =
|
|
||||||
(user.bio || "")
|
|
||||||
|> HTML.filter_tags(User.html_filter_policy(for_user))
|
|
||||||
|> Formatter.emojify(emoji)
|
|
||||||
|
|
||||||
fields =
|
|
||||||
user.info
|
|
||||||
|> User.Info.fields()
|
|
||||||
|> Enum.map(fn %{"name" => name, "value" => value} ->
|
|
||||||
%{
|
|
||||||
"name" => Pleroma.HTML.strip_tags(name),
|
|
||||||
"value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly)
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
|
|
||||||
data =
|
|
||||||
%{
|
|
||||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"description" => HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
|
|
||||||
"description_html" => description_html,
|
|
||||||
"favourites_count" => 0,
|
|
||||||
"followers_count" => user_info[:follower_count],
|
|
||||||
"following" => following,
|
|
||||||
"follows_you" => follows_you,
|
|
||||||
"statusnet_blocking" => statusnet_blocking,
|
|
||||||
"friends_count" => user_info[:following_count],
|
|
||||||
"id" => user.id,
|
|
||||||
"name" => user.name || user.nickname,
|
|
||||||
"name_html" =>
|
|
||||||
if(user.name,
|
|
||||||
do: HTML.strip_tags(user.name) |> Formatter.emojify(emoji),
|
|
||||||
else: user.nickname
|
|
||||||
),
|
|
||||||
"profile_image_url" => image,
|
|
||||||
"profile_image_url_https" => image,
|
|
||||||
"profile_image_url_profile_size" => image,
|
|
||||||
"profile_image_url_original" => image,
|
|
||||||
"screen_name" => user.nickname,
|
|
||||||
"statuses_count" => user_info[:note_count],
|
|
||||||
"statusnet_profile_url" => user.ap_id,
|
|
||||||
"cover_photo" => User.banner_url(user) |> MediaProxy.url(),
|
|
||||||
"background_image" => image_url(user.info.background) |> MediaProxy.url(),
|
|
||||||
"is_local" => user.local,
|
|
||||||
"locked" => user.info.locked,
|
|
||||||
"hide_followers" => user.info.hide_followers,
|
|
||||||
"hide_follows" => user.info.hide_follows,
|
|
||||||
"fields" => fields,
|
|
||||||
|
|
||||||
# Pleroma extension
|
|
||||||
"pleroma" =>
|
|
||||||
%{
|
|
||||||
"confirmation_pending" => user_info.confirmation_pending,
|
|
||||||
"tags" => user.tags,
|
|
||||||
"skip_thread_containment" => user.info.skip_thread_containment
|
|
||||||
}
|
|
||||||
|> maybe_with_activation_status(user, for_user)
|
|
||||||
|> with_notification_settings(user, for_user)
|
|
||||||
}
|
|
||||||
|> maybe_with_user_settings(user, for_user)
|
|
||||||
|> maybe_with_role(user, for_user)
|
|
||||||
|
|
||||||
if assigns[:token] do
|
|
||||||
Map.put(data, "token", token_string(assigns[:token]))
|
|
||||||
else
|
|
||||||
data
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp with_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do
|
|
||||||
Map.put(data, "notification_settings", user.info.notification_settings)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp with_notification_settings(data, _, _), do: data
|
|
||||||
|
|
||||||
defp maybe_with_activation_status(data, user, %User{info: %{is_admin: true}}) do
|
|
||||||
Map.put(data, "deactivated", user.info.deactivated)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp maybe_with_activation_status(data, _, _), do: data
|
|
||||||
|
|
||||||
defp maybe_with_role(data, %User{id: id} = user, %User{id: id}) do
|
|
||||||
Map.merge(data, %{
|
|
||||||
"role" => role(user),
|
|
||||||
"show_role" => user.info.show_role,
|
|
||||||
"rights" => %{
|
|
||||||
"delete_others_notice" => !!user.info.is_moderator,
|
|
||||||
"admin" => !!user.info.is_admin
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
defp maybe_with_role(data, %User{info: %{show_role: true}} = user, _user) do
|
|
||||||
Map.merge(data, %{
|
|
||||||
"role" => role(user),
|
|
||||||
"rights" => %{
|
|
||||||
"delete_others_notice" => !!user.info.is_moderator,
|
|
||||||
"admin" => !!user.info.is_admin
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
defp maybe_with_role(data, _, _), do: data
|
|
||||||
|
|
||||||
defp maybe_with_user_settings(data, %User{info: info, id: id} = _user, %User{id: id}) do
|
|
||||||
data
|
|
||||||
|> Kernel.put_in(["default_scope"], info.default_scope)
|
|
||||||
|> Kernel.put_in(["no_rich_text"], info.no_rich_text)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp maybe_with_user_settings(data, _, _), do: data
|
|
||||||
defp role(%User{info: %{:is_admin => true}}), do: "admin"
|
|
||||||
defp role(%User{info: %{:is_moderator => true}}), do: "moderator"
|
|
||||||
defp role(_), do: "member"
|
|
||||||
|
|
||||||
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
|
|
||||||
defp image_url(_), do: nil
|
|
||||||
|
|
||||||
defp token_string(%Pleroma.Web.OAuth.Token{token: token_str}), do: token_str
|
|
||||||
defp token_string(token), do: token
|
|
||||||
end
|
|
@ -1 +1 @@
|
|||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/lato.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/vendors~app.b2603a50868c68a1c192.css rel=stylesheet><link href=/static/css/app.db80066bde2c96ea6198.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/vendors~app.4b7be53256fba5c365c9.js></script><script type=text/javascript src=/static/js/app.670c36c0acc42fadb4fe.js></script></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/vendors~app.b2603a50868c68a1c192.css rel=stylesheet><link href=/static/css/app.cb3673e4b661fd9526ea.css rel=stylesheet></head><body><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.4cedffe4993b111c7421.js></script><script type=text/javascript src=/static/js/app.8098503330c7dd14a415.js></script></body></html>
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["webpack:///./src/components/tab_switcher/tab_switcher.scss","webpack:///./src/hocs/with_load_more/with_load_more.scss","webpack:///./src/hocs/with_subscription/with_subscription.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACTA;AACA;AACA;AACA;AACA;AACA;AACA,C","file":"static/css/app.cb3673e4b661fd9526ea.css","sourcesContent":[".tab-switcher .contents .hidden {\n display: none;\n}\n.tab-switcher .tabs {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n width: 100%;\n overflow-y: hidden;\n overflow-x: auto;\n padding-top: 5px;\n box-sizing: border-box;\n}\n.tab-switcher .tabs::after, .tab-switcher .tabs::before {\n display: block;\n content: \"\";\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher .tabs .tab-wrapper {\n height: 28px;\n position: relative;\n display: -ms-flexbox;\n display: flex;\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n}\n.tab-switcher .tabs .tab-wrapper .tab {\n width: 100%;\n min-width: 1px;\n position: relative;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n padding: 6px 1em;\n padding-bottom: 99px;\n margin-bottom: -93px;\n white-space: nowrap;\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active) {\n z-index: 4;\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active):hover {\n z-index: 6;\n}\n.tab-switcher .tabs .tab-wrapper .tab.active {\n background: transparent;\n z-index: 5;\n}\n.tab-switcher .tabs .tab-wrapper .tab img {\n max-height: 26px;\n vertical-align: top;\n margin-top: -5px;\n}\n.tab-switcher .tabs .tab-wrapper:not(.active)::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 7;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}",".with-load-more-footer {\n padding: 10px;\n text-align: center;\n border-top: 1px solid;\n border-top-color: #222;\n border-top-color: var(--border, #222);\n}\n.with-load-more-footer .error {\n font-size: 14px;\n}",".with-subscription-loading {\n padding: 10px;\n text-align: center;\n}\n.with-subscription-loading .error {\n font-size: 14px;\n}"],"sourceRoot":""}
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":["webpack:///./src/hocs/with_load_more/with_load_more.scss","webpack:///./src/components/tab_switcher/tab_switcher.scss","webpack:///./src/hocs/with_subscription/with_subscription.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,C;ACzDA;AACA;AACA;AACA;AACA;AACA;AACA,C","file":"static/css/app.db80066bde2c96ea6198.css","sourcesContent":[".with-load-more-footer {\n padding: 10px;\n text-align: center;\n border-top: 1px solid;\n border-top-color: #222;\n border-top-color: var(--border, #222);\n}\n.with-load-more-footer .error {\n font-size: 14px;\n}",".tab-switcher .contents .hidden {\n display: none;\n}\n.tab-switcher .tabs {\n display: flex;\n position: relative;\n width: 100%;\n overflow-y: hidden;\n overflow-x: auto;\n padding-top: 5px;\n box-sizing: border-box;\n}\n.tab-switcher .tabs::after, .tab-switcher .tabs::before {\n display: block;\n content: \"\";\n flex: 1 1 auto;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}\n.tab-switcher .tabs .tab-wrapper {\n height: 28px;\n position: relative;\n display: flex;\n flex: 0 0 auto;\n}\n.tab-switcher .tabs .tab-wrapper .tab {\n width: 100%;\n min-width: 1px;\n position: relative;\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n padding: 6px 1em;\n padding-bottom: 99px;\n margin-bottom: -93px;\n white-space: nowrap;\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active) {\n z-index: 4;\n}\n.tab-switcher .tabs .tab-wrapper .tab:not(.active):hover {\n z-index: 6;\n}\n.tab-switcher .tabs .tab-wrapper .tab.active {\n background: transparent;\n z-index: 5;\n}\n.tab-switcher .tabs .tab-wrapper:not(.active)::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 7;\n border-bottom: 1px solid;\n border-bottom-color: #222;\n border-bottom-color: var(--border, #222);\n}",".with-subscription-loading {\n padding: 10px;\n text-align: center;\n}\n.with-subscription-loading .error {\n font-size: 14px;\n}"],"sourceRoot":""}
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,186 @@
|
|||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Plugs.CacheTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
use Plug.Test
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.Cache
|
||||||
|
|
||||||
|
@miss_resp {200,
|
||||||
|
[
|
||||||
|
{"cache-control", "max-age=0, private, must-revalidate"},
|
||||||
|
{"content-type", "cofe/hot; charset=utf-8"},
|
||||||
|
{"x-cache", "MISS from Pleroma"}
|
||||||
|
], "cofe"}
|
||||||
|
|
||||||
|
@hit_resp {200,
|
||||||
|
[
|
||||||
|
{"cache-control", "max-age=0, private, must-revalidate"},
|
||||||
|
{"content-type", "cofe/hot; charset=utf-8"},
|
||||||
|
{"x-cache", "HIT from Pleroma"}
|
||||||
|
], "cofe"}
|
||||||
|
|
||||||
|
@ttl 5
|
||||||
|
|
||||||
|
setup do
|
||||||
|
Cachex.clear(:web_resp_cache)
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
test "caches a response" do
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
assert_raise(Plug.Conn.AlreadySentError, fn ->
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert @hit_resp ==
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: nil})
|
||||||
|
|> sent_resp()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "ttl is set" do
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: @ttl})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
assert @hit_resp ==
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: @ttl})
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
:timer.sleep(@ttl + 1)
|
||||||
|
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: @ttl})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "set ttl via conn.assigns" do
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> assign(:cache_ttl, @ttl)
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
assert @hit_resp ==
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: nil})
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
:timer.sleep(@ttl + 1)
|
||||||
|
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "ignore query string when `query_params` is false" do
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/?cofe")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
assert @hit_resp ==
|
||||||
|
conn(:get, "/?cofefe")
|
||||||
|
|> Cache.call(%{query_params: false, ttl: nil})
|
||||||
|
|> sent_resp()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "take query string into account when `query_params` is true" do
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/?cofe")
|
||||||
|
|> Cache.call(%{query_params: true, ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/?cofefe")
|
||||||
|
|> Cache.call(%{query_params: true, ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "take specific query params into account when `query_params` is list" do
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/?a=1&b=2&c=3&foo=bar")
|
||||||
|
|> fetch_query_params()
|
||||||
|
|> Cache.call(%{query_params: ["a", "b", "c"], ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
assert @hit_resp ==
|
||||||
|
conn(:get, "/?bar=foo&c=3&b=2&a=1")
|
||||||
|
|> fetch_query_params()
|
||||||
|
|> Cache.call(%{query_params: ["a", "b", "c"], ttl: nil})
|
||||||
|
|> sent_resp()
|
||||||
|
|
||||||
|
assert @miss_resp ==
|
||||||
|
conn(:get, "/?bar=foo&c=3&b=2&a=2")
|
||||||
|
|> fetch_query_params()
|
||||||
|
|> Cache.call(%{query_params: ["a", "b", "c"], ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "ignore not GET requests" do
|
||||||
|
expected =
|
||||||
|
{200,
|
||||||
|
[
|
||||||
|
{"cache-control", "max-age=0, private, must-revalidate"},
|
||||||
|
{"content-type", "cofe/hot; charset=utf-8"}
|
||||||
|
], "cofe"}
|
||||||
|
|
||||||
|
assert expected ==
|
||||||
|
conn(:post, "/")
|
||||||
|
|> Cache.call(%{query_params: true, ttl: nil})
|
||||||
|
|> put_resp_content_type("cofe/hot")
|
||||||
|
|> send_resp(:ok, "cofe")
|
||||||
|
|> sent_resp()
|
||||||
|
end
|
||||||
|
|
||||||
|
test "ignore non-successful responses" do
|
||||||
|
expected =
|
||||||
|
{418,
|
||||||
|
[
|
||||||
|
{"cache-control", "max-age=0, private, must-revalidate"},
|
||||||
|
{"content-type", "tea/iced; charset=utf-8"}
|
||||||
|
], "🥤"}
|
||||||
|
|
||||||
|
assert expected ==
|
||||||
|
conn(:get, "/cofe")
|
||||||
|
|> Cache.call(%{query_params: true, ttl: nil})
|
||||||
|
|> put_resp_content_type("tea/iced")
|
||||||
|
|> send_resp(:im_a_teapot, "🥤")
|
||||||
|
|> sent_resp()
|
||||||
|
end
|
||||||
|
end
|
@ -1,60 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.Representers.ObjectReprenterTest do
|
|
||||||
use Pleroma.DataCase
|
|
||||||
|
|
||||||
alias Pleroma.Object
|
|
||||||
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
|
||||||
|
|
||||||
test "represent an image attachment" do
|
|
||||||
object = %Object{
|
|
||||||
id: 5,
|
|
||||||
data: %{
|
|
||||||
"type" => "Image",
|
|
||||||
"url" => [
|
|
||||||
%{
|
|
||||||
"mediaType" => "sometype",
|
|
||||||
"href" => "someurl"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"uuid" => 6
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expected_object = %{
|
|
||||||
id: 6,
|
|
||||||
url: "someurl",
|
|
||||||
mimetype: "sometype",
|
|
||||||
oembed: false,
|
|
||||||
description: nil
|
|
||||||
}
|
|
||||||
|
|
||||||
assert expected_object == ObjectRepresenter.to_map(object)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "represents mastodon-style attachments" do
|
|
||||||
object = %Object{
|
|
||||||
id: nil,
|
|
||||||
data: %{
|
|
||||||
"mediaType" => "image/png",
|
|
||||||
"name" => "blabla",
|
|
||||||
"type" => "Document",
|
|
||||||
"url" =>
|
|
||||||
"http://mastodon.example.org/system/media_attachments/files/000/000/001/original/8619f31c6edec470.png"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expected_object = %{
|
|
||||||
url:
|
|
||||||
"http://mastodon.example.org/system/media_attachments/files/000/000/001/original/8619f31c6edec470.png",
|
|
||||||
mimetype: "image/png",
|
|
||||||
oembed: false,
|
|
||||||
id: nil,
|
|
||||||
description: "blabla"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert expected_object == ObjectRepresenter.to_map(object)
|
|
||||||
end
|
|
||||||
end
|
|
File diff suppressed because it is too large
Load Diff
@ -1,384 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
|
||||||
use Pleroma.DataCase
|
|
||||||
|
|
||||||
alias Pleroma.Activity
|
|
||||||
alias Pleroma.Object
|
|
||||||
alias Pleroma.Repo
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
|
||||||
alias Pleroma.Web.CommonAPI
|
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
|
||||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
|
||||||
alias Pleroma.Web.TwitterAPI.UserView
|
|
||||||
|
|
||||||
import Pleroma.Factory
|
|
||||||
import Tesla.Mock
|
|
||||||
|
|
||||||
setup do
|
|
||||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
|
|
||||||
import Mock
|
|
||||||
|
|
||||||
test "returns a temporary ap_id based user for activities missing db users" do
|
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
|
|
||||||
|
|
||||||
Repo.delete(user)
|
|
||||||
Cachex.clear(:user_cache)
|
|
||||||
|
|
||||||
%{"user" => tw_user} = ActivityView.render("activity.json", activity: activity)
|
|
||||||
|
|
||||||
assert tw_user["screen_name"] == "erroruser@example.com"
|
|
||||||
assert tw_user["name"] == user.ap_id
|
|
||||||
assert tw_user["statusnet_profile_url"] == user.ap_id
|
|
||||||
end
|
|
||||||
|
|
||||||
test "tries to get a user by nickname if fetching by ap_id doesn't work" do
|
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
|
|
||||||
|
|
||||||
{:ok, user} =
|
|
||||||
user
|
|
||||||
|> Ecto.Changeset.change(%{ap_id: "#{user.ap_id}/extension/#{user.nickname}"})
|
|
||||||
|> Repo.update()
|
|
||||||
|
|
||||||
Cachex.clear(:user_cache)
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: activity)
|
|
||||||
assert result["user"]["id"] == user.id
|
|
||||||
end
|
|
||||||
|
|
||||||
test "tells if the message is muted for some reason" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user)
|
|
||||||
|
|
||||||
{:ok, user} = User.mute(user, other_user)
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "test"})
|
|
||||||
status = ActivityView.render("activity.json", %{activity: activity})
|
|
||||||
|
|
||||||
assert status["muted"] == false
|
|
||||||
|
|
||||||
status = ActivityView.render("activity.json", %{activity: activity, for: user})
|
|
||||||
|
|
||||||
assert status["muted"] == true
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a create activity with a html status" do
|
|
||||||
text = """
|
|
||||||
#Bike log - Commute Tuesday\nhttps://pla.bike/posts/20181211/\n#cycling #CHScycling #commute\nMVIMG_20181211_054020.jpg
|
|
||||||
"""
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(insert(:user), %{"status" => text})
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: activity)
|
|
||||||
|
|
||||||
assert result["statusnet_html"] ==
|
|
||||||
"<a class=\"hashtag\" data-tag=\"bike\" href=\"http://localhost:4001/tag/bike\" rel=\"tag\">#Bike</a> log - Commute Tuesday<br /><a href=\"https://pla.bike/posts/20181211/\">https://pla.bike/posts/20181211/</a><br /><a class=\"hashtag\" data-tag=\"cycling\" href=\"http://localhost:4001/tag/cycling\" rel=\"tag\">#cycling</a> <a class=\"hashtag\" data-tag=\"chscycling\" href=\"http://localhost:4001/tag/chscycling\" rel=\"tag\">#CHScycling</a> <a class=\"hashtag\" data-tag=\"commute\" href=\"http://localhost:4001/tag/commute\" rel=\"tag\">#commute</a><br />MVIMG_20181211_054020.jpg"
|
|
||||||
|
|
||||||
assert result["text"] ==
|
|
||||||
"#Bike log - Commute Tuesday\nhttps://pla.bike/posts/20181211/\n#cycling #CHScycling #commute\nMVIMG_20181211_054020.jpg"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a create activity with a summary containing emoji" do
|
|
||||||
{:ok, activity} =
|
|
||||||
CommonAPI.post(insert(:user), %{
|
|
||||||
"spoiler_text" => ":firefox: meow",
|
|
||||||
"status" => "."
|
|
||||||
})
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: activity)
|
|
||||||
|
|
||||||
expected = ":firefox: meow"
|
|
||||||
|
|
||||||
expected_html =
|
|
||||||
"<img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"http://localhost:4001/emoji/Firefox.gif\" /> meow"
|
|
||||||
|
|
||||||
assert result["summary"] == expected
|
|
||||||
assert result["summary_html"] == expected_html
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a create activity with a summary containing invalid HTML" do
|
|
||||||
{:ok, activity} =
|
|
||||||
CommonAPI.post(insert(:user), %{
|
|
||||||
"spoiler_text" => "<span style=\"color: magenta; font-size: 32px;\">meow</span>",
|
|
||||||
"status" => "."
|
|
||||||
})
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: activity)
|
|
||||||
|
|
||||||
expected = "meow"
|
|
||||||
|
|
||||||
assert result["summary"] == expected
|
|
||||||
assert result["summary_html"] == expected
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a create activity with a note" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user, %{nickname: "shp"})
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
|
|
||||||
object = Object.normalize(activity)
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: activity)
|
|
||||||
|
|
||||||
convo_id = Utils.context_to_conversation_id(object.data["context"])
|
|
||||||
|
|
||||||
expected = %{
|
|
||||||
"activity_type" => "post",
|
|
||||||
"attachments" => [],
|
|
||||||
"attentions" => [
|
|
||||||
UserView.render("show.json", %{user: other_user})
|
|
||||||
],
|
|
||||||
"created_at" => object.data["published"] |> Utils.date_to_asctime(),
|
|
||||||
"external_url" => object.data["id"],
|
|
||||||
"fave_num" => 0,
|
|
||||||
"favorited" => false,
|
|
||||||
"id" => activity.id,
|
|
||||||
"in_reply_to_status_id" => nil,
|
|
||||||
"in_reply_to_screen_name" => nil,
|
|
||||||
"in_reply_to_user_id" => nil,
|
|
||||||
"in_reply_to_profileurl" => nil,
|
|
||||||
"in_reply_to_ostatus_uri" => nil,
|
|
||||||
"is_local" => true,
|
|
||||||
"is_post_verb" => true,
|
|
||||||
"possibly_sensitive" => false,
|
|
||||||
"repeat_num" => 0,
|
|
||||||
"repeated" => false,
|
|
||||||
"pinned" => false,
|
|
||||||
"statusnet_conversation_id" => convo_id,
|
|
||||||
"summary" => "",
|
|
||||||
"summary_html" => "",
|
|
||||||
"statusnet_html" =>
|
|
||||||
"Hey <span class=\"h-card\"><a data-user=\"#{other_user.id}\" class=\"u-url mention\" href=\"#{
|
|
||||||
other_user.ap_id
|
|
||||||
}\">@<span>shp</span></a></span>!",
|
|
||||||
"tags" => [],
|
|
||||||
"text" => "Hey @shp!",
|
|
||||||
"uri" => object.data["id"],
|
|
||||||
"user" => UserView.render("show.json", %{user: user}),
|
|
||||||
"visibility" => "direct",
|
|
||||||
"card" => nil,
|
|
||||||
"muted" => false
|
|
||||||
}
|
|
||||||
|
|
||||||
assert result == expected
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a list of activities" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user, %{nickname: "shp"})
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
|
||||||
object = Object.normalize(activity)
|
|
||||||
|
|
||||||
convo_id = Utils.context_to_conversation_id(object.data["context"])
|
|
||||||
|
|
||||||
mocks = [
|
|
||||||
{
|
|
||||||
Utils,
|
|
||||||
[:passthrough],
|
|
||||||
[context_to_conversation_id: fn _ -> false end]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
User,
|
|
||||||
[:passthrough],
|
|
||||||
[get_cached_by_ap_id: fn _ -> nil end]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
with_mocks mocks do
|
|
||||||
[result] = ActivityView.render("index.json", activities: [activity])
|
|
||||||
|
|
||||||
assert result["statusnet_conversation_id"] == convo_id
|
|
||||||
assert result["user"]
|
|
||||||
refute called(Utils.context_to_conversation_id(:_))
|
|
||||||
refute called(User.get_cached_by_ap_id(user.ap_id))
|
|
||||||
refute called(User.get_cached_by_ap_id(other_user.ap_id))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "an activity that is a reply" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user, %{nickname: "shp"})
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
|
||||||
|
|
||||||
{:ok, answer} =
|
|
||||||
CommonAPI.post(other_user, %{"status" => "Hi!", "in_reply_to_status_id" => activity.id})
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", %{activity: answer})
|
|
||||||
|
|
||||||
assert result["in_reply_to_status_id"] == activity.id
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a like activity" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user, %{nickname: "shp"})
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
|
||||||
{:ok, like, _object} = CommonAPI.favorite(activity.id, other_user)
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: like)
|
|
||||||
activity = Pleroma.Activity.get_by_ap_id(activity.data["id"])
|
|
||||||
|
|
||||||
expected = %{
|
|
||||||
"activity_type" => "like",
|
|
||||||
"created_at" => like.data["published"] |> Utils.date_to_asctime(),
|
|
||||||
"external_url" => like.data["id"],
|
|
||||||
"id" => like.id,
|
|
||||||
"in_reply_to_status_id" => activity.id,
|
|
||||||
"is_local" => true,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"favorited_status" => ActivityView.render("activity.json", activity: activity),
|
|
||||||
"statusnet_html" => "shp favorited a status.",
|
|
||||||
"text" => "shp favorited a status.",
|
|
||||||
"uri" => "tag:#{like.data["id"]}:objectType=Favourite",
|
|
||||||
"user" => UserView.render("show.json", user: other_user)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert result == expected
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a like activity for deleted post" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user, %{nickname: "shp"})
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
|
||||||
{:ok, like, _object} = CommonAPI.favorite(activity.id, other_user)
|
|
||||||
CommonAPI.delete(activity.id, user)
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: like)
|
|
||||||
|
|
||||||
expected = %{
|
|
||||||
"activity_type" => "like",
|
|
||||||
"created_at" => like.data["published"] |> Utils.date_to_asctime(),
|
|
||||||
"external_url" => like.data["id"],
|
|
||||||
"id" => like.id,
|
|
||||||
"in_reply_to_status_id" => nil,
|
|
||||||
"is_local" => true,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"favorited_status" => nil,
|
|
||||||
"statusnet_html" => "shp favorited a status.",
|
|
||||||
"text" => "shp favorited a status.",
|
|
||||||
"uri" => "tag:#{like.data["id"]}:objectType=Favourite",
|
|
||||||
"user" => UserView.render("show.json", user: other_user)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert result == expected
|
|
||||||
end
|
|
||||||
|
|
||||||
test "an announce activity" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user, %{nickname: "shp"})
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
|
||||||
{:ok, announce, object} = CommonAPI.repeat(activity.id, other_user)
|
|
||||||
|
|
||||||
convo_id = Utils.context_to_conversation_id(object.data["context"])
|
|
||||||
|
|
||||||
activity = Activity.get_by_id(activity.id)
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: announce)
|
|
||||||
|
|
||||||
expected = %{
|
|
||||||
"activity_type" => "repeat",
|
|
||||||
"created_at" => announce.data["published"] |> Utils.date_to_asctime(),
|
|
||||||
"external_url" => announce.data["id"],
|
|
||||||
"id" => announce.id,
|
|
||||||
"is_local" => true,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"statusnet_html" => "shp repeated a status.",
|
|
||||||
"text" => "shp repeated a status.",
|
|
||||||
"uri" => "tag:#{announce.data["id"]}:objectType=note",
|
|
||||||
"user" => UserView.render("show.json", user: other_user),
|
|
||||||
"retweeted_status" => ActivityView.render("activity.json", activity: activity),
|
|
||||||
"statusnet_conversation_id" => convo_id
|
|
||||||
}
|
|
||||||
|
|
||||||
assert result == expected
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A follow activity" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user, %{nickname: "shp"})
|
|
||||||
|
|
||||||
{:ok, follower} = User.follow(user, other_user)
|
|
||||||
{:ok, follow} = ActivityPub.follow(follower, other_user)
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: follow)
|
|
||||||
|
|
||||||
expected = %{
|
|
||||||
"activity_type" => "follow",
|
|
||||||
"attentions" => [],
|
|
||||||
"created_at" => follow.data["published"] |> Utils.date_to_asctime(),
|
|
||||||
"external_url" => follow.data["id"],
|
|
||||||
"id" => follow.id,
|
|
||||||
"in_reply_to_status_id" => nil,
|
|
||||||
"is_local" => true,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"statusnet_html" => "#{user.nickname} started following shp",
|
|
||||||
"text" => "#{user.nickname} started following shp",
|
|
||||||
"user" => UserView.render("show.json", user: user)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert result == expected
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a delete activity" do
|
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
|
||||||
{:ok, delete} = CommonAPI.delete(activity.id, user)
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: delete)
|
|
||||||
|
|
||||||
expected = %{
|
|
||||||
"activity_type" => "delete",
|
|
||||||
"attentions" => [],
|
|
||||||
"created_at" => delete.data["published"] |> Utils.date_to_asctime(),
|
|
||||||
"external_url" => delete.data["id"],
|
|
||||||
"id" => delete.id,
|
|
||||||
"in_reply_to_status_id" => nil,
|
|
||||||
"is_local" => true,
|
|
||||||
"is_post_verb" => false,
|
|
||||||
"statusnet_html" => "deleted notice {{tag",
|
|
||||||
"text" => "deleted notice {{tag",
|
|
||||||
"uri" => Object.normalize(delete).data["id"],
|
|
||||||
"user" => UserView.render("show.json", user: user)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert result == expected
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a peertube video" do
|
|
||||||
{:ok, object} =
|
|
||||||
Pleroma.Object.Fetcher.fetch_object_from_id(
|
|
||||||
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
|
|
||||||
)
|
|
||||||
|
|
||||||
%Activity{} = activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: activity)
|
|
||||||
|
|
||||||
assert length(result["attachments"]) == 1
|
|
||||||
assert result["summary"] == "Friday Night"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "special characters are not escaped in text field for status created" do
|
|
||||||
text = "<3 is on the way"
|
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(insert(:user), %{"status" => text})
|
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: activity)
|
|
||||||
|
|
||||||
assert result["text"] == text
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,112 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.NotificationViewTest do
|
|
||||||
use Pleroma.DataCase
|
|
||||||
|
|
||||||
alias Pleroma.Notification
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
|
||||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
|
||||||
alias Pleroma.Web.TwitterAPI.NotificationView
|
|
||||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
|
||||||
alias Pleroma.Web.TwitterAPI.UserView
|
|
||||||
|
|
||||||
import Pleroma.Factory
|
|
||||||
|
|
||||||
setup do
|
|
||||||
user = insert(:user, bio: "<span>Here's some html</span>")
|
|
||||||
[user: user]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A follow notification" do
|
|
||||||
note_activity = insert(:note_activity)
|
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
|
||||||
follower = insert(:user)
|
|
||||||
|
|
||||||
{:ok, follower} = User.follow(follower, user)
|
|
||||||
{:ok, activity} = ActivityPub.follow(follower, user)
|
|
||||||
Cachex.put(:user_cache, "user_info:#{user.id}", User.user_info(Repo.get!(User, user.id)))
|
|
||||||
[follow_notif] = Notification.for_user(user)
|
|
||||||
|
|
||||||
represented = %{
|
|
||||||
"created_at" => follow_notif.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"from_profile" => UserView.render("show.json", %{user: follower, for: user}),
|
|
||||||
"id" => follow_notif.id,
|
|
||||||
"is_seen" => 0,
|
|
||||||
"notice" => ActivityView.render("activity.json", %{activity: activity, for: user}),
|
|
||||||
"ntype" => "follow"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert represented ==
|
|
||||||
NotificationView.render("notification.json", %{notification: follow_notif, for: user})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A mention notification" do
|
|
||||||
user = insert(:user)
|
|
||||||
other_user = insert(:user)
|
|
||||||
|
|
||||||
{:ok, activity} =
|
|
||||||
TwitterAPI.create_status(other_user, %{"status" => "Päivää, @#{user.nickname}"})
|
|
||||||
|
|
||||||
[notification] = Notification.for_user(user)
|
|
||||||
|
|
||||||
represented = %{
|
|
||||||
"created_at" => notification.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"from_profile" => UserView.render("show.json", %{user: other_user, for: user}),
|
|
||||||
"id" => notification.id,
|
|
||||||
"is_seen" => 0,
|
|
||||||
"notice" => ActivityView.render("activity.json", %{activity: activity, for: user}),
|
|
||||||
"ntype" => "mention"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert represented ==
|
|
||||||
NotificationView.render("notification.json", %{notification: notification, for: user})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A retweet notification" do
|
|
||||||
note_activity = insert(:note_activity)
|
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
|
||||||
repeater = insert(:user)
|
|
||||||
|
|
||||||
{:ok, _activity} = TwitterAPI.repeat(repeater, note_activity.id)
|
|
||||||
[notification] = Notification.for_user(user)
|
|
||||||
|
|
||||||
represented = %{
|
|
||||||
"created_at" => notification.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"from_profile" => UserView.render("show.json", %{user: repeater, for: user}),
|
|
||||||
"id" => notification.id,
|
|
||||||
"is_seen" => 0,
|
|
||||||
"notice" =>
|
|
||||||
ActivityView.render("activity.json", %{activity: notification.activity, for: user}),
|
|
||||||
"ntype" => "repeat"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert represented ==
|
|
||||||
NotificationView.render("notification.json", %{notification: notification, for: user})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A like notification" do
|
|
||||||
note_activity = insert(:note_activity)
|
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
|
||||||
liker = insert(:user)
|
|
||||||
|
|
||||||
{:ok, _activity} = TwitterAPI.fav(liker, note_activity.id)
|
|
||||||
[notification] = Notification.for_user(user)
|
|
||||||
|
|
||||||
represented = %{
|
|
||||||
"created_at" => notification.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"from_profile" => UserView.render("show.json", %{user: liker, for: user}),
|
|
||||||
"id" => notification.id,
|
|
||||||
"is_seen" => 0,
|
|
||||||
"notice" =>
|
|
||||||
ActivityView.render("activity.json", %{activity: notification.activity, for: user}),
|
|
||||||
"ntype" => "like"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert represented ==
|
|
||||||
NotificationView.render("notification.json", %{notification: notification, for: user})
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,323 +0,0 @@
|
|||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.UserViewTest do
|
|
||||||
use Pleroma.DataCase
|
|
||||||
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
|
||||||
alias Pleroma.Web.TwitterAPI.UserView
|
|
||||||
|
|
||||||
import Pleroma.Factory
|
|
||||||
|
|
||||||
setup do
|
|
||||||
user = insert(:user, bio: "<span>Here's some html</span>")
|
|
||||||
[user: user]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A user with only a nickname", %{user: user} do
|
|
||||||
user = %{user | name: nil, nickname: "scarlett@catgirl.science"}
|
|
||||||
represented = UserView.render("show.json", %{user: user})
|
|
||||||
assert represented["name"] == user.nickname
|
|
||||||
assert represented["name_html"] == user.nickname
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A user with an avatar object", %{user: user} do
|
|
||||||
image = "image"
|
|
||||||
user = %{user | avatar: %{"url" => [%{"href" => image}]}}
|
|
||||||
represented = UserView.render("show.json", %{user: user})
|
|
||||||
assert represented["profile_image_url"] == image
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A user with emoji in username" do
|
|
||||||
expected =
|
|
||||||
"<img class=\"emoji\" alt=\"karjalanpiirakka\" title=\"karjalanpiirakka\" src=\"/file.png\" /> man"
|
|
||||||
|
|
||||||
user =
|
|
||||||
insert(:user, %{
|
|
||||||
info: %{
|
|
||||||
source_data: %{
|
|
||||||
"tag" => [
|
|
||||||
%{
|
|
||||||
"type" => "Emoji",
|
|
||||||
"icon" => %{"url" => "/file.png"},
|
|
||||||
"name" => ":karjalanpiirakka:"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
name: ":karjalanpiirakka: man"
|
|
||||||
})
|
|
||||||
|
|
||||||
represented = UserView.render("show.json", %{user: user})
|
|
||||||
assert represented["name_html"] == expected
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A user" do
|
|
||||||
note_activity = insert(:note_activity)
|
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
|
||||||
{:ok, user} = User.update_note_count(user)
|
|
||||||
follower = insert(:user)
|
|
||||||
second_follower = insert(:user)
|
|
||||||
|
|
||||||
User.follow(follower, user)
|
|
||||||
User.follow(second_follower, user)
|
|
||||||
User.follow(user, follower)
|
|
||||||
{:ok, user} = User.update_follower_count(user)
|
|
||||||
Cachex.put(:user_cache, "user_info:#{user.id}", User.user_info(Repo.get!(User, user.id)))
|
|
||||||
|
|
||||||
image = "http://localhost:4001/images/avi.png"
|
|
||||||
banner = "http://localhost:4001/images/banner.png"
|
|
||||||
|
|
||||||
represented = %{
|
|
||||||
"id" => user.id,
|
|
||||||
"name" => user.name,
|
|
||||||
"screen_name" => user.nickname,
|
|
||||||
"name_html" => user.name,
|
|
||||||
"description" => HtmlSanitizeEx.strip_tags(user.bio |> String.replace("<br>", "\n")),
|
|
||||||
"description_html" => HtmlSanitizeEx.basic_html(user.bio),
|
|
||||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"favourites_count" => 0,
|
|
||||||
"statuses_count" => 1,
|
|
||||||
"friends_count" => 1,
|
|
||||||
"followers_count" => 2,
|
|
||||||
"profile_image_url" => image,
|
|
||||||
"profile_image_url_https" => image,
|
|
||||||
"profile_image_url_profile_size" => image,
|
|
||||||
"profile_image_url_original" => image,
|
|
||||||
"following" => false,
|
|
||||||
"follows_you" => false,
|
|
||||||
"statusnet_blocking" => false,
|
|
||||||
"statusnet_profile_url" => user.ap_id,
|
|
||||||
"cover_photo" => banner,
|
|
||||||
"background_image" => nil,
|
|
||||||
"is_local" => true,
|
|
||||||
"locked" => false,
|
|
||||||
"hide_follows" => false,
|
|
||||||
"hide_followers" => false,
|
|
||||||
"fields" => [],
|
|
||||||
"pleroma" => %{
|
|
||||||
"confirmation_pending" => false,
|
|
||||||
"tags" => [],
|
|
||||||
"skip_thread_containment" => false
|
|
||||||
},
|
|
||||||
"rights" => %{"admin" => false, "delete_others_notice" => false},
|
|
||||||
"role" => "member"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert represented == UserView.render("show.json", %{user: user})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "User exposes settings for themselves and only for themselves", %{user: user} do
|
|
||||||
as_user = UserView.render("show.json", %{user: user, for: user})
|
|
||||||
assert as_user["default_scope"] == user.info.default_scope
|
|
||||||
assert as_user["no_rich_text"] == user.info.no_rich_text
|
|
||||||
assert as_user["pleroma"]["notification_settings"] == user.info.notification_settings
|
|
||||||
as_stranger = UserView.render("show.json", %{user: user})
|
|
||||||
refute as_stranger["default_scope"]
|
|
||||||
refute as_stranger["no_rich_text"]
|
|
||||||
refute as_stranger["pleroma"]["notification_settings"]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A user for a given other follower", %{user: user} do
|
|
||||||
follower = insert(:user, %{following: [User.ap_followers(user)]})
|
|
||||||
{:ok, user} = User.update_follower_count(user)
|
|
||||||
image = "http://localhost:4001/images/avi.png"
|
|
||||||
banner = "http://localhost:4001/images/banner.png"
|
|
||||||
|
|
||||||
represented = %{
|
|
||||||
"id" => user.id,
|
|
||||||
"name" => user.name,
|
|
||||||
"screen_name" => user.nickname,
|
|
||||||
"name_html" => user.name,
|
|
||||||
"description" => HtmlSanitizeEx.strip_tags(user.bio |> String.replace("<br>", "\n")),
|
|
||||||
"description_html" => HtmlSanitizeEx.basic_html(user.bio),
|
|
||||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"favourites_count" => 0,
|
|
||||||
"statuses_count" => 0,
|
|
||||||
"friends_count" => 0,
|
|
||||||
"followers_count" => 1,
|
|
||||||
"profile_image_url" => image,
|
|
||||||
"profile_image_url_https" => image,
|
|
||||||
"profile_image_url_profile_size" => image,
|
|
||||||
"profile_image_url_original" => image,
|
|
||||||
"following" => true,
|
|
||||||
"follows_you" => false,
|
|
||||||
"statusnet_blocking" => false,
|
|
||||||
"statusnet_profile_url" => user.ap_id,
|
|
||||||
"cover_photo" => banner,
|
|
||||||
"background_image" => nil,
|
|
||||||
"is_local" => true,
|
|
||||||
"locked" => false,
|
|
||||||
"hide_follows" => false,
|
|
||||||
"hide_followers" => false,
|
|
||||||
"fields" => [],
|
|
||||||
"pleroma" => %{
|
|
||||||
"confirmation_pending" => false,
|
|
||||||
"tags" => [],
|
|
||||||
"skip_thread_containment" => false
|
|
||||||
},
|
|
||||||
"rights" => %{"admin" => false, "delete_others_notice" => false},
|
|
||||||
"role" => "member"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert represented == UserView.render("show.json", %{user: user, for: follower})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A user that follows you", %{user: user} do
|
|
||||||
follower = insert(:user)
|
|
||||||
{:ok, follower} = User.follow(follower, user)
|
|
||||||
{:ok, user} = User.update_follower_count(user)
|
|
||||||
image = "http://localhost:4001/images/avi.png"
|
|
||||||
banner = "http://localhost:4001/images/banner.png"
|
|
||||||
|
|
||||||
represented = %{
|
|
||||||
"id" => follower.id,
|
|
||||||
"name" => follower.name,
|
|
||||||
"screen_name" => follower.nickname,
|
|
||||||
"name_html" => follower.name,
|
|
||||||
"description" => HtmlSanitizeEx.strip_tags(follower.bio |> String.replace("<br>", "\n")),
|
|
||||||
"description_html" => HtmlSanitizeEx.basic_html(follower.bio),
|
|
||||||
"created_at" => follower.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"favourites_count" => 0,
|
|
||||||
"statuses_count" => 0,
|
|
||||||
"friends_count" => 1,
|
|
||||||
"followers_count" => 0,
|
|
||||||
"profile_image_url" => image,
|
|
||||||
"profile_image_url_https" => image,
|
|
||||||
"profile_image_url_profile_size" => image,
|
|
||||||
"profile_image_url_original" => image,
|
|
||||||
"following" => false,
|
|
||||||
"follows_you" => true,
|
|
||||||
"statusnet_blocking" => false,
|
|
||||||
"statusnet_profile_url" => follower.ap_id,
|
|
||||||
"cover_photo" => banner,
|
|
||||||
"background_image" => nil,
|
|
||||||
"is_local" => true,
|
|
||||||
"locked" => false,
|
|
||||||
"hide_follows" => false,
|
|
||||||
"hide_followers" => false,
|
|
||||||
"fields" => [],
|
|
||||||
"pleroma" => %{
|
|
||||||
"confirmation_pending" => false,
|
|
||||||
"tags" => [],
|
|
||||||
"skip_thread_containment" => false
|
|
||||||
},
|
|
||||||
"rights" => %{"admin" => false, "delete_others_notice" => false},
|
|
||||||
"role" => "member"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert represented == UserView.render("show.json", %{user: follower, for: user})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a user that is a moderator" do
|
|
||||||
user = insert(:user, %{info: %{is_moderator: true}})
|
|
||||||
represented = UserView.render("show.json", %{user: user, for: user})
|
|
||||||
|
|
||||||
assert represented["rights"]["delete_others_notice"]
|
|
||||||
assert represented["role"] == "moderator"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a user that is a admin" do
|
|
||||||
user = insert(:user, %{info: %{is_admin: true}})
|
|
||||||
represented = UserView.render("show.json", %{user: user, for: user})
|
|
||||||
|
|
||||||
assert represented["rights"]["admin"]
|
|
||||||
assert represented["role"] == "admin"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A moderator with hidden role for another user", %{user: user} do
|
|
||||||
admin = insert(:user, %{info: %{is_moderator: true, show_role: false}})
|
|
||||||
represented = UserView.render("show.json", %{user: admin, for: user})
|
|
||||||
|
|
||||||
assert represented["role"] == nil
|
|
||||||
end
|
|
||||||
|
|
||||||
test "An admin with hidden role for another user", %{user: user} do
|
|
||||||
admin = insert(:user, %{info: %{is_admin: true, show_role: false}})
|
|
||||||
represented = UserView.render("show.json", %{user: admin, for: user})
|
|
||||||
|
|
||||||
assert represented["role"] == nil
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A regular user for the admin", %{user: user} do
|
|
||||||
admin = insert(:user, %{info: %{is_admin: true}})
|
|
||||||
represented = UserView.render("show.json", %{user: user, for: admin})
|
|
||||||
|
|
||||||
assert represented["pleroma"]["deactivated"] == false
|
|
||||||
end
|
|
||||||
|
|
||||||
test "A blocked user for the blocker" do
|
|
||||||
user = insert(:user)
|
|
||||||
blocker = insert(:user)
|
|
||||||
User.block(blocker, user)
|
|
||||||
image = "http://localhost:4001/images/avi.png"
|
|
||||||
banner = "http://localhost:4001/images/banner.png"
|
|
||||||
|
|
||||||
represented = %{
|
|
||||||
"id" => user.id,
|
|
||||||
"name" => user.name,
|
|
||||||
"screen_name" => user.nickname,
|
|
||||||
"name_html" => user.name,
|
|
||||||
"description" => HtmlSanitizeEx.strip_tags(user.bio |> String.replace("<br>", "\n")),
|
|
||||||
"description_html" => HtmlSanitizeEx.basic_html(user.bio),
|
|
||||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
|
||||||
"favourites_count" => 0,
|
|
||||||
"statuses_count" => 0,
|
|
||||||
"friends_count" => 0,
|
|
||||||
"followers_count" => 0,
|
|
||||||
"profile_image_url" => image,
|
|
||||||
"profile_image_url_https" => image,
|
|
||||||
"profile_image_url_profile_size" => image,
|
|
||||||
"profile_image_url_original" => image,
|
|
||||||
"following" => false,
|
|
||||||
"follows_you" => false,
|
|
||||||
"statusnet_blocking" => true,
|
|
||||||
"statusnet_profile_url" => user.ap_id,
|
|
||||||
"cover_photo" => banner,
|
|
||||||
"background_image" => nil,
|
|
||||||
"is_local" => true,
|
|
||||||
"locked" => false,
|
|
||||||
"hide_follows" => false,
|
|
||||||
"hide_followers" => false,
|
|
||||||
"fields" => [],
|
|
||||||
"pleroma" => %{
|
|
||||||
"confirmation_pending" => false,
|
|
||||||
"tags" => [],
|
|
||||||
"skip_thread_containment" => false
|
|
||||||
},
|
|
||||||
"rights" => %{"admin" => false, "delete_others_notice" => false},
|
|
||||||
"role" => "member"
|
|
||||||
}
|
|
||||||
|
|
||||||
blocker = User.get_cached_by_id(blocker.id)
|
|
||||||
assert represented == UserView.render("show.json", %{user: user, for: blocker})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "a user with mastodon fields" do
|
|
||||||
fields = [
|
|
||||||
%{
|
|
||||||
"name" => "Pronouns",
|
|
||||||
"value" => "she/her"
|
|
||||||
},
|
|
||||||
%{
|
|
||||||
"name" => "Website",
|
|
||||||
"value" => "https://example.org/"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
user =
|
|
||||||
insert(:user, %{
|
|
||||||
info: %{
|
|
||||||
source_data: %{
|
|
||||||
"attachment" =>
|
|
||||||
Enum.map(fields, fn field -> Map.put(field, "type", "PropertyValue") end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
userview = UserView.render("show.json", %{user: user})
|
|
||||||
assert userview["fields"] == fields
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in new issue