philomena/lib/philomena/images.ex

978 lines
25 KiB
Elixir
Raw Normal View History

2019-08-18 18:17:05 +02:00
defmodule Philomena.Images do
@moduledoc """
The Images context.
"""
import Ecto.Query, warn: false
2022-07-18 16:13:24 +02:00
require Logger
2019-11-24 19:36:21 +01:00
alias Ecto.Multi
2019-08-18 18:17:05 +02:00
alias Philomena.Repo
alias PhilomenaQuery.Search
alias Philomena.ThumbnailWorker
2020-12-16 16:53:26 +01:00
alias Philomena.ImagePurgeWorker
alias Philomena.DuplicateReports.DuplicateReport
2019-08-18 18:17:05 +02:00
alias Philomena.Images.Image
2019-12-07 06:49:20 +01:00
alias Philomena.Images.Uploader
2019-12-16 23:11:16 +01:00
alias Philomena.Images.Tagging
2020-12-16 16:53:26 +01:00
alias Philomena.Images.Thumbnailer
2023-05-29 14:20:57 +02:00
alias Philomena.Images.Source
alias Philomena.Images.SearchIndex, as: ImageIndex
2020-12-06 17:42:14 +01:00
alias Philomena.IndexWorker
2019-12-16 06:25:06 +01:00
alias Philomena.ImageFeatures.ImageFeature
2019-11-24 19:36:21 +01:00
alias Philomena.SourceChanges.SourceChange
alias Philomena.Notifications.Notification
2020-12-06 17:42:14 +01:00
alias Philomena.NotificationWorker
2019-11-24 19:36:21 +01:00
alias Philomena.TagChanges.TagChange
alias Philomena.Tags
alias Philomena.UserStatistics
alias Philomena.Tags.Tag
alias Philomena.Notifications
2019-12-08 05:53:18 +01:00
alias Philomena.Interactions
alias Philomena.Reports
alias Philomena.Reports.Report
2019-12-21 22:37:06 +01:00
alias Philomena.Comments
alias Philomena.Galleries.Gallery
alias Philomena.Galleries.Interaction
alias Philomena.Users.User
2019-08-18 18:17:05 +02:00
@doc """
Gets a single image.
Raises `Ecto.NoResultsError` if the Image does not exist.
## Examples
iex> get_image!(123)
%Image{}
iex> get_image!(456)
** (Ecto.NoResultsError)
"""
2019-08-18 20:14:36 +02:00
def get_image!(id) do
Repo.one!(Image |> where(id: ^id) |> preload(:tags))
end
2019-08-18 18:17:05 +02:00
@doc """
Gets the tag list for a single image.
"""
def tag_list(%Image{tags: tags}) do
tags
|> Tag.display_order()
|> Enum.map_join(", ", & &1.name)
end
2019-08-18 18:17:05 +02:00
@doc """
Creates a image.
## Examples
iex> create_image(%{field: value})
{:ok, %Image{}}
iex> create_image(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
2019-11-26 05:51:17 +01:00
def create_image(attribution, attrs \\ %{}) do
tags = Tags.get_or_create_tags(attrs["tag_input"])
sources = attrs["sources"]
2019-11-26 05:51:17 +01:00
image =
%Image{}
|> Image.creation_changeset(attrs, attribution)
|> Image.source_changeset(attrs, [], sources)
2019-11-26 05:51:17 +01:00
|> Image.tag_changeset(attrs, [], tags)
|> Image.dnp_changeset(attribution[:user])
2019-12-07 06:49:20 +01:00
|> Uploader.analyze_upload(attrs)
2019-11-26 05:51:17 +01:00
2020-01-11 05:20:19 +01:00
Multi.new()
2019-11-26 05:51:17 +01:00
|> Multi.insert(:image, image)
2019-11-27 06:51:20 +01:00
|> Multi.run(:name_caches, fn repo, %{image: image} ->
image
|> Image.cache_changeset()
|> repo.update()
end)
2019-11-27 02:45:57 +01:00
|> Multi.run(:added_tag_count, fn repo, %{image: image} ->
tag_ids = image.added_tags |> Enum.map(& &1.id)
tags = Tag |> where([t], t.id in ^tag_ids)
{count, nil} = repo.update_all(tags, inc: [images_count: 1])
{:ok, count}
end)
|> maybe_create_subscription_on_upload(attribution[:user])
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
|> Repo.transaction()
|> case do
{:ok, %{image: image}} = result ->
2022-07-18 16:13:24 +02:00
async_upload(image, attrs["image"])
reindex_image(image)
Tags.reindex_tags(image.added_tags)
2022-03-24 17:31:57 +01:00
maybe_approve_image(image, attribution[:user])
result
result ->
result
end
2019-08-18 18:17:05 +02:00
end
2022-07-18 16:13:24 +02:00
defp async_upload(image, plug_upload) do
linked_pid =
spawn(fn ->
# Make sure task will finish before VM exit
Process.flag(:trap_exit, true)
# Wait to be freed up by the caller
receive do
:ready -> nil
end
# Start trying to upload
try_upload(image, 0)
end)
# Give the upload to the linked process
Plug.Upload.give_away(plug_upload, linked_pid, self())
# Free up the linked process
send(linked_pid, :ready)
end
defp try_upload(image, retry_count) when retry_count < 100 do
try do
Uploader.persist_upload(image)
repair_image(image)
rescue
e ->
Logger.error("Upload failed: #{inspect(e)} [try ##{retry_count}]")
Process.sleep(5000)
try_upload(image, retry_count + 1)
end
end
defp try_upload(image, retry_count) do
Logger.error("Aborting upload of #{image.id} after #{retry_count} retries")
end
defp maybe_create_subscription_on_upload(multi, %User{watch_on_upload: true} = user) do
multi
|> Multi.run(:subscribe, fn _repo, %{image: image} ->
create_subscription(image, user)
end)
end
defp maybe_create_subscription_on_upload(multi, _user) do
multi
end
2022-03-24 17:31:57 +01:00
def approve_image(image) do
image
|> Repo.preload(:user)
|> Image.approve_changeset()
|> Repo.update()
|> case do
{:ok, image} ->
reindex_image(image)
increment_user_stats(image.user)
maybe_suggest_user_verification(image.user)
{:ok, image}
error ->
error
end
end
2022-03-24 18:36:49 +01:00
defp maybe_approve_image(_image, nil), do: false
2022-03-24 17:31:57 +01:00
2022-03-24 18:36:49 +01:00
defp maybe_approve_image(_image, %User{verified: false, role: role}) when role == "user",
2022-03-24 17:31:57 +01:00
do: false
defp maybe_approve_image(image, _user), do: approve_image(image)
defp increment_user_stats(nil), do: false
defp increment_user_stats(%User{} = user) do
UserStatistics.inc_stat(user, :uploads)
end
defp maybe_suggest_user_verification(%User{id: id, uploads_count: 5, verified: false}) do
Reports.create_system_report(
id,
"User",
"Verification",
"User has uploaded enough approved images to be considered for verification."
)
end
defp maybe_suggest_user_verification(_user), do: false
def count_pending_approvals(user) do
if Canada.Can.can?(user, :approve, %Image{}) do
Image
|> where(hidden_from_users: false)
|> where(approved: false)
|> Repo.aggregate(:count)
else
nil
end
2022-03-24 17:31:57 +01:00
end
2019-12-16 06:25:06 +01:00
def feature_image(featurer, %Image{} = image) do
%ImageFeature{user_id: featurer.id, image_id: image.id}
|> ImageFeature.changeset(%{})
|> Repo.insert()
2019-12-16 06:25:06 +01:00
end
def destroy_image(%Image{} = image) do
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
image
|> Image.remove_image_changeset()
|> Repo.update()
|> case do
{:ok, image} ->
2020-12-16 16:53:26 +01:00
purge_files(image, image.hidden_image_key)
2022-02-09 01:08:53 +01:00
Thumbnailer.destroy_thumbnails(image)
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
{:ok, image}
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
error ->
error
end
end
2019-12-16 06:25:06 +01:00
def lock_comments(%Image{} = image, locked) do
image
|> Image.lock_comments_changeset(locked)
|> Repo.update()
end
def lock_description(%Image{} = image, locked) do
image
|> Image.lock_description_changeset(locked)
|> Repo.update()
end
def lock_tags(%Image{} = image, locked) do
image
|> Image.lock_tags_changeset(locked)
|> Repo.update()
end
def remove_hash(%Image{} = image) do
image
|> Image.remove_hash_changeset()
|> Repo.update()
end
def update_scratchpad(%Image{} = image, attrs) do
image
|> Image.scratchpad_changeset(attrs)
|> Repo.update()
end
def remove_source_history(%Image{} = image) do
image
|> Repo.preload(:source_changes)
|> Image.remove_source_history_changeset()
|> Repo.update()
end
def repair_image(%Image{} = image) do
Image
|> where(id: ^image.id)
|> Repo.update_all(set: [thumbnails_generated: false, processed: false])
Exq.enqueue(Exq, queue(image.image_mime_type), ThumbnailWorker, [image.id])
2019-12-16 06:25:06 +01:00
end
defp queue("video/webm"), do: "videos"
defp queue(_mime_type), do: "images"
2019-12-16 06:25:06 +01:00
def update_file(%Image{} = image, attrs) do
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
image
|> Image.changeset(attrs)
|> Uploader.analyze_upload(attrs)
|> Repo.update()
|> case do
{:ok, image} ->
Uploader.persist_upload(image)
2019-12-16 06:25:06 +01:00
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
repair_image(image)
2020-12-16 16:53:26 +01:00
purge_files(image, image.hidden_image_key)
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
reindex_image(image)
2019-12-16 06:25:06 +01:00
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
{:ok, image}
error ->
error
end
2019-12-16 06:25:06 +01:00
end
2019-08-18 18:17:05 +02:00
@doc """
Updates a image.
## Examples
iex> update_image(image, %{field: new_value})
{:ok, %Image{}}
iex> update_image(image, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_image(%Image{} = image, attrs) do
image
|> Image.changeset(attrs)
|> Repo.update()
end
2019-11-29 06:39:15 +01:00
def update_description(%Image{} = image, attrs) do
image
|> Image.description_changeset(attrs)
|> Repo.update()
end
2021-10-09 03:33:16 +02:00
def update_sources(%Image{} = image, attribution, attrs) do
old_sources = attrs["old_sources"]
new_sources = attrs["sources"]
2019-11-24 19:36:21 +01:00
2020-01-11 05:20:19 +01:00
Multi.new()
|> Multi.run(:image, fn repo, _chg ->
image = repo.preload(image, [:sources])
image
|> Image.source_changeset(%{}, old_sources, new_sources)
|> repo.update()
|> case do
2021-11-13 18:53:35 +01:00
{:ok, image} ->
{:ok, {image, image.added_sources, image.removed_sources}}
2021-11-13 18:53:35 +01:00
error ->
error
end
end)
2021-10-09 03:33:16 +02:00
|> Multi.run(:added_source_changes, fn repo, %{image: {image, added_sources, _removed}} ->
source_changes =
added_sources
|> Enum.map(&source_change_attributes(attribution, image, &1, true, attribution[:user]))
{count, nil} = repo.insert_all(SourceChange, source_changes)
{:ok, count}
end)
|> Multi.run(:removed_source_changes, fn repo, %{image: {image, _added, removed_sources}} ->
source_changes =
removed_sources
|> Enum.map(&source_change_attributes(attribution, image, &1, false, attribution[:user]))
{count, nil} = repo.insert_all(SourceChange, source_changes)
{:ok, count}
end)
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
|> Repo.transaction()
2019-11-24 19:36:21 +01:00
end
2021-10-09 03:33:16 +02:00
defp source_change_attributes(attribution, image, source, added, user) do
now = DateTime.utc_now() |> DateTime.truncate(:second)
user_id =
case user do
nil -> nil
user -> user.id
end
%{
image_id: image.id,
source_url: source,
2021-10-09 03:33:16 +02:00
user_id: user_id,
created_at: now,
updated_at: now,
ip: attribution[:ip],
fingerprint: attribution[:fingerprint],
user_agent: attribution[:user_agent],
referrer: attribution[:referrer],
added: added
}
end
2021-03-01 18:01:27 +01:00
def update_locked_tags(%Image{} = image, attrs) do
new_tags = Tags.get_or_create_tags(attrs["tag_input"])
image
|> Repo.preload(:locked_tags)
|> Image.locked_tags_changeset(attrs, new_tags)
|> Repo.update()
end
2019-11-24 19:36:21 +01:00
def update_tags(%Image{} = image, attribution, attrs) do
old_tags = Tags.get_or_create_tags(attrs["old_tag_input"])
new_tags = Tags.get_or_create_tags(attrs["tag_input"])
2020-01-11 05:20:19 +01:00
Multi.new()
2019-11-24 19:36:21 +01:00
|> Multi.run(:image, fn repo, _chg ->
2021-03-01 18:01:27 +01:00
image = repo.preload(image, [:tags, :locked_tags])
2019-11-24 19:36:21 +01:00
image
2021-03-01 18:01:27 +01:00
|> Image.tag_changeset(%{}, old_tags, new_tags, image.locked_tags)
2019-11-24 19:36:21 +01:00
|> repo.update()
|> case do
{:ok, image} ->
{:ok, {image, image.added_tags, image.removed_tags}}
error ->
error
end
end)
|> Multi.run(:added_tag_changes, fn repo, %{image: {image, added_tags, _removed}} ->
tag_changes =
added_tags
|> Enum.map(&tag_change_attributes(attribution, image, &1, true, attribution[:user]))
2020-01-11 05:20:19 +01:00
2019-11-24 19:36:21 +01:00
{count, nil} = repo.insert_all(TagChange, tag_changes)
{:ok, count}
end)
|> Multi.run(:removed_tag_changes, fn repo, %{image: {image, _added, removed_tags}} ->
tag_changes =
removed_tags
|> Enum.map(&tag_change_attributes(attribution, image, &1, false, attribution[:user]))
{count, nil} = repo.insert_all(TagChange, tag_changes)
{:ok, count}
end)
|> Multi.run(:added_tag_count, fn
_repo, %{image: {%{hidden_from_users: true}, _added, _removed}} ->
{:ok, 0}
repo, %{image: {_image, added_tags, _removed}} ->
tag_ids = added_tags |> Enum.map(& &1.id)
tags = Tag |> where([t], t.id in ^tag_ids)
{count, nil} = repo.update_all(tags, inc: [images_count: 1])
{:ok, count}
end)
|> Multi.run(:removed_tag_count, fn
_repo, %{image: {%{hidden_from_users: true}, _added, _removed}} ->
{:ok, 0}
repo, %{image: {_image, _added, removed_tags}} ->
tag_ids = removed_tags |> Enum.map(& &1.id)
tags = Tag |> where([t], t.id in ^tag_ids)
{count, nil} = repo.update_all(tags, inc: [images_count: -1])
{:ok, count}
end)
Squashed commit of the following: commit 8ea9cff4af46e24c38020652cedeff72957354fb Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:29:24 2020 -0400 remove remaining serializable aside hiding related commit 99ccf06264db6319ece2a896a104031447447a5f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:20:40 2020 -0400 interactions: remove serializable commit a63bef06a6962368f69cf83afbc3c44f2467618c Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:16:27 2020 -0400 users: remove serializable commit 8053229f6fab507c29a40f0e22dd9cab7971e34f Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:11:14 2020 -0400 user_links: remove serializable commit 9b058add825b0a876a91a1cf2b1b22dc34066e42 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:09:33 2020 -0400 topics: remove serializable commit cd9ea908c34f72c0120fca1c4d581540db60db98 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:05:23 2020 -0400 tags: remove serializable commit c7563fef8fc905c32a0727a4b104222227a6bafa Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:02:22 2020 -0400 static_pages: remove serializable commit 3da661bdd1aec74e4ac5b69ec21124bc1ebc6fb4 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 01:00:15 2020 -0400 posts: remove serializable commit 18a50a4e5bed1ab6e4e6c13c3051a21ae7e8fbb0 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:55:55 2020 -0400 poll_votes: remove serializable commit 7d946ef23d7b27877d4bf0fb6a4db4ae64a9ffab Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:51:49 2020 -0400 galleries: remove serializable commit d8c35a0934e5394b092b050e071abdada4bdb640 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:42:43 2020 -0400 conversations: remove serializable commit 079e6dca6c8064867f2c0f90f351ea83c0f12b75 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:38:28 2020 -0400 comments: remove serializable commit 00ae38bad566fb6badeccceac2e394e65ec9428e Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:37:15 2020 -0400 commissions: remove serializable commit b3c4a4b13671ca73c58080b090dd6165552c87d6 Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:17:12 2020 -0400 bans: remove serializable commit 8be9fe913ff1f6264b899e96ee38fa52032b8bda Author: byte[] <byteslice@airmail.cc> Date: Sun Sep 6 00:02:44 2020 -0400 badges: remove serializable commit 162adda185f705b9749774c4af8c7d8db0d89790 Author: byte[] <byteslice@airmail.cc> Date: Sat Sep 5 23:56:51 2020 -0400 adverts: remove serializable
2020-09-06 07:30:53 +02:00
|> Repo.transaction()
2019-11-24 19:36:21 +01:00
end
defp tag_change_attributes(attribution, image, tag, added, user) do
now = DateTime.utc_now() |> DateTime.truncate(:second)
2020-01-11 05:20:19 +01:00
2019-11-24 19:36:21 +01:00
user_id =
case user do
2020-01-11 05:20:19 +01:00
nil -> nil
2019-11-24 19:36:21 +01:00
user -> user.id
end
%{
image_id: image.id,
tag_id: tag.id,
user_id: user_id,
created_at: now,
updated_at: now,
2019-11-24 19:36:21 +01:00
tag_name_cache: tag.name,
ip: attribution[:ip],
fingerprint: attribution[:fingerprint],
user_agent: attribution[:user_agent],
referrer: attribution[:referrer],
added: added
}
end
2019-12-17 19:53:41 +01:00
def update_uploader(%Image{} = image, attrs) do
image
|> Image.uploader_changeset(attrs)
|> Repo.update()
end
def update_anonymous(%Image{} = image, attrs) do
image
|> Image.anonymous_changeset(attrs)
|> Repo.update()
end
2020-02-01 00:50:50 +01:00
def update_hide_reason(%Image{} = image, attrs) do
image
|> Image.hide_reason_changeset(attrs)
|> Repo.update()
|> case do
{:ok, image} ->
reindex_image(image)
2019-12-08 05:53:18 +01:00
{:ok, image}
2020-01-11 05:20:19 +01:00
error ->
error
end
end
2019-12-17 18:13:05 +01:00
def hide_image(%Image{} = image, user, attrs) do
duplicate_reports =
DuplicateReport
|> where(state: "open")
|> where([d], d.image_id == ^image.id or d.duplicate_of_image_id == ^image.id)
|> update(set: [state: "rejected"])
2019-12-08 05:53:18 +01:00
image
|> Image.hide_changeset(attrs, user)
2020-09-07 20:50:34 +02:00
|> hide_image_multi(image, user, Multi.new())
|> Multi.update_all(:duplicate_reports, duplicate_reports, [])
|> Repo.transaction()
|> process_after_hide()
2019-12-08 05:53:18 +01:00
end
2020-09-07 20:50:34 +02:00
def merge_image(multi \\ nil, %Image{} = image, duplicate_of_image, user) do
multi = multi || Multi.new()
2019-12-28 05:27:37 +01:00
image
|> Image.merge_changeset(duplicate_of_image)
2020-09-07 20:50:34 +02:00
|> hide_image_multi(image, user, multi)
|> Multi.run(:first_seen_at, fn _, %{} ->
update_first_seen_at(
duplicate_of_image,
image.first_seen_at,
duplicate_of_image.first_seen_at
)
end)
|> Multi.run(:copy_tags, fn _, %{} ->
{:ok, Tags.copy_tags(image, duplicate_of_image)}
end)
|> Multi.run(:migrate_sources, fn repo, %{} ->
{:ok,
migrate_sources(
repo.preload(image, [:sources]),
repo.preload(duplicate_of_image, [:sources])
)}
end)
|> Multi.run(:migrate_comments, fn _, %{} ->
{:ok, Comments.migrate_comments(image, duplicate_of_image)}
end)
|> Multi.run(:migrate_subscriptions, fn _, %{} ->
{:ok, migrate_subscriptions(image, duplicate_of_image)}
end)
|> Multi.run(:migrate_interactions, fn _, %{} ->
{:ok, Interactions.migrate_interactions(image, duplicate_of_image)}
end)
|> Repo.transaction()
|> process_after_hide()
|> case do
{:ok, result} ->
reindex_image(duplicate_of_image)
Comments.reindex_comments(duplicate_of_image)
2020-09-10 04:47:35 +02:00
notify_merge(image, duplicate_of_image)
{:ok, result}
error ->
error
end
2019-12-25 14:48:44 +01:00
end
2020-09-07 20:50:34 +02:00
defp hide_image_multi(changeset, image, user, multi) do
reports =
Report
|> where(reportable_type: "Image", reportable_id: ^image.id)
|> select([r], r.id)
2020-09-07 20:50:34 +02:00
|> update(set: [open: false, state: "closed", admin_id: ^user.id])
galleries =
Gallery
|> join(:inner, [g], gi in assoc(g, :interactions), on: gi.image_id == ^image.id)
|> update(inc: [image_count: -1])
gallery_interactions = where(Interaction, image_id: ^image.id)
multi
2019-12-08 05:53:18 +01:00
|> Multi.update(:image, changeset)
|> Multi.update_all(:reports, reports, [])
|> Multi.update_all(:galleries, galleries, [])
|> Multi.delete_all(:gallery_interactions, gallery_interactions, [])
2019-12-08 05:53:18 +01:00
|> Multi.run(:tags, fn repo, %{image: image} ->
image = Repo.preload(image, :tags, force: true)
# I'm not convinced this is a good idea. It leads
# to way too much drift, and the index has to be
# maintained.
tag_ids = Enum.map(image.tags, & &1.id)
query = where(Tag, [t], t.id in ^tag_ids)
repo.update_all(query, inc: [images_count: -1])
{:ok, image.tags}
end)
end
2019-12-08 05:53:18 +01:00
defp process_after_hide(result) do
case result do
{:ok, %{image: image, tags: tags, reports: {_count, reports}} = result} ->
2022-07-01 18:24:51 +02:00
spawn(fn ->
Thumbnailer.hide_thumbnails(image, image.hidden_image_key)
purge_files(image, image.hidden_image_key)
end)
Comments.reindex_comments(image)
Reports.reindex_reports(reports)
Tags.reindex_tags(tags)
reindex_image(image)
reindex_copied_tags(result)
{:ok, result}
error ->
error
end
end
defp reindex_copied_tags(%{copy_tags: tags}), do: Tags.reindex_tags(tags)
defp reindex_copied_tags(_result), do: nil
defp update_first_seen_at(image, time_1, time_2) do
min_time =
case DateTime.compare(time_1, time_2) do
:gt -> time_2
_ -> time_1
end
Image
|> where(id: ^image.id)
|> Repo.update_all(set: [first_seen_at: min_time])
{:ok, image}
2019-12-08 05:53:18 +01:00
end
2019-12-09 05:41:35 +01:00
def unhide_image(%Image{hidden_from_users: true} = image) do
2019-12-08 05:53:18 +01:00
key = image.hidden_image_key
2020-01-11 05:20:19 +01:00
Multi.new()
2019-12-08 05:53:18 +01:00
|> Multi.update(:image, Image.unhide_changeset(image))
|> Multi.run(:tags, fn repo, %{image: image} ->
image = Repo.preload(image, :tags, force: true)
tag_ids = Enum.map(image.tags, & &1.id)
query = where(Tag, [t], t.id in ^tag_ids)
repo.update_all(query, inc: [images_count: 1])
{:ok, image.tags}
end)
|> Repo.transaction()
|> case do
{:ok, %{image: image, tags: tags}} ->
2022-07-01 18:24:51 +02:00
spawn(fn ->
Thumbnailer.unhide_thumbnails(image, key)
end)
2019-12-08 05:53:18 +01:00
reindex_image(image)
2020-12-16 16:53:26 +01:00
purge_files(image, image.hidden_image_key)
Comments.reindex_comments(image)
Tags.reindex_tags(tags)
{:ok, image}
error ->
error
end
2019-12-08 05:53:18 +01:00
end
2020-01-11 05:20:19 +01:00
2019-12-09 05:41:35 +01:00
def unhide_image(image), do: {:ok, image}
2019-12-08 05:53:18 +01:00
2019-12-16 23:11:16 +01:00
def batch_update(image_ids, added_tags, removed_tags, tag_change_attributes) do
image_ids =
Image
|> where([i], i.id in ^image_ids and i.hidden_from_users == false)
|> select([i], i.id)
|> Repo.all()
2019-12-16 23:11:16 +01:00
added_tags = Enum.map(added_tags, & &1.id)
removed_tags = Enum.map(removed_tags, & &1.id)
# Change everything in one go, ignoring any validation errors
# Note: computing the Cartesian product
insertions =
for tag_id <- added_tags, image_id <- image_ids do
%{tag_id: tag_id, image_id: image_id}
end
deletions =
Tagging
|> where([t], t.image_id in ^image_ids and t.tag_id in ^removed_tags)
|> select([t], [t.image_id, t.tag_id])
now = DateTime.utc_now() |> DateTime.truncate(:second)
2019-12-16 23:11:16 +01:00
tag_change_attributes = Map.merge(tag_change_attributes, %{created_at: now, updated_at: now})
tag_attributes = %{name: "", slug: "", created_at: now, updated_at: now}
2019-12-16 23:11:16 +01:00
2020-01-11 05:20:19 +01:00
Repo.transaction(fn ->
{_count, inserted} =
2020-01-11 05:20:19 +01:00
Repo.insert_all(Tagging, insertions,
on_conflict: :nothing,
returning: [:image_id, :tag_id]
)
{_count, deleted} = Repo.delete_all(deletions)
2019-12-16 23:11:16 +01:00
inserted = Enum.map(inserted, &[&1.image_id, &1.tag_id])
2020-01-11 05:20:19 +01:00
added_changes =
Enum.map(inserted, fn [image_id, tag_id] ->
Map.merge(tag_change_attributes, %{image_id: image_id, tag_id: tag_id, added: true})
end)
2019-12-16 23:11:16 +01:00
2020-01-11 05:20:19 +01:00
removed_changes =
Enum.map(deleted, fn [image_id, tag_id] ->
Map.merge(tag_change_attributes, %{image_id: image_id, tag_id: tag_id, added: false})
end)
2019-12-16 23:11:16 +01:00
changes = added_changes ++ removed_changes
Repo.insert_all(TagChange, changes)
# In order to merge into the existing tables here in one go, insert_all
# is used with a query that is guaranteed to conflict on every row by
# using the primary key.
added_upserts =
inserted
|> Enum.group_by(fn [_image_id, tag_id] -> tag_id end)
|> Enum.map(fn {tag_id, instances} ->
Map.merge(tag_attributes, %{id: tag_id, images_count: length(instances)})
end)
removed_upserts =
deleted
|> Enum.group_by(fn [_image_id, tag_id] -> tag_id end)
|> Enum.map(fn {tag_id, instances} ->
Map.merge(tag_attributes, %{id: tag_id, images_count: -length(instances)})
end)
update_query = update(Tag, inc: [images_count: fragment("EXCLUDED.images_count")])
upserts = added_upserts ++ removed_upserts
Repo.insert_all(Tag, upserts, on_conflict: update_query, conflict_target: [:id])
2020-01-11 05:20:19 +01:00
end)
|> case do
{:ok, _} = result ->
reindex_images(image_ids)
Tags.reindex_tags(Enum.map(added_tags ++ removed_tags, &%{id: &1}))
result
result ->
result
end
2019-12-16 23:11:16 +01:00
end
2019-08-18 18:17:05 +02:00
@doc """
Deletes a Image.
## Examples
iex> delete_image(image)
{:ok, %Image{}}
iex> delete_image(image)
{:error, %Ecto.Changeset{}}
"""
def delete_image(%Image{} = image) do
Repo.delete(image)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking image changes.
## Examples
iex> change_image(image)
%Ecto.Changeset{source: %Image{}}
"""
def change_image(%Image{} = image) do
Image.changeset(image, %{})
end
def user_name_reindex(old_name, new_name) do
data = ImageIndex.user_name_update_by_query(old_name, new_name)
Search.update_by_query(Image, data.query, data.set_replacements, data.replacements)
end
2019-11-17 03:20:33 +01:00
def reindex_image(%Image{} = image) do
2020-12-06 17:42:14 +01:00
Exq.enqueue(Exq, "indexing", IndexWorker, ["Images", "id", [image.id]])
2019-12-05 05:12:49 +01:00
image
end
def reindex_images(image_ids) do
2020-12-06 17:42:14 +01:00
Exq.enqueue(Exq, "indexing", IndexWorker, ["Images", "id", image_ids])
2019-11-17 03:20:33 +01:00
2019-12-05 05:12:49 +01:00
image_ids
2019-11-17 03:20:33 +01:00
end
def indexing_preloads do
2020-01-11 05:20:19 +01:00
[
:user,
:favers,
:downvoters,
:upvoters,
:hiders,
:deleter,
:gallery_interactions,
2021-10-09 03:33:16 +02:00
:sources,
2020-01-11 05:20:19 +01:00
tags: [:aliases, :aliased_tag]
]
2019-11-17 03:20:33 +01:00
end
2020-12-06 17:42:14 +01:00
def perform_reindex(column, condition) do
Image
|> preload(^indexing_preloads())
|> where([i], field(i, ^column) in ^condition)
|> Search.reindex(Image)
2020-12-06 17:42:14 +01:00
end
2020-12-16 16:53:26 +01:00
def purge_files(image, hidden_key) do
files =
if is_nil(hidden_key) do
Thumbnailer.thumbnail_urls(image, nil)
else
Thumbnailer.thumbnail_urls(image, hidden_key) ++
Thumbnailer.thumbnail_urls(image, nil)
end
Exq.enqueue(Exq, "indexing", ImagePurgeWorker, [files])
end
def perform_purge(files) do
2022-02-09 01:08:53 +01:00
{_out, 0} = System.cmd("purge-cache", [Jason.encode!(%{files: files})])
:ok
2020-12-16 16:53:26 +01:00
end
alias Philomena.Images.Subscription
2019-11-17 19:18:21 +01:00
def subscribed?(_image, nil), do: false
2020-01-11 05:20:19 +01:00
2019-11-17 18:50:42 +01:00
def subscribed?(image, user) do
Subscription
|> where(image_id: ^image.id, user_id: ^user.id)
|> Repo.exists?()
end
@doc """
Creates a subscription.
## Examples
iex> create_subscription(%{field: value})
{:ok, %Subscription{}}
iex> create_subscription(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
2019-11-18 05:47:09 +01:00
def create_subscription(_image, nil), do: {:ok, nil}
2020-01-11 05:20:19 +01:00
2019-11-17 18:50:42 +01:00
def create_subscription(image, user) do
%Subscription{image_id: image.id, user_id: user.id}
|> Subscription.changeset(%{})
|> Repo.insert(on_conflict: :nothing)
end
@doc """
Deletes a subscription.
## Examples
iex> delete_subscription(subscription)
{:ok, %Subscription{}}
iex> delete_subscription(subscription)
{:error, %Ecto.Changeset{}}
"""
2019-11-17 18:50:42 +01:00
def delete_subscription(image, user) do
clear_notification(image, user)
2019-11-17 18:50:42 +01:00
%Subscription{image_id: image.id, user_id: user.id}
|> Repo.delete()
end
def migrate_subscriptions(source, target) do
subscriptions =
Subscription
|> where(image_id: ^source.id)
|> select([s], %{image_id: type(^target.id, :integer), user_id: s.user_id})
|> Repo.all()
Repo.insert_all(Subscription, subscriptions, on_conflict: :nothing)
{count, nil} =
Notification
|> where(actor_type: "Image", actor_id: ^source.id)
|> Repo.delete_all()
{:ok, count}
end
def migrate_sources(source, target) do
sources =
(source.sources ++ target.sources)
2023-05-29 14:20:57 +02:00
|> Enum.map(fn s -> %Source{image_id: target.id, source: s.source} end)
|> Enum.uniq()
|> Enum.take(10)
target
|> Image.sources_changeset(sources)
|> Repo.update()
end
2020-09-10 04:47:35 +02:00
def notify_merge(source, target) do
2020-12-06 17:42:14 +01:00
Exq.enqueue(Exq, "notifications", NotificationWorker, ["Images", [source.id, target.id]])
end
def perform_notify([source_id, target_id]) do
target = get_image!(target_id)
subscriptions =
target
|> Repo.preload(:subscriptions)
|> Map.fetch!(:subscriptions)
Notifications.notify(
nil,
subscriptions,
%{
actor_id: target.id,
actor_type: "Image",
actor_child_id: nil,
actor_child_type: nil,
action: "merged ##{source_id} into"
}
)
2020-09-10 04:47:35 +02:00
end
2019-12-01 06:03:45 +01:00
def clear_notification(_image, nil), do: nil
2020-01-11 05:20:19 +01:00
def clear_notification(image, user) do
Notifications.delete_unread_notification("Image", image.id, user)
end
2019-08-18 18:17:05 +02:00
end