forked from AkkomaGang/akkoma
Add user hashtag follow/unfollow functions
This commit is contained in:
parent
6b882a2c0b
commit
2edd1cf094
5 changed files with 156 additions and 0 deletions
|
@ -18,6 +18,8 @@ defmodule Pleroma.User do
|
||||||
alias Pleroma.Emoji
|
alias Pleroma.Emoji
|
||||||
alias Pleroma.FollowingRelationship
|
alias Pleroma.FollowingRelationship
|
||||||
alias Pleroma.Formatter
|
alias Pleroma.Formatter
|
||||||
|
alias Pleroma.Hashtag
|
||||||
|
alias Pleroma.User.HashtagFollow
|
||||||
alias Pleroma.HTML
|
alias Pleroma.HTML
|
||||||
alias Pleroma.Keys
|
alias Pleroma.Keys
|
||||||
alias Pleroma.MFA
|
alias Pleroma.MFA
|
||||||
|
@ -168,6 +170,12 @@ defmodule Pleroma.User do
|
||||||
|
|
||||||
has_many(:frontend_profiles, Pleroma.Akkoma.FrontendSettingsProfile)
|
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,
|
for {relationship_type,
|
||||||
[
|
[
|
||||||
{outgoing_relation, outgoing_relation_target},
|
{outgoing_relation, outgoing_relation_target},
|
||||||
|
@ -2550,4 +2558,24 @@ defmodule Pleroma.User do
|
||||||
_ -> {:error, user}
|
_ -> {:error, user}
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
29
lib/pleroma/user/hashtag_follow.ex
Normal file
29
lib/pleroma/user/hashtag_follow.ex
Normal 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
|
|
@ -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
|
|
@ -2679,4 +2679,84 @@ defmodule Pleroma.UserTest do
|
||||||
assert user.ap_id in user3_updated.also_known_as
|
assert user.ap_id in user3_updated.also_known_as
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
@ -716,4 +716,11 @@ defmodule Pleroma.Factory do
|
||||||
user: user
|
user: user
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def hashtag_factory(params \\ %{}) do
|
||||||
|
%Pleroma.Hashtag{
|
||||||
|
name: "test #{sequence(:hashtag_name, & &1)}"
|
||||||
|
}
|
||||||
|
|> Map.merge(params)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue