diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mix/tasks/pleroma/database.ex | 23 | ||||
-rw-r--r-- | lib/pleroma/activity.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/chat/message_reference.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/data_migration_failed_id.ex | 13 | ||||
-rw-r--r-- | lib/pleroma/delivery.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/hashtag.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/hashtag_object.ex | 17 | ||||
-rw-r--r-- | lib/pleroma/migration_helper/legacy_activity.ex | 103 | ||||
-rw-r--r-- | lib/pleroma/migration_helper/object_id.ex | 61 | ||||
-rw-r--r-- | lib/pleroma/migrators/hashtags_table_migrator.ex | 42 | ||||
-rw-r--r-- | lib/pleroma/notification.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/object.ex | 5 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 21 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/object_validators/common_fields.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/utils.ex | 31 | ||||
-rw-r--r-- | lib/pleroma/web/api_spec/schemas/status.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/views/status_view.ex | 14 |
17 files changed, 264 insertions, 87 deletions
diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex index a973beaa9..a87c2c2e6 100644 --- a/lib/mix/tasks/pleroma/database.ex +++ b/lib/mix/tasks/pleroma/database.ex @@ -20,29 +20,6 @@ defmodule Mix.Tasks.Pleroma.Database do @shortdoc "A collection of database related tasks" @moduledoc File.read!("docs/administration/CLI_tasks/database.md") - def run(["remove_embedded_objects" | args]) do - {options, [], []} = - OptionParser.parse( - args, - strict: [ - vacuum: :boolean - ] - ) - - start_pleroma() - Logger.info("Removing embedded objects") - - Repo.query!( - "update activities set data = safe_jsonb_set(data, '{object}'::text[], data->'object'->'id') where data->'object'->>'id' is not null;", - [], - timeout: :infinity - ) - - if Keyword.get(options, :vacuum) do - Maintenance.vacuum("full") - end - end - def run(["bump_all_conversations"]) do start_pleroma() Conversation.bump_for_all_activities() diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 4106feef6..30d8f7092 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -26,7 +26,7 @@ defmodule Pleroma.Activity do @cachex Pleroma.Config.get([:cachex, :provider], Cachex) - schema "activities" do + schema "objects" do field(:data, :map) field(:local, :boolean, default: true) field(:actor, :string) diff --git a/lib/pleroma/chat/message_reference.ex b/lib/pleroma/chat/message_reference.ex index 89537d155..06fdb3401 100644 --- a/lib/pleroma/chat/message_reference.ex +++ b/lib/pleroma/chat/message_reference.ex @@ -20,7 +20,7 @@ defmodule Pleroma.Chat.MessageReference do @primary_key {:id, FlakeId.Ecto.Type, autogenerate: true} schema "chat_message_references" do - belongs_to(:object, Object) + belongs_to(:object, Object, type: FlakeId.Ecto.CompatType) belongs_to(:chat, Chat, type: FlakeId.Ecto.CompatType) field(:unread, :boolean, default: true) diff --git a/lib/pleroma/data_migration_failed_id.ex b/lib/pleroma/data_migration_failed_id.ex new file mode 100644 index 000000000..117795d44 --- /dev/null +++ b/lib/pleroma/data_migration_failed_id.ex @@ -0,0 +1,13 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.DataMigrationFailedId do + use Ecto.Schema + alias Pleroma.DataMigration + + schema "data_migration_failed_ids" do + belongs_to(:data_migration, DataMigration) + field(:record_id, FlakeId.Ecto.CompatType) + end +end diff --git a/lib/pleroma/delivery.ex b/lib/pleroma/delivery.ex index 511d5cf58..b1ed6a8fd 100644 --- a/lib/pleroma/delivery.ex +++ b/lib/pleroma/delivery.ex @@ -15,7 +15,7 @@ defmodule Pleroma.Delivery do schema "deliveries" do belongs_to(:user, User, type: FlakeId.Ecto.CompatType) - belongs_to(:object, Object) + belongs_to(:object, Object, type: FlakeId.Ecto.CompatType) end def changeset(delivery, params \\ %{}) do diff --git a/lib/pleroma/hashtag.ex b/lib/pleroma/hashtag.ex index 53e2e9c89..046c67943 100644 --- a/lib/pleroma/hashtag.ex +++ b/lib/pleroma/hashtag.ex @@ -10,13 +10,14 @@ defmodule Pleroma.Hashtag do alias Ecto.Multi alias Pleroma.Hashtag + alias Pleroma.HashtagObject alias Pleroma.Object alias Pleroma.Repo schema "hashtags" do field(:name, :string) - many_to_many(:objects, Object, join_through: "hashtags_objects", on_replace: :delete) + many_to_many(:objects, Object, join_through: HashtagObject, on_replace: :delete) timestamps() end @@ -80,7 +81,7 @@ defmodule Pleroma.Hashtag do def unlink(%Object{id: object_id}) do with {_, hashtag_ids} <- - from(hto in "hashtags_objects", + from(hto in HashtagObject, where: hto.object_id == ^object_id, select: hto.hashtag_id ) diff --git a/lib/pleroma/hashtag_object.ex b/lib/pleroma/hashtag_object.ex new file mode 100644 index 000000000..12b570715 --- /dev/null +++ b/lib/pleroma/hashtag_object.ex @@ -0,0 +1,17 @@ +defmodule Pleroma.HashtagObject do + @moduledoc """ + Through table relationship between hashtags and objects. + https://hexdocs.pm/ecto/polymorphic-associations-with-many-to-many.html + """ + use Ecto.Schema + + alias Pleroma.Hashtag + alias Pleroma.Object + + @primary_key false + + schema "hashtags_objects" do + belongs_to(:hashtag, Hashtag) + belongs_to(:object, Object, type: FlakeId.Ecto.CompatType) + end +end diff --git a/lib/pleroma/migration_helper/legacy_activity.ex b/lib/pleroma/migration_helper/legacy_activity.ex new file mode 100644 index 000000000..30a139d4e --- /dev/null +++ b/lib/pleroma/migration_helper/legacy_activity.ex @@ -0,0 +1,103 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.MigrationHelper.LegacyActivity do + @moduledoc """ + Legacy "activities" schema needed for old migrations. + """ + use Ecto.Schema + + alias Pleroma.Activity.Queries + alias Pleroma.Bookmark + alias Pleroma.MigrationHelper.LegacyActivity, as: Activity + alias Pleroma.Notification + alias Pleroma.Object + alias Pleroma.Repo + alias Pleroma.ReportNote + alias Pleroma.User + + import Ecto.Query + + @type t :: %__MODULE__{} + @type actor :: String.t() + + @primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true} + + schema "activities" do + field(:data, :map) + field(:local, :boolean, default: true) + field(:actor, :string) + field(:recipients, {:array, :string}, default: []) + field(:thread_muted?, :boolean, virtual: true) + + # A field that can be used if you need to join some kind of other + # id to order / paginate this field by + field(:pagination_id, :string, virtual: true) + + # This is a fake relation, + # do not use outside of with_preloaded_user_actor/with_joined_user_actor + has_one(:user_actor, User, on_delete: :nothing, foreign_key: :id) + # This is a fake relation, do not use outside of with_preloaded_bookmark/get_bookmark + has_one(:bookmark, Bookmark, foreign_key: :activity_id) + # This is a fake relation, do not use outside of with_preloaded_report_notes + has_many(:report_notes, ReportNote, foreign_key: :activity_id) + has_many(:notifications, Notification, on_delete: :delete_all, foreign_key: :activity_id) + + # Attention: this is a fake relation, don't try to preload it blindly and expect it to work! + # The foreign key is embedded in a jsonb field. + # + # To use it, you probably want to do an inner join and a preload: + # + # ``` + # |> join(:inner, [activity], o in Object, + # on: fragment("(?->>'id') = COALESCE((?)->'object'->> 'id', (?)->>'object')", + # o.data, activity.data, activity.data)) + # |> preload([activity, object], [object: object]) + # ``` + # + # As a convenience, Activity.with_preloaded_object() sets up an inner join and preload for the + # typical case. + has_one(:object, Object, on_delete: :nothing, foreign_key: :id) + + timestamps() + end + + def with_joined_object(query, join_type \\ :inner) do + join(query, join_type, [activity], o in Object, + on: + fragment( + "(?->>'id') = COALESCE(?->'object'->>'id', ?->>'object')", + o.data, + activity.data, + activity.data + ), + as: :object + ) + end + + def with_preloaded_object(query, join_type \\ :inner) do + query + |> has_named_binding?(:object) + |> if(do: query, else: with_joined_object(query, join_type)) + |> preload([activity, object: object], object: object) + end + + def all_by_ids_with_object(ids) do + Activity + |> where([a], a.id in ^ids) + |> with_preloaded_object() + |> Repo.all() + end + + @doc """ + Accepts `ap_id` or list of `ap_id`. + Returns a query. + """ + @spec create_by_object_ap_id(String.t() | [String.t()]) :: Ecto.Queryable.t() + def create_by_object_ap_id(ap_id) do + Activity + |> Queries.by_object_id(ap_id) + |> Queries.by_type("Create") + end +end diff --git a/lib/pleroma/migration_helper/object_id.ex b/lib/pleroma/migration_helper/object_id.ex new file mode 100644 index 000000000..3cc487523 --- /dev/null +++ b/lib/pleroma/migration_helper/object_id.ex @@ -0,0 +1,61 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.MigrationHelper.ObjectId do + @moduledoc """ + Functions for migrating Object IDs. + """ + alias Pleroma.Chat.MessageReference + alias Pleroma.DataMigrationFailedId + alias Pleroma.Delivery + alias Pleroma.HashtagObject + alias Pleroma.Object + alias Pleroma.Repo + + import Ecto.Changeset + import Ecto.Query + + @doc "Change an object's ID including all references." + def change_id(%Object{id: old_id} = object, new_id) do + Repo.transaction(fn -> + update_object_fk(MessageReference, old_id, new_id) + update_object_fk(Delivery, old_id, new_id) + update_object_fk(HashtagObject, old_id, new_id) + update_object_fk(DataMigrationFailedId, old_id, new_id, :record_id) + + Repo.update!(change(object, id: new_id)) + end) + end + + defp update_object_fk(schema, old_id, new_id, field \\ :object_id) do + binding = [{field, old_id}] + + schema + |> where(^binding) + |> Repo.update_all(set: [{field, new_id}]) + end + + @doc "Generate a FlakeId from a datetime." + @spec flake_from_time(NaiveDateTime.t()) :: flake_id :: String.t() + def flake_from_time(%NaiveDateTime{} = dt) do + dt + |> build_worker() + |> FlakeId.Worker.gen_flake() + |> FlakeId.to_string() + end + + # Build a one-off FlakeId worker. + defp build_worker(%NaiveDateTime{} = dt) do + %FlakeId.Worker{ + node: FlakeId.Worker.worker_id(), + time: get_timestamp(dt, :millisecond) + } + end + + # Convert a NaiveDateTime into a Unix timestamp. + @epoch ~N[1970-01-01 00:00:00] + defp get_timestamp(%NaiveDateTime{} = dt, unit) do + NaiveDateTime.diff(dt, @epoch, unit) + end +end diff --git a/lib/pleroma/migrators/hashtags_table_migrator.ex b/lib/pleroma/migrators/hashtags_table_migrator.ex index b84058e11..b5add9659 100644 --- a/lib/pleroma/migrators/hashtags_table_migrator.ex +++ b/lib/pleroma/migrators/hashtags_table_migrator.ex @@ -12,10 +12,14 @@ defmodule Pleroma.Migrators.HashtagsTableMigrator do use Pleroma.Migrators.Support.BaseMigrator + alias Pleroma.DataMigrationFailedId alias Pleroma.Hashtag + alias Pleroma.HashtagObject alias Pleroma.Migrators.Support.BaseMigrator alias Pleroma.Object + import Ecto.Query + @impl BaseMigrator def feature_config_path, do: [:features, :improved_hashtag_timeline] @@ -50,19 +54,20 @@ defmodule Pleroma.Migrators.HashtagsTableMigrator do for failed_id <- failed_ids do _ = - Repo.query( - "INSERT INTO data_migration_failed_ids(data_migration_id, record_id) " <> - "VALUES ($1, $2) ON CONFLICT DO NOTHING;", - [data_migration_id, failed_id] - ) + %DataMigrationFailedId{ + data_migration_id: data_migration_id, + record_id: failed_id + } + |> Repo.insert(on_conflict: :nothing) end + record_ids = object_ids -- failed_ids + _ = - Repo.query( - "DELETE FROM data_migration_failed_ids " <> - "WHERE data_migration_id = $1 AND record_id = ANY($2)", - [data_migration_id, object_ids -- failed_ids] - ) + DataMigrationFailedId + |> where(data_migration_id: ^data_migration_id) + |> where([dmf], dmf.record_id in ^record_ids) + |> Repo.delete_all() max_object_id = Enum.at(object_ids, -1) @@ -120,7 +125,7 @@ defmodule Pleroma.Migrators.HashtagsTableMigrator do try do with {rows_count, _} when is_integer(rows_count) <- - Repo.insert_all("hashtags_objects", maps, on_conflict: :nothing) do + Repo.insert_all(HashtagObject, maps, on_conflict: :nothing) do object.id else e -> @@ -147,14 +152,13 @@ defmodule Pleroma.Migrators.HashtagsTableMigrator do failed_objects_query() |> Repo.chunk_stream(100, :one) - |> Stream.each(fn object -> + |> Stream.each(fn %{id: object_id} = object -> with {res, _} when res != :error <- transfer_object_hashtags(object) do _ = - Repo.query( - "DELETE FROM data_migration_failed_ids " <> - "WHERE data_migration_id = $1 AND record_id = $2", - [data_migration_id, object.id] - ) + DataMigrationFailedId + |> where(data_migration_id: ^data_migration_id) + |> where(record_id: ^object_id) + |> Repo.delete_all() end end) |> Stream.run() @@ -167,9 +171,7 @@ defmodule Pleroma.Migrators.HashtagsTableMigrator do defp failed_objects_query do from(o in Object) - |> join(:inner, [o], dmf in fragment("SELECT * FROM data_migration_failed_ids"), - on: dmf.record_id == o.id - ) + |> join(:inner, [o], dmf in DataMigrationFailedId, on: dmf.record_id == o.id) |> where([_o, dmf], dmf.data_migration_id == ^data_migration_id()) |> order_by([o], asc: o.id) end diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 9e0ce0329..0853b7619 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -138,7 +138,7 @@ defmodule Pleroma.Notification do blocked_ap_ids = opts[:blocked_users_ap_ids] || User.blocked_users_ap_ids(user) query - |> where([n, a], a.actor not in ^blocked_ap_ids) + |> where([n, a], fragment("not (? && ?)", [a.actor], ^blocked_ap_ids)) |> FollowingRelationship.keep_following_or_not_domain_blocked(user) end @@ -149,7 +149,7 @@ defmodule Pleroma.Notification do blocker_ap_ids = User.incoming_relationships_ungrouped_ap_ids(user, [:block]) query - |> where([n, a], a.actor not in ^blocker_ap_ids) + |> where([n, a], fragment("not (? && ?)", [a.actor], ^blocker_ap_ids)) end end diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex index c3ea1b98b..8569fed8c 100644 --- a/lib/pleroma/object.ex +++ b/lib/pleroma/object.ex @@ -11,6 +11,7 @@ defmodule Pleroma.Object do alias Pleroma.Activity alias Pleroma.Config alias Pleroma.Hashtag + alias Pleroma.HashtagObject alias Pleroma.Object alias Pleroma.Object.Fetcher alias Pleroma.ObjectTombstone @@ -22,6 +23,8 @@ defmodule Pleroma.Object do @type t() :: %__MODULE__{} + @primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true} + @derive {Jason.Encoder, only: [:data]} @cachex Pleroma.Config.get([:cachex, :provider], Cachex) @@ -29,7 +32,7 @@ defmodule Pleroma.Object do schema "objects" do field(:data, :map) - many_to_many(:hashtags, Hashtag, join_through: "hashtags_objects", on_replace: :delete) + many_to_many(:hashtags, Hashtag, join_through: HashtagObject, on_replace: :delete) timestamps() end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index e6475a2b7..216758467 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do alias Pleroma.Conversation.Participation alias Pleroma.Filter alias Pleroma.Hashtag + alias Pleroma.HashtagObject alias Pleroma.Maps alias Pleroma.Notification alias Pleroma.Object @@ -96,14 +97,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp increase_replies_count_if_reply(_create_data), do: :noop - @object_types ~w[ChatMessage Question Answer Audio Video Event Article Note Page] - @impl true - def persist(%{"type" => type} = object, meta) when type in @object_types do - with {:ok, object} <- Object.create(object) do - {:ok, object, meta} - end - end - @impl true def persist(object, meta) do with local <- Keyword.fetch!(meta, :local), @@ -780,8 +773,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_embedded_tag_reject_any(query, _), do: query defp object_ids_query_for_tags(tags) do - from(hto in "hashtags_objects") - |> join(:inner, [hto], ht in Pleroma.Hashtag, on: hto.hashtag_id == ht.id) + from(hto in HashtagObject) + |> join(:inner, [hto], ht in Hashtag, on: hto.hashtag_id == ht.id) |> where([hto, ht], ht.name in ^tags) |> select([hto], hto.object_id) |> distinct([hto], true) @@ -830,7 +823,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do # Note: NO extra ordering should be done on "activities.id desc nulls last" for optimal plan from( [_activity, object] in query, - join: hto in "hashtags_objects", + join: hto in HashtagObject, on: hto.object_id == object.id, where: hto.hashtag_id in ^hashtag_ids, distinct: [desc: object.id], @@ -1035,7 +1028,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do from( [activity, object: o] in query, # You don't block the author - where: fragment("not (? = ANY(?))", activity.actor, ^blocked_ap_ids), + where: fragment("not (? && ?)", [activity.actor], ^blocked_ap_ids), # You don't block any recipients, and didn't author the post where: @@ -1099,7 +1092,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do from( activity in query, # The author doesn't block you - where: fragment("not (? = ANY(?))", activity.actor, ^blocker_ap_ids), + where: fragment("not (? && ?)", [activity.actor], ^blocker_ap_ids), # It's not a boost of a user that blocks you where: @@ -1165,7 +1158,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_instance(query, %{instance: instance}) when is_binary(instance) do from( activity in query, - where: fragment("split_part(actor::text, '/'::text, 3) = ?", ^instance) + where: fragment("split_part(?::text, '/'::text, 3) = ?", activity.actor, ^instance) ) end diff --git a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex index 872f80ec3..cb1f4e144 100644 --- a/lib/pleroma/web/activity_pub/object_validators/common_fields.ex +++ b/lib/pleroma/web/activity_pub/object_validators/common_fields.ex @@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.CommonFields do field(:context, :string) # short identifier for PleromaFE to group statuses by context - field(:context_id, :integer) + field(:context_id, :string) field(:sensitive, :boolean, default: false) field(:replies_count, :integer, default: 0) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index c1f6b2b49..d5f0a3245 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -712,9 +712,10 @@ defmodule Pleroma.Web.ActivityPub.Utils do defp build_flag_object(%{statuses: statuses}) do Enum.map(statuses || [], &build_flag_object/1) + |> Enum.reject(&is_nil/1) end - defp build_flag_object(%Activity{data: %{"id" => id}, object: %{data: data}}) do + defp build_flag_object(%Activity{data: %{"id" => id, "type" => "Create"}, object: %{data: data}}) do activity_actor = User.get_by_ap_id(data["actor"]) %{ @@ -730,28 +731,26 @@ defmodule Pleroma.Web.ActivityPub.Utils do } end - defp build_flag_object(act) when is_map(act) or is_binary(act) do - id = - case act do - %Activity{} = act -> act.data["id"] - act when is_map(act) -> act["id"] - act when is_binary(act) -> act - end + defp build_flag_object(%{data: %{"id" => id}}), do: build_flag_object(id) + defp build_flag_object(%{"id" => id}), do: build_flag_object(id) - case Activity.get_by_ap_id_with_object(id) do - %Activity{} = activity -> + defp build_flag_object(ap_id) when is_binary(ap_id) do + case Activity.get_by_ap_id_with_object(ap_id) do + %Activity{data: %{"type" => "Create"}} = activity -> build_flag_object(activity) - nil -> - if activity = Activity.get_by_object_ap_id_with_object(id) do - build_flag_object(activity) - else - %{"id" => id, "deleted" => true} + _ -> + case Activity.get_by_object_ap_id_with_object(ap_id) do + %Activity{data: %{"type" => "Create"}} = activity -> + build_flag_object(activity) + + _ -> + %{"id" => ap_id, "deleted" => true} end end end - defp build_flag_object(_), do: [] + defp build_flag_object(_), do: nil #### Report-related helpers def get_reports(params, page, page_size) do diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex index 3caab0f00..2129e351a 100644 --- a/lib/pleroma/web/api_spec/schemas/status.ex +++ b/lib/pleroma/web/api_spec/schemas/status.ex @@ -143,7 +143,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do "A map consisting of alternate representations of the `content` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`" }, conversation_id: %Schema{ - type: :integer, + type: :string, description: "The ID of the AP context the status is associated with (if any)" }, direct_conversation_id: %Schema{ @@ -319,7 +319,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do "pinned" => false, "pleroma" => %{ "content" => %{"text/plain" => "foobar"}, - "conversation_id" => 345_972, + "conversation_id" => "AEXFhY7X4zd8hZK8oK", "direct_conversation_id" => nil, "emoji_reactions" => [], "expires_at" => nil, diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 463f34198..ce350ad23 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -57,11 +57,19 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do end) end - defp get_context_id(%{data: %{"context_id" => context_id}}) when not is_nil(context_id), + defp get_context_id(%{data: %{"context_id" => context_id}}) when is_binary(context_id), do: context_id - defp get_context_id(%{data: %{"context" => context}}) when is_binary(context), - do: Utils.context_to_conversation_id(context) + defp get_context_id(%{data: %{"context_id" => context_id}}) when is_integer(context_id), + do: to_string(context_id) + + defp get_context_id(%{data: %{"context" => context}}) when is_binary(context) do + case Utils.context_to_conversation_id(context) do + id when is_binary(id) -> id + id when is_integer(id) -> to_string(id) + _ -> nil + end + end defp get_context_id(_), do: nil |