+ Options:
+ * `:type`: presets for activity type (defaults to Document) and size limits from app configuration
+ * `:description`: upload alternative text
+ * `:base_url`: override base url
+ * `:uploader`: override uploader
+ * `:filters`: override filters
+ * `:size_limit`: override size limit
+ * `:activity_type`: override activity type
+
+ The `%Pleroma.Upload{}` struct: all documented fields are meant to be overwritten in filters:
+
+ * `:id` - the upload id.
+ * `:name` - the upload file name.
+ * `:path` - the upload path: set at first to `id/name` but can be changed. Keep in mind that the path
+ 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.
+
+ Related behaviors:
+
+ * `Pleroma.Uploaders.Uploader`
+ * `Pleroma.Upload.Filter`
+
+ """
+ alias Ecto.UUID
+ require Logger
+
+ @type source ::
+ Plug.Upload.t()
+ | (data_uri_string :: String.t())
+ | {:from_local, name :: String.t(), id :: String.t(), path :: String.t()}
+
+ @type option ::
+ {:type, :avatar | :banner | :background}
+ | {:description, String.t()}
+ | {:activity_type, String.t()}
+ | {:size_limit, nil | non_neg_integer()}
+ | {:uploader, module()}
+ | {:filters, [module()]}
+
+ @type t :: %__MODULE__{
+ id: String.t(),
+ name: String.t(),
+ tempfile: String.t(),
+ content_type: String.t(),
+ path: String.t()