- MastoAPI: Accept BooleanLike input on `/api/v1/accounts/:id/follow` (fixes follows with mastodon.py)
- Relays from akkoma are now off by default
- NormalizeMarkup MRF is now on by default
+- Follow/Block/Mute imports now spin off into *n* tasks to avoid the oban timeout
## 2022.11
require Logger
@spec perform(atom(), User.t(), list()) :: :ok | list() | {:error, any()}
- def perform(:mutes_import, %User{} = user, [_ | _] = identifiers) do
- Enum.map(
- identifiers,
- fn identifier ->
- with {:ok, %User{} = muted_user} <- User.get_or_fetch(identifier),
- {:ok, _} <- User.mute(user, muted_user) do
- muted_user
- else
- error -> handle_error(:mutes_import, identifier, error)
- end
- end
- )
+ def perform(:mutes_import, %User{} = user, identifier) do
+ with {:ok, %User{} = muted_user} <- User.get_or_fetch(identifier),
+ {:ok, _} <- User.mute(user, muted_user) do
+ muted_user
+ else
+ error -> handle_error(:mutes_import, identifier, error)
+ end
end
- def perform(:blocks_import, %User{} = blocker, [_ | _] = identifiers) do
- Enum.map(
- identifiers,
- fn identifier ->
- with {:ok, %User{} = blocked} <- User.get_or_fetch(identifier),
- {:ok, _block} <- CommonAPI.block(blocker, blocked) do
- blocked
- else
- error -> handle_error(:blocks_import, identifier, error)
- end
- end
- )
+ def perform(:blocks_import, %User{} = blocker, identifier) do
+ with {:ok, %User{} = blocked} <- User.get_or_fetch(identifier),
+ {:ok, _block} <- CommonAPI.block(blocker, blocked) do
+ blocked
+ else
+ error -> handle_error(:blocks_import, identifier, error)
+ end
end
- def perform(:follow_import, %User{} = follower, [_ | _] = identifiers) do
- Enum.map(
- identifiers,
- fn identifier ->
- with {:ok, %User{} = followed} <- User.get_or_fetch(identifier),
- {:ok, follower, followed} <- User.maybe_direct_follow(follower, followed),
- {:ok, _, _, _} <- CommonAPI.follow(follower, followed) do
- followed
- else
- error -> handle_error(:follow_import, identifier, error)
- end
- end
- )
+ def perform(:follow_import, %User{} = follower, identifier) do
+ with {:ok, %User{} = followed} <- User.get_or_fetch(identifier),
+ {:ok, follower, followed} <- User.maybe_direct_follow(follower, followed),
+ {:ok, _, _, _} <- CommonAPI.follow(follower, followed) do
+ followed
+ else
+ error -> handle_error(:follow_import, identifier, error)
+ end
end
def perform(_, _, _), do: :ok
error
end
- def blocks_import(%User{} = blocker, [_ | _] = identifiers) do
- BackgroundWorker.enqueue(
- "blocks_import",
- %{"user_id" => blocker.id, "identifiers" => identifiers}
+ defp enqueue_many(op, user, identifiers) do
+ Enum.map(
+ identifiers,
+ fn identifier ->
+ BackgroundWorker.enqueue(op, %{"user_id" => user.id, "identifier" => identifier})
+ end
)
end
+ def blocks_import(%User{} = blocker, [_ | _] = identifiers) do
+ enqueue_many("blocks_import", blocker, identifiers)
+ end
+
def follow_import(%User{} = follower, [_ | _] = identifiers) do
- BackgroundWorker.enqueue(
- "follow_import",
- %{"user_id" => follower.id, "identifiers" => identifiers}
- )
+ enqueue_many("follow_import", follower, identifiers)
end
def mutes_import(%User{} = user, [_ | _] = identifiers) do
- BackgroundWorker.enqueue(
- "mutes_import",
- %{"user_id" => user.id, "identifiers" => identifiers}
- )
+ enqueue_many("mutes_import", user, identifiers)
end
end
User.perform(:force_password_reset, user)
end
- def perform(%Job{args: %{"op" => op, "user_id" => user_id, "identifiers" => identifiers}})
+ def perform(%Job{args: %{"op" => op, "user_id" => user_id, "identifier" => identifier}})
when op in ["blocks_import", "follow_import", "mutes_import"] do
user = User.get_cached_by_id(user_id)
- {:ok, User.Import.perform(String.to_atom(op), user, identifiers)}
+ {:ok, User.Import.perform(String.to_atom(op), user, identifier)}
end
def perform(%Job{
text = "I love :firefox:"
expected_result =
- "I love <img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\"/>"
+ "I love <img alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\"/>"
assert Formatter.emojify(text) == expected_result
end
user3.nickname
]
- {:ok, job} = User.Import.follow_import(user1, identifiers)
+ [{:ok, job1}, {:ok, job2}] = User.Import.follow_import(user1, identifiers)
+
+ assert {:ok, result} = ObanHelpers.perform(job1)
+ assert result == refresh_record(user2)
+
+ assert {:ok, result} = ObanHelpers.perform(job2)
+ assert result == refresh_record(user3)
- assert {:ok, result} = ObanHelpers.perform(job)
- assert is_list(result)
- assert result == [refresh_record(user2), refresh_record(user3)]
assert User.following?(user1, user2)
assert User.following?(user1, user3)
end
user3.nickname
]
- {:ok, job} = User.Import.blocks_import(user1, identifiers)
+ [{:ok, job1}, {:ok, job2}] = User.Import.blocks_import(user1, identifiers)
+
+ assert {:ok, result} = ObanHelpers.perform(job1)
+ assert result == user2
+
+ assert {:ok, result} = ObanHelpers.perform(job2)
+ assert result == user3
- assert {:ok, result} = ObanHelpers.perform(job)
- assert is_list(result)
- assert result == [user2, user3]
assert User.blocks?(user1, user2)
assert User.blocks?(user1, user3)
end
user3.nickname
]
- {:ok, job} = User.Import.mutes_import(user1, identifiers)
+ [{:ok, job1}, {:ok, job2}] = User.Import.mutes_import(user1, identifiers)
+
+ assert {:ok, result} = ObanHelpers.perform(job1)
+ assert result == user2
+
+ assert {:ok, result} = ObanHelpers.perform(job2)
+ assert result == user3
- assert {:ok, result} = ObanHelpers.perform(job)
- assert is_list(result)
- assert result == [user2, user3]
assert User.mutes?(user1, user2)
assert User.mutes?(user1, user3)
end
|> json_response_and_validate_schema(200)
assert [{:ok, job_result}] = ObanHelpers.perform_all()
- assert job_result == [refresh_record(user2)]
- assert [%Pleroma.User{follower_count: 1}] = job_result
+ assert job_result == refresh_record(user2)
+ assert %Pleroma.User{follower_count: 1} = job_result
end
end
|> post("/api/pleroma/follow_import", %{"list" => identifiers})
|> json_response_and_validate_schema(200)
- assert [{:ok, job_result}] = ObanHelpers.perform_all()
- assert job_result == Enum.map(users, &refresh_record/1)
+ job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+ assert job_results == Enum.map(users, &refresh_record/1)
end
end
})
|> json_response_and_validate_schema(200)
- assert [{:ok, job_result}] = ObanHelpers.perform_all()
- assert job_result == users
+ job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+ assert job_results == users
end
end
|> post("/api/pleroma/blocks_import", %{"list" => identifiers})
|> json_response_and_validate_schema(200)
- assert [{:ok, job_result}] = ObanHelpers.perform_all()
- assert job_result == users
+ job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+ assert job_results == users
end
end
|> post("/api/pleroma/mutes_import", %{"list" => "#{user2.ap_id}"})
|> json_response_and_validate_schema(200)
- assert [{:ok, job_result}] = ObanHelpers.perform_all()
- assert job_result == [user2]
+ job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+ assert job_results == [user2]
assert Pleroma.User.mutes?(user, user2)
end
- test "it imports mutes users from file", %{user: user, conn: conn} do
+ test "it imports muted users from file", %{user: user, conn: conn} do
users = [user2, user3] = insert_list(2, :user)
with_mocks([
})
|> json_response_and_validate_schema(200)
- assert [{:ok, job_result}] = ObanHelpers.perform_all()
- assert job_result == users
+ job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+ assert job_results == users
assert Enum.all?(users, &Pleroma.User.mutes?(user, &1))
end
end
|> post("/api/pleroma/mutes_import", %{"list" => identifiers})
|> json_response_and_validate_schema(200)
- assert [{:ok, job_result}] = ObanHelpers.perform_all()
- assert job_result == users
+ job_results = Enum.map(ObanHelpers.perform_all(), fn {:ok, result} -> result end)
+ assert job_results == users
assert Enum.all?(users, &Pleroma.User.mutes?(user, &1))
end
end