Add Twitter API for the pinned statuses

```
# Only return statuses that have been pinned
GET /api/statuses/user_timeline.json?pinned=true

# Pin
POST /api/statuses/pin/:id

# Unpin
POST /api/statuses/unpin/:id
```
This commit is contained in:
Egor Kislitsyn 2019-01-09 19:54:19 +07:00
parent 1b06e6fdf3
commit 44a1e69484
8 changed files with 119 additions and 3 deletions

View File

@ -355,6 +355,9 @@ defmodule Pleroma.Web.Router do
post("/statuses/unretweet/:id", TwitterAPI.Controller, :unretweet) post("/statuses/unretweet/:id", TwitterAPI.Controller, :unretweet)
post("/statuses/destroy/:id", TwitterAPI.Controller, :delete_post) post("/statuses/destroy/:id", TwitterAPI.Controller, :delete_post)
post("/statuses/pin/:id", TwitterAPI.Controller, :pin)
post("/statuses/unpin/:id", TwitterAPI.Controller, :unpin)
get("/pleroma/friend_requests", TwitterAPI.Controller, :friend_requests) get("/pleroma/friend_requests", TwitterAPI.Controller, :friend_requests)
post("/pleroma/friendships/approve", TwitterAPI.Controller, :approve_friend_request) post("/pleroma/friendships/approve", TwitterAPI.Controller, :approve_friend_request)
post("/pleroma/friendships/deny", TwitterAPI.Controller, :deny_friend_request) post("/pleroma/friendships/deny", TwitterAPI.Controller, :deny_friend_request)

View File

@ -153,6 +153,7 @@ def to_map(
announcement_count = object["announcement_count"] || 0 announcement_count = object["announcement_count"] || 0
favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || []) favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || [])
repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || []) repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || [])
pinned = activity.id in user.info.pinned_activities
mentions = opts[:mentioned] || [] mentions = opts[:mentioned] || []
@ -202,6 +203,7 @@ def to_map(
"repeat_num" => announcement_count, "repeat_num" => announcement_count,
"favorited" => to_boolean(favorited), "favorited" => to_boolean(favorited),
"repeated" => to_boolean(repeated), "repeated" => to_boolean(repeated),
"pinned" => pinned,
"external_url" => object["external_url"] || object["id"], "external_url" => object["external_url"] || object["id"],
"tags" => tags, "tags" => tags,
"activity_type" => "post", "activity_type" => "post",

View File

@ -82,6 +82,14 @@ def unrepeat(%User{} = user, ap_id_or_id) do
end end
end end
def pin(%User{} = user, ap_id_or_id) do
CommonAPI.pin(ap_id_or_id, user)
end
def unpin(%User{} = user, ap_id_or_id) do
CommonAPI.unpin(ap_id_or_id, user)
end
def fav(%User{} = user, ap_id_or_id) do def fav(%User{} = user, ap_id_or_id) do
with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user), with {:ok, _fav, %{data: %{"id" => id}}} <- CommonAPI.favorite(ap_id_or_id, user),
%Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do

View File

@ -375,6 +375,30 @@ def unretweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do
end end
end end
def pin(%{assigns: %{user: user}} = conn, %{"id" => id}) do
with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)},
{:ok, activity} <- TwitterAPI.pin(user, id) do
conn
|> put_view(ActivityView)
|> render("activity.json", %{activity: activity, for: user})
else
{:error, message} -> bad_request_reply(conn, message)
err -> err
end
end
def unpin(%{assigns: %{user: user}} = conn, %{"id" => id}) do
with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)},
{:ok, activity} <- TwitterAPI.unpin(user, id) do
conn
|> put_view(ActivityView)
|> render("activity.json", %{activity: activity, for: user})
else
{:error, message} -> bad_request_reply(conn, message)
err -> err
end
end
def register(conn, params) do def register(conn, params) do
with {:ok, user} <- TwitterAPI.register_user(params) do with {:ok, user} <- TwitterAPI.register_user(params) do
conn conn

