1
0
Fork 0
mirror of https://git.pleroma.social/pleroma/pleroma.git synced 2026-02-15 17:16:57 +00:00

Make chat backup be in separate files

This commit is contained in:
Ekaterina Vaartis 2025-05-30 17:50:37 +03:00 committed by vaartis
parent a1f9205b5e
commit 78c6e971a9
2 changed files with 58 additions and 49 deletions

View file

@ -14,8 +14,8 @@ defmodule Pleroma.User.Backup do
alias Pleroma.Activity
alias Pleroma.Bookmark
alias Pleroma.Config
alias Pleroma.Chat
alias Pleroma.Config
alias Pleroma.Repo
alias Pleroma.SafeZip
alias Pleroma.Uploaders.Uploader
@ -180,16 +180,20 @@ defmodule Pleroma.User.Backup do
|> Repo.update()
end
@files [
"actor.json",
"outbox.json",
"likes.json",
"bookmarks.json",
"followers.json",
"following.json",
'chats.json',
'chat_messages.json'
]
defp files(%{id: user_id}) do
[
"actor.json",
"outbox.json",
"likes.json",
"bookmarks.json",
"followers.json",
"following.json",
"chats.json"
] ++
(Chat.for_user_query(user_id)
|> Repo.all()
|> Enum.map(fn ch -> "#{chat_file(ch)}.json" end))
end
@spec run(t()) :: {:ok, t()} | {:error, :failed}
def run(%__MODULE__{} = backup) do
@ -203,10 +207,10 @@ defmodule Pleroma.User.Backup do
{_, :ok} <- {:bookmarks, bookmarks(backup.tempdir, backup.user)},
{_, :ok} <- {:followers, followers(backup.tempdir, backup.user)},
{_, :ok} <- {:following, following(backup.tempdir, backup.user)},
{_, :ok} <- chats(dir, backup.user, caller_pid),
{_, :ok} <- chat_messages(dir, backup.user, caller_pid),
{_, :ok} <- {:chats, chats(backup.tempdir, backup.user)},
{_, :ok} <- {:chat_messages, chat_messages(backup.tempdir, backup.user)},
{_, {:ok, _zip_path}} <-
{:zip, SafeZip.zip(tempfile, @files, backup.tempdir)},
{:zip, SafeZip.zip(tempfile, files(backup.user), backup.tempdir)},
{_, {:ok, %File.Stat{size: zip_size}}} <- {:filestat, File.stat(tempfile)},
{:ok, updated_backup} <- update_record(backup, %{file_size: zip_size}) do
{:ok, updated_backup}
@ -354,7 +358,9 @@ defmodule Pleroma.User.Backup do
)
end
defp chats(dir, user, caller_pid) do
defp chat_file(%{:id => chat_id}), do: "chat_messages_#{chat_id}"
defp chats(dir, user) do
Chat.for_user_query(user.id)
|> write(
dir,
@ -367,43 +373,43 @@ defmodule Pleroma.User.Backup do
"actor" => user.ap_id,
"to" => [chat.recipient],
"published" =>
chat.inserted_at |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601()
chat.inserted_at |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601(),
"messages" => "#{chat_file(chat)}.json"
}}
end,
caller_pid
end
)
end
defp chat_messages(dir, %{id: user_id}, caller_pid) do
chats_subquery =
from(c in Chat,
where: c.user_id == ^user_id,
select: c.id
)
defp chat_messages(dir, %{id: user_id}) do
results =
Chat.for_user_query(user_id)
|> Repo.all()
|> Enum.map(fn ch ->
from(
cr in Chat.MessageReference,
where: cr.chat_id == ^ch.id,
preload: [:object]
)
|> write(
dir,
chat_file(ch),
fn reference ->
with {:ok, activity} <- Transmogrifier.prepare_outgoing(reference.object.data),
{:ok, activity} <-
{:ok,
Map.put(
activity,
"context",
"#{Pleroma.Web.Endpoint.url()}/chats/#{reference.chat_id}"
)} do
{:ok, Map.delete(activity, "@context")}
end
end
)
end)
from(cr in Chat.MessageReference,
where: cr.chat_id in subquery(chats_subquery),
preload: [:object]
)
|> write(
dir,
"chat_messages",
fn reference ->
with {:ok, activity} <- Transmogrifier.prepare_outgoing(reference.object.data),
{:ok, activity} <-
{:ok,
Map.put(
activity,
"context",
"#{Pleroma.Web.Endpoint.url()}/chats/#{reference.chat_id}"
)} do
{:ok, Map.delete(activity, "@context")}
end
end,
caller_pid
)
if Enum.all?(results, fn r -> r == :ok end), do: :ok, else: results
end
end
defp followers(dir, user) do
User.get_followers_query(user)

View file

@ -271,7 +271,7 @@ defmodule Pleroma.User.BackupTest do
"type" => "OrderedCollection"
} = Jason.decode!(json)
assert {:ok, {'chats.json', json}} = :zip.zip_get('chats.json', zipfile)
assert {:ok, {~c"chats.json", json}} = :zip.zip_get(~c"chats.json", zipfile)
chat_id = "http://localhost:4001/chats/#{chat.id}"
@ -290,13 +290,16 @@ defmodule Pleroma.User.BackupTest do
"type" => "OrderedCollection"
} = Jason.decode!(json)
assert {:ok, {'chat_messages.json', json}} = :zip.zip_get('chat_messages.json', zipfile)
chat_json_name = ~c'chat_messages_#{chat.id}.json'
chat_json_name_string = to_string(chat_json_name)
assert {:ok, {^chat_json_name, json}} = :zip.zip_get(chat_json_name, zipfile)
chat_id = "http://localhost:4001/chats/#{chat.id}"
assert %{
"@context" => "https://www.w3.org/ns/activitystreams",
"id" => "chat_messages.json",
"id" => ^chat_json_name_string,
"orderedItems" => [
%{
"type" => "ChatMessage",