api changes

This commit is contained in:
byte[] 2019-12-03 19:50:23 -05:00
parent d73c2b7131
commit 12fb45170c
11 changed files with 187 additions and 61 deletions

View 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

View file

@ -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

View 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

View file

@ -1,4 +1,4 @@
defmodule PhilomenaWeb.Api.WatchedController do
defmodule PhilomenaWeb.Api.Rss.WatchedController do
use PhilomenaWeb, :controller
alias Philomena.Images.{Image, Query}

View file

@ -1,10 +1,7 @@
defmodule PhilomenaWeb.Search.ReverseController do
use PhilomenaWeb, :controller
alias Philomena.Processors
alias Philomena.DuplicateReports
alias Philomena.Repo
import Ecto.Query
alias PhilomenaWeb.ImageReverse
plug PhilomenaWeb.ScraperPlug, [params_key: "image", params_name: "image"] when action in [:create]
@ -13,53 +10,9 @@ defmodule PhilomenaWeb.Search.ReverseController do
end
def create(conn, %{"image" => image_params}) do
images =
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
images = ImageReverse.images(image_params)
conn
|> render("index.html", images: images)
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

View 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

View file

@ -17,6 +17,7 @@ defmodule PhilomenaWeb.ImageLoader do
sort_queries = Keyword.get(options, :queries, [])
sort_sorts = Keyword.get(options, :sorts, [%{created_at: :desc}])
pagination = Keyword.get(options, :pagination, conn.assigns.image_pagination)
queryable = Keyword.get(options, :queryable, Image |> preload(:tags))
user = conn.assigns.current_user
filter = conn.assigns.compiled_filter
@ -33,7 +34,7 @@ defmodule PhilomenaWeb.ImageLoader do
sort: sort_sorts
},
pagination,
Image |> preload(:tags)
queryable
)
end

View 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

View file

@ -21,19 +21,19 @@ defmodule PhilomenaWeb.Router do
plug PhilomenaWeb.ChannelPlug
end
pipeline :rss do
plug :accepts, ["rss"]
pipeline :api do
plug PhilomenaWeb.ApiTokenPlug
plug Pow.Plug.RequireAuthenticated,
error_handler: Pow.Phoenix.PlugErrorHandler
plug PhilomenaWeb.EnsureUserEnabledPlug
plug PhilomenaWeb.CurrentFilterPlug
plug PhilomenaWeb.ImageFilterPlug
plug PhilomenaWeb.PaginationPlug
end
pipeline :api do
pipeline :accepts_rss do
plug :accepts, ["rss"]
end
pipeline :accepts_json do
plug :accepts, ["json"]
end
@ -66,12 +66,21 @@ defmodule PhilomenaWeb.Router do
end
end
scope "/api/rss", PhilomenaWeb.Api, as: :api_rss do
pipe_through :rss
scope "/api/v1/rss", PhilomenaWeb.Api.Rss, as: :api_rss do
pipe_through [:accepts_rss, :protected, :api]
resources "/watched", WatchedController, only: [:index]
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
pipe_through [:browser, :ensure_totp, :protected]

View file

@ -1,4 +1,4 @@
defmodule PhilomenaWeb.Api.WatchedView do
defmodule PhilomenaWeb.Api.Rss.WatchedView do
use PhilomenaWeb, :view
alias PhilomenaWeb.ImageView