Backup chats and chat messages
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
139057f346
commit
3c21a33656
4 changed files with 120 additions and 3 deletions
1
changelog.d/backups-chats.add
Normal file
1
changelog.d/backups-chats.add
Normal file
|
@ -0,0 +1 @@
|
|||
Backup chats and chat messages
|
|
@ -17,7 +17,7 @@ defmodule Pleroma.Chat.MessageReference do
|
|||
import Ecto.Changeset
|
||||
import Ecto.Query
|
||||
|
||||
@primary_key {:id, FlakeId.Ecto.Type, autogenerate: true}
|
||||
@primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
|
||||
|
||||
schema "chat_message_references" do
|
||||
belongs_to(:object, Object)
|
||||
|
|
|
@ -14,6 +14,7 @@ defmodule Pleroma.User.Backup do
|
|||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Chat
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.User.Backup.State
|
||||
|
@ -196,7 +197,14 @@ defp wait_backup(backup, current_processed, task) do
|
|||
end
|
||||
end
|
||||
|
||||
@files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json']
|
||||
@files [
|
||||
'actor.json',
|
||||
'outbox.json',
|
||||
'likes.json',
|
||||
'bookmarks.json',
|
||||
'chats.json',
|
||||
'chat_messages.json'
|
||||
]
|
||||
@spec export(Pleroma.User.Backup.t(), pid()) :: {:ok, String.t()} | :error
|
||||
def export(%__MODULE__{} = backup, caller_pid) do
|
||||
backup = Repo.preload(backup, :user)
|
||||
|
@ -207,6 +215,8 @@ def export(%__MODULE__{} = backup, caller_pid) do
|
|||
:ok <- statuses(dir, backup.user, caller_pid),
|
||||
:ok <- likes(dir, backup.user, caller_pid),
|
||||
:ok <- bookmarks(dir, backup.user, caller_pid),
|
||||
:ok <- chats(dir, backup.user, caller_pid),
|
||||
:ok <- chat_messages(dir, backup.user, caller_pid),
|
||||
{:ok, zip_path} <- :zip.create(backup.file_name, @files, cwd: dir),
|
||||
{:ok, _} <- File.rm_rf(dir) do
|
||||
{:ok, zip_path}
|
||||
|
@ -357,6 +367,56 @@ defp statuses(dir, user, caller_pid) do
|
|||
caller_pid
|
||||
)
|
||||
end
|
||||
|
||||
defp chats(dir, user, caller_pid) do
|
||||
Chat.for_user_query(user.id)
|
||||
|> write(
|
||||
dir,
|
||||
"chats",
|
||||
fn chat ->
|
||||
{:ok,
|
||||
%{
|
||||
"type" => "Chat",
|
||||
"id" => "#{Pleroma.Web.Endpoint.url()}/chats/#{chat.id}",
|
||||
"actor" => user.ap_id,
|
||||
"to" => [chat.recipient],
|
||||
"published" =>
|
||||
chat.inserted_at |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601()
|
||||
}}
|
||||
end,
|
||||
caller_pid
|
||||
)
|
||||
end
|
||||
|
||||
def chat_messages(dir, %{id: user_id}, caller_pid) do
|
||||
chats_subquery =
|
||||
from(c in Chat,
|
||||
where: c.user_id == ^user_id,
|
||||
select: c.id
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
defmodule Pleroma.User.Backup.ProcessorAPI do
|
||||
|
|
|
@ -12,9 +12,11 @@ defmodule Pleroma.User.BackupTest do
|
|||
import Mox
|
||||
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Chat
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.UnstubbedConfigMock, as: ConfigMock
|
||||
alias Pleroma.Uploaders.S3.ExAwsMock
|
||||
alias Pleroma.User
|
||||
alias Pleroma.User.Backup
|
||||
alias Pleroma.User.Backup.ProcessorMock
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
@ -165,7 +167,10 @@ test "it removes outdated backups after creating a fresh one" do
|
|||
end
|
||||
|
||||
test "it creates a zip archive with user data" do
|
||||
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
|
||||
%User{ap_id: ap_id} =
|
||||
user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"})
|
||||
|
||||
%User{ap_id: other_ap_id} = other_user = insert(:user)
|
||||
|
||||
{:ok, %{object: %{data: %{"id" => id1}}} = status1} =
|
||||
CommonAPI.post(user, %{status: "status1"})
|
||||
|
@ -182,6 +187,11 @@ test "it creates a zip archive with user data" do
|
|||
Bookmark.create(user.id, status2.id)
|
||||
Bookmark.create(user.id, status3.id)
|
||||
|
||||
{:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
|
||||
|
||||
{:ok, _message_1} = CommonAPI.post_chat_message(user, other_user, "hey")
|
||||
{:ok, _message_2} = CommonAPI.post_chat_message(other_user, user, "ho")
|
||||
|
||||
assert {:ok, backup} = user |> Backup.new() |> Repo.insert()
|
||||
assert {:ok, path} = Backup.export(backup, self())
|
||||
assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(path), [:memory])
|
||||
|
@ -261,6 +271,52 @@ test "it creates a zip archive with user data" do
|
|||
"type" => "OrderedCollection"
|
||||
} = Jason.decode!(json)
|
||||
|
||||
assert {:ok, {'chats.json', json}} = :zip.zip_get('chats.json', zipfile)
|
||||
|
||||
chat_id = "http://localhost:4001/chats/#{chat.id}"
|
||||
|
||||
assert %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"id" => "chats.json",
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"type" => "Chat",
|
||||
"id" => ^chat_id,
|
||||
"actor" => ^ap_id,
|
||||
"to" => [^other_ap_id]
|
||||
}
|
||||
],
|
||||
"totalItems" => 1,
|
||||
"type" => "OrderedCollection"
|
||||
} = Jason.decode!(json)
|
||||
|
||||
assert {:ok, {'chat_messages.json', json}} = :zip.zip_get('chat_messages.json', zipfile)
|
||||
|
||||
chat_id = "http://localhost:4001/chats/#{chat.id}"
|
||||
|
||||
assert %{
|
||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||
"id" => "chat_messages.json",
|
||||
"orderedItems" => [
|
||||
%{
|
||||
"type" => "ChatMessage",
|
||||
"actor" => ^ap_id,
|
||||
"to" => [^other_ap_id],
|
||||
"context" => ^chat_id,
|
||||
"content" => "hey"
|
||||
},
|
||||
%{
|
||||
"type" => "ChatMessage",
|
||||
"actor" => ^other_ap_id,
|
||||
"to" => [^ap_id],
|
||||
"context" => ^chat_id,
|
||||
"content" => "ho"
|
||||
}
|
||||
],
|
||||
"totalItems" => 2,
|
||||
"type" => "OrderedCollection"
|
||||
} = Jason.decode!(json)
|
||||
|
||||
:zip.zip_close(zipfile)
|
||||
File.rm!(path)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue