aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/config.exs3
-rw-r--r--docs/config.md1
-rw-r--r--installation/pleroma.nginx4
-rw-r--r--installation/pleroma.service18
-rw-r--r--lib/pleroma/formatter.ex6
-rw-r--r--lib/pleroma/html.ex8
-rw-r--r--lib/pleroma/http/http.ex3
-rw-r--r--lib/pleroma/http/request_builder.ex7
-rw-r--r--lib/pleroma/stats.ex5
-rw-r--r--lib/pleroma/upload.ex11
-rw-r--r--lib/pleroma/user.ex21
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex10
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex39
-rw-r--r--lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex29
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex20
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex21
-rw-r--r--lib/pleroma/web/activity_pub/views/object_view.ex34
-rw-r--r--lib/pleroma/web/common_api/common_api.ex9
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex6
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex19
-rw-r--r--lib/pleroma/web/rich_media/parser.ex6
-rw-r--r--lib/pleroma/web/rich_media/parsers/oembed_parser.ex27
-rw-r--r--lib/pleroma/web/router.ex1
-rw-r--r--lib/pleroma/web/twitter_api/views/activity_view.ex12
-rw-r--r--lib/pleroma/web/websub/websub.ex6
-rw-r--r--lib/pleroma/web/websub/websub_controller.ex7
-rw-r--r--test/fixtures/rich_media/oembed.html3
-rw-r--r--test/fixtures/rich_media/oembed.json1
-rw-r--r--test/formatter_test.exs16
-rw-r--r--test/support/factory.ex25
-rw-r--r--test/upload_test.exs30
-rw-r--r--test/web/activity_pub/activity_pub_controller_test.exs40
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs23
-rw-r--r--test/web/mastodon_api/mastodon_api_controller_test.exs82
-rw-r--r--test/web/mastodon_api/status_view_test.exs30
-rw-r--r--test/web/rich_media/parser_test.exs41
-rw-r--r--test/web/twitter_api/twitter_api_controller_test.exs6
-rw-r--r--test/web/twitter_api/twitter_api_test.exs4
-rw-r--r--test/web/twitter_api/views/activity_view_test.exs6
39 files changed, 559 insertions, 81 deletions
diff --git a/config/config.exs b/config/config.exs
index 9c4d73465..e8cf2ed3a 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -139,7 +139,8 @@ config :pleroma, :instance,
finmoji_enabled: true,
mrf_transparency: true,
autofollowed_nicknames: [],
- max_pinned_statuses: 1
+ max_pinned_statuses: 1,
+ no_attachment_links: false
config :pleroma, :markup,
# XXX - unfortunately, inline images must be enabled by default right now, because
diff --git a/docs/config.md b/docs/config.md
index b9ad2aef7..5464fa90d 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -95,6 +95,7 @@ config :pleroma, Pleroma.Mailer,
older software for theses nicknames.
* `max_pinned_statuses`: The maximum number of pinned statuses. `0` will disable the feature.
* `autofollowed_nicknames`: Set to nicknames of (local) users that every new user should automatically follow.
+* `no_attachment_links`: Set to true to disable automatically adding attachment link text to statuses
## :logger
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx
index 46b84fb50..a24bb0e61 100644
--- a/installation/pleroma.nginx
+++ b/installation/pleroma.nginx
@@ -79,8 +79,10 @@ server {
proxy_cache_valid 200 206 301 304 1h;
proxy_cache_lock on;
proxy_ignore_client_abort on;
- proxy_buffering off;
+ proxy_buffering on;
chunked_transfer_encoding on;
+ proxy_ignore_headers Cache-Control;
+ proxy_hide_header Cache-Control;
proxy_pass http://localhost:4000;
}
}
diff --git a/installation/pleroma.service b/installation/pleroma.service
index f1ed56cb3..72090bbc7 100644
--- a/installation/pleroma.service
+++ b/installation/pleroma.service
@@ -3,15 +3,23 @@ Description=Pleroma social network
After=network.target postgresql.service
[Service]
-User=pleroma
-WorkingDirectory=/home/pleroma/pleroma
-Environment="HOME=/home/pleroma"
-Environment="MIX_ENV=prod"
-ExecStart=/usr/local/bin/mix phx.server
ExecReload=/bin/kill $MAINPID
KillMode=process
Restart=on-failure
+; Name of the user that runs the Pleroma service.
+User=pleroma
+; Declares that Pleroma runs in production mode.
+Environment="MIX_ENV=prod"
+
+; Make sure that all paths fit your installation.
+; Path to the home directory of the user running the Pleroma service.
+Environment="HOME=/home/pleroma"
+; Path to the folder containing the Pleroma installation.
+WorkingDirectory=/home/pleroma/pleroma
+; Path to the Mix binary.
+ExecStart=/usr/bin/mix phx.server
+
; Some security directives.
; Use private /tmp and /var/tmp folders inside a new file system namespace, which are discarded after the process stops.
PrivateTmp=true
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index 2696f41c0..9e50ea3f4 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -155,7 +155,9 @@ defmodule Pleroma.Formatter do
short_match = String.split(match, "@") |> tl() |> hd()
{uuid,
- "<span><a data-user='#{id}' class='mention' href='#{ap_id}'>@<span>#{short_match}</span></a></span>"}
+ "<span class='h-card'><a data-user='#{id}' class='u-url mention' href='#{ap_id}'>@<span>#{
+ short_match
+ }</span></a></span>"}
end)
{subs, uuid_text}
@@ -178,7 +180,7 @@ defmodule Pleroma.Formatter do
subs ++
Enum.map(tags, fn {tag_text, tag, uuid} ->
url =
- "<a data-tag='#{tag}' href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>#{
+ "<a class='hashtag' data-tag='#{tag}' href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>#{
tag_text
}</a>"
diff --git a/lib/pleroma/html.ex b/lib/pleroma/html.ex
index 0c5b0f03f..f5c6e5033 100644
--- a/lib/pleroma/html.ex
+++ b/lib/pleroma/html.ex
@@ -78,14 +78,14 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
# links
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
- Meta.allow_tag_with_these_attributes("a", ["name", "title"])
+ Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"])
# paragraphs and linebreaks
Meta.allow_tag_with_these_attributes("br", [])
Meta.allow_tag_with_these_attributes("p", [])
# microformats
- Meta.allow_tag_with_these_attributes("span", [])
+ Meta.allow_tag_with_these_attributes("span", ["class"])
# allow inline images for custom emoji
@allow_inline_images Keyword.get(@markup, :allow_inline_images)
@@ -119,7 +119,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
Meta.strip_comments()
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
- Meta.allow_tag_with_these_attributes("a", ["name", "title"])
+ Meta.allow_tag_with_these_attributes("a", ["name", "title", "class"])
Meta.allow_tag_with_these_attributes("abbr", ["title"])
@@ -134,7 +134,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
Meta.allow_tag_with_these_attributes("ol", [])
Meta.allow_tag_with_these_attributes("p", [])
Meta.allow_tag_with_these_attributes("pre", [])
- Meta.allow_tag_with_these_attributes("span", [])
+ Meta.allow_tag_with_these_attributes("span", ["class"])
Meta.allow_tag_with_these_attributes("strong", [])
Meta.allow_tag_with_these_attributes("u", [])
Meta.allow_tag_with_these_attributes("ul", [])
diff --git a/lib/pleroma/http/http.ex b/lib/pleroma/http/http.ex
index b8103cef6..75c58e6c9 100644
--- a/lib/pleroma/http/http.ex
+++ b/lib/pleroma/http/http.ex
@@ -31,12 +31,15 @@ defmodule Pleroma.HTTP do
process_request_options(options)
|> process_sni_options(url)
+ params = Keyword.get(options, :params, [])
+
%{}
|> Builder.method(method)
|> Builder.headers(headers)
|> Builder.opts(options)
|> Builder.url(url)
|> Builder.add_param(:body, :body, body)
+ |> Builder.add_param(:query, :query, params)
|> Enum.into([])
|> (&Tesla.request(Connection.new(), &1)).()
end
diff --git a/lib/pleroma/http/request_builder.ex b/lib/pleroma/http/request_builder.ex
index bffc7c6fe..5f2cff2c0 100644
--- a/lib/pleroma/http/request_builder.ex
+++ b/lib/pleroma/http/request_builder.ex
@@ -100,6 +100,8 @@ defmodule Pleroma.HTTP.RequestBuilder do
Map
"""
@spec add_param(map(), atom, atom, any()) :: map()
+ def add_param(request, :query, :query, values), do: Map.put(request, :query, values)
+
def add_param(request, :body, :body, value), do: Map.put(request, :body, value)
def add_param(request, :body, key, value) do
@@ -107,7 +109,10 @@ defmodule Pleroma.HTTP.RequestBuilder do
|> Map.put_new_lazy(:body, &Tesla.Multipart.new/0)
|> Map.update!(
:body,
- &Tesla.Multipart.add_field(&1, key, Poison.encode!(value),
+ &Tesla.Multipart.add_field(
+ &1,
+ key,
+ Jason.encode!(value),
headers: [{:"Content-Type", "application/json"}]
)
)
diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex
index 8a030ecd0..b3566ceb6 100644
--- a/lib/pleroma/stats.ex
+++ b/lib/pleroma/stats.ex
@@ -34,10 +34,11 @@ defmodule Pleroma.Stats do
peers =
from(
u in Pleroma.User,
- select: fragment("distinct ?->'host'", u.info),
+ select: fragment("distinct split_part(?, '@', 2)", u.nickname),
where: u.local != ^true
)
|> Repo.all()
+ |> Enum.filter(& &1)
domain_count = Enum.count(peers)
@@ -45,7 +46,7 @@ defmodule Pleroma.Stats do
from(u in User.local_user_query(), select: fragment("sum((?->>'note_count')::int)", u.info))
status_count = Repo.one(status_query)
- user_count = Repo.aggregate(User.local_user_query(), :count, :id)
+ user_count = Repo.aggregate(User.active_local_user_query(), :count, :id)
Agent.update(__MODULE__, fn _ ->
{peers, %{domain_count: domain_count, status_count: status_count, user_count: user_count}}
diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex
index 0b1bdeec4..0a19e737b 100644
--- a/lib/pleroma/upload.ex
+++ b/lib/pleroma/upload.ex
@@ -34,8 +34,9 @@ defmodule Pleroma.Upload do
require Logger
@type source ::
- Plug.Upload.t() | data_uri_string ::
- String.t() | {:from_local, name :: String.t(), id :: String.t(), path :: String.t()}
+ Plug.Upload.t()
+ | (data_uri_string :: String.t())
+ | {:from_local, name :: String.t(), id :: String.t(), path :: String.t()}
@type option ::
{:type, :avatar | :banner | :background}
@@ -215,6 +216,12 @@ defmodule Pleroma.Upload do
end
defp url_from_spec(base_url, {:file, path}) do
+ path =
+ path
+ |> URI.encode()
+ |> String.replace("?", "%3F")
+ |> String.replace(":", "%3A")
+
[base_url, "media", path]
|> Path.join()
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 13a476fd2..5137af917 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -822,7 +822,7 @@ defmodule Pleroma.User do
update_and_set_cache(cng)
end
- def local_user_query() do
+ def local_user_query do
from(
u in User,
where: u.local == true,
@@ -830,7 +830,14 @@ defmodule Pleroma.User do
)
end
- def moderator_user_query() do
+ def active_local_user_query do
+ from(
+ u in local_user_query(),
+ where: fragment("?->'deactivated' @> 'false'", u.info)
+ )
+ end
+
+ def moderator_user_query do
from(
u in User,
where: u.local == true,
@@ -1066,4 +1073,14 @@ defmodule Pleroma.User do
@strict_local_nickname_regex
end
end
+
+ def error_user(ap_id) do
+ %User{
+ name: ap_id,
+ ap_id: ap_id,
+ info: %User.Info{},
+ nickname: "erroruser@example.com",
+ inserted_at: NaiveDateTime.utc_now()
+ }
+ end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 9c1eb377f..5b87f7462 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -515,15 +515,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_reblogs(query, _), do: query
- # Only search through last 100_000 activities by default
- defp restrict_recent(query, %{"whole_db" => true}), do: query
-
- defp restrict_recent(query, _) do
- since = (Repo.aggregate(Activity, :max, :id) || 0) - 100_000
-
- from(activity in query, where: activity.id > ^since)
- end
-
defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do
blocks = info.blocks || []
domain_blocks = info.domain_blocks || []
@@ -574,7 +565,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_actor(opts)
|> restrict_type(opts)
|> restrict_favorited_by(opts)
- |> restrict_recent(opts)
|> restrict_blocked(opts)
|> restrict_media(opts)
|> restrict_visibility(opts)
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 73ca07e84..7eed0a600 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -54,6 +54,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
+ def object_likes(conn, %{"uuid" => uuid, "page" => page}) do
+ with ap_id <- o_status_url(conn, :object, uuid),
+ %Object{} = object <- Object.get_cached_by_ap_id(ap_id),
+ {_, true} <- {:public?, ActivityPub.is_public?(object)},
+ likes <- Utils.get_object_likes(object) do
+ {page, _} = Integer.parse(page)
+
+ conn
+ |> put_resp_header("content-type", "application/activity+json")
+ |> json(ObjectView.render("likes.json", ap_id, likes, page))
+ else
+ {:public?, false} ->
+ {:error, :not_found}
+ end
+ end
+
+ def object_likes(conn, %{"uuid" => uuid}) do
+ with ap_id <- o_status_url(conn, :object, uuid),
+ %Object{} = object <- Object.get_cached_by_ap_id(ap_id),
+ {_, true} <- {:public?, ActivityPub.is_public?(object)},
+ likes <- Utils.get_object_likes(object) do
+ conn
+ |> put_resp_header("content-type", "application/activity+json")
+ |> json(ObjectView.render("likes.json", ap_id, likes))
+ else
+ {:public?, false} ->
+ {:error, :not_found}
+ end
+ end
+
def activity(conn, %{"uuid" => uuid}) do
with ap_id <- o_status_url(conn, :activity, uuid),
%Activity{} = activity <- Activity.normalize(ap_id),
@@ -204,6 +234,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
end
+ def handle_user_activity(user, %{"type" => "Like"} = params) do
+ with %Object{} = object <- Object.normalize(params["object"]),
+ {:ok, activity, _object} <- ActivityPub.like(user, object) do
+ {:ok, activity}
+ else
+ _ -> {:error, "Can't like object"}
+ end
+ end
+
def handle_user_activity(_, _) do
{:error, "Unhandled activity type"}
end
diff --git a/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
new file mode 100644
index 000000000..081456046
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/mrf/no_placeholder_text_policy.ex
@@ -0,0 +1,29 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.NoPlaceholderTextPolicy do
+ @behaviour Pleroma.Web.ActivityPub.MRF
+
+ @impl true
+ def filter(
+ %{
+ "type" => "Create",
+ "object" => %{"content" => content, "attachment" => _attachment} = child_object
+ } = object
+ )
+ when content in [".", "<p>.</p>"] do
+ child_object =
+ child_object
+ |> Map.put("content", "")
+
+ object =
+ object
+ |> Map.put("object", child_object)
+
+ {:ok, object}
+ end
+
+ @impl true
+ def filter(object), do: {:ok, object}
+end
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 87b7fc07f..86d11c874 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -629,6 +629,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> add_mention_tags
|> add_emoji_tags
|> add_attributed_to
+ |> add_likes
|> prepare_attachments
|> set_conversation
|> set_reply_to_uri
@@ -641,7 +642,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
# internal -> Mastodon
# """
- def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
+ def prepare_outgoing(%{"type" => "Create", "object" => object} = data) do
object =
object
|> prepare_object
@@ -788,6 +789,22 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("attributedTo", attributedTo)
end
+ def add_likes(%{"id" => id, "like_count" => likes} = object) do
+ likes = %{
+ "id" => "#{id}/likes",
+ "first" => "#{id}/likes?page=1",
+ "type" => "OrderedCollection",
+ "totalItems" => likes
+ }
+
+ object
+ |> Map.put("likes", likes)
+ end
+
+ def add_likes(object) do
+ object
+ end
+
def prepare_attachments(object) do
attachments =
(object["attachment"] || [])
@@ -803,7 +820,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
defp strip_internal_fields(object) do
object
|> Map.drop([
- "likes",
"like_count",
"announcements",
"announcement_count",
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index b313996db..6ecab773c 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -231,6 +231,27 @@ defmodule Pleroma.Web.ActivityPub.Utils do
Repo.one(query)
end
+ @doc """
+ Returns like activities targeting an object
+ """
+ def get_object_likes(%{data: %{"id" => id}}) do
+ query =
+ from(
+ activity in Activity,
+ # this is to use the index
+ where:
+ fragment(
+ "coalesce((?)->'object'->>'id', (?)->>'object') = ?",
+ activity.data,
+ activity.data,
+ ^id
+ ),
+ where: fragment("(?)->>'type' = 'Like'", activity.data)
+ )
+
+ Repo.all(query)
+ end
+
def make_like_data(%User{ap_id: ap_id} = actor, %{data: %{"id" => id}} = object, activity_id) do
data = %{
"type" => "Like",
diff --git a/lib/pleroma/web/activity_pub/views/object_view.ex b/lib/pleroma/web/activity_pub/views/object_view.ex
index b5c9bf8d0..394d82fbc 100644
--- a/lib/pleroma/web/activity_pub/views/object_view.ex
+++ b/lib/pleroma/web/activity_pub/views/object_view.ex
@@ -35,4 +35,38 @@ defmodule Pleroma.Web.ActivityPub.ObjectView do
Map.merge(base, additional)
end
+
+ def render("likes.json", ap_id, likes, page) do
+ collection(likes, "#{ap_id}/likes", page)
+ |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header())
+ end
+
+ def render("likes.json", ap_id, likes) do
+ %{
+ "id" => "#{ap_id}/likes",
+ "type" => "OrderedCollection",
+ "totalItems" => length(likes),
+ "first" => collection(likes, "#{ap_id}/likes", 1)
+ }
+ |> Map.merge(Pleroma.Web.ActivityPub.Utils.make_json_ld_header())
+ end
+
+ def collection(collection, iri, page) do
+ offset = (page - 1) * 10
+ items = Enum.slice(collection, offset, 10)
+ items = Enum.map(items, fn object -> Transmogrifier.prepare_object(object.data) end)
+ total = length(collection)
+
+ map = %{
+ "id" => "#{iri}?page=#{page}",
+ "type" => "OrderedCollectionPage",
+ "partOf" => iri,
+ "totalItems" => total,
+ "orderedItems" => items
+ }
+
+ if offset < total do
+ Map.put(map, "next", "#{iri}?page=#{page + 1}")
+ end
+ end
end
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index 9a748d65e..504670439 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -103,7 +103,14 @@ defmodule Pleroma.Web.CommonAPI do
attachments,
tags,
get_content_type(data["content_type"]),
- true
+ Enum.member?(
+ [true, "true"],
+ Map.get(
+ data,
+ "no_attachment_links",
+ Pleroma.Config.get([:instance, :no_attachment_links], false)
+ )
+ )
),
context <- make_context(inReplyTo),
cw <- data["spoiler_text"],
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index e00a3fb87..daad89185 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -341,7 +341,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
params =
params
|> Map.put("in_reply_to_status_id", params["in_reply_to_id"])
- |> Map.put("no_attachment_links", true)
idempotency_key =
case get_req_header(conn, "idempotency-key") do
@@ -824,9 +823,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
json(conn, res)
end
- def favourites(%{assigns: %{user: user}} = conn, _) do
+ def favourites(%{assigns: %{user: user}} = conn, params) do
params =
- %{}
+ params
|> Map.put("type", "Create")
|> Map.put("favorited_by", user.ap_id)
|> Map.put("blocking_user", user)
@@ -836,6 +835,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> Enum.reverse()
conn
+ |> add_link_headers(:favourites, activities)
|> put_view(StatusView)
|> render("index.json", %{activities: activities, for: user, as: :activity})
end
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index db543ffe5..7f5a52ea3 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -32,6 +32,19 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end)
end
+ defp get_user(ap_id) do
+ cond do
+ 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
replied_to_activities = get_replied_to_activities(opts.activities)
@@ -48,7 +61,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
"status.json",
%{activity: %{data: %{"type" => "Announce", "object" => object}} = activity} = opts
) do
- user = User.get_cached_by_ap_id(activity.data["actor"])
+ user = get_user(activity.data["actor"])
created_at = Utils.to_masto_date(activity.data["published"])
reblogged = Activity.get_create_activity_by_object_ap_id(object)
@@ -93,7 +106,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end
def render("status.json", %{activity: %{data: %{"object" => object}} = activity} = opts) do
- user = User.get_cached_by_ap_id(activity.data["actor"])
+ user = get_user(activity.data["actor"])
like_count = object["like_count"] || 0
announcement_count = object["announcement_count"] || 0
@@ -116,7 +129,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
created_at = Utils.to_masto_date(object["published"])
reply_to = get_reply_to(activity, opts)
- reply_to_user = reply_to && User.get_cached_by_ap_id(reply_to.data["actor"])
+ reply_to_user = reply_to && get_user(reply_to.data["actor"])
content =
object
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
index fe092bf19..6da83c6e4 100644
--- a/lib/pleroma/web/rich_media/parser.ex
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -1,5 +1,9 @@
defmodule Pleroma.Web.RichMedia.Parser do
- @parsers [Pleroma.Web.RichMedia.Parsers.OGP, Pleroma.Web.RichMedia.Parsers.TwitterCard]
+ @parsers [
+ Pleroma.Web.RichMedia.Parsers.OGP,
+ Pleroma.Web.RichMedia.Parsers.TwitterCard,
+ Pleroma.Web.RichMedia.Parsers.OEmbed
+ ]
if Mix.env() == :test do
def parse(url), do: parse_url(url)
diff --git a/lib/pleroma/web/rich_media/parsers/oembed_parser.ex b/lib/pleroma/web/rich_media/parsers/oembed_parser.ex
new file mode 100644
index 000000000..ca7226faf
--- /dev/null
+++ b/lib/pleroma/web/rich_media/parsers/oembed_parser.ex
@@ -0,0 +1,27 @@
+defmodule Pleroma.Web.RichMedia.Parsers.OEmbed do
+ def parse(html, _data) do
+ with elements = [_ | _] <- get_discovery_data(html),
+ {:ok, oembed_url} <- get_oembed_url(elements),
+ {:ok, oembed_data} <- get_oembed_data(oembed_url) do
+ {:ok, oembed_data}
+ else
+ _e -> {:error, "No OEmbed data found"}
+ end
+ end
+
+ defp get_discovery_data(html) do
+ html |> Floki.find("link[type='application/json+oembed']")
+ end
+
+ defp get_oembed_url(nodes) do
+ {"link", attributes, _children} = nodes |> hd()
+
+ {:ok, Enum.into(attributes, %{})["href"]}
+ end
+
+ defp get_oembed_data(url) do
+ {:ok, %Tesla.Env{body: json}} = Pleroma.HTTP.get(url)
+
+ {:ok, Poison.decode!(json)}
+ end
+end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 25e866c48..68b02d8ca 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -431,6 +431,7 @@ defmodule Pleroma.Web.Router do
get("/users/:nickname/followers", ActivityPubController, :followers)
get("/users/:nickname/following", ActivityPubController, :following)
get("/users/:nickname/outbox", ActivityPubController, :outbox)
+ get("/objects/:uuid/likes", ActivityPubController, :object_likes)
end
pipeline :activitypub_client do
diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex
index 108e7bfc5..03708d84c 100644
--- a/lib/pleroma/web/twitter_api/views/activity_view.ex
+++ b/lib/pleroma/web/twitter_api/views/activity_view.ex
@@ -101,20 +101,10 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
user
true ->
- error_user(ap_id)
+ User.error_user(ap_id)
end
end
- defp error_user(ap_id) do
- %User{
- name: ap_id,
- ap_id: ap_id,
- info: %User.Info{},
- nickname: "erroruser@example.com",
- inserted_at: NaiveDateTime.utc_now()
- }
- end
-
def render("index.json", opts) do
context_ids = collect_context_ids(opts.activities)
users = collect_users(opts.activities)
diff --git a/lib/pleroma/web/websub/websub.ex b/lib/pleroma/web/websub/websub.ex
index 3a287edd9..7ca62c83b 100644
--- a/lib/pleroma/web/websub/websub.ex
+++ b/lib/pleroma/web/websub/websub.ex
@@ -121,6 +121,12 @@ defmodule Pleroma.Web.Websub do
end
end
+ def incoming_subscription_request(user, params) do
+ Logger.info("Unhandled WebSub request for #{user.nickname}: #{inspect(params)}")
+
+ {:error, "Invalid WebSub request"}
+ end
+
defp get_subscription(topic, callback) do
Repo.get_by(WebsubServerSubscription, topic: topic, callback: callback) ||
%WebsubServerSubscription{}
diff --git a/lib/pleroma/web/websub/websub_controller.ex b/lib/pleroma/web/websub/websub_controller.ex
index 27304d988..e58f144e5 100644
--- a/lib/pleroma/web/websub/websub_controller.ex
+++ b/lib/pleroma/web/websub/websub_controller.ex
@@ -67,6 +67,13 @@ defmodule Pleroma.Web.Websub.WebsubController do
end
end
+ def websub_subscription_confirmation(conn, params) do
+ Logger.info("Invalid WebSub confirmation request: #{inspect(params)}")
+
+ conn
+ |> send_resp(500, "Invalid parameters")
+ end
+
def websub_incoming(conn, %{"id" => id}) do
with "sha1=" <> signature <- hd(get_req_header(conn, "x-hub-signature")),
signature <- String.downcase(signature),
diff --git a/test/fixtures/rich_media/oembed.html b/test/fixtures/rich_media/oembed.html
new file mode 100644
index 000000000..55f17004b
--- /dev/null
+++ b/test/fixtures/rich_media/oembed.html
@@ -0,0 +1,3 @@
+<link rel="alternate" type="application/json+oembed"
+ href="http://example.com/oembed.json"
+ title="Bacon Lollys oEmbed Profile" />
diff --git a/test/fixtures/rich_media/oembed.json b/test/fixtures/rich_media/oembed.json
new file mode 100644
index 000000000..2a5f7a771
--- /dev/null
+++ b/test/fixtures/rich_media/oembed.json
@@ -0,0 +1 @@
+{"type":"photo","flickr_type":"photo","title":"Bacon Lollys","author_name":"\u202e\u202d\u202cbees\u202c","author_url":"https:\/\/www.flickr.com\/photos\/bees\/","width":"1024","height":"768","url":"https:\/\/farm4.staticflickr.com\/3040\/2362225867_4a87ab8baf_b.jpg","web_page":"https:\/\/www.flickr.com\/photos\/bees\/2362225867\/","thumbnail_url":"https:\/\/farm4.staticflickr.com\/3040\/2362225867_4a87ab8baf_q.jpg","thumbnail_width":150,"thumbnail_height":150,"web_page_short_url":"https:\/\/flic.kr\/p\/4AK2sc","license":"All Rights Reserved","license_id":0,"html":"<a data-flickr-embed=\"true\" href=\"https:\/\/www.flickr.com\/photos\/bees\/2362225867\/\" title=\"Bacon Lollys by \u202e\u202d\u202cbees\u202c, on Flickr\"><img src=\"https:\/\/farm4.staticflickr.com\/3040\/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"><\/a><script async src=\"https:\/\/embedr.flickr.com\/assets\/client-code.js\" charset=\"utf-8\"><\/script>","version":"1.0","cache_age":3600,"provider_name":"Flickr","provider_url":"https:\/\/www.flickr.com\/"}
diff --git a/test/formatter_test.exs b/test/formatter_test.exs
index c76149e38..bd8844458 100644
--- a/test/formatter_test.exs
+++ b/test/formatter_test.exs
@@ -19,7 +19,7 @@ defmodule Pleroma.FormatterTest do
text = "I love #cofe and #2hu"
expected_text =
- "I love <a data-tag='cofe' href='http://localhost:4001/tag/cofe' rel='tag'>#cofe</a> and <a data-tag='2hu' href='http://localhost:4001/tag/2hu' rel='tag'>#2hu</a>"
+ "I love <a class='hashtag' data-tag='cofe' href='http://localhost:4001/tag/cofe' rel='tag'>#cofe</a> and <a class='hashtag' data-tag='2hu' href='http://localhost:4001/tag/2hu' rel='tag'>#2hu</a>"
tags = Formatter.parse_tags(text)
@@ -31,7 +31,7 @@ defmodule Pleroma.FormatterTest do
text = "Fact #3: pleroma does what mastodon't"
expected_text =
- "Fact <a data-tag='3' href='http://localhost:4001/tag/3' rel='tag'>#3</a>: pleroma does what mastodon't"
+ "Fact <a class='hashtag' data-tag='3' href='http://localhost:4001/tag/3' rel='tag'>#3</a>: pleroma does what mastodon't"
tags = Formatter.parse_tags(text)
@@ -144,11 +144,13 @@ defmodule Pleroma.FormatterTest do
Enum.each(subs, fn {uuid, _} -> assert String.contains?(text, uuid) end)
expected_text =
- "<span><a data-user='#{gsimg.id}' class='mention' href='#{gsimg.ap_id}'>@<span>gsimg</span></a></span> According to <span><a data-user='#{
+ "<span class='h-card'><a data-user='#{gsimg.id}' class='u-url mention' href='#{
+ gsimg.ap_id
+ }'>@<span>gsimg</span></a></span> According to <span class='h-card'><a data-user='#{
archaeme.id
- }' class='mention' href='#{"https://archeme/@archa_eme_"}'>@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span><a data-user='#{
+ }' class='u-url mention' href='#{"https://archeme/@archa_eme_"}'>@<span>archa_eme_</span></a></span>, that is @daggsy. Also hello <span class='h-card'><a data-user='#{
archaeme_remote.id
- }' class='mention' href='#{archaeme_remote.ap_id}'>@<span>archaeme</span></a></span>"
+ }' class='u-url mention' href='#{archaeme_remote.ap_id}'>@<span>archaeme</span></a></span>"
assert expected_text == Formatter.finalize({subs, text})
end
@@ -166,7 +168,7 @@ defmodule Pleroma.FormatterTest do
Enum.each(subs, fn {uuid, _} -> assert String.contains?(text, uuid) end)
expected_text =
- "<span><a data-user='#{mike.id}' class='mention' href='#{mike.ap_id}'>@<span>mike</span></a></span> test"
+ "<span class='h-card'><a data-user='#{mike.id}' class='u-url mention' href='#{mike.ap_id}'>@<span>mike</span></a></span> test"
assert expected_text == Formatter.finalize({subs, text})
end
@@ -183,7 +185,7 @@ defmodule Pleroma.FormatterTest do
Enum.each(subs, fn {uuid, _} -> assert String.contains?(text, uuid) end)
expected_text =
- "<span><a data-user='#{o.id}' class='mention' href='#{o.ap_id}'>@<span>o</span></a></span> hi"
+ "<span class='h-card'><a data-user='#{o.id}' class='u-url mention' href='#{o.ap_id}'>@<span>o</span></a></span> hi"
assert expected_text == Formatter.finalize({subs, text})
end
diff --git a/test/support/factory.ex b/test/support/factory.ex
index 57fa4a79d..4ac77981a 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -57,6 +57,11 @@ defmodule Pleroma.Factory do
%Pleroma.Object{data: Map.merge(data, %{"to" => [user2.ap_id]})}
end
+ def article_factory do
+ note_factory()
+ |> Map.put("type", "Article")
+ end
+
def tombstone_factory do
data = %{
"type" => "Tombstone",
@@ -110,6 +115,26 @@ defmodule Pleroma.Factory do
}
end
+ def article_activity_factory do
+ article = insert(:article)
+
+ data = %{
+ "id" => Pleroma.Web.ActivityPub.Utils.generate_activity_id(),
+ "type" => "Create",
+ "actor" => article.data["actor"],
+ "to" => article.data["to"],
+ "object" => article.data,
+ "published" => DateTime.utc_now() |> DateTime.to_iso8601(),
+ "context" => article.data["context"]
+ }
+
+ %Pleroma.Activity{
+ data: data,
+ actor: data["actor"],
+ recipients: data["to"]
+ }
+ end
+
def announce_activity_factory do
note_activity = insert(:note_activity)
user = insert(:user)
diff --git a/test/upload_test.exs b/test/upload_test.exs
index d4ea3a573..b2d9eca38 100644
--- a/test/upload_test.exs
+++ b/test/upload_test.exs
@@ -137,5 +137,35 @@ defmodule Pleroma.UploadTest do
refute data["name"] == "an [image.jpg"
end
+
+ test "escapes invalid characters in url" do
+ File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image_tmp.jpg"),
+ filename: "an… image.jpg"
+ }
+
+ {:ok, data} = Upload.store(file)
+ [attachment_url | _] = data["url"]
+
+ assert Path.basename(attachment_url["href"]) == "an%E2%80%A6%20image.jpg"
+ end
+
+ test "replaces : (colon) and ? (question-mark) to %3A and %3F (respectively)" do
+ File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image_tmp.jpg"),
+ filename: "is:an?image.jpg"
+ }
+
+ {:ok, data} = Upload.store(file)
+ [attachment_url | _] = data["url"]
+
+ assert Path.basename(attachment_url["href"]) == "is%3Aan%3Fimage.jpg"
+ end
end
end
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index 7aed8c71d..52e67f046 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -89,6 +89,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
end
end
+ describe "/object/:uuid/likes" do
+ test "it returns the like activities in a collection", %{conn: conn} do
+ like = insert(:like_activity)
+ uuid = String.split(like.data["object"], "/") |> List.last()
+
+ result =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get("/objects/#{uuid}/likes")
+ |> json_response(200)
+
+ assert List.first(result["first"]["orderedItems"])["id"] == like.data["id"]
+ end
+ end
+
describe "/activities/:uuid" do
test "it returns a json representation of the activity", %{conn: conn} do
activity = insert(:note_activity)
@@ -292,6 +307,31 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
assert json_response(conn, 400)
end
+
+ test "it increases like count when receiving a like action", %{conn: conn} do
+ note_activity = insert(:note_activity)
+ user = User.get_cached_by_ap_id(note_activity.data["actor"])
+
+ data = %{
+ type: "Like",
+ object: %{
+ id: note_activity.data["object"]["id"]
+ }
+ }
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/outbox", data)
+
+ result = json_response(conn, 201)
+ assert Activity.get_by_ap_id(result["id"])
+
+ object = Object.get_by_ap_id(note_activity.data["object"]["id"])
+ assert object
+ assert object.data["like_count"] == 1
+ end
end
describe "/users/:nickname/followers" do
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index a5fd87ed4..87d0ab559 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -829,12 +829,33 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert length(modified["object"]["tag"]) == 2
assert is_nil(modified["object"]["emoji"])
- assert is_nil(modified["object"]["likes"])
assert is_nil(modified["object"]["like_count"])
assert is_nil(modified["object"]["announcements"])
assert is_nil(modified["object"]["announcement_count"])
assert is_nil(modified["object"]["context_id"])
end
+
+ test "it strips internal fields of article" do
+ activity = insert(:article_activity)
+
+ {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
+
+ assert length(modified["object"]["tag"]) == 2
+
+ assert is_nil(modified["object"]["emoji"])
+ assert is_nil(modified["object"]["like_count"])
+ assert is_nil(modified["object"]["announcements"])
+ assert is_nil(modified["object"]["announcement_count"])
+ assert is_nil(modified["object"]["context_id"])
+ end
+
+ test "it adds like collection to object" do
+ activity = insert(:note_activity)
+ {:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
+
+ assert modified["object"]["likes"]["type"] == "OrderedCollection"
+ assert modified["object"]["likes"]["totalItems"] == 0
+ end
end
describe "user upgrade" do
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index b448d13f5..dd84052a3 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -386,7 +386,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|> assign(:user, user)
|> get("/api/v1/filters/#{filter.filter_id}")
- assert response = json_response(conn, 200)
+ assert _response = json_response(conn, 200)
end
test "update a filter", %{conn: conn} do
@@ -600,7 +600,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|> get("/api/v1/notifications")
expected_response =
- "hi <span><a data-user=\"#{user.id}\" href=\"#{user.ap_id}\">@<span>#{user.nickname}</span></a></span>"
+ "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
+ user.ap_id
+ }\">@<span>#{user.nickname}</span></a></span>"
assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200)
assert response == expected_response
@@ -621,7 +623,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|> get("/api/v1/notifications/#{notification.id}")
expected_response =
- "hi <span><a data-user=\"#{user.id}\" href=\"#{user.ap_id}\">@<span>#{user.nickname}</span></a></span>"
+ "hi <span class=\"h-card\"><a data-user=\"#{user.id}\" class=\"u-url mention\" href=\"#{
+ user.ap_id
+ }\">@<span>#{user.nickname}</span></a></span>"
assert %{"status" => %{"content" => response}} = json_response(conn, 200)
assert response == expected_response
@@ -1349,13 +1353,42 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
{:ok, _, _} = CommonAPI.favorite(activity.id, user)
- conn =
+ first_conn =
conn
|> assign(:user, user)
|> get("/api/v1/favourites")
- assert [status] = json_response(conn, 200)
+ assert [status] = json_response(first_conn, 200)
assert status["id"] == to_string(activity.id)
+
+ assert [{"link", _link_header}] =
+ Enum.filter(first_conn.resp_headers, fn element -> match?({"link", _}, element) end)
+
+ # Honours query params
+ {:ok, second_activity} =
+ CommonAPI.post(other_user, %{
+ "status" =>
+ "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
+ })
+
+ {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
+
+ last_like = status["id"]
+
+ second_conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/favourites?since_id=#{last_like}")
+
+ assert [second_status] = json_response(second_conn, 200)
+ assert second_status["id"] == to_string(second_activity.id)
+
+ third_conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/favourites?limit=0")
+
+ assert [] = json_response(third_conn, 200)
end
describe "updating credentials" do
@@ -1373,9 +1406,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert user = json_response(conn, 200)
assert user["note"] ==
- "I drink <a data-tag=\"cofe\" href=\"http://localhost:4001/tag/cofe\">#cofe</a> with <span><a data-user=\"#{
+ "I drink <a class=\"hashtag\" data-tag=\"cofe\" href=\"http://localhost:4001/tag/cofe\">#cofe</a> with <span class=\"h-card\"><a data-user=\"#{
user2.id
- }\" href=\"#{user2.ap_id}\">@<span>#{user2.nickname}</span></a></span>"
+ }\" class=\"u-url mention\" href=\"#{user2.ap_id}\">@<span>#{user2.nickname}</span></a></span>"
end
test "updates the user's locking status", %{conn: conn} do
@@ -1440,22 +1473,41 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
end
test "get instance information", %{conn: conn} do
- insert(:user, %{local: true})
user = insert(:user, %{local: true})
- insert(:user, %{local: false})
+
+ user2 = insert(:user, %{local: true})
+ {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated)
+
+ insert(:user, %{local: false, nickname: "u@peer1.com"})
+ insert(:user, %{local: false, nickname: "u@peer2.com"})
{:ok, _} = TwitterAPI.create_status(user, %{"status" => "cofe"})
Pleroma.Stats.update_stats()
- conn =
- conn
- |> get("/api/v1/instance")
+ conn = get(conn, "/api/v1/instance")
+
+ assert result = json_response(conn, 200)
+
+ stats = result["stats"]
+
+ assert stats
+ assert stats["user_count"] == 1
+ assert stats["status_count"] == 1
+ assert stats["domain_count"] == 2
+ end
+
+ test "get peers", %{conn: conn} do
+ insert(:user, %{local: false, nickname: "u@peer1.com"})
+ insert(:user, %{local: false, nickname: "u@peer2.com"})
+
+ Pleroma.Stats.update_stats()
+
+ conn = get(conn, "/api/v1/instance/peers")
assert result = json_response(conn, 200)
- assert result["stats"]["user_count"] == 2
- assert result["stats"]["status_count"] == 1
+ assert ["peer1.com", "peer2.com"] == Enum.sort(result)
end
test "put settings", %{conn: conn} do
@@ -1466,7 +1518,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|> assign(:user, user)
|> put("/api/web/settings", %{"data" => %{"programming" => "socks"}})
- assert result = json_response(conn, 200)
+ assert _result = json_response(conn, 200)
user = User.get_cached_by_ap_id(user.ap_id)
assert user.info.settings == %{"programming" => "socks"}
diff --git a/test/web/mastodon_api/status_view_test.exs b/test/web/mastodon_api/status_view_test.exs
index 1076b5002..d30ae6149 100644
--- a/test/web/mastodon_api/status_view_test.exs
+++ b/test/web/mastodon_api/status_view_test.exs
@@ -19,6 +19,36 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
:ok
end
+ 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)
+
+ %{account: ms_user} = StatusView.render("status.json", activity: activity)
+
+ assert ms_user.acct == "erroruser@example.com"
+ 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 = StatusView.render("status.json", activity: activity)
+
+ assert result[:account][:id] == to_string(user.id)
+ end
+
test "a note with null content" do
note = insert(:note_activity)
diff --git a/test/web/rich_media/parser_test.exs b/test/web/rich_media/parser_test.exs
index ff3486a6d..e14b5061a 100644
--- a/test/web/rich_media/parser_test.exs
+++ b/test/web/rich_media/parser_test.exs
@@ -15,6 +15,18 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
} ->
%Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/twitter_card.html")}
+ %{
+ method: :get,
+ url: "http://example.com/oembed"
+ } ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/oembed.html")}
+
+ %{
+ method: :get,
+ url: "http://example.com/oembed.json"
+ } ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/oembed.json")}
+
%{method: :get, url: "http://example.com/empty"} ->
%Tesla.Env{status: 200, body: "hello"}
end)
@@ -48,4 +60,33 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
description: "View the album on Flickr."
}}
end
+
+ test "parses OEmbed" do
+ assert Pleroma.Web.RichMedia.Parser.parse("http://example.com/oembed") ==
+ {:ok,
+ %{
+ "author_name" => "‮‭‬bees‬",
+ "author_url" => "https://www.flickr.com/photos/bees/",
+ "cache_age" => 3600,
+ "flickr_type" => "photo",
+ "height" => "768",
+ "html" =>
+ "<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/bees/2362225867/\" title=\"Bacon Lollys by ‮‭‬bees‬, on Flickr\"><img src=\"https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg\" width=\"1024\" height=\"768\" alt=\"Bacon Lollys\"></a><script async src=\"https://embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>",
+ "license" => "All Rights Reserved",
+ "license_id" => 0,
+ "provider_name" => "Flickr",
+ "provider_url" => "https://www.flickr.com/",
+ "thumbnail_height" => 150,
+ "thumbnail_url" =>
+ "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_q.jpg",
+ "thumbnail_width" => 150,
+ "title" => "Bacon Lollys",
+ "type" => "photo",
+ "url" => "https://farm4.staticflickr.com/3040/2362225867_4a87ab8baf_b.jpg",
+ "version" => "1.0",
+ "web_page" => "https://www.flickr.com/photos/bees/2362225867/",
+ "web_page_short_url" => "https://flic.kr/p/4AK2sc",
+ "width" => "1024"
+ }}
+ end
end
diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs
index 5f13e7959..e08edc525 100644
--- a/test/web/twitter_api/twitter_api_controller_test.exs
+++ b/test/web/twitter_api/twitter_api_controller_test.exs
@@ -1357,9 +1357,9 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
assert user.name == "new name"
assert user.bio ==
- "hi <span><a data-user='#{user2.id}' class='mention' href='#{user2.ap_id}'>@<span>#{
- user2.nickname
- }</span></a></span>"
+ "hi <span class='h-card'><a data-user='#{user2.id}' class='u-url mention' href='#{
+ user2.ap_id
+ }'>@<span>#{user2.nickname}</span></a></span>"
assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user})
end
diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs
index b9feb23d4..547592ff2 100644
--- a/test/web/twitter_api/twitter_api_test.exs
+++ b/test/web/twitter_api/twitter_api_test.exs
@@ -38,7 +38,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
{:ok, activity = %Activity{}} = TwitterAPI.create_status(user, input)
expected_text =
- "Hello again, <span><a data-user='#{mentioned_user.id}' class='mention' href='shp'>@<span>shp</span></a></span>.&lt;script&gt;&lt;/script&gt;<br>This is on another :moominmamma: line. <a data-tag='2hu' href='http://localhost:4001/tag/2hu' rel='tag'>#2hu</a> <a data-tag='epic' href='http://localhost:4001/tag/epic' rel='tag'>#epic</a> <a data-tag='phantasmagoric' href='http://localhost:4001/tag/phantasmagoric' rel='tag'>#phantasmagoric</a><br><a href=\"http://example.org/image.jpg\" class='attachment'>image.jpg</a>"
+ "Hello again, <span class='h-card'><a data-user='#{mentioned_user.id}' class='u-url mention' href='shp'>@<span>shp</span></a></span>.&lt;script&gt;&lt;/script&gt;<br>This is on another :moominmamma: line. <a class='hashtag' data-tag='2hu' href='http://localhost:4001/tag/2hu' rel='tag'>#2hu</a> <a class='hashtag' data-tag='epic' href='http://localhost:4001/tag/epic' rel='tag'>#epic</a> <a class='hashtag' data-tag='phantasmagoric' href='http://localhost:4001/tag/phantasmagoric' rel='tag'>#phantasmagoric</a><br><a href=\"http://example.org/image.jpg\" class='attachment'>image.jpg</a>"
assert get_in(activity.data, ["object", "content"]) == expected_text
assert get_in(activity.data, ["object", "type"]) == "Note"
@@ -328,7 +328,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
{:ok, user2} = TwitterAPI.register_user(data2)
expected_text =
- "<span><a data-user='#{user1.id}' class='mention' href='#{user1.ap_id}'>@<span>john</span></a></span> test"
+ "<span class='h-card'><a data-user='#{user1.id}' class='u-url mention' href='#{user1.ap_id}'>@<span>john</span></a></span> test"
assert user2.bio == expected_text
end
diff --git a/test/web/twitter_api/views/activity_view_test.exs b/test/web/twitter_api/views/activity_view_test.exs
index 8b5a16add..3d6b264b1 100644
--- a/test/web/twitter_api/views/activity_view_test.exs
+++ b/test/web/twitter_api/views/activity_view_test.exs
@@ -66,7 +66,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
result = ActivityView.render("activity.json", activity: activity)
assert result["statusnet_html"] ==
- "<a data-tag=\"bike\" href=\"http://localhost:4001/tag/bike\">#Bike</a> log - Commute Tuesday<br /><a href=\"https://pla.bike/posts/20181211/\">https://pla.bike/posts/20181211/</a><br /><a data-tag=\"cycling\" href=\"http://localhost:4001/tag/cycling\">#cycling</a> <a data-tag=\"chscycling\" href=\"http://localhost:4001/tag/chscycling\">#CHScycling</a> <a data-tag=\"commute\" href=\"http://localhost:4001/tag/commute\">#commute</a><br />MVIMG_20181211_054020.jpg"
+ "<a class=\"hashtag\" data-tag=\"bike\" href=\"http://localhost:4001/tag/bike\">#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\">#cycling</a> <a class=\"hashtag\" data-tag=\"chscycling\" href=\"http://localhost:4001/tag/chscycling\">#CHScycling</a> <a class=\"hashtag\" data-tag=\"commute\" href=\"http://localhost:4001/tag/commute\">#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"
@@ -141,7 +141,9 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
"summary" => "",
"summary_html" => "",
"statusnet_html" =>
- "Hey <span><a data-user=\"#{other_user.id}\" href=\"#{other_user.ap_id}\">@<span>shp</span></a></span>!",
+ "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" => activity.data["object"]["id"],