Use EXIF data of image to prefill image description

During attachment upload Pleroma returns a "description" field. Pleroma-fe has an MR to use that to pre-fill the image description field, <https://git.pleroma.social/pleroma/pleroma-fe/-/merge_requests/1399>

* This MR allows Pleroma to read the EXIF data during upload and return the description to the FE
    * If a description is already present (e.g. because a previous module added it), it will use that
    * Otherwise it will read from the EXIF data. First it will check -ImageDescription, if that's empty, it will check -iptc:Caption-Abstract
    * If no description is found, it will simply return nil, just like before
* When people set up a new instance, they will be asked if they want to read metadata and this module will be activated if so

This was taken from an MR i did on Pleroma and isn't finished yet.
This commit is contained in:
Ilja 2022-02-14 13:14:25 +01:00
commit cd316d7269
11 changed files with 219 additions and 14 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 KiB

View file

@ -69,6 +69,8 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do
"./test/../test/instance/static/",
"--strip-uploads",
"y",
"--read-uploads-data",
"y",
"--dedupe-uploads",
"n",
"--anonymize-uploads",
@ -91,7 +93,10 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do
assert generated_config =~ "password: \"dbpass\""
assert generated_config =~ "configurable_from_database: true"
assert generated_config =~ "http: [ip: {127, 0, 0, 1}, port: 4000]"
assert generated_config =~ "filters: [Pleroma.Upload.Filter.Exiftool]"
assert generated_config =~
"filters: [Pleroma.Upload.Filter.Exiftool, Pleroma.Upload.Filter.ExiftoolReadData]"
assert File.read!(tmp_path() <> "setup.psql") == generated_setup_psql()
assert File.exists?(Path.expand("./test/instance/static/robots.txt"))
end

View file

@ -0,0 +1,106 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Upload.Filter.ExiftoolReadDataTest do
use Pleroma.DataCase, async: true
alias Pleroma.Upload.Filter
@uploads %Pleroma.Upload{
name: "portrait_of_owls_imagedescription_and_caption-abstract.jpg",
content_type: "image/jpeg",
path:
Path.absname("test/fixtures/portrait_of_owls_imagedescription_and_caption-abstract.jpg"),
tempfile:
Path.absname("test/fixtures/portrait_of_owls_imagedescription_and_caption-abstract_tmp.jpg"),
description: nil
}
test "keeps description when not empty" do
uploads = %Pleroma.Upload{
name: "portrait_of_owls_imagedescription_and_caption-abstract.jpg",
content_type: "image/jpeg",
path:
Path.absname("test/fixtures/portrait_of_owls_imagedescription_and_caption-abstract.jpg"),
tempfile:
Path.absname(
"test/fixtures/portrait_of_owls_imagedescription_and_caption-abstract_tmp.jpg"
),
description: "Eight different owls"
}
assert Filter.ExiftoolReadData.filter(uploads) ==
{:ok, :noop}
end
test "otherwise returns ImageDescription when present" do
uploads_after = %Pleroma.Upload{
name: "portrait_of_owls_imagedescription_and_caption-abstract.jpg",
content_type: "image/jpeg",
path:
Path.absname("test/fixtures/portrait_of_owls_imagedescription_and_caption-abstract.jpg"),
tempfile:
Path.absname(
"test/fixtures/portrait_of_owls_imagedescription_and_caption-abstract_tmp.jpg"
),
description: "Pictures of eight different owls"
}
assert Filter.ExiftoolReadData.filter(@uploads) ==
{:ok, :filtered, uploads_after}
end
test "otherwise returns iptc:Caption-Abstract when present" do
upload = %Pleroma.Upload{
name: "portrait_of_owls_caption-abstract.jpg",
content_type: "image/jpeg",
path: Path.absname("test/fixtures/portrait_of_owls_caption-abstract.jpg"),
tempfile: Path.absname("test/fixtures/portrait_of_owls_caption-abstract_tmp.jpg"),
description: nil
}
upload_after = %Pleroma.Upload{
name: "portrait_of_owls_caption-abstract.jpg",
content_type: "image/jpeg",
path: Path.absname("test/fixtures/portrait_of_owls_caption-abstract.jpg"),
tempfile: Path.absname("test/fixtures/portrait_of_owls_caption-abstract_tmp.jpg"),
description: "Pictures of eight different owls - iptc"
}
assert Filter.ExiftoolReadData.filter(upload) ==
{:ok, :filtered, upload_after}
end
test "otherwise returns nil" do
uploads = %Pleroma.Upload{
name: "portrait_of_owls_no_description-abstract.jpg",
content_type: "image/jpeg",
path: Path.absname("test/fixtures/portrait_of_owls_no_description.jpg"),
tempfile: Path.absname("test/fixtures/portrait_of_owls_no_description_tmp.jpg"),
description: nil
}
assert Filter.ExiftoolReadData.filter(uploads) ==
{:ok, :filtered, uploads}
end
test "Return nil when image description from EXIF data exceeds the maximum length" do
clear_config([:instance, :description_limit], 5)
assert Filter.ExiftoolReadData.filter(@uploads) ==
{:ok, :filtered, @uploads}
end
test "Return nil when image description from EXIF data can't be read" do
uploads = %Pleroma.Upload{
name: "non-existant.jpg",
content_type: "image/jpeg",
path: Path.absname("test/fixtures/non-existant.jpg"),
tempfile: Path.absname("test/fixtures/non-existant_tmp.jpg"),
description: nil
}
assert Filter.ExiftoolReadData.filter(uploads) ==
{:ok, :filtered, uploads}
end
end