Add more Mastodon API methods.
authorRoger Braun <roger@rogerbraun.net>
Sat, 9 Sep 2017 11:15:01 +0000 (13:15 +0200)
committerRoger Braun <roger@rogerbraun.net>
Sat, 9 Sep 2017 11:15:01 +0000 (13:15 +0200)
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/router.ex
test/web/mastodon_api/mastodon_api_controller_test.exs [new file with mode: 0644]

index 62522439c2674e9bfb3c1c8182b172ad3173a7ab..3a568cf2b2c7d2a31c66bbc2696108e329855943 100644 (file)
@@ -1,9 +1,11 @@
 defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
   use Pleroma.Web, :controller
-  alias Pleroma.{Repo}
+  alias Pleroma.{Repo, Activity}
   alias Pleroma.Web.OAuth.App
   alias Pleroma.Web
-  alias Pleroma.Web.MastodonAPI.AccountView
+  alias Pleroma.Web.MastodonAPI.{StatusView, AccountView}
+  alias Pleroma.Web.ActivityPub.ActivityPub
+  alias Pleroma.Web.TwitterAPI.TwitterAPI
 
   def create_app(conn, params) do
     with cs <- App.register_changeset(%App{}, params) |> IO.inspect,
@@ -33,4 +35,37 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
 
     json(conn, response)
   end
+
+  def home_timeline(%{assigns: %{user: user}} = conn, params) do
+    activities = ActivityPub.fetch_activities([user.ap_id | user.following], Map.put(params, "type", "Create"))
+    render conn, StatusView, "index.json", %{activities: activities, for: user, as: :activity}
+  end
+
+  def public_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)
+
+    render conn, StatusView, "index.json", %{activities: activities, for: user, as: :activity}
+  end
+
+  def get_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+    with %Activity{} = activity <- Repo.get(Activity, id) do
+      render conn, StatusView, "status.json", %{activity: activity, for: user}
+    end
+  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
+  end
 end
index a8577c30b32d20750d5c98c6aba43ea4d56e5cd6..46cbf4e4e170cdd77e97a3e3a90bdb60755853a3 100644 (file)
@@ -10,6 +10,7 @@ defmodule Pleroma.Web.Router do
   pipeline :api do
     plug :accepts, ["json"]
     plug :fetch_session
+    plug Pleroma.Plugs.OAuthPlug
     plug Pleroma.Plugs.AuthenticationPlug, %{fetcher: &Router.user_fetcher/1, optional: true}
   end
 
@@ -40,14 +41,21 @@ defmodule Pleroma.Web.Router do
 
   scope "/api/v1", Pleroma.Web.MastodonAPI do
     pipe_through :api
-    get "/instance", MastodonAPO.Controller, :masto_instance
+    get "/instance", MastodonAPIController, :masto_instance
     post "/apps", MastodonAPIController, :create_app
+
+    get "/timelines/public", MastodonAPIController, :public_timeline
+
+    get "/statuses/:id", MastodonAPIController, :get_status
   end
 
   scope "/api/v1", Pleroma.Web.MastodonAPI do
     pipe_through :authenticated_api
 
     get "/accounts/verify_credentials", MastodonAPIController, :verify_credentials
+    get "/timelines/home", MastodonAPIController, :home_timeline
+
+    post "/statuses", MastodonAPIController, :post_status
   end
 
   scope "/api", Pleroma.Web do
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
new file mode 100644 (file)
index 0000000..a3692c9
--- /dev/null
@@ -0,0 +1,96 @@
+defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
+  use Pleroma.Web.ConnCase
+
+  alias Pleroma.Web.TwitterAPI.TwitterAPI
+  alias Pleroma.{Repo, User, Activity}
+  alias Pleroma.Web.OStatus
+
+  import Pleroma.Factory
+
+  test "the home timeline", %{conn: conn} do
+    user = insert(:user)
+    following = insert(:user)
+
+    {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
+
+    conn = conn
+    |> assign(:user, user)
+    |> get("/api/v1/timelines/home")
+
+    assert length(json_response(conn, 200)) == 0
+
+    {:ok, user} = User.follow(user, following)
+
+    conn = build_conn()
+    |> assign(:user, user)
+    |> get("/api/v1/timelines/home")
+
+    assert [%{"content" => "test"}] = json_response(conn, 200)
+  end
+
+  test "the public timeline", %{conn: conn} do
+    following = insert(:user)
+
+    {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"})
+    {:ok, [_activity]} = OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
+
+    conn = conn
+    |> get("/api/v1/timelines/public")
+
+    assert length(json_response(conn, 200)) == 2
+
+    conn = build_conn()
+    |> get("/api/v1/timelines/public", %{"local" => "True"})
+
+    assert [%{"content" => "test"}] = json_response(conn, 200)
+  end
+
+  test "posting a status", %{conn: conn} do
+    user = insert(:user)
+
+    conn = conn
+    |> assign(:user, user)
+    |> post("/api/v1/statuses", %{"status" => "cofe"})
+
+    assert %{"content" => "cofe", "id" => id} = json_response(conn, 200)
+    assert Repo.get(Activity, id)
+  end
+
+  test "replying to a status", %{conn: conn} do
+    user = insert(:user)
+
+    {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"})
+
+    conn = conn
+    |> assign(:user, user)
+    |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id})
+
+    assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
+
+    activity = Repo.get(Activity, id)
+
+    assert activity.data["context"] == replied_to.data["context"]
+    assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
+  end
+
+  test "verify_credentials", %{conn: conn} do
+    user = insert(:user)
+
+    conn = conn
+    |> assign(:user, user)
+    |> get("/api/v1/accounts/verify_credentials")
+
+    assert %{"id" => id} = json_response(conn, 200)
+    assert id == user.id
+  end
+
+  test "get a status", %{conn: conn} do
+    activity = insert(:note_activity)
+
+    conn = conn
+    |> get("/api/v1/statuses/#{activity.id}")
+
+    assert %{"id" => id} = json_response(conn, 200)
+    assert id == activity.id
+  end
+end