logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

uploads.ex (2963B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Mix.Tasks.Pleroma.Uploads do
  5. use Mix.Task
  6. import Mix.Pleroma
  7. alias Pleroma.Upload
  8. alias Pleroma.Uploaders.Local
  9. require Logger
  10. @log_every 50
  11. @shortdoc "Migrates uploads from local to remote storage"
  12. @moduledoc File.read!("docs/administration/CLI_tasks/uploads.md")
  13. def run(["migrate_local", target_uploader | args]) do
  14. delete? = Enum.member?(args, "--delete")
  15. start_pleroma()
  16. local_path = Pleroma.Config.get!([Local, :uploads])
  17. uploader = Module.concat(Pleroma.Uploaders, target_uploader)
  18. unless Code.ensure_loaded?(uploader) do
  19. raise("The uploader #{inspect(uploader)} is not an existing/loaded module.")
  20. end
  21. target_enabled? = Pleroma.Config.get([Upload, :uploader]) == uploader
  22. unless target_enabled? do
  23. Pleroma.Config.put([Upload, :uploader], uploader)
  24. end
  25. shell_info("Migrating files from local #{local_path} to #{to_string(uploader)}")
  26. if delete? do
  27. shell_info(
  28. "Attention: uploaded files will be deleted, hope you have backups! (--delete ; cancel with ^C)"
  29. )
  30. :timer.sleep(:timer.seconds(5))
  31. end
  32. uploads =
  33. File.ls!(local_path)
  34. |> Enum.map(fn id ->
  35. root_path = Path.join(local_path, id)
  36. cond do
  37. File.dir?(root_path) ->
  38. files = for file <- File.ls!(root_path), do: {id, file, Path.join([root_path, file])}
  39. case List.first(files) do
  40. {id, file, path} ->
  41. {%Pleroma.Upload{id: id, name: file, path: id <> "/" <> file, tempfile: path},
  42. root_path}
  43. _ ->
  44. nil
  45. end
  46. File.exists?(root_path) ->
  47. file = Path.basename(id)
  48. hash = Path.rootname(id)
  49. {%Pleroma.Upload{id: hash, name: file, path: file, tempfile: root_path}, root_path}
  50. true ->
  51. nil
  52. end
  53. end)
  54. |> Enum.filter(& &1)
  55. total_count = length(uploads)
  56. shell_info("Found #{total_count} uploads")
  57. uploads
  58. |> Task.async_stream(
  59. fn {upload, root_path} ->
  60. case Upload.store(upload, uploader: uploader, filters: [], size_limit: nil) do
  61. {:ok, _} ->
  62. if delete?, do: File.rm_rf!(root_path)
  63. Logger.debug("uploaded: #{inspect(upload.path)} #{inspect(upload)}")
  64. :ok
  65. error ->
  66. shell_error("failed to upload #{inspect(upload.path)}: #{inspect(error)}")
  67. end
  68. end,
  69. timeout: 150_000
  70. )
  71. |> Stream.chunk_every(@log_every)
  72. # credo:disable-for-next-line Credo.Check.Warning.UnusedEnumOperation
  73. |> Enum.reduce(0, fn done, count ->
  74. count = count + length(done)
  75. shell_info("Uploaded #{count}/#{total_count} files")
  76. count
  77. end)
  78. shell_info("Done!")
  79. end
  80. end