mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-01-31 19:36:44 +01:00
api changes
This commit is contained in:
parent
d73c2b7131
commit
12fb45170c
11 changed files with 187 additions and 61 deletions
12
lib/philomena_web/controllers/api/json/image_controller.ex
Normal file
12
lib/philomena_web/controllers/api/json/image_controller.ex
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
defmodule PhilomenaWeb.Api.Json.ImageController do
|
||||||
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
|
alias PhilomenaWeb.ImageJson
|
||||||
|
alias Philomena.Images.Image
|
||||||
|
|
||||||
|
plug :load_and_authorize_resource, model: Image, only: [:show], preload: [:tags, :user]
|
||||||
|
|
||||||
|
def show(conn, _params) do
|
||||||
|
json(conn, %{image: ImageJson.as_json(conn, conn.assigns.image)})
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,24 @@
|
||||||
|
defmodule PhilomenaWeb.Api.Json.Search.ReverseController do
|
||||||
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
|
alias PhilomenaWeb.ImageReverse
|
||||||
|
|
||||||
|
plug :set_scraper_cache
|
||||||
|
plug PhilomenaWeb.ScraperPlug, [params_key: "image", params_name: "image"]
|
||||||
|
|
||||||
|
def create(conn, %{"image" => image_params}) do
|
||||||
|
images = ImageReverse.images(image_params)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> json(%{images: images})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp set_scraper_cache(conn, _opts) do
|
||||||
|
params =
|
||||||
|
conn.params
|
||||||
|
|> Map.put("image", %{})
|
||||||
|
|> Map.put("scraper_cache", conn.params["url"])
|
||||||
|
|
||||||
|
%{conn | params: params}
|
||||||
|
end
|
||||||
|
end
|
33
lib/philomena_web/controllers/api/json/search_controller.ex
Normal file
33
lib/philomena_web/controllers/api/json/search_controller.ex
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule PhilomenaWeb.Api.Json.SearchController do
|
||||||
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
|
alias PhilomenaWeb.ImageLoader
|
||||||
|
alias PhilomenaWeb.ImageJson
|
||||||
|
alias Philomena.ImageSorter
|
||||||
|
alias Philomena.Interactions
|
||||||
|
alias Philomena.Images.Image
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
def index(conn, params) do
|
||||||
|
queryable = Image |> preload([:tags, :user])
|
||||||
|
user = conn.assigns.current_user
|
||||||
|
sort = ImageSorter.parse_sort(params)
|
||||||
|
|
||||||
|
case ImageLoader.search_string(conn, params["q"], sorts: sort.sorts, queries: sort.queries, queryable: queryable) do
|
||||||
|
{:ok, images} ->
|
||||||
|
interactions =
|
||||||
|
Interactions.user_interactions(images, user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> json(%{
|
||||||
|
images: Enum.map(images, &ImageJson.as_json(conn, &1)),
|
||||||
|
interactions: interactions
|
||||||
|
})
|
||||||
|
|
||||||
|
{:error, msg} ->
|
||||||
|
conn
|
||||||
|
|> Plug.Conn.put_status(:bad_request)
|
||||||
|
|> json(%{error: msg})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule PhilomenaWeb.Api.WatchedController do
|
defmodule PhilomenaWeb.Api.Rss.WatchedController do
|
||||||
use PhilomenaWeb, :controller
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
alias Philomena.Images.{Image, Query}
|
alias Philomena.Images.{Image, Query}
|
|
@ -1,10 +1,7 @@
|
||||||
defmodule PhilomenaWeb.Search.ReverseController do
|
defmodule PhilomenaWeb.Search.ReverseController do
|
||||||
use PhilomenaWeb, :controller
|
use PhilomenaWeb, :controller
|
||||||
|
|
||||||
alias Philomena.Processors
|
alias PhilomenaWeb.ImageReverse
|
||||||
alias Philomena.DuplicateReports
|
|
||||||
alias Philomena.Repo
|
|
||||||
import Ecto.Query
|
|
||||||
|
|
||||||
plug PhilomenaWeb.ScraperPlug, [params_key: "image", params_name: "image"] when action in [:create]
|
plug PhilomenaWeb.ScraperPlug, [params_key: "image", params_name: "image"] when action in [:create]
|
||||||
|
|
||||||
|
@ -13,53 +10,9 @@ defmodule PhilomenaWeb.Search.ReverseController do
|
||||||
end
|
end
|
||||||
|
|
||||||
def create(conn, %{"image" => image_params}) do
|
def create(conn, %{"image" => image_params}) do
|
||||||
images =
|
images = ImageReverse.images(image_params)
|
||||||
image_params["image"].path
|
|
||||||
|> mime()
|
|
||||||
|> analyze()
|
|
||||||
|> intensities()
|
|
||||||
|> case do
|
|
||||||
:error ->
|
|
||||||
[]
|
|
||||||
|
|
||||||
{analysis, intensities} ->
|
|
||||||
{width, height} = analysis.dimensions
|
|
||||||
aspect = width / height
|
|
||||||
dist = normalize_dist(image_params)
|
|
||||||
|
|
||||||
DuplicateReports.duplicates_of(intensities, aspect, dist, dist)
|
|
||||||
|> preload(:tags)
|
|
||||||
|> Repo.all()
|
|
||||||
end
|
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> render("index.html", images: images)
|
|> render("index.html", images: images)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp mime(file) do
|
|
||||||
{:ok, mime} = Philomena.Mime.file(file)
|
|
||||||
|
|
||||||
{mime, file}
|
|
||||||
end
|
|
||||||
|
|
||||||
defp analyze({mime, file}) do
|
|
||||||
case Processors.analyzers(mime) do
|
|
||||||
nil -> :error
|
|
||||||
a -> {a.analyze(file), mime, file}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp intensities(:error), do: :error
|
|
||||||
defp intensities({analysis, mime, file}) do
|
|
||||||
{analysis, Processors.processors(mime).intensities(analysis, file)}
|
|
||||||
end
|
|
||||||
|
|
||||||
# The distance metric is taxicab distance, not Euclidean,
|
|
||||||
# because this is more efficient to index.
|
|
||||||
defp normalize_dist(%{"distance" => distance}) do
|
|
||||||
distance
|
|
||||||
|> String.to_float()
|
|
||||||
|> max(0.01)
|
|
||||||
|> min(1.0)
|
|
||||||
end
|
|
||||||
end
|
end
|
38
lib/philomena_web/image_json.ex
Normal file
38
lib/philomena_web/image_json.ex
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
defmodule PhilomenaWeb.ImageJson do
|
||||||
|
alias PhilomenaWeb.ImageView
|
||||||
|
|
||||||
|
def as_json(conn, image) do
|
||||||
|
%{
|
||||||
|
id: image.id,
|
||||||
|
created_at: image.created_at,
|
||||||
|
updated_at: image.updated_at,
|
||||||
|
first_seen_at: image.first_seen_at,
|
||||||
|
width: image.image_width,
|
||||||
|
height: image.image_height,
|
||||||
|
mime_type: image.image_mime_type,
|
||||||
|
format: image.image_format,
|
||||||
|
aspect_ratio: image.image_aspect_ratio,
|
||||||
|
name: image.image_name,
|
||||||
|
sha512_hash: image.image_sha512_hash,
|
||||||
|
orig_sha512_hash: image.image_orig_sha512_hash,
|
||||||
|
tags: Enum.map(image.tags, & &1.name),
|
||||||
|
tag_ids: Enum.map(image.tags, & &1.id),
|
||||||
|
uploader: if(!!image.user and !image.anonymous, do: image.user.name),
|
||||||
|
uploader_id: if(!!image.user and !image.anonymous, do: image.user.id),
|
||||||
|
wilson_score: Philomena.Images.Elasticsearch.wilson_score(image),
|
||||||
|
score: image.score,
|
||||||
|
upvotes: image.upvotes_count,
|
||||||
|
downvotes: image.downvotes_count,
|
||||||
|
faves: image.faves_count,
|
||||||
|
comment_count: image.comments_count,
|
||||||
|
tag_count: length(image.tags),
|
||||||
|
description: image.description,
|
||||||
|
source_url: image.source_url,
|
||||||
|
view_url: ImageView.pretty_url(image, false, false),
|
||||||
|
representations: ImageView.thumb_urls(image, false),
|
||||||
|
spoilered: ImageView.filter_or_spoiler_hits?(conn, image),
|
||||||
|
thumbnails_generated: image.thumbnails_generated,
|
||||||
|
processed: image.processed
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -17,6 +17,7 @@ defmodule PhilomenaWeb.ImageLoader do
|
||||||
sort_queries = Keyword.get(options, :queries, [])
|
sort_queries = Keyword.get(options, :queries, [])
|
||||||
sort_sorts = Keyword.get(options, :sorts, [%{created_at: :desc}])
|
sort_sorts = Keyword.get(options, :sorts, [%{created_at: :desc}])
|
||||||
pagination = Keyword.get(options, :pagination, conn.assigns.image_pagination)
|
pagination = Keyword.get(options, :pagination, conn.assigns.image_pagination)
|
||||||
|
queryable = Keyword.get(options, :queryable, Image |> preload(:tags))
|
||||||
|
|
||||||
user = conn.assigns.current_user
|
user = conn.assigns.current_user
|
||||||
filter = conn.assigns.compiled_filter
|
filter = conn.assigns.compiled_filter
|
||||||
|
@ -33,7 +34,7 @@ defmodule PhilomenaWeb.ImageLoader do
|
||||||
sort: sort_sorts
|
sort: sort_sorts
|
||||||
},
|
},
|
||||||
pagination,
|
pagination,
|
||||||
Image |> preload(:tags)
|
queryable
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
56
lib/philomena_web/image_reverse.ex
Normal file
56
lib/philomena_web/image_reverse.ex
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
defmodule PhilomenaWeb.ImageReverse do
|
||||||
|
alias Philomena.Processors
|
||||||
|
alias Philomena.DuplicateReports
|
||||||
|
alias Philomena.Repo
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
def images(image_params) do
|
||||||
|
image_params
|
||||||
|
|> Map.get("image")
|
||||||
|
|> Map.get(:path)
|
||||||
|
|> mime()
|
||||||
|
|> analyze()
|
||||||
|
|> intensities()
|
||||||
|
|> case do
|
||||||
|
:error ->
|
||||||
|
[]
|
||||||
|
|
||||||
|
{analysis, intensities} ->
|
||||||
|
{width, height} = analysis.dimensions
|
||||||
|
aspect = width / height
|
||||||
|
dist = normalize_dist(image_params)
|
||||||
|
|
||||||
|
DuplicateReports.duplicates_of(intensities, aspect, dist, dist)
|
||||||
|
|> preload([:tags, :user])
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp mime(file) do
|
||||||
|
{:ok, mime} = Philomena.Mime.file(file)
|
||||||
|
|
||||||
|
{mime, file}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp analyze({mime, file}) do
|
||||||
|
case Processors.analyzers(mime) do
|
||||||
|
nil -> :error
|
||||||
|
a -> {a.analyze(file), mime, file}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp intensities(:error), do: :error
|
||||||
|
defp intensities({analysis, mime, file}) do
|
||||||
|
{analysis, Processors.processors(mime).intensities(analysis, file)}
|
||||||
|
end
|
||||||
|
|
||||||
|
# The distance metric is taxicab distance, not Euclidean,
|
||||||
|
# because this is more efficient to index.
|
||||||
|
defp normalize_dist(%{"distance" => distance}) do
|
||||||
|
distance
|
||||||
|
|> String.to_float()
|
||||||
|
|> max(0.01)
|
||||||
|
|> min(1.0)
|
||||||
|
end
|
||||||
|
defp normalize_dist(_dist), do: 0.25
|
||||||
|
end
|
|
@ -21,19 +21,19 @@ defmodule PhilomenaWeb.Router do
|
||||||
plug PhilomenaWeb.ChannelPlug
|
plug PhilomenaWeb.ChannelPlug
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :rss do
|
pipeline :api do
|
||||||
plug :accepts, ["rss"]
|
|
||||||
|
|
||||||
plug PhilomenaWeb.ApiTokenPlug
|
plug PhilomenaWeb.ApiTokenPlug
|
||||||
plug Pow.Plug.RequireAuthenticated,
|
|
||||||
error_handler: Pow.Phoenix.PlugErrorHandler
|
|
||||||
plug PhilomenaWeb.EnsureUserEnabledPlug
|
plug PhilomenaWeb.EnsureUserEnabledPlug
|
||||||
plug PhilomenaWeb.CurrentFilterPlug
|
plug PhilomenaWeb.CurrentFilterPlug
|
||||||
plug PhilomenaWeb.ImageFilterPlug
|
plug PhilomenaWeb.ImageFilterPlug
|
||||||
plug PhilomenaWeb.PaginationPlug
|
plug PhilomenaWeb.PaginationPlug
|
||||||
end
|
end
|
||||||
|
|
||||||
pipeline :api do
|
pipeline :accepts_rss do
|
||||||
|
plug :accepts, ["rss"]
|
||||||
|
end
|
||||||
|
|
||||||
|
pipeline :accepts_json do
|
||||||
plug :accepts, ["json"]
|
plug :accepts, ["json"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -66,12 +66,21 @@ defmodule PhilomenaWeb.Router do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/rss", PhilomenaWeb.Api, as: :api_rss do
|
scope "/api/v1/rss", PhilomenaWeb.Api.Rss, as: :api_rss do
|
||||||
pipe_through :rss
|
pipe_through [:accepts_rss, :protected, :api]
|
||||||
|
|
||||||
resources "/watched", WatchedController, only: [:index]
|
resources "/watched", WatchedController, only: [:index]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scope "/api/v1/json", PhilomenaWeb.Api.Json, as: :api_json do
|
||||||
|
pipe_through [:accepts_json, :api]
|
||||||
|
resources "/images", ImageController, only: [:show]
|
||||||
|
|
||||||
|
scope "/search", Search, as: :search do
|
||||||
|
resources "/reverse", ReverseController, only: [:create]
|
||||||
|
end
|
||||||
|
resources "/search", SearchController, only: [:index]
|
||||||
|
end
|
||||||
|
|
||||||
scope "/", PhilomenaWeb do
|
scope "/", PhilomenaWeb do
|
||||||
pipe_through [:browser, :ensure_totp, :protected]
|
pipe_through [:browser, :ensure_totp, :protected]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule PhilomenaWeb.Api.WatchedView do
|
defmodule PhilomenaWeb.Api.Rss.WatchedView do
|
||||||
use PhilomenaWeb, :view
|
use PhilomenaWeb, :view
|
||||||
|
|
||||||
alias PhilomenaWeb.ImageView
|
alias PhilomenaWeb.ImageView
|
Loading…
Reference in a new issue