Drop conversation addressing
No known client ever used this. Currently among akkoma-fe, pleroma-fe, Husky, Mangane and pl-fe only the latter acknowledes the existence of the in_reply_to_conversation_id paramter in its API definitions, but even pl-fe does never actually use the parameter anywhere. Since the API parameter already was converted to DMs internally, we do not need to make special considerations for already existing old conversation-addressed posts. Since they share the context they should also continue to show up in the intended thread anyway. The pleroma.participants subkey mentioned in docs did already not exist prior to this commit. Instead the accounts key doesn’t automatically update and this affects conversations retrieved from the Mastodon API endpoint too (which may be considered a pre-existing bug). If desired clients can already avoid unintended participant additions by using the explicit-addressing feature originally introduced in https://git.pleroma.social/pleroma/pleroma/-/merge_requests/1239. With the above-mentioned feature/bug of conversation participants not updating automatically it can replace almost everything conversation addressing was able to do. The sole exception being creating new non-reply posts in the same context. Neither conversation addressing nor explicit addressing achieves robust, federated group chats though. Resolves: https://akkoma.dev/AkkomaGang/akkoma/issues/812
This commit is contained in:
parent
271110c1a5
commit
865cfabf88
9 changed files with 15 additions and 95 deletions
|
|
@ -216,7 +216,6 @@ Additional parameters can be added to the JSON body/Form data:
|
|||
- `to`: A list of nicknames (like `admin@otp.akkoma.dev` or `admin` on the local server) that will be used to determine who is going to be addressed by this post. Using this will disable the implicit addressing by mentioned names in the `status` body, only the people in the `to` list will be addressed. The normal rules for post visibility are not affected by this and will still apply.
|
||||
- `visibility`: string, besides standard MastoAPI values (`direct`, `private`, `unlisted`, `local` or `public`) it can be used to address a List by setting it to `list:LIST_ID`.
|
||||
- `expires_in`: The number of seconds the posted activity should expire in. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated. This needs to be longer than an hour.
|
||||
- `in_reply_to_conversation_id`: Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`.
|
||||
|
||||
## GET `/api/v1/statuses`
|
||||
|
||||
|
|
|
|||
|
|
@ -376,13 +376,8 @@ See [Admin-API](admin_api.md)
|
|||
|
||||
Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints:
|
||||
|
||||
1. Pleroma Conversations never add or remove recipients, unless explicitly changed by the user.
|
||||
1. Pleroma Conversations never add or remove recipients (`accounts` key), unless explicitly changed by the user.
|
||||
2. Pleroma Conversations statuses can be requested by Conversation id.
|
||||
3. Pleroma Conversations can be replied to.
|
||||
|
||||
Conversations have the additional field `recipients` under the `pleroma` key. This holds a list of all the accounts that will receive a message in this conversation.
|
||||
|
||||
The status posting endpoint takes an additional parameter, `in_reply_to_conversation_id`, which, when set, will set the visiblity to direct and address only the people who are the recipients of that Conversation.
|
||||
|
||||
⚠ Conversation IDs can be found in direct messages with the `pleroma.direct_conversation_id` key, do not confuse it with `pleroma.conversation_id`.
|
||||
|
||||
|
|
|
|||
|
|
@ -563,12 +563,6 @@ defp create_request do
|
|||
description:
|
||||
"The number of seconds the posted activity should expire in. When a posted activity expires it will be deleted from the server, and a delete request for it will be federated. This needs to be longer than an hour."
|
||||
},
|
||||
in_reply_to_conversation_id: %Schema{
|
||||
nullable: true,
|
||||
type: :string,
|
||||
description:
|
||||
"Will reply to a given conversation, addressing only the people who are part of the recipient set of that conversation. Sets the visibility to `direct`."
|
||||
},
|
||||
quote_id: %Schema{
|
||||
nullable: true,
|
||||
type: :string,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
defmodule Pleroma.Web.CommonAPI do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.ThreadMute
|
||||
alias Pleroma.User
|
||||
|
|
@ -294,18 +293,16 @@ def announce_visibility(_, %{visibility: visibility})
|
|||
|
||||
def announce_visibility(object, _), do: Visibility.get_visibility(object)
|
||||
|
||||
def get_visibility(_, _, %Participation{}), do: {"direct", "direct"}
|
||||
|
||||
def get_visibility(%{visibility: visibility}, in_reply_to, _)
|
||||
def get_visibility(%{visibility: visibility}, in_reply_to)
|
||||
when visibility in ~w{public local unlisted private direct},
|
||||
do: {visibility, get_replied_to_visibility(in_reply_to)}
|
||||
|
||||
def get_visibility(_, in_reply_to, _) when not is_nil(in_reply_to) do
|
||||
def get_visibility(_, in_reply_to) when not is_nil(in_reply_to) do
|
||||
visibility = get_replied_to_visibility(in_reply_to)
|
||||
{visibility, visibility}
|
||||
end
|
||||
|
||||
def get_visibility(_, in_reply_to, _), do: {"public", get_replied_to_visibility(in_reply_to)}
|
||||
def get_visibility(_, nil), do: {"public", nil}
|
||||
|
||||
def get_replied_to_visibility(nil), do: nil
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
defmodule Pleroma.Web.CommonAPI.ActivityDraft do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Web.ActivityPub.Builder
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
|
@ -22,7 +21,6 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
|
|||
full_payload: nil,
|
||||
attachments: [],
|
||||
in_reply_to: nil,
|
||||
in_reply_to_conversation: nil,
|
||||
language: nil,
|
||||
content_map: %{},
|
||||
quote_id: nil,
|
||||
|
|
@ -56,7 +54,6 @@ def create(user, params) do
|
|||
|> expires_at()
|
||||
|> poll()
|
||||
|> with_valid(&in_reply_to/1)
|
||||
|> with_valid(&in_reply_to_conversation/1)
|
||||
|> with_valid(&visibility/1)
|
||||
|> with_valid("e_id/1)
|
||||
|> content()
|
||||
|
|
@ -133,11 +130,6 @@ defp in_reply_to(%{params: %{in_reply_to_status_id: %Activity{} = in_reply_to}}
|
|||
|
||||
defp in_reply_to(draft), do: draft
|
||||
|
||||
defp in_reply_to_conversation(draft) do
|
||||
in_reply_to_conversation = Participation.get(draft.params[:in_reply_to_conversation_id])
|
||||
%__MODULE__{draft | in_reply_to_conversation: in_reply_to_conversation}
|
||||
end
|
||||
|
||||
defp quote_id(%{params: %{quote_id: ""}} = draft), do: draft
|
||||
|
||||
defp quote_id(%{params: %{quote_id: id}} = draft) when is_binary(id) do
|
||||
|
|
@ -175,7 +167,7 @@ defp language(%{content_html: content} = draft) do
|
|||
end
|
||||
|
||||
defp visibility(%{params: params} = draft) do
|
||||
case CommonAPI.get_visibility(params, draft.in_reply_to, draft.in_reply_to_conversation) do
|
||||
case CommonAPI.get_visibility(params, draft.in_reply_to) do
|
||||
{visibility, "direct"} when visibility != "direct" ->
|
||||
add_error(draft, dgettext("errors", "The message visibility must be direct"))
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
alias Calendar.Strftime
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
|
|
@ -52,11 +51,6 @@ def get_attachment(media_id) do
|
|||
|
||||
@spec get_to_and_cc(ActivityDraft.t()) :: {list(String.t()), list(String.t())}
|
||||
|
||||
def get_to_and_cc(%{in_reply_to_conversation: %Participation{} = participation}) do
|
||||
participation = Repo.preload(participation, :recipients)
|
||||
{Enum.map(participation.recipients, & &1.ap_id), []}
|
||||
end
|
||||
|
||||
def get_to_and_cc(%{visibility: visibility} = draft) do
|
||||
# If the OP is a DM already, add the implicit actor
|
||||
mentions =
|
||||
|
|
@ -229,10 +223,6 @@ def get_content_type(content_type) do
|
|||
end
|
||||
end
|
||||
|
||||
def make_context(%{in_reply_to_conversation: %Participation{} = participation}) do
|
||||
Repo.preload(participation, :conversation).conversation.ap_id
|
||||
end
|
||||
|
||||
def make_context(%{in_reply_to: %Activity{data: %{"context" => context}}}), do: context
|
||||
def make_context(%{quote: %Activity{data: %{"context" => context}}}), do: context
|
||||
def make_context(_), do: Utils.generate_context_id()
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ test "for a new conversation or a reply, it doesn't mark the author's participat
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _} =
|
||||
{:ok, op_activity} =
|
||||
CommonAPI.post(user, %{status: "Hey @#{other_user.nickname}.", visibility: "direct"})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
other_user = User.get_cached_by_id(other_user.id)
|
||||
|
||||
[%{read: true}] = Participation.for_user(user)
|
||||
[%{read: false} = participation] = Participation.for_user(other_user)
|
||||
[%{read: false}] = Participation.for_user(other_user)
|
||||
assert Participation.unread_count(user) == 0
|
||||
assert Participation.unread_count(other_user) == 1
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ test "for a new conversation or a reply, it doesn't mark the author's participat
|
|||
CommonAPI.post(other_user, %{
|
||||
status: "Hey @#{user.nickname}.",
|
||||
visibility: "direct",
|
||||
in_reply_to_conversation_id: participation.id
|
||||
in_reply_to_id: op_activity.id
|
||||
})
|
||||
|
||||
user = User.get_cached_by_id(user.id)
|
||||
|
|
@ -317,7 +317,7 @@ test "the conversation with the blocked user is not marked as unread on a reply"
|
|||
blocked = insert(:user)
|
||||
third_user = insert(:user)
|
||||
|
||||
{:ok, _direct1} =
|
||||
{:ok, direct1} =
|
||||
CommonAPI.post(blocker, %{
|
||||
status: "Hi @#{third_user.nickname}, @#{blocked.nickname}",
|
||||
visibility: "direct"
|
||||
|
|
@ -327,27 +327,25 @@ test "the conversation with the blocked user is not marked as unread on a reply"
|
|||
assert [%{read: true}] = Participation.for_user(blocker)
|
||||
|
||||
assert Participation.unread_count(blocker) == 0
|
||||
assert [blocked_participation] = Participation.for_user(blocked)
|
||||
|
||||
# When it's a reply from the blocked user
|
||||
{:ok, _direct2} =
|
||||
{:ok, direct2} =
|
||||
CommonAPI.post(blocked, %{
|
||||
status: "reply",
|
||||
visibility: "direct",
|
||||
in_reply_to_conversation_id: blocked_participation.id
|
||||
in_reply_to_id: direct1.id
|
||||
})
|
||||
|
||||
assert [%{read: true}] = Participation.for_user(blocker)
|
||||
|
||||
assert Participation.unread_count(blocker) == 0
|
||||
assert [third_user_participation] = Participation.for_user(third_user)
|
||||
|
||||
# When it's a reply from the third user
|
||||
# When it's a reply from the third user to the blocked user
|
||||
{:ok, _direct3} =
|
||||
CommonAPI.post(third_user, %{
|
||||
status: "reply",
|
||||
visibility: "direct",
|
||||
in_reply_to_conversation_id: third_user_participation.id
|
||||
in_reply_to_id: direct2.id
|
||||
})
|
||||
|
||||
assert [%{read: true}] = Participation.for_user(blocker)
|
||||
|
|
|
|||
|
|
@ -318,49 +318,6 @@ test "repeating race condition" do
|
|||
assert object.data["announcement_count"] == 20
|
||||
end
|
||||
|
||||
test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"})
|
||||
|
||||
[participation] = Participation.for_user(user)
|
||||
|
||||
{:ok, convo_reply} =
|
||||
CommonAPI.post(user, %{status: ".", in_reply_to_conversation_id: participation.id})
|
||||
|
||||
assert Visibility.is_direct?(convo_reply)
|
||||
|
||||
assert activity.data["context"] == convo_reply.data["context"]
|
||||
end
|
||||
|
||||
test "when replying to a conversation / participation, it only mentions the recipients explicitly declared in the participation" do
|
||||
har = insert(:user)
|
||||
jafnhar = insert(:user)
|
||||
tridi = insert(:user)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{
|
||||
status: "@#{jafnhar.nickname} hey",
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
assert har.ap_id in activity.recipients
|
||||
assert jafnhar.ap_id in activity.recipients
|
||||
|
||||
[participation] = Participation.for_user(har)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(har, %{
|
||||
status: "I don't really like @#{tridi.nickname}",
|
||||
visibility: "direct",
|
||||
in_reply_to_status_id: activity.id,
|
||||
in_reply_to_conversation_id: participation.id
|
||||
})
|
||||
|
||||
assert har.ap_id in activity.recipients
|
||||
assert jafnhar.ap_id in activity.recipients
|
||||
refute tridi.ap_id in activity.recipients
|
||||
end
|
||||
|
||||
test "with the safe_dm_mention option set, it does not mention people beyond the initial tags" do
|
||||
har = insert(:user)
|
||||
jafnhar = insert(:user)
|
||||
|
|
|
|||
|
|
@ -45,8 +45,7 @@ test "/api/v1/pleroma/conversations/:id/statuses" do
|
|||
{:ok, activity_two} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Hi!",
|
||||
in_reply_to_status_id: activity.id,
|
||||
in_reply_to_conversation_id: participation.id
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
result =
|
||||
|
|
@ -63,8 +62,7 @@ test "/api/v1/pleroma/conversations/:id/statuses" do
|
|||
{:ok, %{id: id_three}} =
|
||||
CommonAPI.post(other_user, %{
|
||||
status: "Bye!",
|
||||
in_reply_to_status_id: activity.id,
|
||||
in_reply_to_conversation_id: participation.id
|
||||
in_reply_to_status_id: activity.id
|
||||
})
|
||||
|
||||
assert [%{"id" => ^id_two}, %{"id" => ^id_three}] =
|
||||
|
|
|
|||
Loading…
Reference in a new issue