mirror of
https://git.pleroma.social/pleroma/pleroma.git
synced 2024-05-19 10:08:06 +00:00
Compare commits
9 commits
cc468513d1
...
2925e1d517
Author | SHA1 | Date | |
---|---|---|---|
2925e1d517 | |||
50af909c01 | |||
6f6bede900 | |||
87b8ac3ce6 | |||
71a0373232 | |||
a299ddb10e | |||
741f22bfe0 | |||
8a16504ce1 | |||
a4097e0802 |
1
changelog.d/card-image-description.add
Normal file
1
changelog.d/card-image-description.add
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Include image description in status media cards
|
1
changelog.d/ffmpeg-limiter.add
Normal file
1
changelog.d/ffmpeg-limiter.add
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Framegrabs with ffmpeg will execute with a 5 second timeout and cache the URLs of failures with a TTL of 15 minutes to prevent excessive retries.
|
1
changelog.d/receiverworker-error-handling.fix
Normal file
1
changelog.d/receiverworker-error-handling.fix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ReceiverWorker: Make sure non-{:ok, _} is returned as {:error, …}
|
|
@ -156,6 +156,7 @@ defmodule Pleroma.Application do
|
||||||
build_cachex("web_resp", limit: 2500),
|
build_cachex("web_resp", limit: 2500),
|
||||||
build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
|
build_cachex("emoji_packs", expiration: emoji_packs_expiration(), limit: 10),
|
||||||
build_cachex("failed_proxy_url", limit: 2500),
|
build_cachex("failed_proxy_url", limit: 2500),
|
||||||
|
build_cachex("failed_media_helper_url", default_ttl: :timer.minutes(15), limit: 2_500),
|
||||||
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000),
|
build_cachex("banned_urls", default_ttl: :timer.hours(24 * 30), limit: 5_000),
|
||||||
build_cachex("chat_message_id_idempotency_key",
|
build_cachex("chat_message_id_idempotency_key",
|
||||||
expiration: chat_message_id_idempotency_key_expiration(),
|
expiration: chat_message_id_idempotency_key_expiration(),
|
||||||
|
|
|
@ -12,6 +12,8 @@ defmodule Pleroma.Helpers.MediaHelper do
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||||
|
|
||||||
def missing_dependencies do
|
def missing_dependencies do
|
||||||
Enum.reduce([ffmpeg: "ffmpeg"], [], fn {sym, executable}, acc ->
|
Enum.reduce([ffmpeg: "ffmpeg"], [], fn {sym, executable}, acc ->
|
||||||
if Pleroma.Utils.command_available?(executable) do
|
if Pleroma.Utils.command_available?(executable) do
|
||||||
|
@ -43,29 +45,40 @@ defmodule Pleroma.Helpers.MediaHelper do
|
||||||
@spec video_framegrab(String.t()) :: {:ok, binary()} | {:error, any()}
|
@spec video_framegrab(String.t()) :: {:ok, binary()} | {:error, any()}
|
||||||
def video_framegrab(url) do
|
def video_framegrab(url) do
|
||||||
with executable when is_binary(executable) <- System.find_executable("ffmpeg"),
|
with executable when is_binary(executable) <- System.find_executable("ffmpeg"),
|
||||||
|
false <- @cachex.exists?(:failed_media_helper_cache, url),
|
||||||
{:ok, env} <- HTTP.get(url, [], pool: :media),
|
{:ok, env} <- HTTP.get(url, [], pool: :media),
|
||||||
{:ok, pid} <- StringIO.open(env.body) do
|
{:ok, pid} <- StringIO.open(env.body) do
|
||||||
body_stream = IO.binstream(pid, 1)
|
body_stream = IO.binstream(pid, 1)
|
||||||
|
|
||||||
result =
|
task =
|
||||||
Exile.stream!(
|
Task.async(fn ->
|
||||||
[
|
Exile.stream!(
|
||||||
executable,
|
[
|
||||||
"-i",
|
executable,
|
||||||
"pipe:0",
|
"-i",
|
||||||
"-vframes",
|
"pipe:0",
|
||||||
"1",
|
"-vframes",
|
||||||
"-f",
|
"1",
|
||||||
"mjpeg",
|
"-f",
|
||||||
"pipe:1"
|
"mjpeg",
|
||||||
],
|
"pipe:1"
|
||||||
input: body_stream,
|
],
|
||||||
ignore_epipe: true,
|
input: body_stream,
|
||||||
stderr: :disable
|
ignore_epipe: true,
|
||||||
)
|
stderr: :disable
|
||||||
|> Enum.into(<<>>)
|
)
|
||||||
|
|> Enum.into(<<>>)
|
||||||
|
end)
|
||||||
|
|
||||||
{:ok, result}
|
case Task.yield(task, 5_000) do
|
||||||
|
nil ->
|
||||||
|
Task.shutdown(task)
|
||||||
|
@cachex.put(:failed_media_helper_cache, url, nil)
|
||||||
|
{:error, {:ffmpeg, :timeout}}
|
||||||
|
|
||||||
|
result ->
|
||||||
|
{:ok, result}
|
||||||
|
end
|
||||||
else
|
else
|
||||||
nil -> {:error, {:ffmpeg, :command_not_found}}
|
nil -> {:error, {:ffmpeg, :command_not_found}}
|
||||||
{:error, _} = error -> error
|
{:error, _} = error -> error
|
||||||
|
|
|
@ -58,6 +58,10 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
|
||||||
format: :uri,
|
format: :uri,
|
||||||
description: "Preview thumbnail"
|
description: "Preview thumbnail"
|
||||||
},
|
},
|
||||||
|
image_description: %Schema{
|
||||||
|
type: :string,
|
||||||
|
description: "Alternate text that describes what is in the thumbnail"
|
||||||
|
},
|
||||||
title: %Schema{type: :string, description: "Title of linked resource"},
|
title: %Schema{type: :string, description: "Title of linked resource"},
|
||||||
description: %Schema{type: :string, description: "Description of preview"}
|
description: %Schema{type: :string, description: "Description of preview"}
|
||||||
}
|
}
|
||||||
|
|
|
@ -589,6 +589,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
||||||
provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
|
provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
|
||||||
url: page_url,
|
url: page_url,
|
||||||
image: image_url,
|
image: image_url,
|
||||||
|
image_description: rich_media["image:alt"] || "",
|
||||||
title: rich_media["title"] || "",
|
title: rich_media["title"] || "",
|
||||||
description: rich_media["description"] || "",
|
description: rich_media["description"] || "",
|
||||||
pleroma: %{
|
pleroma: %{
|
||||||
|
|
|
@ -52,7 +52,8 @@ defmodule Pleroma.Workers.ReceiverWorker do
|
||||||
{:error, {:reject, reason}} -> {:cancel, reason}
|
{:error, {:reject, reason}} -> {:cancel, reason}
|
||||||
{:signature, false} -> {:cancel, :invalid_signature}
|
{:signature, false} -> {:cancel, :invalid_signature}
|
||||||
{:error, {:error, reason = "Object has been deleted"}} -> {:cancel, reason}
|
{:error, {:error, reason = "Object has been deleted"}} -> {:cancel, reason}
|
||||||
e -> e
|
{:error, _} = e -> e
|
||||||
|
e -> {:error, e}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,6 +25,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
||||||
import Tesla.Mock
|
import Tesla.Mock
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
|
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||||
|
clear_config([Pleroma.Uploaders.Local, :uploads], "uploads")
|
||||||
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||||
|
|
||||||
ConfigMock
|
ConfigMock
|
||||||
|
|
|
@ -36,6 +36,8 @@ defmodule Pleroma.Web.CommonAPITest do
|
||||||
end
|
end
|
||||||
|
|
||||||
setup_all do
|
setup_all do
|
||||||
|
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||||
|
clear_config([Pleroma.Uploaders.Local, :uploads], "uploads")
|
||||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,9 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
|
||||||
|
setup do: clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||||
|
setup do: clear_config([Pleroma.Uploaders.Local, :uploads], "uploads")
|
||||||
|
|
||||||
describe "Upload media" do
|
describe "Upload media" do
|
||||||
setup do: oauth_access(["write:media"])
|
setup do: oauth_access(["write:media"])
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
||||||
setup do: clear_config([:instance, :allow_relay])
|
setup do: clear_config([:instance, :allow_relay])
|
||||||
setup do: clear_config([:mrf, :policies])
|
setup do: clear_config([:mrf, :policies])
|
||||||
setup do: clear_config([:mrf_keyword, :reject])
|
setup do: clear_config([:mrf_keyword, :reject])
|
||||||
|
setup do: clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||||
|
setup do: clear_config([Pleroma.Uploaders.Local, :uploads], "uploads")
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
Pleroma.UnstubbedConfigMock
|
Pleroma.UnstubbedConfigMock
|
||||||
|
@ -1717,6 +1719,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
||||||
|
|
||||||
card_data = %{
|
card_data = %{
|
||||||
"image" => "http://ia.media-imdb.com/images/rock.jpg",
|
"image" => "http://ia.media-imdb.com/images/rock.jpg",
|
||||||
|
"image_description" => "",
|
||||||
"provider_name" => "example.com",
|
"provider_name" => "example.com",
|
||||||
"provider_url" => "https://example.com",
|
"provider_url" => "https://example.com",
|
||||||
"title" => "The Rock",
|
"title" => "The Rock",
|
||||||
|
@ -1770,6 +1773,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
|
||||||
"title" => "Pleroma",
|
"title" => "Pleroma",
|
||||||
"description" => "",
|
"description" => "",
|
||||||
"image" => nil,
|
"image" => nil,
|
||||||
|
"image_description" => "",
|
||||||
"provider_name" => "example.com",
|
"provider_name" => "example.com",
|
||||||
"provider_url" => "https://example.com",
|
"provider_url" => "https://example.com",
|
||||||
"url" => "https://example.com/ogp-missing-data",
|
"url" => "https://example.com/ogp-missing-data",
|
||||||
|
|
|
@ -773,6 +773,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
||||||
page_url = "http://example.com"
|
page_url = "http://example.com"
|
||||||
|
|
||||||
card = %{
|
card = %{
|
||||||
|
"image:alt" => "Example image description",
|
||||||
url: page_url,
|
url: page_url,
|
||||||
site_name: "Example site name",
|
site_name: "Example site name",
|
||||||
title: "Example website",
|
title: "Example website",
|
||||||
|
@ -780,7 +781,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
||||||
description: "Example description"
|
description: "Example description"
|
||||||
}
|
}
|
||||||
|
|
||||||
%{provider_name: "example.com"} =
|
%{provider_name: "example.com", image_description: "Example image description"} =
|
||||||
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
StatusView.render("card.json", %{page_url: page_url, rich_media: card})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ defmodule Pleroma.Web.PleromaAPI.BackupControllerTest do
|
||||||
alias Pleroma.Web.PleromaAPI.BackupView
|
alias Pleroma.Web.PleromaAPI.BackupView
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
clear_config([Pleroma.Upload, :uploader])
|
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||||
|
clear_config([Pleroma.Uploaders.Local, :uploads], "uploads")
|
||||||
clear_config([Backup, :limit_days])
|
clear_config([Backup, :limit_days])
|
||||||
|
|
||||||
ConfigMock
|
ConfigMock
|
||||||
|
|
|
@ -109,6 +109,9 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it works with an attachment", %{conn: conn, user: user} do
|
test "it works with an attachment", %{conn: conn, user: user} do
|
||||||
|
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||||
|
clear_config([Pleroma.Uploaders.Local, :uploads], "uploads")
|
||||||
|
|
||||||
file = %Plug.Upload{
|
file = %Plug.Upload{
|
||||||
content_type: "image/jpeg",
|
content_type: "image/jpeg",
|
||||||
path: Path.absname("test/fixtures/image.jpg"),
|
path: Path.absname("test/fixtures/image.jpg"),
|
||||||
|
|
|
@ -430,6 +430,8 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
|
||||||
|
|
||||||
test "with media proxy" do
|
test "with media proxy" do
|
||||||
clear_config([:media_proxy, :enabled], true)
|
clear_config([:media_proxy, :enabled], true)
|
||||||
|
clear_config([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
|
||||||
|
clear_config([Pleroma.Uploaders.Local, :uploads], "uploads")
|
||||||
|
|
||||||
ConfigMock
|
ConfigMock
|
||||||
|> stub_with(Pleroma.Test.StaticConfig)
|
|> stub_with(Pleroma.Test.StaticConfig)
|
||||||
|
|
Loading…
Reference in a new issue