logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma
commit: 4d627a5117bebc5eb298879d3fb3ccdb9801e077
parent: b451a92d78b184dda63e6647f815f89c0e37fd98
Author: kaniini <nenolod@gmail.com>
Date:   Wed,  7 Nov 2018 22:33:06 +0000

Merge branch 'feature/qvitter-notifications-dismiss' into 'develop'

qvitter notifications: add new "read notifications" API

See merge request pleroma/pleroma!431

Diffstat:

Mlib/pleroma/notification.ex14++++++++++++++
Mlib/pleroma/web/router.ex4++++
Mlib/pleroma/web/twitter_api/twitter_api_controller.ex13+++++++++++++
Mtest/notification_test.exs35+++++++++++++++++++++++++++++++++++
Mtest/web/twitter_api/twitter_api_controller_test.exs50++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 116 insertions(+), 0 deletions(-)

diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex @@ -42,6 +42,20 @@ defmodule Pleroma.Notification do Repo.all(query) end + def set_read_up_to(%{id: user_id} = _user, id) do + query = + from( + n in Notification, + where: n.user_id == ^user_id, + where: n.id <= ^id, + update: [ + set: [seen: true] + ] + ) + + Repo.update_all(query, []) + end + def get(%{id: user_id} = _user, id) do query = from( diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex @@ -272,6 +272,10 @@ defmodule Pleroma.Web.Router do get("/statuses/mentions_timeline", TwitterAPI.Controller, :mentions_timeline) get("/qvitter/statuses/notifications", TwitterAPI.Controller, :notifications) + # XXX: this is really a pleroma API, but we want to keep the pleroma namespace clean + # for now. + post("/qvitter/statuses/notifications/read", TwitterAPI.Controller, :notifications_read) + post("/statuses/update", TwitterAPI.Controller, :status_update) post("/statuses/retweet/:id", TwitterAPI.Controller, :retweet) post("/statuses/unretweet/:id", TwitterAPI.Controller, :unretweet) diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -133,6 +133,19 @@ defmodule Pleroma.Web.TwitterAPI.Controller do |> render(NotificationView, "notification.json", %{notifications: notifications, for: user}) end + def notifications_read(%{assigns: %{user: user}} = conn, %{"latest_id" => latest_id} = params) do + Notification.set_read_up_to(user, latest_id) + + notifications = Notification.for_user(user, params) + + conn + |> render(NotificationView, "notification.json", %{notifications: notifications, for: user}) + end + + def notifications_read(%{assigns: %{user: user}} = conn, _) do + bad_request_reply(conn, "You need to specify latest_id") + end + def follow(%{assigns: %{user: user}} = conn, params) do case TwitterAPI.follow(user, params) do {:ok, user, followed, _activity} -> diff --git a/test/notification_test.exs b/test/notification_test.exs @@ -121,6 +121,41 @@ defmodule Pleroma.NotificationTest do end end + describe "set_read_up_to()" do + test "it sets all notifications as read up to a specified notification ID" do + user = insert(:user) + other_user = insert(:user) + + {:ok, activity} = + TwitterAPI.create_status(user, %{ + "status" => "hey @#{other_user.nickname}!" + }) + + {:ok, activity} = + TwitterAPI.create_status(user, %{ + "status" => "hey again @#{other_user.nickname}!" + }) + + [n2, n1] = notifs = Notification.for_user(other_user) + assert length(notifs) == 2 + + assert n2.id > n1.id + + {:ok, activity} = + TwitterAPI.create_status(user, %{ + "status" => "hey yet again @#{other_user.nickname}!" + }) + + Notification.set_read_up_to(other_user, n2.id) + + [n3, n2, n1] = notifs = Notification.for_user(other_user) + + assert n1.seen == true + assert n2.seen == true + assert n3.seen == false + end + end + describe "notification lifecycle" do test "liking an activity results in 1 notification, then 0 if the activity is deleted" do user = insert(:user) diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs @@ -331,6 +331,56 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do end end + describe "POST /api/qvitter/statuses/notifications/read" do + setup [:valid_user] + + test "without valid credentials", %{conn: conn} do + conn = post(conn, "/api/qvitter/statuses/notifications/read", %{"latest_id" => 1_234_567}) + assert json_response(conn, 403) == %{"error" => "Invalid credentials."} + end + + test "with credentials, without any params", %{conn: conn, user: current_user} do + conn = + conn + |> with_credentials(current_user.nickname, "test") + |> post("/api/qvitter/statuses/notifications/read") + + assert json_response(conn, 400) == %{ + "error" => "You need to specify latest_id", + "request" => "/api/qvitter/statuses/notifications/read" + } + end + + test "with credentials, with params", %{conn: conn, user: current_user} do + other_user = insert(:user) + + {:ok, _activity} = + ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: other_user}) + + response_conn = + conn + |> with_credentials(current_user.nickname, "test") + |> get("/api/qvitter/statuses/notifications.json") + + [notification] = response = json_response(response_conn, 200) + + assert length(response) == 1 + + assert notification["is_seen"] == 0 + + response_conn = + conn + |> with_credentials(current_user.nickname, "test") + |> post("/api/qvitter/statuses/notifications/read", %{"latest_id" => notification["id"]}) + + [notification] = response = json_response(response_conn, 200) + + assert length(response) == 1 + + assert notification["is_seen"] == 1 + end + end + describe "GET /statuses/user_timeline.json" do setup [:valid_user]