aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/list.ex
diff options
context:
space:
mode:
authordcc <dcc@logografos.com>2023-09-02 00:52:52 -0700
committerdcc <dcc@logografos.com>2023-09-02 00:52:52 -0700
commit3a4773c3c2bd0bbef244eb519b07208da9108e49 (patch)
tree973567a6f3abb37bfb0f785b1cad14ed55840ef5 /lib/pleroma/list.ex
downloadanni-3a4773c3c2bd0bbef244eb519b07208da9108e49.tar.gz
anni-3a4773c3c2bd0bbef244eb519b07208da9108e49.tar.bz2
anni-3a4773c3c2bd0bbef244eb519b07208da9108e49.zip
First
Diffstat (limited to 'lib/pleroma/list.ex')
-rw-r--r--lib/pleroma/list.ex152
1 files changed, 152 insertions, 0 deletions
diff --git a/lib/pleroma/list.ex b/lib/pleroma/list.ex
new file mode 100644
index 0000000..b446b91
--- /dev/null
+++ b/lib/pleroma/list.ex
@@ -0,0 +1,152 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.List do
+ use Ecto.Schema
+
+ import Ecto.Query
+ import Ecto.Changeset
+
+ alias Pleroma.Activity
+ alias Pleroma.Repo
+ alias Pleroma.User
+
+ schema "lists" do
+ belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
+ field(:title, :string)
+ field(:following, {:array, :string}, default: [])
+ field(:ap_id, :string)
+
+ timestamps()
+ end
+
+ def title_changeset(list, attrs \\ %{}) do
+ list
+ |> cast(attrs, [:title])
+ |> validate_required([:title])
+ end
+
+ def follow_changeset(list, attrs \\ %{}) do
+ list
+ |> cast(attrs, [:following])
+ |> validate_required([:following])
+ end
+
+ def for_user(user, _opts) do
+ query =
+ from(
+ l in Pleroma.List,
+ where: l.user_id == ^user.id,
+ order_by: [desc: l.id],
+ limit: 50
+ )
+
+ Repo.all(query)
+ end
+
+ def get(id, %{id: user_id} = _user) do
+ query =
+ from(
+ l in Pleroma.List,
+ where: l.id == ^id,
+ where: l.user_id == ^user_id
+ )
+
+ Repo.one(query)
+ end
+
+ def get_by_ap_id(ap_id) do
+ Repo.get_by(__MODULE__, ap_id: ap_id)
+ end
+
+ def get_following(%Pleroma.List{following: following} = _list) do
+ q =
+ from(
+ u in User,
+ where: u.follower_address in ^following
+ )
+
+ {:ok, Repo.all(q)}
+ end
+
+ # Get lists the activity should be streamed to.
+ def get_lists_from_activity(%Activity{actor: ap_id}) do
+ actor = User.get_cached_by_ap_id(ap_id)
+
+ query =
+ from(
+ l in Pleroma.List,
+ where: fragment("? && ?", l.following, ^[actor.follower_address])
+ )
+
+ Repo.all(query)
+ end
+
+ # Get lists to which the account belongs.
+ 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
+ list
+ |> title_changeset(%{title: title})
+ |> Repo.update()
+ end
+
+ def create(title, %User{} = creator) do
+ 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{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{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
+
+ def delete(%Pleroma.List{} = list) do
+ Repo.delete(list)
+ end
+
+ def update_follows(%Pleroma.List{} = list, attrs) do
+ list
+ |> follow_changeset(attrs)
+ |> Repo.update()
+ end
+
+ def memberships(%User{follower_address: follower_address}) do
+ Pleroma.List
+ |> where([l], ^follower_address in l.following)
+ |> select([l], l.ap_id)
+ |> Repo.all()
+ 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