From 15864ab742d2b7d31a9a5452e4053fdba7fa72b0 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Tue, 24 Dec 2019 03:26:01 -0500 Subject: [PATCH] api search controllers --- lib/philomena/galleries/query.ex | 27 ++++++++++++ lib/philomena_web/comment_json.ex | 13 ++++++ .../api/json/search/comment_controller.ex | 43 +++++++++++++++++++ .../api/json/search/gallery_controller.ex | 30 +++++++++++++ .../image_controller.ex} | 2 +- .../api/json/search/post_controller.ex | 40 +++++++++++++++++ .../api/json/search/tag_controller.ex | 27 ++++++++++++ .../controllers/api/json/tag_controller.ex | 36 +--------------- lib/philomena_web/gallery_json.ex | 13 ++++++ lib/philomena_web/post_json.ex | 13 ++++++ lib/philomena_web/router.ex | 10 ++++- lib/philomena_web/tag_json.ex | 34 +++++++++++++++ 12 files changed, 252 insertions(+), 36 deletions(-) create mode 100644 lib/philomena/galleries/query.ex create mode 100644 lib/philomena_web/comment_json.ex create mode 100644 lib/philomena_web/controllers/api/json/search/comment_controller.ex create mode 100644 lib/philomena_web/controllers/api/json/search/gallery_controller.ex rename lib/philomena_web/controllers/api/json/{search_controller.ex => search/image_controller.ex} (93%) create mode 100644 lib/philomena_web/controllers/api/json/search/post_controller.ex create mode 100644 lib/philomena_web/controllers/api/json/search/tag_controller.ex create mode 100644 lib/philomena_web/gallery_json.ex create mode 100644 lib/philomena_web/post_json.ex create mode 100644 lib/philomena_web/tag_json.ex diff --git a/lib/philomena/galleries/query.ex b/lib/philomena/galleries/query.ex new file mode 100644 index 00000000..c13ecefe --- /dev/null +++ b/lib/philomena/galleries/query.ex @@ -0,0 +1,27 @@ +defmodule Philomena.Galleries.Query do + alias Search.Parser + + int_fields = ~W(id image_count watcher_count) + literal_fields = ~W(title user image_ids watcher_ids) + date_fields = ~W(created_at updated_at) + ngram_fields = ~W(description) + default_field = "title" + aliases = %{ + "user" => "creator" + } + + @gallery_parser Parser.parser( + int_fields: int_fields, + literal_fields: literal_fields, + date_fields: date_fields, + ngram_fields: ngram_fields, + default_field: default_field, + aliases: aliases + ) + + def compile(query_string) do + query_string = query_string || "" + + Parser.parse(@gallery_parser, query_string) + end +end diff --git a/lib/philomena_web/comment_json.ex b/lib/philomena_web/comment_json.ex new file mode 100644 index 00000000..6aae1e99 --- /dev/null +++ b/lib/philomena_web/comment_json.ex @@ -0,0 +1,13 @@ +defmodule PhilomenaWeb.CommentJson do + alias PhilomenaWeb.UserAttributionView + + def as_json(comment) do + %{ + id: comment.id, + image_id: comment.image_id, + user_id: if(not comment.anonymous, do: comment.user_id), + author: if(comment.anonymous or is_nil(comment.user), do: UserAttributionView.anonymous_name(comment), else: comment.user.name), + body: if(not comment.image.hidden_from_users and not comment.hidden_from_users, do: comment.body) + } + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/api/json/search/comment_controller.ex b/lib/philomena_web/controllers/api/json/search/comment_controller.ex new file mode 100644 index 00000000..d8ea3033 --- /dev/null +++ b/lib/philomena_web/controllers/api/json/search/comment_controller.ex @@ -0,0 +1,43 @@ +defmodule PhilomenaWeb.Api.Json.Search.CommentController do + use PhilomenaWeb, :controller + + alias PhilomenaWeb.CommentJson + alias Philomena.Comments.Comment + alias Philomena.Comments.Query + import Ecto.Query + + def index(conn, params) do + user = conn.assigns.current_user + filter = conn.assigns.current_filter + + case Query.compile(user, params["q"] || "") do + {:ok, query} -> + comments = + Comment.search_records( + %{ + query: %{ + bool: %{ + must: [ + query, + %{term: %{hidden_from_users: false}} + ], + must_not: %{ + terms: %{image_tag_ids: filter.hidden_tag_ids} + } + } + }, + sort: %{posted_at: :desc} + }, + conn.assigns.pagination, + preload(Comment, [:image, :user]) + ) + + json(conn, %{comments: Enum.map(comments, &CommentJson.as_json/1)}) + + {:error, msg} -> + conn + |> put_status(:bad_request) + |> json(%{error: msg}) + end + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/api/json/search/gallery_controller.ex b/lib/philomena_web/controllers/api/json/search/gallery_controller.ex new file mode 100644 index 00000000..779adc96 --- /dev/null +++ b/lib/philomena_web/controllers/api/json/search/gallery_controller.ex @@ -0,0 +1,30 @@ +defmodule PhilomenaWeb.Api.Json.Search.GalleryController do + use PhilomenaWeb, :controller + + alias PhilomenaWeb.GalleryJson + alias Philomena.Galleries.Gallery + alias Philomena.Galleries.Query + import Ecto.Query + + def index(conn, params) do + case Query.compile(params["q"] || "") do + {:ok, query} -> + galleries = + Gallery.search_records( + %{ + query: query, + sort: %{created_at: :desc} + }, + conn.assigns.pagination, + preload(Gallery, [:creator]) + ) + + json(conn, %{galleries: Enum.map(galleries, &GalleryJson.as_json/1)}) + + {:error, msg} -> + conn + |> put_status(:bad_request) + |> json(%{error: msg}) + end + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/api/json/search_controller.ex b/lib/philomena_web/controllers/api/json/search/image_controller.ex similarity index 93% rename from lib/philomena_web/controllers/api/json/search_controller.ex rename to lib/philomena_web/controllers/api/json/search/image_controller.ex index 66d998c3..7d0f7d2c 100644 --- a/lib/philomena_web/controllers/api/json/search_controller.ex +++ b/lib/philomena_web/controllers/api/json/search/image_controller.ex @@ -1,4 +1,4 @@ -defmodule PhilomenaWeb.Api.Json.SearchController do +defmodule PhilomenaWeb.Api.Json.Search.ImageController do use PhilomenaWeb, :controller alias PhilomenaWeb.ImageLoader diff --git a/lib/philomena_web/controllers/api/json/search/post_controller.ex b/lib/philomena_web/controllers/api/json/search/post_controller.ex new file mode 100644 index 00000000..3292bf7b --- /dev/null +++ b/lib/philomena_web/controllers/api/json/search/post_controller.ex @@ -0,0 +1,40 @@ +defmodule PhilomenaWeb.Api.Json.Search.PostController do + use PhilomenaWeb, :controller + + alias PhilomenaWeb.PostJson + alias Philomena.Posts.Post + alias Philomena.Posts.Query + import Ecto.Query + + def index(conn, params) do + user = conn.assigns.current_user + + case Query.compile(user, params["q"] || "") do + {:ok, query} -> + posts = + Post.search_records( + %{ + query: %{ + bool: %{ + must: [ + query, + %{term: %{deleted: false}}, + %{term: %{access_level: "normal"}} + ], + } + }, + sort: %{created_at: :desc} + }, + conn.assigns.pagination, + preload(Post, [:user, :topic]) + ) + + json(conn, %{posts: Enum.map(posts, &PostJson.as_json/1)}) + + {:error, msg} -> + conn + |> put_status(:bad_request) + |> json(%{error: msg}) + end + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/api/json/search/tag_controller.ex b/lib/philomena_web/controllers/api/json/search/tag_controller.ex new file mode 100644 index 00000000..cbb1146c --- /dev/null +++ b/lib/philomena_web/controllers/api/json/search/tag_controller.ex @@ -0,0 +1,27 @@ +defmodule PhilomenaWeb.Api.Json.Search.TagController do + use PhilomenaWeb, :controller + + alias PhilomenaWeb.TagJson + alias Philomena.Tags.Tag + alias Philomena.Tags.Query + import Ecto.Query + + def index(conn, params) do + case Query.compile(params["q"] || "") do + {:ok, query} -> + tags = + Tag.search_records( + %{query: query, sort: %{images: :desc}}, + conn.assigns.pagination, + preload(Tag, [:aliased_tag, :aliases, :implied_tags, :implied_by_tags, :dnp_entries]) + ) + + json(conn, %{tags: Enum.map(tags, &TagJson.as_json/1)}) + + {:error, msg} -> + conn + |> put_status(:bad_request) + |> json(%{error: msg}) + end + end +end \ No newline at end of file diff --git a/lib/philomena_web/controllers/api/json/tag_controller.ex b/lib/philomena_web/controllers/api/json/tag_controller.ex index d28619c9..c045661f 100644 --- a/lib/philomena_web/controllers/api/json/tag_controller.ex +++ b/lib/philomena_web/controllers/api/json/tag_controller.ex @@ -1,45 +1,13 @@ defmodule PhilomenaWeb.Api.Json.TagController do use PhilomenaWeb, :controller + alias PhilomenaWeb.TagJson alias Philomena.Tags.Tag plug PhilomenaWeb.RecodeParameterPlug, [name: "id"] when action in [:show] plug :load_resource, model: Tag, id_field: "slug", persisted: true, preload: [:aliased_tag, :aliases, :implied_tags, :implied_by_tags, :dnp_entries] def show(conn, _params) do - json(conn, %{tag: tag_json(conn.assigns.tag)}) - end - - defp tag_json(tag) do - %{ - id: tag.id, - name: tag.name, - slug: tag.slug, - description: tag.description, - short_description: tag.short_description, - images: tag.images_count, - spoiler_image_uri: tag_image(tag), - namespace: tag.namespace, - name_in_namespace: tag.name_in_namespace, - category: tag.category, - aliased_tag: aliased_tag(tag), - aliases: Enum.map(tag.aliases, & &1.slug), - implied_tags: Enum.map(tag.implied_tags, & &1.slug), - implied_by_tags: Enum.map(tag.implied_by_tags, & &1.slug), - dnp_entries: Enum.map(tag.dnp_entries, &%{conditions: &1.conditions}) - } - end - - defp aliased_tag(%{aliased_tag: nil}), do: nil - defp aliased_tag(%{aliased_tag: t}), do: t.slug - - # TODO: copied from Tag.Fetch - defp tag_image(%{image: image}) when image not in [nil, ""], - do: tag_url_root() <> "/" <> image - defp tag_image(_other), - do: nil - - defp tag_url_root do - Application.get_env(:philomena, :tag_url_root) + json(conn, %{tag: TagJson.as_json(conn.assigns.tag)}) end end \ No newline at end of file diff --git a/lib/philomena_web/gallery_json.ex b/lib/philomena_web/gallery_json.ex new file mode 100644 index 00000000..ea6ad8f2 --- /dev/null +++ b/lib/philomena_web/gallery_json.ex @@ -0,0 +1,13 @@ +defmodule PhilomenaWeb.GalleryJson do + def as_json(gallery) do + %{ + id: gallery.id, + title: gallery.title, + thumbnail_id: gallery.thumbnail_id, + spoiler_warning: gallery.spoiler_warning, + description: gallery.description, + user: gallery.creator.name, + user_id: gallery.creator_id + } + end +end \ No newline at end of file diff --git a/lib/philomena_web/post_json.ex b/lib/philomena_web/post_json.ex new file mode 100644 index 00000000..fa2ba82a --- /dev/null +++ b/lib/philomena_web/post_json.ex @@ -0,0 +1,13 @@ +defmodule PhilomenaWeb.PostJson do + alias PhilomenaWeb.UserAttributionView + + def as_json(post) do + %{ + id: post.id, + topic_id: post.topic_id, + user_id: if(not post.anonymous, do: post.user_id), + author: if(post.anonymous or is_nil(post.user), do: UserAttributionView.anonymous_name(post), else: post.user.name), + body: if(not post.topic.hidden_from_users and not post.hidden_from_users, do: post.body) + } + end +end \ No newline at end of file diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index 00d80330..76da0c35 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -99,8 +99,16 @@ defmodule PhilomenaWeb.Router do scope "/search", Search, as: :search do resources "/reverse", ReverseController, only: [:create] + resources "/images", ImageController, only: [:index] + resources "/tags", TagController, only: [:index] + resources "/posts", PostController, only: [:index] + resources "/comments", CommentController, only: [:index] + resources "/galleries", GalleryController, only: [:index] end - resources "/search", SearchController, only: [:index] + + # Convenience alias + get "/search", Search.ImageController, :index + resources "/oembed", OembedController, only: [:index] resources "/tags", TagController, only: [:show] end diff --git a/lib/philomena_web/tag_json.ex b/lib/philomena_web/tag_json.ex new file mode 100644 index 00000000..83bb931e --- /dev/null +++ b/lib/philomena_web/tag_json.ex @@ -0,0 +1,34 @@ +defmodule PhilomenaWeb.TagJson do + def as_json(tag) do + %{ + id: tag.id, + name: tag.name, + slug: tag.slug, + description: tag.description, + short_description: tag.short_description, + images: tag.images_count, + spoiler_image_uri: tag_image(tag), + namespace: tag.namespace, + name_in_namespace: tag.name_in_namespace, + category: tag.category, + aliased_tag: aliased_tag(tag), + aliases: Enum.map(tag.aliases, & &1.slug), + implied_tags: Enum.map(tag.implied_tags, & &1.slug), + implied_by_tags: Enum.map(tag.implied_by_tags, & &1.slug), + dnp_entries: Enum.map(tag.dnp_entries, &%{conditions: &1.conditions}) + } + end + + defp aliased_tag(%{aliased_tag: nil}), do: nil + defp aliased_tag(%{aliased_tag: t}), do: t.slug + + # TODO: copied from Tag.Fetch + defp tag_image(%{image: image}) when image not in [nil, ""], + do: tag_url_root() <> "/" <> image + defp tag_image(_other), + do: nil + + defp tag_url_root do + Application.get_env(:philomena, :tag_url_root) + end +end \ No newline at end of file