Add user hashtag follow/unfollow functions

This commit is contained in:
FloatingGhost 2022-12-04 00:33:23 +00:00
parent ec6bf8c3f7
commit cb889a1539
5 changed files with 156 additions and 0 deletions

View File

@ -18,6 +18,8 @@ defmodule Pleroma.User do
alias Pleroma.Emoji
alias Pleroma.FollowingRelationship
alias Pleroma.Formatter
alias Pleroma.Hashtag
alias Pleroma.User.HashtagFollow
alias Pleroma.HTML
alias Pleroma.Keys
alias Pleroma.MFA
@ -168,6 +170,12 @@ defmodule Pleroma.User do
has_many(:frontend_profiles, Pleroma.Akkoma.FrontendSettingsProfile)
many_to_many(:followed_hashtags, Hashtag,
on_replace: :delete,
on_delete: :delete_all,
join_through: HashtagFollow
)
for {relationship_type,
[
{outgoing_relation, outgoing_relation_target},
@ -2550,4 +2558,24 @@ defmodule Pleroma.User do
_ -> {:error, user}
end
end
def hashtag_follows(%User{} = user) do
HashtagFollow
|> where(user_id: ^user.id)
|> Repo.all()
end
def follow_hashtag(%User{} = user, %Hashtag{} = hashtag) do
Logger.debug("Follow hashtag #{hashtag.name} for user #{user.nickname}")
HashtagFollow.new(user, hashtag)
end
def unfollow_hashtag(%User{} = user, %Hashtag{} = hashtag) do
Logger.debug("Unfollow hashtag #{hashtag.name} for user #{user.nickname}")
from(hf in HashtagFollow)
|> where([hf], hf.user_id == ^user.id and hf.hashtag_id == ^hashtag.id)
|> Repo.delete_all()
end
end

View File

@ -0,0 +1,29 @@
defmodule Pleroma.User.HashtagFollow do
use Ecto.Schema
import Ecto.Changeset
alias Pleroma.User
alias Pleroma.Hashtag
alias Pleroma.Repo
schema "user_follows_hashtag" do
belongs_to(:user, User, type: FlakeId.Ecto.CompatType)
belongs_to(:hashtag, Hashtag)
end
def changeset(%__MODULE__{} = user_hashtag_follow, attrs) do
user_hashtag_follow
|> cast(attrs, [:user_id, :hashtag_id])
|> unique_constraint(:hashtag_id,
name: :user_hashtag_follows_user_id_hashtag_id_index,
message: "already following"
)
|> validate_required([:user_id, :hashtag_id])
end
def new(%User{} = user, %Hashtag{} = hashtag) do
%__MODULE__{}
|> changeset(%{user_id: user.id, hashtag_id: hashtag.id})
|> Repo.insert(on_conflict: :nothing)
end
end

View File

@ -0,0 +1,12 @@
defmodule Pleroma.Repo.Migrations.AddUserFollowsHashtag do
use Ecto.Migration
def change do
create table(:user_follows_hashtag) do
add(:hashtag_id, references(:hashtags))
add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
end
create(unique_index(:user_follows_hashtag, [:user_id, :hashtag_id]))
end
end

View File

@ -2679,4 +2679,84 @@ defmodule Pleroma.UserTest do
assert user.ap_id in user3_updated.also_known_as
end
end
describe "follow_hashtag/2" do
test "should follow a hashtag" do
user = insert(:user)
hashtag = insert(:hashtag)
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
user =
User.get_cached_by_ap_id(user.ap_id)
|> Repo.preload(:followed_hashtags)
assert user.followed_hashtags |> length() == 1
assert hashtag.name in Enum.map(user.followed_hashtags, fn %{name: name} -> name end)
end
test "should not follow a hashtag twice" do
user = insert(:user)
hashtag = insert(:hashtag)
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
user =
User.get_cached_by_ap_id(user.ap_id)
|> Repo.preload(:followed_hashtags)
assert user.followed_hashtags |> length() == 1
assert hashtag.name in Enum.map(user.followed_hashtags, fn %{name: name} -> name end)
end
test "can follow multiple hashtags" do
user = insert(:user)
hashtag = insert(:hashtag)
other_hashtag = insert(:hashtag)
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
assert {:ok, _} = user |> User.follow_hashtag(other_hashtag)
user =
User.get_cached_by_ap_id(user.ap_id)
|> Repo.preload(:followed_hashtags)
assert user.followed_hashtags |> length() == 2
assert hashtag.name in Enum.map(user.followed_hashtags, fn %{name: name} -> name end)
assert other_hashtag.name in Enum.map(user.followed_hashtags, fn %{name: name} -> name end)
end
end
describe "unfollow_hashtag/2" do
test "should unfollow a hashtag" do
user = insert(:user)
hashtag = insert(:hashtag)
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
assert {1, nil} = user |> User.unfollow_hashtag(hashtag)
user =
User.get_cached_by_ap_id(user.ap_id)
|> Repo.preload(:followed_hashtags)
assert user.followed_hashtags |> length() == 0
end
test "should not error when trying to unfollow a hashtag twice" do
user = insert(:user)
hashtag = insert(:hashtag)
assert {:ok, _} = user |> User.follow_hashtag(hashtag)
assert {1, nil} = user |> User.unfollow_hashtag(hashtag)
assert {0, nil} = user |> User.unfollow_hashtag(hashtag)
user =
User.get_cached_by_ap_id(user.ap_id)
|> Repo.preload(:followed_hashtags)
assert user.followed_hashtags |> length() == 0
end
end
end

View File

@ -716,4 +716,11 @@ defmodule Pleroma.Factory do
user: user
}
end
def hashtag_factory(params \\ %{}) do
%Pleroma.Hashtag{
name: "test #{sequence(:hashtag_name, & &1)}"
}
|> Map.merge(params)
end
end