forked from AkkomaGang/akkoma
Merge branch 'features/mastoapi-cards' into 'develop'
MastoAPI: Add Rich-Media support See merge request pleroma/pleroma!664
This commit is contained in:
commit
e91f867cc9
6 changed files with 70 additions and 12 deletions
|
@ -58,6 +58,20 @@ defp generate_scrubber_signature(scrubbers) do
|
||||||
"#{signature}#{to_string(scrubber)}"
|
"#{signature}#{to_string(scrubber)}"
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def extract_first_external_url(object, content) do
|
||||||
|
key = "URL|#{object.id}"
|
||||||
|
|
||||||
|
Cachex.fetch!(:scrubber_cache, key, fn _key ->
|
||||||
|
result =
|
||||||
|
content
|
||||||
|
|> Floki.filter_out("a.mention")
|
||||||
|
|> Floki.attribute("a", "href")
|
||||||
|
|> Enum.at(0)
|
||||||
|
|
||||||
|
{:commit, result}
|
||||||
|
end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule Pleroma.HTML.Scrubber.TwitterText do
|
defmodule Pleroma.HTML.Scrubber.TwitterText do
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
alias Pleroma.{Repo, Object, Activity, User, Notification, Stats}
|
alias Pleroma.{Repo, Object, Activity, User, Notification, Stats}
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
|
alias Pleroma.HTML
|
||||||
|
|
||||||
alias Pleroma.Web.MastodonAPI.{
|
alias Pleroma.Web.MastodonAPI.{
|
||||||
StatusView,
|
StatusView,
|
||||||
|
@ -1322,6 +1323,29 @@ def suggestions(%{assigns: %{user: user}} = conn, _) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_status_card(status_id) do
|
||||||
|
with %Activity{} = activity <- Repo.get(Activity, status_id),
|
||||||
|
true <- ActivityPub.is_public?(activity),
|
||||||
|
%Object{} = object <- Object.normalize(activity.data["object"]),
|
||||||
|
page_url <- HTML.extract_first_external_url(object, object.data["content"]),
|
||||||
|
{:ok, rich_media} <- Pleroma.Web.RichMedia.Parser.parse(page_url) do
|
||||||
|
page_url = rich_media[:url] || page_url
|
||||||
|
site_name = rich_media[:site_name] || URI.parse(page_url).host
|
||||||
|
|
||||||
|
rich_media
|
||||||
|
|> Map.take([:image, :title, :description])
|
||||||
|
|> Map.put(:type, "link")
|
||||||
|
|> Map.put(:provider_name, site_name)
|
||||||
|
|> Map.put(:url, page_url)
|
||||||
|
else
|
||||||
|
_ -> %{}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def status_card(conn, %{"id" => status_id}) do
|
||||||
|
json(conn, get_status_card(status_id))
|
||||||
|
end
|
||||||
|
|
||||||
def try_render(conn, target, params)
|
def try_render(conn, target, params)
|
||||||
when is_binary(target) do
|
when is_binary(target) do
|
||||||
res = render(conn, target, params)
|
res = render(conn, target, params)
|
||||||
|
|
|
@ -258,7 +258,7 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
get("/statuses/:id", MastodonAPIController, :get_status)
|
get("/statuses/:id", MastodonAPIController, :get_status)
|
||||||
get("/statuses/:id/context", MastodonAPIController, :get_context)
|
get("/statuses/:id/context", MastodonAPIController, :get_context)
|
||||||
get("/statuses/:id/card", MastodonAPIController, :empty_object)
|
get("/statuses/:id/card", MastodonAPIController, :status_card)
|
||||||
get("/statuses/:id/favourited_by", MastodonAPIController, :favourited_by)
|
get("/statuses/:id/favourited_by", MastodonAPIController, :favourited_by)
|
||||||
get("/statuses/:id/reblogged_by", MastodonAPIController, :reblogged_by)
|
get("/statuses/:id/reblogged_by", MastodonAPIController, :reblogged_by)
|
||||||
|
|
||||||
|
|
|
@ -653,6 +653,14 @@ def get("https://social.heldscal.la/user/23211", _, _, Accept: "application/acti
|
||||||
{:ok, Tesla.Mock.json(%{"id" => "https://social.heldscal.la/user/23211"}, status: 200)}
|
{:ok, Tesla.Mock.json(%{"id" => "https://social.heldscal.la/user/23211"}, status: 200)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get("http://example.com/ogp", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/ogp.html")}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get("http://example.com/empty", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 200, body: "hello"}}
|
||||||
|
end
|
||||||
|
|
||||||
def get(url, query, body, headers) do
|
def get(url, query, body, headers) do
|
||||||
{:error,
|
{:error,
|
||||||
"Not implemented the mock response for get #{inspect(url)}, #{query}, #{inspect(body)}, #{
|
"Not implemented the mock response for get #{inspect(url)}, #{query}, #{inspect(body)}, #{
|
||||||
|
|
|
@ -1623,5 +1623,22 @@ test "max pinned statuses", %{conn: conn, user: user, activity: activity_one} do
|
||||||
|> post("/api/v1/statuses/#{activity_two.id}/pin")
|
|> post("/api/v1/statuses/#{activity_two.id}/pin")
|
||||||
|> json_response(400)
|
|> json_response(400)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "Status rich-media Card", %{conn: conn, user: user} do
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "http://example.com/ogp"})
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/statuses/#{activity.id}/card")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert response == %{
|
||||||
|
"image" => "http://ia.media-imdb.com/images/rock.jpg",
|
||||||
|
"provider_name" => "www.imdb.com",
|
||||||
|
"title" => "The Rock",
|
||||||
|
"type" => "link",
|
||||||
|
"url" => "http://www.imdb.com/title/tt0117500/"
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.RichMedia.RichMediaControllerTest do
|
defmodule Pleroma.Web.RichMedia.RichMediaControllerTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
import Tesla.Mock
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
Tesla.Mock.mock(fn
|
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||||
%{
|
|
||||||
method: :get,
|
|
||||||
url: "http://example.com/ogp"
|
|
||||||
} ->
|
|
||||||
%Tesla.Env{status: 200, body: File.read!("test/fixtures/rich_media/ogp.html")}
|
|
||||||
|
|
||||||
%{method: :get, url: "http://example.com/empty"} ->
|
|
||||||
%Tesla.Env{status: 200, body: "hello"}
|
|
||||||
end)
|
|
||||||
|
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue