diff --git a/lib/philomena_web/controllers/api/watched_controller.ex b/lib/philomena_web/controllers/api/watched_controller.ex new file mode 100644 index 00000000..75702e58 --- /dev/null +++ b/lib/philomena_web/controllers/api/watched_controller.ex @@ -0,0 +1,34 @@ +defmodule PhilomenaWeb.Api.WatchedController do + use PhilomenaWeb, :controller + + alias Philomena.Images.{Image, Query} + import Ecto.Query + + def index(conn, _params) do + user = conn.assigns.current_user + filter = conn.assigns.compiled_filter + + {:ok, query} = Query.compile(user, "my:watched") + + images = + Image.search_records( + %{ + query: %{ + bool: %{ + must: query, + must_not: [ + filter, + %{term: %{hidden_from_users: true}} + ] + } + }, + sort: %{created_at: :desc} + }, + conn.assigns.image_pagination, + Image |> preload(:tags) + ) + + conn + |> render("index.rss", images: images) + end +end \ No newline at end of file diff --git a/lib/philomena_web/plugs/api_token_plug.ex b/lib/philomena_web/plugs/api_token_plug.ex new file mode 100644 index 00000000..e5f1ed8f --- /dev/null +++ b/lib/philomena_web/plugs/api_token_plug.ex @@ -0,0 +1,32 @@ +defmodule PhilomenaWeb.ApiTokenPlug do + + alias Philomena.Users.User + alias Philomena.Repo + alias Pow.Plug + import Ecto.Query + + def init([]), do: [] + + def call(conn, _opts) do + conn + |> maybe_find_user(conn.params["key"]) + |> maybe_assign_user() + end + + defp maybe_find_user(conn, nil), do: {conn, nil} + defp maybe_find_user(conn, key) do + user = + User + |> where(authentication_token: ^key) + |> Repo.one() + + {conn, user} + end + + defp maybe_assign_user({conn, nil}), do: conn + defp maybe_assign_user({conn, user}) do + config = Plug.fetch_config(conn) + + Plug.assign_current_user(conn, user, config) + end +end \ No newline at end of file diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index f5cb17b7..5216e087 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -21,6 +21,18 @@ defmodule PhilomenaWeb.Router do plug PhilomenaWeb.ChannelPlug end + pipeline :rss do + plug :accepts, ["rss"] + + 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 plug :accepts, ["json"] end @@ -54,6 +66,12 @@ defmodule PhilomenaWeb.Router do end end + scope "/api/rss", PhilomenaWeb.Api, as: :api_rss do + pipe_through :rss + + resources "/watched", WatchedController, only: [:index] + end + scope "/", PhilomenaWeb do pipe_through [:browser, :ensure_totp, :protected] diff --git a/lib/philomena_web/templates/api/watched/index.rss.eex b/lib/philomena_web/templates/api/watched/index.rss.eex new file mode 100644 index 00000000..e684cbb7 --- /dev/null +++ b/lib/philomena_web/templates/api/watched/index.rss.eex @@ -0,0 +1,26 @@ + + + + Derpibooru Watchlist + Your watched tags feed from Derpibooru + <%= Routes.api_rss_watched_url(@conn, :index) %> + <%= last_build_date() %> + + <%= for image <- @images do %> + + <%= "##{image.id} - #{image.tag_list_cache}" %> + + + + <%= mouseovertext %> + + ]]> + + <%= NaiveDateTime.to_iso8601(image.created_at) %> + <%= Routes.image_url(@conn, :show, image) %> + <%= Routes.image_url(@conn, :show, image) %> + + <% end %> + + diff --git a/lib/philomena_web/templates/setting/edit.html.slime b/lib/philomena_web/templates/setting/edit.html.slime index 4a680aad..4eae82a0 100644 --- a/lib/philomena_web/templates/setting/edit.html.slime +++ b/lib/philomena_web/templates/setting/edit.html.slime @@ -38,6 +38,14 @@ h1 Content Settings => checkbox f, :no_spoilered_in_watched, class: "checkbox" => label f, :no_spoilered_in_watched, "Hide images spoilered by filter in watchlist" + h4 Other + p + ' RSS feed link (for Google Reader, Thunderbird, etc.): + br + = url_input f, :subscribe_url, value: Routes.api_rss_watched_url(@conn, :index, key: @conn.assigns.current_user.authentication_token), class: "input input--wide" + br + ' Do not share this URL with anyone, it may allow an attacker to compromise your account. + .block__tab.hidden.flex.flex--maybe-wrap data-tab="display" div .field diff --git a/lib/philomena_web/views/api/watched_view.ex b/lib/philomena_web/views/api/watched_view.ex new file mode 100644 index 00000000..4444d628 --- /dev/null +++ b/lib/philomena_web/views/api/watched_view.ex @@ -0,0 +1,16 @@ +defmodule PhilomenaWeb.Api.WatchedView do + use PhilomenaWeb, :view + + alias PhilomenaWeb.ImageView + + def last_build_date do + DateTime.utc_now() + |> DateTime.to_iso8601() + end + + def medium_url(image) do + image + |> ImageView.thumb_urls(false) + |> Map.get(:medium) + end +end \ No newline at end of file