giant massive dep upgrade and dialyxir-found error emporium (#371)
[akkoma] / lib / pleroma / upload / filter / analyze_metadata.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Upload.Filter.AnalyzeMetadata do
6 @moduledoc """
7 Extracts metadata about the upload, such as width/height
8 """
9 require Logger
10
11 @behaviour Pleroma.Upload.Filter
12
13 @spec filter(Pleroma.Upload.t()) ::
14 {:ok, :filtered, Pleroma.Upload.t()} | {:ok, :noop} | {:error, String.t()}
15 def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _} = upload) do
16 try do
17 image =
18 file
19 |> Mogrify.open()
20 |> Mogrify.verbose()
21
22 upload =
23 upload
24 |> Map.put(:width, image.width)
25 |> Map.put(:height, image.height)
26 |> Map.put(:blurhash, get_blurhash(file))
27
28 {:ok, :filtered, upload}
29 rescue
30 e in ErlangError ->
31 Logger.warn("#{__MODULE__}: #{inspect(e)}")
32 {:ok, :noop}
33 end
34 end
35
36 def filter(%Pleroma.Upload{tempfile: file, content_type: "video" <> _} = upload) do
37 try do
38 result = media_dimensions(file)
39
40 upload =
41 upload
42 |> Map.put(:width, result.width)
43 |> Map.put(:height, result.height)
44
45 {:ok, :filtered, upload}
46 rescue
47 e in ErlangError ->
48 Logger.warn("#{__MODULE__}: #{inspect(e)}")
49 {:ok, :noop}
50 end
51 end
52
53 def filter(_), do: {:ok, :noop}
54
55 defp get_blurhash(file) do
56 with {:ok, blurhash} <- :eblurhash.magick(file) do
57 blurhash
58 else
59 _ -> nil
60 end
61 end
62
63 defp media_dimensions(file) do
64 with executable when is_binary(executable) <- System.find_executable("ffprobe"),
65 args = [
66 "-v",
67 "error",
68 "-show_entries",
69 "stream=width,height",
70 "-of",
71 "csv=p=0:s=x",
72 file
73 ],
74 {result, 0} <- System.cmd(executable, args),
75 [width, height] <-
76 String.split(String.trim(result), "x") |> Enum.map(&String.to_integer(&1)) do
77 %{width: width, height: height}
78 else
79 nil -> {:error, {:ffprobe, :command_not_found}}
80 end
81 end
82 end