Save follower count and note count in user.
authorRoger Braun <roger@rogerbraun.net>
Sat, 22 Jul 2017 15:42:15 +0000 (17:42 +0200)
committerRoger Braun <roger@rogerbraun.net>
Sat, 22 Jul 2017 15:42:15 +0000 (17:42 +0200)
lib/pleroma/user.ex
lib/pleroma/web/ostatus/handlers/note_handler.ex
lib/pleroma/web/twitter_api/twitter_api.ex
test/support/factory.ex
test/user_test.exs
test/web/ostatus/ostatus_test.exs
test/web/twitter_api/twitter_api_test.exs
test/web/twitter_api/views/user_view_test.exs

index d5befa67bb9ee738bcf8adc56eda4ef4fe5286fe..f28f0deb0cad55c2b418f444cef94b28522f77e3 100644 (file)
@@ -54,18 +54,10 @@ defmodule Pleroma.User do
   end
 
   def user_info(%User{} = user) do
-    note_count_query = from a in Object,
-      where: fragment("? @> ?", a.data, ^%{actor: user.ap_id, type: "Note"}),
-      select: count(a.id)
-
-    follower_count_query = from u in User,
-      where: fragment("? @> ?", u.following, ^user.follower_address),
-      select: count(u.id)
-
     %{
       following_count: length(user.following),
-      note_count: Repo.one(note_count_query),
-      follower_count: Repo.one(follower_count_query)
+      note_count: user.info["note_count"] || 0,
+      follower_count: user.info["follower_count"] || 0
     }
   end
 
@@ -127,9 +119,13 @@ defmodule Pleroma.User do
       following = [ap_followers | follower.following]
       |> Enum.uniq
 
-      follower
+      follower = follower
       |> follow_changeset(%{following: following})
       |> Repo.update
+
+      {:ok, followed} = update_follower_count(followed)
+
+      follower
     end
   end
 
@@ -142,7 +138,10 @@ defmodule Pleroma.User do
       { :ok, follower } = follower
       |> follow_changeset(%{following: following})
       |> Repo.update
-      { :ok, follower, Utils.fetch_latest_follow(follower, followed)}
+
+      {:ok, followed} = update_follower_count(followed)
+
+      {:ok, follower, Utils.fetch_latest_follow(follower, followed)}
     else
       {:error, "Not subscribed!"}
     end
@@ -203,4 +202,32 @@ defmodule Pleroma.User do
 
     {:ok, Repo.all(q)}
   end
+
+  def update_note_count(%User{} = user) do
+    note_count_query = from a in Object,
+      where: fragment("? @> ?", a.data, ^%{actor: user.ap_id, type: "Note"}),
+      select: count(a.id)
+
+    note_count = Repo.one(note_count_query)
+
+    new_info = Map.put(user.info, "note_count", note_count)
+
+    cs = info_changeset(user, %{info: new_info})
+
+    Repo.update(cs)
+  end
+
+  def update_follower_count(%User{} = user) do
+    follower_count_query = from u in User,
+      where: fragment("? @> ?", u.following, ^user.follower_address),
+      select: count(u.id)
+
+    follower_count = Repo.one(follower_count_query)
+
+    new_info = Map.put(user.info, "follower_count", follower_count)
+
+    cs = info_changeset(user, %{info: new_info})
+
+    Repo.update(cs)
+  end
 end
index f675901b208305f5551b2cf4a4999a4b0eb007cf..e55f972b21bc89d25046acf76658b9a346d9bfe9 100644 (file)
@@ -92,7 +92,9 @@ defmodule Pleroma.Web.OStatus.NoteHandler do
          # TODO: Handle this case in make_note_data
          note <- (if inReplyTo && !inReplyToActivity, do: note |> Map.put("inReplyTo", inReplyTo), else: note)
       do
-      ActivityPub.create(to, actor, context, note, %{}, date, false)
+      res = ActivityPub.create(to, actor, context, note, %{}, date, false)
+      User.update_note_count(actor)
+      res
     else
       %Activity{} = activity -> {:ok, activity}
       e -> {:error, e}
index 04c1d914cba96e4a5dfc9291a3a3dbb09a8d7d1c..dc66e27adba77965769539eed976b15a7daa8cdf 100644 (file)
@@ -39,7 +39,9 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
          context <- make_context(inReplyTo),
          tags <- Formatter.parse_tags(status),
          object <- make_note_data(user.ap_id, to, context, content_html, attachments, inReplyTo, tags) do
-      ActivityPub.create(to, user, context, object)
+      res = ActivityPub.create(to, user, context, object)
+      User.update_note_count(user)
+      res
     end
   end
 
index 1356ebde9a82093728c0133344e545f9afe603e6..eca73725dccea2839fb8f2172bbd2c3e7808b491 100644 (file)
@@ -7,7 +7,7 @@ defmodule Pleroma.Factory do
       email: sequence(:email, &"user#{&1}@example.com"),
       nickname: sequence(:nickname, &"nick#{&1}"),
       password_hash: Comeonin.Pbkdf2.hashpwsalt("test"),
-      bio: sequence(:bio, &"Tester Number #{&1}"),
+      bio: sequence(:bio, &"Tester Number #{&1}")
     }
     %{ user | ap_id: Pleroma.User.ap_id(user), follower_address: Pleroma.User.ap_followers(user) }
   end
index 81827afa318a11e43d88dd6d8a8bd73f8e25b92b..097d7d98e9740a727071232f6c22405fc27f02d4 100644 (file)
@@ -37,6 +37,9 @@ defmodule Pleroma.UserTest do
 
     user = Repo.get(User, user.id)
 
+    followed = User.get_by_ap_id(followed.ap_id)
+    assert followed.info["follower_count"] == 1
+
     assert user.following == [User.ap_followers(followed)]
   end
 
@@ -224,8 +227,37 @@ defmodule Pleroma.UserTest do
 
       {:ok, res} = User.get_friends(user)
 
+      followed_one = User.get_by_ap_id(followed_one.ap_id)
+      followed_two = User.get_by_ap_id(followed_two.ap_id)
       assert res == [followed_one, followed_two]
     end
   end
+
+  describe "updating note and follower count" do
+    test "it sets the info->note_count property" do
+      note = insert(:note)
+
+      user = User.get_by_ap_id(note.data["actor"])
+
+      assert user.info["note_count"] == nil
+
+      {:ok, user} = User.update_note_count(user)
+
+      assert user.info["note_count"] == 1
+    end
+
+    test "it sets the info->follower_count property" do
+      user = insert(:user)
+      follower = insert(:user)
+
+      User.follow(follower, user)
+
+      assert user.info["follower_count"] == nil
+
+      {:ok, user} = User.update_follower_count(user)
+
+      assert user.info["follower_count"] == 1
+    end
+  end
 end
 
index 34bfaa005261d4f41ac28a10dfc983df67611aa2..959b744afaa4dd2d5f5cfc1540f57a2f6d2c308d 100644 (file)
@@ -15,6 +15,8 @@ defmodule Pleroma.Web.OStatusTest do
     incoming = File.read!("test/fixtures/incoming_note_activity.xml")
     {:ok, [activity]} = OStatus.handle_incoming(incoming)
 
+    user = User.get_by_ap_id(activity.data["actor"])
+    assert user.info["note_count"] == 1
     assert activity.data["type"] == "Create"
     assert activity.data["object"]["type"] == "Note"
     assert activity.data["object"]["id"] == "tag:gs.example.org:4040,2017-04-23:noticeId=29:objectType=note"
index 48d48eb2b98664456aa26b3db78a7d212f3f7079..bbb261eff3c143459a90b9058b3ba4827fadd3cc 100644 (file)
@@ -9,8 +9,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
   import Pleroma.Factory
 
   test "create a status" do
-    # user = UserBuilder.build(%{ap_id: "142344"})
-    user = insert(:user, %{ap_id: "142344"})
+    user = insert(:user)
     _mentioned_user = UserBuilder.insert(%{nickname: "shp", ap_id: "shp"})
 
     object_data = %{
@@ -53,10 +52,14 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
     assert is_list(activity.data["object"]["attachment"])
 
     assert activity.data["object"] == Object.get_by_ap_id(activity.data["object"]["id"]).data
+
+    user = User.get_by_ap_id(user.ap_id)
+
+    assert user.info["note_count"] == 1
   end
 
   test "create a status that is a reply" do
-    user = UserBuilder.build(%{ap_id: "some_cool_id"})
+    user = insert(:user)
     input = %{
       "status" => "Hello again."
     }
@@ -74,7 +77,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
     assert get_in(reply.data, ["object", "context"]) == get_in(activity.data, ["object", "context"])
     assert get_in(reply.data, ["object", "inReplyTo"]) == get_in(activity.data, ["object", "id"])
     assert get_in(reply.data, ["object", "inReplyToStatusId"]) == activity.id
-    assert Enum.member?(get_in(reply.data, ["to"]), "some_cool_id")
+    assert Enum.member?(get_in(reply.data, ["to"]), user.ap_id)
   end
 
   test "fetch public statuses, excluding remote ones." do
@@ -188,6 +191,9 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
     {:ok, user, followed, _activity } = TwitterAPI.follow(user, %{"screen_name" => followed.nickname})
     assert user.following == [User.ap_followers(followed)]
 
+    followed = User.get_by_ap_id(followed.ap_id)
+    assert followed.info["follower_count"] == 1
+
     { :error, msg } = TwitterAPI.follow(user, %{"screen_name" => followed.nickname})
     assert msg == "Could not follow user: #{followed.nickname} is already on your list."
   end
index de2cd3d3019961e1d3900d07bd150262724a2c71..b81d3d64dce753c36e04df3264a0e8e4223854be 100644 (file)
@@ -22,6 +22,7 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
   test "A user" do
     note_activity = insert(:note_activity)
     user = User.get_cached_by_ap_id(note_activity.data["actor"])
+    {:ok, user} = User.update_note_count(user)
     follower = insert(:user)
     second_follower = insert(:user)
 
@@ -57,6 +58,7 @@ defmodule Pleroma.Web.TwitterAPI.UserViewTest do
 
   test "A user for a given other follower", %{user: user} do
     {:ok, follower} = UserBuilder.insert(%{following: [User.ap_followers(user)]})
+    {:ok, user} = User.update_follower_count(user)
     image = "https://placehold.it/48x48"
     represented = %{
       "id" => user.id,