Merge pull request 'Purge broken, unused and/or useless features' (#1008) from Oneric/akkoma:purge-broken into develop
Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/1008
This commit is contained in:
commit
5e4475d61e
26 changed files with 184 additions and 578 deletions
|
|
@ -1218,24 +1218,10 @@ Loads JSON generated from `config/descriptions.exs`.
|
|||
|
||||
## `GET /api/v1/pleroma/admin/stats`
|
||||
|
||||
### Stats
|
||||
**DEPRECATED; DO NOT USE**!!
|
||||
|
||||
- Query Params:
|
||||
- *optional* `instance`: **string** instance hostname (without protocol) to get stats for
|
||||
- Example: `https://mypleroma.org/api/v1/pleroma/admin/stats?instance=lain.com`
|
||||
|
||||
- Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"status_visibility": {
|
||||
"direct": 739,
|
||||
"private": 9,
|
||||
"public": 17,
|
||||
"unlisted": 14
|
||||
}
|
||||
}
|
||||
```
|
||||
Returned information is only stubbed out.
|
||||
The endpoint will be removed entirely in an upcoming release.
|
||||
|
||||
## `GET /api/v1/pleroma/admin/oauth_app`
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ Home, public, hashtag & list timelines further accept:
|
|||
|
||||
## Statuses
|
||||
|
||||
- `visibility`: has additional possible values `list` and `local` (for local-only statuses)
|
||||
- `visibility`: has additional possible value `local` (for local-only statuses)
|
||||
- `emoji_reactions`: additional field since Akkoma 3.2.0; identical to `pleroma/emoji_reactions`
|
||||
|
||||
Has these additional fields under the `pleroma` object:
|
||||
|
|
@ -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`.
|
||||
|
||||
|
|
|
|||
|
|
@ -267,17 +267,33 @@ special meaning to the potential local-scope identifier.
|
|||
however those are also shown publicly on the local web interface
|
||||
and are thus visible to non-members.
|
||||
|
||||
## List post scope
|
||||
|
||||
Messages originally addressed to a custom list will contain
|
||||
a `listMessage` field with an unresolvable pseudo ActivityPub id.
|
||||
|
||||
# Deprecated and Removed Extensions
|
||||
|
||||
The following extensions were used in the past but have been dropped.
|
||||
Documentation is retained here as a reference and since old objects might
|
||||
still contains related fields.
|
||||
|
||||
## List post scope
|
||||
|
||||
Messages originally addressed to a custom list will contain
|
||||
a `listMessage` field with an unresolvable pseudo ActivityPub id.
|
||||
|
||||
!!! note
|
||||
The concept did not work out too well in practice with even remote servers
|
||||
recognising the `listMessage` extension being unaware of the state of the
|
||||
list and resulting weird desyncs in thread display and handling between
|
||||
servers.
|
||||
As it was it also never found its way in any known clients or frontends.
|
||||
|
||||
A more consistent superset of what this was able to actually do
|
||||
can be achieved without ActivityPub extensions by explicitly addressing
|
||||
all intended participants without inline mentions.
|
||||
While true federated and moderated "lists" or "groups"
|
||||
will need more work and a different approach.
|
||||
|
||||
Thus suport for it was removed and it is recommended
|
||||
to not create any new implementation of it.
|
||||
|
||||
## Actor endpoints
|
||||
|
||||
The following endpoints used to be present:
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.RefreshCounterCache do
|
||||
@shortdoc "Refreshes counter cache"
|
||||
|
||||
use Mix.Task
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.CounterCache
|
||||
alias Pleroma.Repo
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
def run([]) do
|
||||
Mix.Pleroma.start_pleroma()
|
||||
|
||||
instances =
|
||||
Activity
|
||||
|> distinct([a], true)
|
||||
|> select([a], fragment("split_part(?, '/', 3)", a.actor))
|
||||
|> Repo.all()
|
||||
|
||||
instances
|
||||
|> Enum.with_index(1)
|
||||
|> Enum.each(fn {instance, i} ->
|
||||
counters = instance_counters(instance)
|
||||
CounterCache.set(instance, counters)
|
||||
|
||||
Mix.Pleroma.shell_info(
|
||||
"[#{i}/#{length(instances)}] Setting #{instance} counters: #{inspect(counters)}"
|
||||
)
|
||||
end)
|
||||
|
||||
Mix.Pleroma.shell_info("Done")
|
||||
end
|
||||
|
||||
defp instance_counters(instance) do
|
||||
counters = %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0}
|
||||
|
||||
Activity
|
||||
|> where([a], fragment("(? ->> 'type'::text) = 'Create'", a.data))
|
||||
|> where([a], fragment("split_part(?, '/', 3) = ?", a.actor, ^instance))
|
||||
|> select(
|
||||
[a],
|
||||
{fragment(
|
||||
"activity_visibility(?, ?, ?)",
|
||||
a.actor,
|
||||
a.recipients,
|
||||
a.data
|
||||
), count(a.id)}
|
||||
)
|
||||
|> group_by(
|
||||
[a],
|
||||
fragment(
|
||||
"activity_visibility(?, ?, ?)",
|
||||
a.actor,
|
||||
a.recipients,
|
||||
a.data
|
||||
)
|
||||
)
|
||||
|> Repo.all(timeout: :timer.minutes(30))
|
||||
|> Enum.reduce(counters, fn {visibility, count}, acc ->
|
||||
Map.put(acc, visibility, count)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
|
@ -22,6 +22,27 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
|||
"\n* `config :pleroma, :instance, :quarantined_instances` is now covered by `:pleroma, :mrf_simple, :reject`"}
|
||||
]
|
||||
|
||||
def check_skip_thread_containment do
|
||||
# The default in config/config.exs is "true" since 593b8b1e6a8502cca9bf5559b8bec86f172bbecb
|
||||
# but when the default is retrieved in code the fallback is still "false"
|
||||
uses_thread_visibility_filtering = !Config.get([:instance, :skip_thread_containment], false)
|
||||
|
||||
if uses_thread_visibility_filtering do
|
||||
Logger.warning("""
|
||||
!!!DEPRECATION WARNING!!!
|
||||
Your config is explicitly enabling thread-based visibility containment by setting the below:
|
||||
```
|
||||
config :pleroma, :instance, skip_thread_containment: false
|
||||
```
|
||||
|
||||
This feature comes with a very high performance overhead and is considered for removal.
|
||||
If you actually need or strongly prefer keeping it, speak up NOW(!) by filing a ticket at
|
||||
https://akkoma.dev/AkkomaGang/akkoma/issues
|
||||
Complaints only after the removal happened are much less likely to have any effect.
|
||||
""")
|
||||
end
|
||||
end
|
||||
|
||||
def check_exiftool_filter do
|
||||
filters = Config.get([Pleroma.Upload]) |> Keyword.get(:filters, [])
|
||||
|
||||
|
|
@ -222,7 +243,8 @@ def warn do
|
|||
check_http_adapter(),
|
||||
check_uploader_base_url_set(),
|
||||
check_uploader_base_url_is_not_base_domain(),
|
||||
check_exiftool_filter()
|
||||
check_exiftool_filter(),
|
||||
check_skip_thread_containment()
|
||||
]
|
||||
|> Enum.reduce(:ok, fn
|
||||
:ok, :ok -> :ok
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.CounterCache do
|
||||
alias Pleroma.CounterCache
|
||||
alias Pleroma.Repo
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
import Ecto.Query
|
||||
|
||||
schema "counter_cache" do
|
||||
field(:instance, :string)
|
||||
field(:public, :integer)
|
||||
field(:unlisted, :integer)
|
||||
field(:private, :integer)
|
||||
field(:direct, :integer)
|
||||
end
|
||||
|
||||
def changeset(struct, params) do
|
||||
struct
|
||||
|> cast(params, [:instance, :public, :unlisted, :private, :direct])
|
||||
|> validate_required([:instance])
|
||||
|> unique_constraint(:instance)
|
||||
end
|
||||
|
||||
def get_by_instance(instance) do
|
||||
CounterCache
|
||||
|> select([c], %{
|
||||
"public" => c.public,
|
||||
"unlisted" => c.unlisted,
|
||||
"private" => c.private,
|
||||
"direct" => c.direct
|
||||
})
|
||||
|> where([c], c.instance == ^instance)
|
||||
|> Repo.one()
|
||||
|> case do
|
||||
nil -> %{"public" => 0, "unlisted" => 0, "private" => 0, "direct" => 0}
|
||||
val -> val
|
||||
end
|
||||
end
|
||||
|
||||
def get_sum do
|
||||
CounterCache
|
||||
|> select([c], %{
|
||||
"public" => type(sum(c.public), :integer),
|
||||
"unlisted" => type(sum(c.unlisted), :integer),
|
||||
"private" => type(sum(c.private), :integer),
|
||||
"direct" => type(sum(c.direct), :integer)
|
||||
})
|
||||
|> Repo.one()
|
||||
end
|
||||
|
||||
def set(instance, values) do
|
||||
params =
|
||||
Enum.reduce(
|
||||
["public", "private", "unlisted", "direct"],
|
||||
%{"instance" => instance},
|
||||
fn param, acc ->
|
||||
Map.put_new(acc, param, Map.get(values, param, 0))
|
||||
end
|
||||
)
|
||||
|
||||
%CounterCache{}
|
||||
|> changeset(params)
|
||||
|> Repo.insert(
|
||||
on_conflict: [
|
||||
set: [
|
||||
public: params["public"],
|
||||
private: params["private"],
|
||||
unlisted: params["unlisted"],
|
||||
direct: params["direct"]
|
||||
]
|
||||
],
|
||||
returning: true,
|
||||
conflict_target: :instance
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -7,7 +7,6 @@ defmodule Pleroma.Stats do
|
|||
|
||||
import Ecto.Query
|
||||
|
||||
alias Pleroma.CounterCache
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Instances.Instance
|
||||
|
|
@ -107,15 +106,6 @@ def calculate_stat_data do
|
|||
}
|
||||
end
|
||||
|
||||
@spec get_status_visibility_count(String.t() | nil) :: map()
|
||||
def get_status_visibility_count(instance \\ nil) do
|
||||
if is_nil(instance) do
|
||||
CounterCache.get_sum()
|
||||
else
|
||||
CounterCache.get_by_instance(instance)
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_continue(:calculate_stats, _) do
|
||||
stats = calculate_stat_data()
|
||||
|
|
|
|||
|
|
@ -53,25 +53,11 @@ def is_direct?(activity) do
|
|||
!is_public?(activity) && !is_private?(activity)
|
||||
end
|
||||
|
||||
def is_list?(%{data: %{"listMessage" => _}}), do: true
|
||||
def is_list?(_), do: false
|
||||
|
||||
@spec visible_for_user?(Object.t() | Activity.t() | nil, User.t() | nil) :: boolean()
|
||||
def visible_for_user?(%Object{data: %{"type" => "Tombstone"}}, _), do: false
|
||||
def visible_for_user?(%Activity{actor: ap_id}, %User{ap_id: ap_id}), do: true
|
||||
def visible_for_user?(%Object{data: %{"actor" => ap_id}}, %User{ap_id: ap_id}), do: true
|
||||
def visible_for_user?(nil, _), do: false
|
||||
def visible_for_user?(%Activity{data: %{"listMessage" => _}}, nil), do: false
|
||||
|
||||
def visible_for_user?(
|
||||
%Activity{data: %{"listMessage" => list_ap_id}} = activity,
|
||||
%User{} = user
|
||||
) do
|
||||
user.ap_id in activity.data["to"] ||
|
||||
list_ap_id
|
||||
|> Pleroma.List.get_by_ap_id()
|
||||
|> Pleroma.List.member?(user)
|
||||
end
|
||||
|
||||
def visible_for_user?(%{__struct__: module} = message, nil)
|
||||
when module in [Activity, Object] do
|
||||
|
|
@ -141,9 +127,6 @@ def get_visibility(object) do
|
|||
object.data["directMessage"] == true ->
|
||||
"direct"
|
||||
|
||||
is_binary(object.data["listMessage"]) ->
|
||||
"list"
|
||||
|
||||
length(cc) > 0 ->
|
||||
"private"
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
alias Pleroma.Config
|
||||
alias Pleroma.MFA
|
||||
alias Pleroma.ModerationLog
|
||||
alias Pleroma.Stats
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.AdminAPI
|
||||
|
|
@ -399,10 +398,17 @@ def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" =
|
|||
json(conn, "")
|
||||
end
|
||||
|
||||
def stats(conn, params) do
|
||||
counters = Stats.get_status_visibility_count(params["instance"])
|
||||
|
||||
json(conn, %{"status_visibility" => counters})
|
||||
# Legacy endpoint, stubbed out for a transition period before removal
|
||||
# (atm only used by admin-fe)
|
||||
def stats(conn, _params) do
|
||||
json(conn, %{
|
||||
"status_visibility" => %{
|
||||
"direct" => 0,
|
||||
"private" => 0,
|
||||
"public" => 0,
|
||||
"unlisted" => 0
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
def create_backup(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
|
||||
|
|
|
|||
|
|
@ -553,10 +553,9 @@ defp create_request do
|
|||
nullable: true,
|
||||
anyOf: [
|
||||
VisibilityScope,
|
||||
%Schema{type: :string, description: "`list:LIST_ID`", example: "LIST:123"}
|
||||
%Schema{type: :string, description: "scope name", example: "unlisted"}
|
||||
],
|
||||
description:
|
||||
"Visibility of the posted status. Besides standard MastoAPI values (`direct`, `private`, `unlisted` or `public`) it can be used to address a List by setting it to `list:LIST_ID`"
|
||||
description: "Visibility of the posted status."
|
||||
},
|
||||
expires_in: %Schema{
|
||||
nullable: true,
|
||||
|
|
@ -564,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,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ defmodule Pleroma.Web.ApiSpec.Schemas.VisibilityScope do
|
|||
title: "VisibilityScope",
|
||||
description: "Status visibility",
|
||||
type: :string,
|
||||
enum: ["public", "unlisted", "local", "private", "direct", "list"]
|
||||
enum: ["public", "unlisted", "local", "private", "direct"]
|
||||
})
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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,23 +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(%{visibility: "list:" <> list_id}, in_reply_to, _) do
|
||||
visibility = {:list, String.to_integer(list_id)}
|
||||
{visibility, get_replied_to_visibility(in_reply_to)}
|
||||
end
|
||||
|
||||
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"))
|
||||
|
||||
|
|
@ -298,7 +290,6 @@ defp changes(draft) do
|
|||
object: draft.object,
|
||||
additional: additional
|
||||
}
|
||||
|> Utils.maybe_add_list_data(draft.user, draft.visibility)
|
||||
|
||||
%__MODULE__{draft | changes: changes}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
@ -118,31 +112,12 @@ def get_to_and_cc_for_visibility("direct", _, _, mentions) do
|
|||
{mentions, []}
|
||||
end
|
||||
|
||||
def get_to_and_cc_for_visibility({:list, _}, _, _, mentions) do
|
||||
{mentions, []}
|
||||
end
|
||||
|
||||
def get_addressed_users(_, to) when is_list(to) do
|
||||
User.get_ap_ids_by_nicknames(to)
|
||||
end
|
||||
|
||||
def get_addressed_users(mentioned_users, _), do: mentioned_users
|
||||
|
||||
def maybe_add_list_data(activity_params, user, {:list, list_id}) do
|
||||
case Pleroma.List.get(list_id, user) do
|
||||
%Pleroma.List{} = list ->
|
||||
activity_params
|
||||
|> put_in([:additional, "bcc"], [list.ap_id])
|
||||
|> put_in([:additional, "listMessage"], list.ap_id)
|
||||
|> put_in([:object, "listMessage"], list.ap_id)
|
||||
|
||||
_ ->
|
||||
activity_params
|
||||
end
|
||||
end
|
||||
|
||||
def maybe_add_list_data(activity_params, _, _), do: activity_params
|
||||
|
||||
def make_poll_data(%{"poll" => %{"expires_in" => expires_in}} = data)
|
||||
when is_binary(expires_in) do
|
||||
# In some cases mastofe sends out strings instead of integers
|
||||
|
|
@ -248,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()
|
||||
|
|
|
|||
93
priv/repo/migrations/20251109000000_purge_counter_cache.exs
Normal file
93
priv/repo/migrations/20251109000000_purge_counter_cache.exs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
defmodule Pleroma.Repo.Migrations.PurgeCounterCache do
|
||||
use Ecto.Migration
|
||||
|
||||
@function_name "update_status_visibility_counter_cache"
|
||||
@trigger_name "status_visibility_counter_cache_trigger"
|
||||
@table_name "counter_cache"
|
||||
|
||||
def up() do
|
||||
execute("DROP TRIGGER IF EXISTS " <> @trigger_name <> " ON activities;")
|
||||
execute("DROP FUNCTION IF EXISTS " <> @function_name <> ";")
|
||||
|
||||
# automatically drops indices
|
||||
drop table(@table_name)
|
||||
end
|
||||
|
||||
def down() do
|
||||
create_if_not_exists table(:counter_cache) do
|
||||
add(:instance, :string, null: false)
|
||||
add(:direct, :bigint, null: false, default: 0)
|
||||
add(:private, :bigint, null: false, default: 0)
|
||||
add(:unlisted, :bigint, null: false, default: 0)
|
||||
add(:public, :bigint, null: false, default: 0)
|
||||
end
|
||||
|
||||
"""
|
||||
CREATE OR REPLACE FUNCTION #{@function_name}()
|
||||
RETURNS TRIGGER AS
|
||||
$$
|
||||
DECLARE
|
||||
hostname character varying(255);
|
||||
visibility_new character varying(64);
|
||||
visibility_old character varying(64);
|
||||
actor character varying(255);
|
||||
BEGIN
|
||||
IF TG_OP = 'DELETE' THEN
|
||||
actor := OLD.actor;
|
||||
ELSE
|
||||
actor := NEW.actor;
|
||||
END IF;
|
||||
hostname := split_part(actor, '/', 3);
|
||||
IF TG_OP = 'INSERT' THEN
|
||||
visibility_new := activity_visibility(NEW.actor, NEW.recipients, NEW.data);
|
||||
IF NEW.data->>'type' = 'Create'
|
||||
AND visibility_new IN ('public', 'unlisted', 'private', 'direct') THEN
|
||||
EXECUTE format('INSERT INTO "counter_cache" ("instance", %1$I) VALUES ($1, 1)
|
||||
ON CONFLICT ("instance") DO
|
||||
UPDATE SET %1$I = "counter_cache".%1$I + 1', visibility_new)
|
||||
USING hostname;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
ELSIF TG_OP = 'UPDATE' THEN
|
||||
visibility_new := activity_visibility(NEW.actor, NEW.recipients, NEW.data);
|
||||
visibility_old := activity_visibility(OLD.actor, OLD.recipients, OLD.data);
|
||||
IF (NEW.data->>'type' = 'Create')
|
||||
AND (OLD.data->>'type' = 'Create')
|
||||
AND visibility_new != visibility_old
|
||||
AND visibility_new IN ('public', 'unlisted', 'private', 'direct') THEN
|
||||
EXECUTE format('UPDATE "counter_cache" SET
|
||||
%1$I = greatest("counter_cache".%1$I - 1, 0),
|
||||
%2$I = "counter_cache".%2$I + 1
|
||||
WHERE "instance" = $1', visibility_old, visibility_new)
|
||||
USING hostname;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
ELSIF TG_OP = 'DELETE' THEN
|
||||
IF OLD.data->>'type' = 'Create' THEN
|
||||
visibility_old := activity_visibility(OLD.actor, OLD.recipients, OLD.data);
|
||||
EXECUTE format('UPDATE "counter_cache" SET
|
||||
%1$I = greatest("counter_cache".%1$I - 1, 0)
|
||||
WHERE "instance" = $1', visibility_old)
|
||||
USING hostname;
|
||||
END IF;
|
||||
RETURN OLD;
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
LANGUAGE 'plpgsql';
|
||||
"""
|
||||
|> execute()
|
||||
|
||||
"""
|
||||
CREATE TRIGGER #{@trigger_name}
|
||||
BEFORE
|
||||
INSERT
|
||||
OR UPDATE of recipients, data
|
||||
OR DELETE
|
||||
ON activities
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE #{@function_name}();
|
||||
"""
|
||||
|> execute()
|
||||
end
|
||||
end
|
||||
|
|
@ -522,7 +522,6 @@ test "We don't have unexpected tables which may contain objects that are referen
|
|||
["conversation_participation_recipient_ships"],
|
||||
["conversation_participations"],
|
||||
["conversations"],
|
||||
["counter_cache"],
|
||||
["data_migration_failed_ids"],
|
||||
["data_migrations"],
|
||||
["deliveries"],
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mix.Tasks.Pleroma.RefreshCounterCacheTest do
|
||||
# Uses log capture, has to stay synchronous
|
||||
use Pleroma.DataCase
|
||||
alias Pleroma.Web.CommonAPI
|
||||
import ExUnit.CaptureIO, only: [capture_io: 1]
|
||||
import Pleroma.Factory
|
||||
|
||||
test "counts statuses" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
|
||||
CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
|
||||
Enum.each(0..1, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
visibility: "unlisted",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(0..2, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
visibility: "direct",
|
||||
status: "hey @#{other_user.nickname}"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(0..3, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
visibility: "private",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
assert capture_io(fn -> Mix.Tasks.Pleroma.RefreshCounterCache.run([]) end) =~ "Done\n"
|
||||
|
||||
assert %{"direct" => 3, "private" => 4, "public" => 1, "unlisted" => 2} =
|
||||
Pleroma.Stats.get_status_visibility_count()
|
||||
end
|
||||
end
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ defmodule Pleroma.StatsTest do
|
|||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Stats
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
describe "user count" do
|
||||
test "it ignores internal users" do
|
||||
|
|
@ -19,104 +18,4 @@ test "it ignores internal users" do
|
|||
assert match?(%{stats: %{user_count: 1}}, Stats.calculate_stat_data())
|
||||
end
|
||||
end
|
||||
|
||||
describe "status visibility sum count" do
|
||||
test "on new status" do
|
||||
instance2 = "instance2.tld"
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
|
||||
|
||||
CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
|
||||
Enum.each(0..1, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
visibility: "unlisted",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(0..2, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
visibility: "direct",
|
||||
status: "hey @#{other_user.nickname}"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(0..3, fn _ ->
|
||||
CommonAPI.post(user, %{
|
||||
visibility: "private",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
assert %{"direct" => 3, "private" => 4, "public" => 1, "unlisted" => 2} =
|
||||
Stats.get_status_visibility_count()
|
||||
end
|
||||
|
||||
test "on status delete" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
assert %{"public" => 1} = Stats.get_status_visibility_count()
|
||||
CommonAPI.delete(activity.id, user)
|
||||
assert %{"public" => 0} = Stats.get_status_visibility_count()
|
||||
end
|
||||
|
||||
test "on status visibility update" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
assert %{"public" => 1, "private" => 0} = Stats.get_status_visibility_count()
|
||||
{:ok, _} = CommonAPI.update_activity_scope(activity.id, %{visibility: "private"})
|
||||
assert %{"public" => 0, "private" => 1} = Stats.get_status_visibility_count()
|
||||
end
|
||||
|
||||
test "doesn't count unrelated activities" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
_ = CommonAPI.follow(user, other_user)
|
||||
CommonAPI.favorite(other_user, activity.id)
|
||||
CommonAPI.repeat(activity.id, other_user)
|
||||
|
||||
assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 0} =
|
||||
Stats.get_status_visibility_count()
|
||||
end
|
||||
end
|
||||
|
||||
describe "status visibility by instance count" do
|
||||
test "single instance" do
|
||||
local_instance = Pleroma.Web.Endpoint.url() |> String.split("//") |> Enum.at(1)
|
||||
instance2 = "instance2.tld"
|
||||
user1 = insert(:user)
|
||||
user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
|
||||
|
||||
CommonAPI.post(user1, %{visibility: "public", status: "hey"})
|
||||
|
||||
Enum.each(1..5, fn _ ->
|
||||
CommonAPI.post(user1, %{
|
||||
visibility: "unlisted",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(1..10, fn _ ->
|
||||
CommonAPI.post(user1, %{
|
||||
visibility: "direct",
|
||||
status: "hey @#{user2.nickname}"
|
||||
})
|
||||
end)
|
||||
|
||||
Enum.each(1..20, fn _ ->
|
||||
CommonAPI.post(user2, %{
|
||||
visibility: "private",
|
||||
status: "hey"
|
||||
})
|
||||
end)
|
||||
|
||||
assert %{"direct" => 10, "private" => 0, "public" => 1, "unlisted" => 5} =
|
||||
Stats.get_status_visibility_count(local_instance)
|
||||
|
||||
assert %{"direct" => 0, "private" => 20, "public" => 0, "unlisted" => 0} =
|
||||
Stats.get_status_visibility_count(instance2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,12 +36,18 @@ defmodule Pleroma.Web.ActivityPub.VisibilityTest do
|
|||
|
||||
{:ok, local} = CommonAPI.post(user, %{status: "@#{mentioned.nickname}", visibility: "local"})
|
||||
|
||||
{:ok, list} =
|
||||
# list visibility is no longer supported, but we want to check any
|
||||
# leftover entreis are handled sensibly, so we nned to manually fix up the data
|
||||
{:ok, list_activity} =
|
||||
CommonAPI.post(user, %{
|
||||
status: "@#{mentioned.nickname}",
|
||||
visibility: "list:#{list.id}"
|
||||
visibility: "direct"
|
||||
})
|
||||
|
||||
list_object = Object.normalize(list_activity)
|
||||
{:ok, list_object} = Object.update_data(list_object, %{"listMessage" => list.ap_id})
|
||||
list_activity = %Activity{list_activity | object: list_object}
|
||||
|
||||
%{
|
||||
public: public,
|
||||
private: private,
|
||||
|
|
@ -51,7 +57,7 @@ defmodule Pleroma.Web.ActivityPub.VisibilityTest do
|
|||
mentioned: mentioned,
|
||||
following: following,
|
||||
unrelated: unrelated,
|
||||
list: list,
|
||||
list: list_activity,
|
||||
local: local,
|
||||
remote: remote
|
||||
}
|
||||
|
|
@ -69,8 +75,8 @@ test "is_direct?", %{
|
|||
refute Visibility.is_direct?(public)
|
||||
refute Visibility.is_direct?(private)
|
||||
refute Visibility.is_direct?(unlisted)
|
||||
assert Visibility.is_direct?(list)
|
||||
refute Visibility.is_direct?(local)
|
||||
assert Visibility.is_direct?(list)
|
||||
end
|
||||
|
||||
test "is_public?", %{
|
||||
|
|
@ -105,22 +111,6 @@ test "is_private?", %{
|
|||
refute Visibility.is_private?(local)
|
||||
end
|
||||
|
||||
test "is_list?", %{
|
||||
public: public,
|
||||
private: private,
|
||||
direct: direct,
|
||||
unlisted: unlisted,
|
||||
list: list,
|
||||
local: local
|
||||
} do
|
||||
refute Visibility.is_list?(direct)
|
||||
refute Visibility.is_list?(public)
|
||||
refute Visibility.is_list?(private)
|
||||
refute Visibility.is_list?(unlisted)
|
||||
assert Visibility.is_list?(list)
|
||||
refute Visibility.is_list?(local)
|
||||
end
|
||||
|
||||
test "visible_for_user? Activity", %{
|
||||
public: public,
|
||||
private: private,
|
||||
|
|
@ -177,9 +167,6 @@ test "visible_for_user? Activity", %{
|
|||
refute Visibility.visible_for_user?(direct, nil)
|
||||
refute Visibility.visible_for_user?(local, nil)
|
||||
|
||||
# Visible for a list member
|
||||
assert Visibility.visible_for_user?(list, unrelated)
|
||||
|
||||
# Local not visible to remote user
|
||||
refute Visibility.visible_for_user?(local, remote)
|
||||
end
|
||||
|
|
@ -270,15 +257,16 @@ test "get_visibility", %{
|
|||
assert Visibility.get_visibility(private) == "private"
|
||||
assert Visibility.get_visibility(direct) == "direct"
|
||||
assert Visibility.get_visibility(unlisted) == "unlisted"
|
||||
assert Visibility.get_visibility(list) == "list"
|
||||
# legacy, no longer supported visibility type doesn't leak out now
|
||||
assert Visibility.get_visibility(list) == "direct"
|
||||
end
|
||||
|
||||
test "get_visibility with directMessage flag" do
|
||||
assert Visibility.get_visibility(%{data: %{"directMessage" => true}}) == "direct"
|
||||
end
|
||||
|
||||
test "get_visibility with listMessage flag" do
|
||||
assert Visibility.get_visibility(%{data: %{"listMessage" => ""}}) == "list"
|
||||
test "get_visibility treats legacy list messages as direct" do
|
||||
assert Visibility.get_visibility(%{data: %{"listMessage" => ""}}) == "direct"
|
||||
end
|
||||
|
||||
describe "entire_thread_visible_for_user?/2" do
|
||||
|
|
|
|||
|
|
@ -808,41 +808,6 @@ test "it resend emails for two users", %{conn: conn, admin: admin} do
|
|||
end
|
||||
end
|
||||
|
||||
describe "/api/v1/pleroma/admin/stats" do
|
||||
test "status visibility count", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
CommonAPI.post(user, %{visibility: "public", status: "hey"})
|
||||
CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
|
||||
CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/stats")
|
||||
|> json_response(200)
|
||||
|
||||
assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
|
||||
response["status_visibility"]
|
||||
end
|
||||
|
||||
test "by instance", %{conn: conn} do
|
||||
user1 = insert(:user)
|
||||
instance2 = "instance2.tld"
|
||||
user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
|
||||
|
||||
CommonAPI.post(user1, %{visibility: "public", status: "hey"})
|
||||
CommonAPI.post(user2, %{visibility: "unlisted", status: "hey"})
|
||||
CommonAPI.post(user2, %{visibility: "private", status: "hey"})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/stats", instance: instance2)
|
||||
|> json_response(200)
|
||||
|
||||
assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
|
||||
response["status_visibility"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "/api/v1/pleroma/backups" do
|
||||
test "it creates a backup", %{conn: conn} do
|
||||
admin = %{id: admin_id, nickname: admin_nickname} = insert(:user, is_admin: true)
|
||||
|
|
|
|||
|
|
@ -609,27 +609,6 @@ test "returns [] when not pass media_ids" do
|
|||
end
|
||||
end
|
||||
|
||||
describe "maybe_add_list_data/3" do
|
||||
test "adds list params when found user list" do
|
||||
user = insert(:user)
|
||||
{:ok, %Pleroma.List{} = list} = Pleroma.List.create("title", user)
|
||||
|
||||
assert Utils.maybe_add_list_data(%{additional: %{}, object: %{}}, user, {:list, list.id}) ==
|
||||
%{
|
||||
additional: %{"bcc" => [list.ap_id], "listMessage" => list.ap_id},
|
||||
object: %{"listMessage" => list.ap_id}
|
||||
}
|
||||
end
|
||||
|
||||
test "returns original params when list not found" do
|
||||
user = insert(:user)
|
||||
{:ok, %Pleroma.List{} = list} = Pleroma.List.create("title", insert(:user))
|
||||
|
||||
assert Utils.maybe_add_list_data(%{additional: %{}, object: %{}}, user, {:list, list.id}) ==
|
||||
%{additional: %{}, object: %{}}
|
||||
end
|
||||
end
|
||||
|
||||
describe "maybe_add_attachments/3" do
|
||||
test "returns parsed results when attachment_links is false" do
|
||||
assert Utils.maybe_add_attachments(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -543,17 +500,6 @@ test "replying with a direct message will NOT auto-add the author of the reply t
|
|||
refute user.ap_id in secret_answer.recipients
|
||||
end
|
||||
|
||||
test "it allows to address a list" do
|
||||
user = insert(:user)
|
||||
{:ok, list} = Pleroma.List.create("foo", user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
|
||||
|
||||
assert activity.data["bcc"] == [list.ap_id]
|
||||
assert activity.recipients == [list.ap_id, user.ap_id]
|
||||
assert activity.data["listMessage"] == list.ap_id
|
||||
end
|
||||
|
||||
test "it adds the htmlMFM term to MFM posts and properly processes it" do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
|
|||
|
|
@ -942,18 +942,6 @@ test "does not embed a relationship in the account in reposts" do
|
|||
assert_schema(result, "Status", Pleroma.Web.ApiSpec.spec())
|
||||
end
|
||||
|
||||
test "visibility/list" do
|
||||
user = insert(:user)
|
||||
|
||||
{:ok, list} = Pleroma.List.create("foo", user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "foobar", visibility: "list:#{list.id}"})
|
||||
|
||||
status = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert status.visibility == "list"
|
||||
end
|
||||
|
||||
test "has a field for parent visibility" do
|
||||
user = insert(:user)
|
||||
poster = 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