import Mix.Pleroma
alias Ecto.Changeset
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.UserInviteToken
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.Pipeline
@shortdoc "Manages Pleroma users"
- @moduledoc File.read!("docs/administration/CLI_tasks/user.md")
+ @moduledoc File.read!("docs/docs/administration/CLI_tasks/user.md")
def run(["new", nickname, email | rest]) do
{options, [], []} =
A user will be created with the following information:
- nickname: #{nickname}
- email: #{email}
- - password: #{
- if(generated_password?, do: "[generated; a reset link will be created]", else: password)
- }
+ - password: #{if(generated_password?, do: "[generated; a reset link will be created]", else: password)}
- name: #{name}
- bio: #{bio}
- moderator: #{if(moderator?, do: "true", else: "false")}
shell_info("Generated password reset token for #{user.nickname}")
IO.puts(
- "URL: #{
- Pleroma.Web.Router.Helpers.reset_password_url(
- Pleroma.Web.Endpoint,
- :reset,
- token.token
- )
- }"
+ "URL: #{Pleroma.Web.Router.Helpers.reset_password_url(Pleroma.Web.Endpoint,
+ :reset,
+ token.token)}"
)
else
_ ->
end
end
+ def run(["refetch_public_keys"]) do
+ start_pleroma()
+
+ Pleroma.User.Query.build(%{
+ external: true,
+ is_active: true
+ })
+ |> refetch_public_keys()
+ end
+
+ def run(["refetch_public_keys" | rest]) do
+ start_pleroma()
+
+ Pleroma.User.Query.build(%{
+ ap_id: rest
+ })
+ |> refetch_public_keys()
+ end
+
def run(["invite" | rest]) do
{options, [], []} =
OptionParser.parse(rest,
end
shell_info(
- "ID: #{invite.id} | Token: #{invite.token} | Token type: #{invite.invite_type} | Used: #{
- invite.used
- }#{expire_info}#{using_info}"
+ "ID: #{invite.id} | Token: #{invite.token} | Token type: #{invite.invite_type} | Used: #{invite.used}#{expire_info}#{using_info}"
)
end)
end
def run(["show", nickname]) do
start_pleroma()
- nickname
- |> User.get_cached_by_nickname()
- |> IO.inspect()
+ user =
+ nickname
+ |> User.get_cached_by_nickname()
+
+ shell_info("#{inspect(user)}")
end
def run(["send_confirmation", nickname]) do
with %User{} = user <- User.get_cached_by_nickname(nickname) do
user
|> Pleroma.Emails.UserEmail.account_confirmation_email()
- |> IO.inspect()
|> Pleroma.Emails.Mailer.deliver!()
shell_info("#{nickname}'s email sent")
end
end
+ def run(["blocking", nickname]) do
+ start_pleroma()
+
+ with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
+ blocks = User.following_ap_ids(user)
+ IO.puts("#{inspect(blocks)}")
+ end
+ end
+
+ def run(["timeline_query", nickname]) do
+ start_pleroma()
+
+ params = %{local: true}
+
+ with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
+ followed_hashtags =
+ user
+ |> User.followed_hashtags()
+ |> Enum.map(& &1.id)
+
+ params =
+ params
+ |> Map.put(:type, ["Create", "Announce"])
+ |> Map.put(:limit, 20)
+ |> Map.put(:blocking_user, user)
+ |> Map.put(:muting_user, user)
+ |> Map.put(:reply_filtering_user, user)
+ |> Map.put(:announce_filtering_user, user)
+ |> Map.put(:user, user)
+ |> Map.put(:local_only, params[:local])
+ |> Map.put(:hashtags, followed_hashtags)
+ |> Map.delete(:local)
+
+ _activities =
+ [user.ap_id | User.following(user)]
+ |> ActivityPub.fetch_activities(params)
+ end
+ end
+
def run(["list"]) do
start_pleroma()
users
|> Enum.each(fn user ->
shell_info(
- "#{user.nickname} moderator: #{user.is_moderator}, admin: #{user.is_admin}, locked: #{
- user.is_locked
- }, is_active: #{user.is_active}"
+ "#{user.nickname} moderator: #{user.is_moderator}, admin: #{user.is_admin}, locked: #{user.is_locked}, is_active: #{user.is_active}"
)
end)
end)
|> Stream.run()
end
+ def run(["fix_follow_state", local_user, remote_user]) do
+ start_pleroma()
+
+ with {:local, %User{} = local} <- {:local, User.get_by_nickname(local_user)},
+ {:remote, %User{} = remote} <- {:remote, User.get_by_nickname(remote_user)},
+ {:follow_data, %{data: %{"state" => request_state}}} <-
+ {:follow_data, Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(local, remote)} do
+ calculated_state = User.following?(local, remote)
+
+ IO.puts(
+ "Request state is #{request_state}, vs calculated state of following=#{calculated_state}"
+ )
+
+ if calculated_state == false && request_state == "accept" do
+ IO.puts("Discrepancy found, fixing")
+ Pleroma.Web.CommonAPI.reject_follow_request(local, remote)
+ shell_info("Relationship fixed")
+ else
+ shell_info("No discrepancy found")
+ end
+ else
+ {:local, _} ->
+ shell_error("No local user #{local_user}")
+
+ {:remote, _} ->
+ shell_error("No remote user #{remote_user}")
+
+ {:follow_data, _} ->
+ shell_error("No follow data for #{local_user} and #{remote_user}")
+ end
+ end
+
+ def run(["convert_id", id]) do
+ {:ok, uuid} = FlakeId.Ecto.Type.dump(id)
+ {:ok, raw_id} = Ecto.UUID.load(uuid)
+ shell_info(raw_id)
+ end
+
+ defp refetch_public_keys(query) do
+ query
+ |> Pleroma.Repo.chunk_stream(50, :batches)
+ |> Stream.each(fn users ->
+ users
+ |> Enum.each(fn user ->
+ IO.puts("Re-Resolving: #{user.ap_id}")
+
+ with {:ok, user} <- Pleroma.User.fetch_by_ap_id(user.ap_id),
+ changeset <- Pleroma.User.update_changeset(user),
+ {:ok, _user} <- Pleroma.User.update_and_set_cache(changeset) do
+ :ok
+ else
+ error -> IO.puts("Could not resolve: #{user.ap_id}, #{inspect(error)}")
+ end
+ end)
+ end)
+ |> Stream.run()
+ end
+
defp set_moderator(user, value) do
{:ok, user} =
user