uploading works

This commit is contained in:
byte[] 2019-11-25 23:51:17 -05:00
parent 56db3807aa
commit 84abf98b30
9 changed files with 168 additions and 18 deletions

View file

@ -14,7 +14,8 @@ config :philomena,
otp_secret_key: "Wn7O/8DD+qxL0X4X7bvT90wOkVGcA90bIHww4twR03Ci//zq7PnMw8ypqyyT/b/C", otp_secret_key: "Wn7O/8DD+qxL0X4X7bvT90wOkVGcA90bIHww4twR03Ci//zq7PnMw8ypqyyT/b/C",
image_url_root: "/img", image_url_root: "/img",
avatar_url_root: "/avatars", avatar_url_root: "/avatars",
badge_url_root: "/media" badge_url_root: "/media",
image_file_root: "priv/static/system/images"
config :philomena, :pow, config :philomena, :pow,
user: Philomena.Users.User, user: Philomena.Users.User,

View file

@ -62,7 +62,7 @@ defmodule Philomena.Conversations.Conversation do
defp put_recipient(changeset) do defp put_recipient(changeset) do
recipient = changeset |> get_field(:recipient) recipient = changeset |> get_field(:recipient)
user = Repo.get_by(User, name: recipient) |> IO.inspect() user = Repo.get_by(User, name: recipient)
changeset changeset
|> put_change(:to, user) |> put_change(:to, user)

View file

@ -20,5 +20,6 @@ defmodule Philomena.ImageIntensities.ImageIntensity do
image_intensity image_intensity
|> cast(attrs, [:nw, :ne, :sw, :se]) |> cast(attrs, [:nw, :ne, :sw, :se])
|> validate_required([:image_id, :nw, :ne, :sw, :se]) |> validate_required([:image_id, :nw, :ne, :sw, :se])
|> unique_constraint(:image_id, name: :index_image_intensities_on_image_id)
end end
end end

View file

@ -13,6 +13,7 @@ defmodule Philomena.Images do
alias Philomena.TagChanges.TagChange alias Philomena.TagChanges.TagChange
alias Philomena.Tags alias Philomena.Tags
alias Philomena.Tags.Tag alias Philomena.Tags.Tag
alias Philomena.Processors
@doc """ @doc """
Gets a single image. Gets a single image.
@ -44,10 +45,23 @@ defmodule Philomena.Images do
{:error, %Ecto.Changeset{}} {:error, %Ecto.Changeset{}}
""" """
def create_image(attrs \\ %{}) do def create_image(attribution, attrs \\ %{}) do
tags = Tags.get_or_create_tags(attrs["tag_input"])
image =
%Image{} %Image{}
|> Image.changeset(attrs) |> Image.creation_changeset(attrs, attribution)
|> Repo.insert() |> Image.tag_changeset(attrs, [], tags)
|> Processors.after_upload(attrs)
Multi.new
|> Multi.insert(:image, image)
|> Multi.run(:after, fn _repo, %{image: image} ->
Processors.after_insert(image)
{:ok, nil}
end)
|> Repo.transaction()
end end
@doc """ @doc """

View file

@ -109,8 +109,11 @@ defmodule Philomena.Images.Image do
end end
def creation_changeset(image, attrs, attribution) do def creation_changeset(image, attrs, attribution) do
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
image image
|> cast(attrs, [:source_url, :description]) |> cast(attrs, [:source_url, :description])
|> change(first_seen_at: now)
|> change(attribution) |> change(attribution)
end end
@ -119,12 +122,14 @@ defmodule Philomena.Images.Image do
|> cast(attrs, [ |> cast(attrs, [
:image, :image_name, :image_width, :image_height, :image_size, :image, :image_name, :image_width, :image_height, :image_size,
:image_format, :image_mime_type, :image_aspect_ratio, :image_format, :image_mime_type, :image_aspect_ratio,
:image_orig_sha512_hash, :image_sha512_hash, :uploaded_image :image_orig_sha512_hash, :image_sha512_hash, :uploaded_image,
:is_animated
]) ])
|> validate_required([ |> validate_required([
:image, :image_width, :image_height, :image_size, :image, :image_width, :image_height, :image_size,
:image_format, :image_mime_type, :image_aspect_ratio, :image_format, :image_mime_type, :image_aspect_ratio,
:image_orig_sha512_hash, :image_sha512_hash, :uploaded_image :image_orig_sha512_hash, :image_sha512_hash, :uploaded_image,
:is_animated
]) ])
|> validate_number(:image_size, greater_than: 0, less_than_or_equal_to: 26214400) |> validate_number(:image_size, greater_than: 0, less_than_or_equal_to: 26214400)
|> validate_number(:image_width, greater_than: 0, less_than_or_equal_to: 32767) |> validate_number(:image_width, greater_than: 0, less_than_or_equal_to: 32767)

View file

@ -32,10 +32,22 @@ defmodule Philomena.Processors do
"video/webm" => Philomena.Processors.Webm "video/webm" => Philomena.Processors.Webm
} }
@versions [
thumb_tiny: {50, 50},
thumb_small: {150, 150},
thumb: {250, 250},
small: {320, 240},
medium: {800, 600},
large: {1280, 1024},
tall: {1024, 4096},
full: nil
]
def after_upload(image, params) do def after_upload(image, params) do
with upload when not is_nil(upload) <- params["image"], with upload when not is_nil(upload) <- params["image"],
file <- upload.path, file <- upload.path,
mime <- @mimes[Mime.file(file)], {:ok, mime} <- Mime.file(file),
mime <- @mimes[mime],
analyzer when not is_nil(analyzer) <- @analyzers[mime], analyzer when not is_nil(analyzer) <- @analyzers[mime],
analysis <- analyzer.analyze(file), analysis <- analyzer.analyze(file),
changes <- analysis_to_changes(analysis, file, upload.filename) changes <- analysis_to_changes(analysis, file, upload.filename)
@ -50,7 +62,10 @@ defmodule Philomena.Processors do
end end
def after_insert(image) do def after_insert(image) do
File.cp!(image.uploaded_image, Path.join([image_file_root(), image.image])) file = image_file(image)
dir = Path.dirname(file)
File.mkdir_p!(dir)
File.cp!(image.uploaded_image, file)
ImageProcessor.cast(self(), image.id) ImageProcessor.cast(self(), image.id)
end end
@ -62,7 +77,7 @@ defmodule Philomena.Processors do
analyzer = @analyzers[mime] analyzer = @analyzers[mime]
analysis = analyzer.analyze(file) analysis = analyzer.analyze(file)
processor = @processors[mime] processor = @processors[mime]
process = processor.process(analysis, file) process = processor.process(analysis, file, @versions)
apply_edit_script(image, process) apply_edit_script(image, process)
sha512 = Sha512.file(file) sha512 = Sha512.file(file)
@ -102,22 +117,27 @@ defmodule Philomena.Processors do
defp apply_thumbnail(_image, thumb_dir, {:copy, new_file, destination}) do defp apply_thumbnail(_image, thumb_dir, {:copy, new_file, destination}) do
new_destination = Path.join([thumb_dir, destination]) new_destination = Path.join([thumb_dir, destination])
dir = Path.dirname(new_destination)
File.cp(new_file, new_destination) File.mkdir_p!(dir)
File.chmod(new_destination, 0o755) File.cp!(new_file, new_destination)
File.chmod!(new_destination, 0o755)
end end
defp apply_thumbnail(image, thumb_dir, {:symlink_original, destination}) do defp apply_thumbnail(image, thumb_dir, {:symlink_original, destination}) do
file = image_file(image) file = Path.absname(image_file(image))
new_destination = Path.join([thumb_dir, destination]) new_destination = Path.join([thumb_dir, destination])
dir = Path.dirname(new_destination)
File.ln_s(file, new_destination) File.mkdir_p!(dir)
File.chmod(new_destination, 0o755) File.rm(new_destination)
File.ln_s!(file, new_destination)
File.chmod!(new_destination, 0o755)
end end
defp analysis_to_changes(analysis, file, upload_name) do defp analysis_to_changes(analysis, file, upload_name) do
{width, height} = analysis.dimensions {width, height} = analysis.dimensions
%{size: size} = File.stat(file) {:ok, %{size: size}} = File.stat(file)
sha512 = Sha512.file(file) sha512 = Sha512.file(file)
filename = build_filename(analysis.extension) filename = build_filename(analysis.extension)
@ -132,6 +152,7 @@ defmodule Philomena.Processors do
"image_aspect_ratio" => aspect_ratio(width, height), "image_aspect_ratio" => aspect_ratio(width, height),
"image_orig_sha512_hash" => sha512, "image_orig_sha512_hash" => sha512,
"image_sha512_hash" => sha512, "image_sha512_hash" => sha512,
"is_animated" => analysis.animated?,
"uploaded_image" => file "uploaded_image" => file
} }
end end

View file

@ -9,6 +9,10 @@ defmodule PhilomenaWeb.ImageController do
plug :load_and_authorize_resource, model: Image, only: :show, preload: [:tags, user: [awards: :badge]] plug :load_and_authorize_resource, model: Image, only: :show, preload: [:tags, user: [awards: :badge]]
plug PhilomenaWeb.FilterBannedUsersPlug when action in [:new, :create]
plug PhilomenaWeb.UserAttributionPlug when action in [:create]
plug PhilomenaWeb.CaptchaPlug when action in [:create]
def index(conn, _params) do def index(conn, _params) do
query = conn.assigns.compiled_filter query = conn.assigns.compiled_filter
@ -77,4 +81,29 @@ defmodule PhilomenaWeb.ImageController do
layout_class: "layout--wide" layout_class: "layout--wide"
) )
end end
def new(conn, _params) do
changeset =
%Image{}
|> Images.change_image()
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"image" => image_params}) do
attributes = conn.assigns.attributes
case Images.create_image(attributes, image_params) do
{:ok, %{image: image}} ->
Images.reindex_image(image)
conn
|> put_flash(:info, "Image created successfully.")
|> redirect(to: Routes.image_path(conn, :show, image))
{:error, :image, changeset, _} ->
conn
|> render("new.html", changeset: changeset)
end
end
end end

View file

@ -83,7 +83,7 @@ defmodule PhilomenaWeb.Router do
get "/", ActivityController, :index get "/", ActivityController, :index
resources "/activity", ActivityController, only: [:index] resources "/activity", ActivityController, only: [:index]
resources "/images", ImageController, only: [:index, :show] do resources "/images", ImageController, only: [:index, :show, :new, :create] do
resources "/comments", Image.CommentController, only: [:index, :show, :create] resources "/comments", Image.CommentController, only: [:index, :show, :create]
resources "/tags", Image.TagController, only: [:update], singleton: true resources "/tags", Image.TagController, only: [:update], singleton: true
resources "/sources", Image.SourceController, only: [:update], singleton: true resources "/sources", Image.SourceController, only: [:update], singleton: true

View file

@ -0,0 +1,79 @@
= form_for @changeset, Routes.image_path(@conn, :create), [multipart: true], fn f ->
.dnp-warning
h4
' Read the
a> href="/pages/rules" site rules
' and check our
a> href="/dnp" do-not-post list
p
' Don't post content the artist doesn't want here (or shared in general),
strong including commercial content.
= if !@conn.assigns.current_user do
p
strong<> Sorry, but due to spam, anonymous uploaders need to fill this out.
| If you're logged in, you can still post anonymously and won't have to deal with captchas!
.field
= checkbox f, :captcha, class: "js-captcha", value: 0
= label f, :captcha, "I am not a robot!"
p
strong
' Please check it isn't already here with
a href="/search/reverse" reverse search.
/ todo: extract this
h4 Select an image
.image-other
#js-image-upload-previews
p Upload a file from your computer
.field
= file_input f, :image, class: "input js-scraper"
= error_tag f, :image_size
= error_tag f, :image_width
= error_tag f, :image_height
= error_tag f, :image_name
= error_tag f, :image_mime_type
.field-error-js.hidden.js-scraper
h4 About this image
.field
= label f, :source_url, "The page you found this image on"
= url_input f, :source_url, class: "input input--wide js-image-input", placeholder: "Source URL"
.field
label for="image[tag_input]"
' Describe with
strong> 3+
' tags, including ratings and applicable artist tags
= render PhilomenaWeb.TagView, "_tag_editor.html", f: f, name: :tag_input, type: :upload
button.button.button--state-success.button--separate-left.button--bold id="tagsinput-save" type="button" title="This button saves the tags listed above to your browser, allowing you to retrieve them again by clicking the Load button" Save
button.button.button--state-warning.button--separate-left.button--bold id="tagsinput-load" type="button" title="This button loads any saved tags from your browser" Load
button.button.button--state-danger.button--separate-left.button--bold id="tagsinput-clear" type="button" title="This button will clear the list of tags above" Clear
br
.field
.block
.block__header.block__header--js-tabbed
= link "Description", to: "#", class: "selected", data: [click_tab: "write"]
= link "Preview", to: "#", data: [click_tab: "preview"]
.block__tab.selected data-tab="write"
/= render partial: 'layouts/textile_toolbar'
= textarea f, :description, class: "input input--wide input--text js-preview-description js-image-input js-toolbar-input", placeholder: "Describe this image in plain words - this should generally be info about the image that doesn't belong in the tags or source."
.block__tab.hidden data-tab="preview"
| Loading preview...
= if @conn.assigns.current_user do
.field
= label f, :anonymous, "Post anonymously"
= checkbox f, :anonymous, class: "checkbox"
.actions
= submit "Upload", class: "button", autocomplete: "off", data: [disable_with: "Please wait..."]