View File

@ -243,6 +243,7 @@ def render(
announcement_count = object["announcement_count"] || 0 announcement_count = object["announcement_count"] || 0
favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || []) favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || [])
repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || []) repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || [])
pinned = activity.id in user.info.pinned_activities
attentions = attentions =
activity.recipients activity.recipients
@ -300,6 +301,7 @@ def render(
"repeat_num" => announcement_count, "repeat_num" => announcement_count,
"favorited" => !!favorited, "favorited" => !!favorited,
"repeated" => !!repeated, "repeated" => !!repeated,
"pinned" => pinned,
"external_url" => object["external_url"] || object["id"], "external_url" => object["external_url"] || object["id"],
"tags" => tags, "tags" => tags,
"activity_type" => "post", "activity_type" => "post",

View File

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do
@ -157,6 +157,7 @@ test "an activity" do
"repeat_num" => 3, "repeat_num" => 3,
"favorited" => false, "favorited" => false,
"repeated" => false, "repeated" => false,
"pinned" => false,
"external_url" => "some url", "external_url" => "some url",
"tags" => ["nsfw", "content", "mentioning"], "tags" => ["nsfw", "content", "mentioning"],
"activity_type" => "post", "activity_type" => "post",

View File

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.TwitterAPI.ControllerTest do defmodule Pleroma.Web.TwitterAPI.ControllerTest do
@ -1694,4 +1694,79 @@ test "it updates `data[name]` of referenced Object with provided value", %{
assert object.data["name"] == description assert object.data["name"] == description
end end
end end
describe "POST /api/statuses/user_timeline.json?user_id=:user_id&pinned=true" do
test "it returns a list of pinned statuses", %{conn: conn} do
Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
user = insert(:user, %{name: "egor"})
{:ok, %{id: activity_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
{:ok, _} = CommonAPI.pin(activity_id, user)
resp =
conn
|> get("/api/statuses/user_timeline.json", %{user_id: user.id, pinned: true})
|> json_response(200)
assert length(resp) == 1
assert [%{"id" => ^activity_id, "pinned" => true}] = resp
end
end
describe "POST /api/statuses/pin/:id" do
setup do
Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
[user: insert(:user)]
end
test "without valid credentials", %{conn: conn} do
note_activity = insert(:note_activity)
conn = post(conn, "/api/statuses/pin/#{note_activity.id}.json")
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: user} do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
request_path = "/api/statuses/pin/#{activity.id}.json"
response =
conn
|> with_credentials(user.nickname, "test")
|> post(request_path)
user = refresh_record(user)
assert json_response(response, 200) == ActivityRepresenter.to_map(activity, %{user: user})
end
end
describe "POST /api/statuses/unpin/:id" do
setup do
Pleroma.Config.put([:instance, :max_pinned_statuses], 1)
[user: insert(:user)]
end
test "without valid credentials", %{conn: conn} do
note_activity = insert(:note_activity)
conn = post(conn, "/api/statuses/unpin/#{note_activity.id}.json")
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: user} do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test!"})
{:ok, activity} = CommonAPI.pin(activity.id, user)
request_path = "/api/statuses/unpin/#{activity.id}.json"
response =
conn
|> with_credentials(user.nickname, "test")
|> post(request_path)
user = refresh_record(user)
assert json_response(response, 200) == ActivityRepresenter.to_map(activity, %{user: user})
end
end
end end

View File

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
@ -132,6 +132,7 @@ test "a create activity with a note" do
"possibly_sensitive" => false, "possibly_sensitive" => false,
"repeat_num" => 0, "repeat_num" => 0,
"repeated" => false, "repeated" => false,
"pinned" => false,
"statusnet_conversation_id" => convo_id, "statusnet_conversation_id" => convo_id,
"summary" => "", "summary" => "",
"statusnet_html" => "statusnet_html" =>