X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fpleroma%2Fweb%2Fmastodon_api%2Fmastodon_api_controller.ex;h=9399dee867d756e443578a3f7ec4858f59986f52;hb=502cb38cd69f9f8c15a0ee597584364f9d36bdf1;hp=f17cf40e6f997f3af467c87edb3a613ac3a028e8;hpb=d168ef5a9eb4fc074b042a6dea6d7971d1972c06;p=akkoma diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index f17cf40e6..9399dee86 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -39,12 +39,23 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end end + @instance Application.get_env(:pleroma, :instance) + def masto_instance(conn, _params) do response = %{ uri: Web.base_url, - title: Web.base_url, + title: Keyword.get(@instance, :name), description: "A Pleroma instance, an alternative fediverse server", - version: "Pleroma Dev" + version: Keyword.get(@instance, :version), + email: Keyword.get(@instance, :email), + urls: %{ + streaming_api: String.replace(Web.base_url, ["http","https"], "wss") + }, + stats: %{ + user_count: 1, + status_count: 2, + domain_count: 3 + } } json(conn, response) @@ -66,7 +77,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end def home_timeline(%{assigns: %{user: user}} = conn, params) do - activities = ActivityPub.fetch_activities([user.ap_id | user.following], Map.put(params, "type", "Create")) + params = params + |> Map.put("type", ["Create", "Announce"]) + + activities = ActivityPub.fetch_activities([user.ap_id | user.following], params) |> Enum.reverse conn @@ -76,7 +90,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do def public_timeline(%{assigns: %{user: user}} = conn, params) do params = params - |> Map.put("type", "Create") + |> Map.put("type", ["Create", "Announce"]) |> Map.put("local_only", !!params["local"]) activities = ActivityPub.fetch_public_activities(params) @@ -87,10 +101,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) end + # TODO: Link headers def user_statuses(%{assigns: %{user: user}} = conn, params) do with %User{ap_id: ap_id} <- Repo.get(User, params["id"]) do params = params - |> Map.put("type", "Create") + |> Map.put("type", ["Create", "Announce"]) |> Map.put("actor_id", ap_id) activities = ActivityPub.fetch_activities([], params) @@ -121,15 +136,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do end def post_status(%{assigns: %{user: user}} = conn, %{"status" => status} = params) do - l = status |> String.trim |> String.length - params = params |> Map.put("in_reply_to_status_id", params["in_reply_to_id"]) - if l > 0 && l < 5000 do - {:ok, activity} = TwitterAPI.create_status(user, params) - render conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity} - end + {:ok, activity} = CommonAPI.post(user, params) + render conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity} end def delete_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do @@ -199,6 +210,149 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do render conn, AccountView, "relationships.json", %{user: user, targets: targets} end + def upload(%{assigns: %{user: user}} = conn, %{"file" => file}) do + with {:ok, object} <- ActivityPub.upload(file) do + data = object.data + |> Map.put("id", object.id) + + render conn, StatusView, "attachment.json", %{attachment: data} + end + end + + def favourited_by(conn, %{"id" => id}) do + with %Activity{data: %{"object" => %{"likes" => likes} = data}} <- Repo.get(Activity, id) do + q = from u in User, + where: u.ap_id in ^likes + users = Repo.all(q) + render conn, AccountView, "accounts.json", %{users: users, as: :user} + else + _ -> json(conn, []) + end + end + + def reblogged_by(conn, %{"id" => id}) do + with %Activity{data: %{"object" => %{"announcements" => announces}}} <- Repo.get(Activity, id) do + q = from u in User, + where: u.ap_id in ^announces + users = Repo.all(q) + render conn, AccountView, "accounts.json", %{users: users, as: :user} + else + _ -> json(conn, []) + end + end + + # TODO: Link headers + def hashtag_timeline(%{assigns: %{user: user}} = conn, params) do + params = params + |> Map.put("type", "Create") + |> Map.put("local_only", !!params["local"]) + + activities = ActivityPub.fetch_public_activities(params) + |> Enum.reverse + + conn + |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + end + + # TODO: Pagination + def followers(conn, %{"id" => id}) do + with %User{} = user <- Repo.get(User, id), + {:ok, followers} <- User.get_followers(user) do + render conn, AccountView, "accounts.json", %{users: followers, as: :user} + end + end + + def following(conn, %{"id" => id}) do + with %User{} = user <- Repo.get(User, id), + {:ok, followers} <- User.get_friends(user) do + render conn, AccountView, "accounts.json", %{users: followers, as: :user} + end + end + + def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do + with %User{} = followed <- Repo.get(User, id), + {:ok, follower} <- User.follow(follower, followed), + {:ok, activity} <- ActivityPub.follow(follower, followed) do + render conn, AccountView, "relationship.json", %{user: follower, target: followed} + else + {:error, message} = err -> + conn + |> put_resp_content_type("application/json") + |> send_resp(403, Poison.encode!(%{"error" => message})) + end + end + + def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do + with %User{} = followed <- Repo.get_by(User, nickname: uri), + {:ok, follower} <- User.follow(follower, followed), + {:ok, activity} <- ActivityPub.follow(follower, followed) do + render conn, AccountView, "account.json", %{user: followed} + else + {:error, message} = err -> + conn + |> put_resp_content_type("application/json") + |> send_resp(403, Poison.encode!(%{"error" => message})) + end + end + + # TODO: Clean up and unify + def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do + with %User{} = followed <- Repo.get(User, id), + { :ok, follower, follow_activity } <- User.unfollow(follower, followed), + { :ok, _activity } <- ActivityPub.insert(%{ + "type" => "Undo", + "actor" => follower.ap_id, + "object" => follow_activity.data["id"] # get latest Follow for these users + }) do + render conn, AccountView, "relationship.json", %{user: follower, target: followed} + end + end + + def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do + accounts = User.search(query, params["resolve"] == "true") + + q = from a in Activity, + where: fragment("?->>'type' = 'Create'", a.data), + where: fragment("to_tsvector('english', ?->'object'->>'content') @@ plainto_tsquery('english', ?)", a.data, ^query), + limit: 20 + statuses = Repo.all(q) + + res = %{ + "accounts" => AccountView.render("accounts.json", users: accounts, for: user, as: :user), + "statuses" => StatusView.render("index.json", activities: statuses, for: user, as: :activity), + "hashtags" => [] + } + + json(conn, res) + end + + def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do + accounts = User.search(query, params["resolve"] == "true") + + res = AccountView.render("accounts.json", users: accounts, for: user, as: :user) + + json(conn, res) + end + + def favourites(%{assigns: %{user: user}} = conn, params) do + params = conn + |> Map.put("type", "Create") + |> Map.put("favorited_by", user.ap_id) + + activities = ActivityPub.fetch_activities([], params) + |> Enum.reverse + + conn + |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + end + + def relationship_noop(%{assigns: %{user: user}} = conn, %{"id" => id}) do + Logger.debug("Unimplemented, returning unmodified relationship") + with %User{} = target <- Repo.get(User, id) do + render conn, AccountView, "relationship.json", %{user: user, target: target} + end + end + def empty_array(conn, _) do Logger.debug("Unimplemented, returning an empty array") json(conn, [])