Merge pull request 'Manually define PATH for Arch Linux users in systemd unit' (...
[akkoma] / lib / pleroma / upload.ex
index db2cc1dae278009701222528e3bd159a7b7a494e..9bf8e03df49aab6c7b1fb64952ee6befd10168a0 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Upload do
@@ -23,6 +23,9 @@ defmodule Pleroma.Upload do
     is once created permanent and changing it (especially in uploaders) is probably a bad idea!
   * `:tempfile` - path to the temporary file. Prefer in-place changes on the file rather than changing the
   path as the temporary file is also tracked by `Plug.Upload{}` and automatically deleted once the request is over.
+  * `:width` - width of the media in pixels
+  * `:height` - height of the media in pixels
+  * `:blurhash` - string hash of the image encoded with the blurhash algorithm (https://blurha.sh/)
 
   Related behaviors:
 
@@ -31,6 +34,9 @@ defmodule Pleroma.Upload do
 
   """
   alias Ecto.UUID
+  alias Pleroma.Config
+  alias Pleroma.Maps
+  alias Pleroma.Web.ActivityPub.Utils
   require Logger
 
   @type source ::
@@ -52,9 +58,12 @@ defmodule Pleroma.Upload do
           name: String.t(),
           tempfile: String.t(),
           content_type: String.t(),
+          width: integer(),
+          height: integer(),
+          blurhash: String.t(),
           path: String.t()
         }
-  defstruct [:id, :name, :tempfile, :content_type, :path]
+  defstruct [:id, :name, :tempfile, :content_type, :width, :height, :blurhash, :path]
 
   defp get_description(opts, upload) do
     case {opts[:description], Pleroma.Config.get([Pleroma.Upload, :default_description])} do
@@ -80,6 +89,7 @@ defmodule Pleroma.Upload do
          {:ok, url_spec} <- Pleroma.Uploaders.Uploader.put_file(opts.uploader, upload) do
       {:ok,
        %{
+         "id" => Utils.generate_object_id(),
          "type" => opts.activity_type,
          "mediaType" => upload.content_type,
          "url" => [
@@ -88,9 +98,12 @@ defmodule Pleroma.Upload do
              "mediaType" => upload.content_type,
              "href" => url_from_spec(upload, opts.base_url, url_spec)
            }
+           |> Maps.put_if_present("width", upload.width)
+           |> Maps.put_if_present("height", upload.height)
          ],
          "name" => description
-       }}
+       }
+       |> Maps.put_if_present("blurhash", upload.blurhash)}
     else
       {:description_limit, _} ->
         {:error, :description_too_long}
@@ -130,12 +143,7 @@ defmodule Pleroma.Upload do
       uploader: Keyword.get(opts, :uploader, Pleroma.Config.get([__MODULE__, :uploader])),
       filters: Keyword.get(opts, :filters, Pleroma.Config.get([__MODULE__, :filters])),
       description: Keyword.get(opts, :description),
-      base_url:
-        Keyword.get(
-          opts,
-          :base_url,
-          Pleroma.Config.get([__MODULE__, :base_url], Pleroma.Web.base_url())
-        )
+      base_url: base_url()
     }
   end
 
@@ -216,16 +224,46 @@ defmodule Pleroma.Upload do
           ""
         end
 
-    prefix =
-      if is_nil(Pleroma.Config.get([__MODULE__, :base_url])) do
-        "media"
-      else
-        ""
-      end
-
-    [base_url, prefix, path]
+    [base_url, path]
     |> Path.join()
   end
 
   defp url_from_spec(_upload, _base_url, {:url, url}), do: url
+
+  def base_url do
+    uploader = Config.get([Pleroma.Upload, :uploader])
+    upload_base_url = Config.get([Pleroma.Upload, :base_url])
+    public_endpoint = Config.get([uploader, :public_endpoint])
+
+    case uploader do
+      Pleroma.Uploaders.Local ->
+        upload_base_url || Pleroma.Web.Endpoint.url() <> "/media/"
+
+      Pleroma.Uploaders.S3 ->
+        bucket = Config.get([Pleroma.Uploaders.S3, :bucket])
+        truncated_namespace = Config.get([Pleroma.Uploaders.S3, :truncated_namespace])
+        namespace = Config.get([Pleroma.Uploaders.S3, :bucket_namespace])
+
+        bucket_with_namespace =
+          cond do
+            !is_nil(truncated_namespace) ->
+              truncated_namespace
+
+            !is_nil(namespace) ->
+              namespace <> ":" <> bucket
+
+            true ->
+              bucket
+          end
+
+        if public_endpoint do
+          Path.join([public_endpoint, bucket_with_namespace])
+        else
+          Path.join([upload_base_url, bucket_with_namespace])
+        end
+
+      _ ->
+        public_endpoint || upload_base_url || Pleroma.Web.Endpoint.url() <> "/media/"
+    end
+  end
 end