mobilizon/lib/web/controllers/feed_controller.ex

101 lines
2.9 KiB
Elixir
Raw Permalink Normal View History

2020-01-26 21:36:50 +01:00
defmodule Mobilizon.Web.FeedController do
@moduledoc """
Controller to serve RSS, ATOM and iCal Feeds
"""
2020-01-26 21:36:50 +01:00
use Mobilizon.Web, :controller
plug(:put_layout, false)
2020-01-26 21:36:50 +01:00
action_fallback(Mobilizon.Web.FallbackController)
alias Mobilizon.Config
require Logger
@spec instance(Plug.Conn.t(), map()) :: Plug.Conn.t()
def instance(conn, %{"format" => format}) do
if Config.get([:instance, :enable_instance_feeds], false) do
return_data(conn, format, "instance", Config.instance_name())
else
send_resp(conn, 401, "Instance feeds are not enabled.")
end
end
@spec actor(Plug.Conn.t(), map()) :: Plug.Conn.t() | {:error, :not_found}
def actor(conn, %{"format" => format, "name" => name}) do
return_data(conn, format, "actor_" <> name, name)
end
def actor(_conn, _) do
{:error, :not_found}
end
@spec event(Plug.Conn.t(), map()) :: Plug.Conn.t() | {:error, :not_found}
def event(conn, %{"uuid" => uuid, "format" => "ics"}) do
return_data(conn, "ics", "event_" <> uuid, "event")
end
def event(_conn, _) do
{:error, :not_found}
end
@spec going(Plug.Conn.t(), map()) :: Plug.Conn.t() | {:error, :not_found}
def going(conn, %{"token" => token, "format" => format}) do
return_data(conn, format, "token_" <> token, "events")
end
def going(_conn, _) do
{:error, :not_found}
end
@spec return_data(Plug.Conn.t(), String.t(), String.t(), String.t()) ::
Plug.Conn.t() | {:error, :not_found}
defp return_data(conn, "atom", key, filename) do
case Cachex.fetch(:feed, key) do
{status, data} when status in [:commit, :ok] ->
conn
|> put_resp_content_type("application/atom+xml")
|> put_resp_header(
"content-disposition",
"attachment; filename=\"#{filename}.atom\""
)
|> send_resp(200, data)
# No need to log these two
{:ignore, :actor_not_found} ->
{:error, :not_found}
{:ignore, :actor_not_public} ->
{:error, :not_found}
err ->
Logger.warning("Unable to find feed data cached for key #{key}, returned #{inspect(err)}")
{:error, :not_found}
end
end
defp return_data(conn, "ics", key, filename) do
case Cachex.fetch(:ics, key) do
{status, data} when status in [:commit, :ok] ->
conn
|> put_resp_content_type("text/calendar")
|> put_resp_header(
"content-disposition",
"attachment; filename=\"#{filename}.ics\""
)
|> send_resp(200, data)
# No need to log these two
{:ignore, :actor_not_found} ->
{:error, :not_found}
{:ignore, :actor_not_public} ->
{:error, :not_found}
err ->
Logger.warning("Unable to find feed data cached for key #{key}, returned #{inspect(err)}")
{:error, :not_found}
end
end
defp return_data(_conn, _, _, _) do
{:error, :not_found}
end
end