defmodule ClacksWeb.FrontendController do use ClacksWeb, :controller alias Clacks.{Actor, User, Timeline, Repo, ActivityPub, Activity, Object} alias ClacksWeb.Router.Helpers, as: Routes alias ClacksWeb.Endpoint def index(%Plug.Conn{assigns: %{user: user}} = conn, params) do user = Repo.preload(user, :actor) render(conn, "home.html", %{ user: user, actor: user.actor, statuses_with_authors: Timeline.home_timeline(user, params, true) }) end def index(conn, params) do Application.get_env(:clacks, :frontend, %{}) |> Keyword.get(:unauthenticated_homepage, :public_timeline) |> index(conn, params) end defp index(:public_timeline, conn, params) do # tood: show public timeline end defp index({:profile, nickname}, conn, params) do case Actor.get_by_nickname(nickname) do %Actor{local: true} = actor -> # only local profiles are shown render(conn, "profile.html", %{ actor: actor, statuses: actor_statuses(actor, params, only_public: true) }) _ -> # otherwise show public timeline index(:public_timeline, conn) end end defp actor_statuses(actor, params, only_public: only_public) do Timeline.actor_timeline(actor, params, only_public) end def status(conn, %{"id" => id}) do current_user = conn.assigns[:user] |> Repo.preload(:actor) with %Activity{ local: true, data: %{ "type" => "Create", "object" => %{"type" => "Note", "attributedTo" => author_id} = note } } <- Activity.get(id), %Actor{} = author <- Actor.get_by_ap_id(author_id) do render(conn, "status.html", %{ current_user: current_user, note: note, author: author }) else nil -> put_status(conn, 404) %Activity{local: false, data: %{"id" => ap_id}} -> redirect(conn, external: ap_id) end end def profile(conn, %{"username" => username} = params) do current_user = conn.assigns[:user] |> Repo.preload(:actor) case User.get_by_username(username) do nil -> put_status(conn, 404) user -> user = Repo.preload(user, :actor) render(conn, "profile.html", %{ current_user: current_user, actor: user.actor, statuses: actor_statuses(user.actor, params, only_public: true) }) end end def post_status(conn, %{"content" => content} = params) do current_user = conn.assigns[:user] |> Repo.preload(:actor) note = ActivityPub.note(current_user.actor.ap_id, content) note_changeset = Object.changeset_for_creating(note) {:ok, object} = Repo.insert(note_changeset) create = ActivityPub.create(note) create_changeset = Activity.changeset_for_creating(create, true) {:ok, activity} = Repo.insert(create_changeset) %{id: activity.id, actor_id: current_user.actor.id} |> Clacks.Worker.Federate.new() |> Oban.insert() path = Map.get(params, "continue", Routes.frontend_path(Endpoint, :status, activity.id)) redirect(conn, to: path) end end