Merge pull request 'metrics' (#375) from stats into develop
[akkoma] / lib / pleroma / list.ex
index 81b842e9cd909048c77b7dbaf37e880e9404b1f7..fe5721c342de61fcf2b71a0f5c8c985196bdfaee 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.List do
@@ -12,12 +12,11 @@ defmodule Pleroma.List do
   alias Pleroma.Repo
   alias Pleroma.User
 
-  @ap_id_regex ~r/^\/users\/(?<nickname>\w+)\/lists\/(?<list_id>\d+)/
-
   schema "lists" do
-    belongs_to(:user, User, type: Pleroma.FlakeId)
+    belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
     field(:title, :string)
     field(:following, {:array, :string}, default: [])
+    field(:ap_id, :string)
 
     timestamps()
   end
@@ -34,12 +33,6 @@ defmodule Pleroma.List do
     |> validate_required([:following])
   end
 
-  def ap_id(%User{nickname: nickname}, list_id) do
-    Pleroma.Web.Endpoint.url() <> "/users/#{nickname}/lists/#{list_id}"
-  end
-
-  def ap_id({nickname, list_id}), do: ap_id(%User{nickname: nickname}, list_id)
-
   def for_user(user, _opts) do
     query =
       from(
@@ -64,16 +57,7 @@ defmodule Pleroma.List do
   end
 
   def get_by_ap_id(ap_id) do
-    host = Pleroma.Web.Endpoint.host()
-
-    with %{host: ^host, path: path} <- URI.parse(ap_id),
-         %{"list_id" => list_id, "nickname" => nickname} <-
-           Regex.named_captures(@ap_id_regex, path),
-         %User{} = user <- User.get_cached_by_nickname(nickname) do
-      get(list_id, user)
-    else
-      _ -> nil
-    end
+    Repo.get_by(__MODULE__, ap_id: ap_id)
   end
 
   def get_following(%Pleroma.List{following: following} = _list) do
@@ -100,22 +84,11 @@ defmodule Pleroma.List do
   end
 
   # Get lists to which the account belongs.
-  def get_lists_account_belongs(%User{} = owner, account_id) do
-    user = User.get_cached_by_id(account_id)
-
-    query =
-      from(
-        l in Pleroma.List,
-        where:
-          l.user_id == ^owner.id and
-            fragment(
-              "? = ANY(?)",
-              ^user.follower_address,
-              l.following
-            )
-      )
-
-    Repo.all(query)
+  def get_lists_account_belongs(%User{} = owner, user) do
+    Pleroma.List
+    |> where([l], l.user_id == ^owner.id)
+    |> where([l], fragment("? = ANY(?)", ^user.follower_address, l.following))
+    |> Repo.all()
   end
 
   def rename(%Pleroma.List{} = list, title) do
@@ -125,15 +98,30 @@ defmodule Pleroma.List do
   end
 
   def create(title, %User{} = creator) do
-    list = %Pleroma.List{user_id: creator.id, title: title}
-    Repo.insert(list)
+    changeset = title_changeset(%Pleroma.List{user_id: creator.id}, %{title: title})
+
+    if changeset.valid? do
+      Repo.transaction(fn ->
+        list = Repo.insert!(changeset)
+
+        list
+        |> change(ap_id: "#{creator.ap_id}/lists/#{list.id}")
+        |> Repo.update!()
+      end)
+    else
+      {:error, changeset}
+    end
   end
 
-  def follow(%Pleroma.List{following: following} = list, %User{} = followed) do
+  def follow(%Pleroma.List{id: id}, %User{} = followed) do
+    list = Repo.get(Pleroma.List, id)
+    %{following: following} = list
     update_follows(list, %{following: Enum.uniq([followed.follower_address | following])})
   end
 
-  def unfollow(%Pleroma.List{following: following} = list, %User{} = unfollowed) do
+  def unfollow(%Pleroma.List{id: id}, %User{} = unfollowed) do
+    list = Repo.get(Pleroma.List, id)
+    %{following: following} = list
     update_follows(list, %{following: List.delete(following, unfollowed.follower_address)})
   end
 
@@ -150,11 +138,15 @@ defmodule Pleroma.List do
   def memberships(%User{follower_address: follower_address}) do
     Pleroma.List
     |> where([l], ^follower_address in l.following)
-    |> join(:inner, [l], u in User, on: l.user_id == u.id)
-    |> select([l, u], {u.nickname, l.id})
+    |> select([l], l.ap_id)
     |> Repo.all()
-    |> Enum.map(&ap_id/1)
   end
 
   def memberships(_), do: []
+
+  def member?(%Pleroma.List{following: following}, %User{follower_address: follower_address}) do
+    Enum.member?(following, follower_address)
+  end
+
+  def member?(_, _), do: false
 end