frenzy/lib/frenzy_web/controllers/fever_controller.ex

190 lines
4.1 KiB
Elixir
Raw Normal View History

2019-02-11 22:22:35 +00:00
defmodule FrenzyWeb.FeverController do
use FrenzyWeb, :controller
alias Frenzy.{Repo, Feed, Item}
import Ecto.Query
plug :api_check
def api_check(conn, _) do
if Map.has_key?(conn.params, "api") do
conn
else
conn |> resp(400, "Invalid request") |> halt()
end
end
def get(conn, params) do
json(conn, %{api_version: 2, auth: 0})
end
def post(conn, %{"api_key" => api_key} = params) do
case validate_key(api_key) do
:invalid ->
resp(conn, 401, "Invalid API key")
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
:ok ->
json(conn, fever_response(params))
end
end
defp validate_key(api_key) do
auth = Application.get_env(:frenzy, :auth)
username = auth[:username]
password = auth[:password]
expected = :crypto.hash(:md5, "#{username}:#{password}") |> Base.encode16(case: :lower)
2019-03-11 02:23:28 +00:00
case api_key |> String.downcase() do
2019-02-11 22:22:35 +00:00
^expected -> :ok
_ -> :invalid
end
end
defp fever_response(params) do
2019-03-11 02:23:28 +00:00
res =
%{api_version: 2, auth: 1}
2019-02-11 22:22:35 +00:00
|> mark(params)
|> unread_recently_read(params)
|> groups(params)
|> feeds(params)
|> favicons(params)
|> links(params)
|> unread(params)
|> saved(params)
|> items(params)
end
defp mark(res, %{"mark" => "item", "id" => id, "as" => as} = params) do
item = Repo.get(Item, id) |> Repo.preload(:feed)
2019-03-11 02:23:28 +00:00
diff =
case as do
"read" ->
%{read: true, read_date: Timex.now()}
"unread" ->
%{read: false, read_date: nil}
_ ->
%{}
end
2019-02-11 22:22:35 +00:00
changeset = Item.changeset(item, diff)
Repo.update(changeset)
res
end
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
defp mark(res, _), do: res
defp unread_recently_read(res, %{"unread_recently_read" => 1}) do
Repo.all(from i in Item, where: i.read, where: i.read_date >= from_now(-1, "hour"))
2019-03-11 02:23:28 +00:00
|> Enum.map(fn i -> Item.changeset(i, %{read: false, read_date: nil}) end)
|> Enum.map(&Repo.update/1)
2019-02-11 22:22:35 +00:00
res
end
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
defp unread_recently_read(res, _), do: res
defp groups(res, %{"groups" => _}) do
res
2019-03-11 02:23:28 +00:00
|> Map.put(:groups, [])
|> Map.put(:feeds_groups, [])
2019-02-11 22:22:35 +00:00
end
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
defp groups(res, _), do: res
defp feeds(res, %{"feeds" => _}) do
2019-03-11 02:23:28 +00:00
feeds =
Repo.all(Feed)
2019-02-11 22:22:35 +00:00
|> Enum.map(&Feed.to_fever/1)
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
res
2019-03-11 02:23:28 +00:00
|> Map.put(:feeds, feeds)
|> Map.put(:feeds_groups, [])
2019-02-11 22:22:35 +00:00
end
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
defp feeds(res, _), do: res
defp favicons(res, %{"favicons" => _}) do
res
2019-03-11 02:23:28 +00:00
|> Map.put(:favicons, [])
2019-02-11 22:22:35 +00:00
end
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
defp favicons(res, _), do: res
defp links(res, %{"links" => _}) do
res
2019-03-11 02:23:28 +00:00
|> Map.put(:links, [])
2019-02-11 22:22:35 +00:00
end
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
defp links(res, _), do: res
defp unread(res, %{"unread_item_ids" => _}) do
2019-03-11 02:23:28 +00:00
unread =
Repo.all(from Item, where: [read: false])
2019-02-11 22:22:35 +00:00
|> Enum.map(fn item -> item.id end)
|> Enum.join(",")
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
res
2019-03-11 02:23:28 +00:00
|> Map.put(:unread_item_ids, unread)
2019-02-11 22:22:35 +00:00
end
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
defp unread(res, _), do: res
defp saved(res, %{"saved_item_ids" => _}) do
res
2019-03-11 02:23:28 +00:00
|> Map.put(:saved_item_ids, "")
2019-02-11 22:22:35 +00:00
end
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
defp saved(res, _), do: res
defp items(res, %{"items" => _} = params) do
2019-03-11 02:23:28 +00:00
items =
cond do
Map.has_key?(params, "with_ids") ->
params["with_ids"]
2019-02-11 22:22:35 +00:00
|> String.split(",")
|> Enum.map(fn id ->
2019-03-11 02:23:28 +00:00
{id, _} = id |> String.trim() |> Integer.parse()
2019-02-11 22:22:35 +00:00
Repo.get(Item, id)
end)
2019-03-11 02:23:28 +00:00
Map.has_key?(params, "since_id") ->
since = Repo.get(Item, params["since_id"])
{since, _} = Integer.parse(since)
Repo.all(
from i in Item,
where: i.inserted_at > ^since.inserted_at,
order_by: [asc: :id],
limit: 50
)
Map.has_key?(params, "max_id") ->
max = Repo.get(Item, params["max_id"])
{max, _} = Integer.parse(max)
Repo.all(
from i in Item,
where: i.inserted_at < ^max.inserted_at,
order_by: [desc: :id],
limit: 50
)
true ->
[]
end
items =
items
2019-02-11 22:22:35 +00:00
|> Enum.reject(&is_nil/1)
|> Enum.map(&Item.to_fever/1)
2019-03-11 02:23:28 +00:00
2019-02-11 22:22:35 +00:00
res
2019-03-11 02:23:28 +00:00
|> Map.put(:items, items)
|> Map.put(:total_items, Enum.count(items))
2019-02-11 22:22:35 +00:00
end
2019-03-11 02:23:28 +00:00
defp items(res, _), do: res
end