Merge branch 'feature/mastoapi-ext-conversation-id' into 'develop'
Mastodon API: add conversation_id extension See merge request pleroma/pleroma!961
This commit is contained in:
commit
b548181b52
|
@ -19,6 +19,7 @@ Adding the parameter `with_muted=true` to the timeline queries will also return
|
||||||
Has these additional fields under the `pleroma` object:
|
Has these additional fields under the `pleroma` object:
|
||||||
|
|
||||||
- `local`: true if the post was made on the local instance.
|
- `local`: true if the post was made on the local instance.
|
||||||
|
- `conversation_id`: the ID of the conversation the status is associated with (if any)
|
||||||
|
|
||||||
## Attachments
|
## Attachments
|
||||||
|
|
||||||
|
|
|
@ -344,4 +344,33 @@ def get_report_statuses(%User{ap_id: actor}, %{"status_ids" => status_ids}) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_report_statuses(_, _), do: {:ok, nil}
|
def get_report_statuses(_, _), do: {:ok, nil}
|
||||||
|
|
||||||
|
# DEPRECATED mostly, context objects are now created at insertion time.
|
||||||
|
def context_to_conversation_id(context) do
|
||||||
|
with %Object{id: id} <- Object.get_cached_by_ap_id(context) do
|
||||||
|
id
|
||||||
|
else
|
||||||
|
_e ->
|
||||||
|
changeset = Object.context_mapping(context)
|
||||||
|
|
||||||
|
case Repo.insert(changeset) do
|
||||||
|
{:ok, %{id: id}} ->
|
||||||
|
id
|
||||||
|
|
||||||
|
# This should be solved by an upsert, but it seems ecto
|
||||||
|
# has problems accessing the constraint inside the jsonb.
|
||||||
|
{:error, _} ->
|
||||||
|
Object.get_cached_by_ap_id(context).id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def conversation_id_to_context(id) do
|
||||||
|
with %Object{data: %{"id" => context}} <- Repo.get(Object, id) do
|
||||||
|
context
|
||||||
|
else
|
||||||
|
_e ->
|
||||||
|
{:error, "No such conversation"}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -46,6 +46,14 @@ defp get_user(ap_id) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_context_id(%{data: %{"context_id" => context_id}}) when not is_nil(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(_), do: nil
|
||||||
|
|
||||||
def render("index.json", opts) do
|
def render("index.json", opts) do
|
||||||
replied_to_activities = get_replied_to_activities(opts.activities)
|
replied_to_activities = get_replied_to_activities(opts.activities)
|
||||||
|
|
||||||
|
@ -186,7 +194,8 @@ def render("status.json", %{activity: %{data: %{"object" => object}} = activity}
|
||||||
language: nil,
|
language: nil,
|
||||||
emojis: build_emojis(activity.data["object"]["emoji"]),
|
emojis: build_emojis(activity.data["object"]["emoji"]),
|
||||||
pleroma: %{
|
pleroma: %{
|
||||||
local: activity.local
|
local: activity.local,
|
||||||
|
conversation_id: get_context_id(activity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Mailer
|
alias Pleroma.Mailer
|
||||||
alias Pleroma.Object
|
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.UserEmail
|
alias Pleroma.UserEmail
|
||||||
|
@ -282,35 +281,6 @@ def search(_user, %{"q" => query} = params) do
|
||||||
_activities = Repo.all(q)
|
_activities = Repo.all(q)
|
||||||
end
|
end
|
||||||
|
|
||||||
# DEPRECATED mostly, context objects are now created at insertion time.
|
|
||||||
def context_to_conversation_id(context) do
|
|
||||||
with %Object{id: id} <- Object.get_cached_by_ap_id(context) do
|
|
||||||
id
|
|
||||||
else
|
|
||||||
_e ->
|
|
||||||
changeset = Object.context_mapping(context)
|
|
||||||
|
|
||||||
case Repo.insert(changeset) do
|
|
||||||
{:ok, %{id: id}} ->
|
|
||||||
id
|
|
||||||
|
|
||||||
# This should be solved by an upsert, but it seems ecto
|
|
||||||
# has problems accessing the constraint inside the jsonb.
|
|
||||||
{:error, _} ->
|
|
||||||
Object.get_cached_by_ap_id(context).id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def conversation_id_to_context(id) do
|
|
||||||
with %Object{data: %{"id" => context}} <- Repo.get(Object, id) do
|
|
||||||
context
|
|
||||||
else
|
|
||||||
_e ->
|
|
||||||
{:error, "No such conversation"}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_external_profile(for_user, uri) do
|
def get_external_profile(for_user, uri) do
|
||||||
with %User{} = user <- User.get_or_fetch(uri) do
|
with %User{} = user <- User.get_or_fetch(uri) do
|
||||||
{:ok, UserView.render("show.json", %{user: user, for: for_user})}
|
{:ok, UserView.render("show.json", %{user: user, for: for_user})}
|
||||||
|
|
|
@ -16,6 +16,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.OAuth.Token
|
alias Pleroma.Web.OAuth.Token
|
||||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
alias Pleroma.Web.TwitterAPI.ActivityView
|
||||||
alias Pleroma.Web.TwitterAPI.NotificationView
|
alias Pleroma.Web.TwitterAPI.NotificationView
|
||||||
|
@ -278,7 +279,7 @@ def fetch_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def fetch_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
with context when is_binary(context) <- TwitterAPI.conversation_id_to_context(id),
|
with context when is_binary(context) <- Utils.conversation_id_to_context(id),
|
||||||
activities <-
|
activities <-
|
||||||
ActivityPub.fetch_activities_for_context(context, %{
|
ActivityPub.fetch_activities_for_context(context, %{
|
||||||
"blocking_user" => user,
|
"blocking_user" => user,
|
||||||
|
|
|
@ -15,7 +15,6 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
alias Pleroma.Web.TwitterAPI.ActivityView
|
||||||
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
||||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
|
||||||
alias Pleroma.Web.TwitterAPI.UserView
|
alias Pleroma.Web.TwitterAPI.UserView
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
@ -78,7 +77,7 @@ defp get_context_id(%{data: %{"context" => nil}}, _), do: nil
|
||||||
defp get_context_id(%{data: %{"context" => context}}, options) do
|
defp get_context_id(%{data: %{"context" => context}}, options) do
|
||||||
cond do
|
cond do
|
||||||
id = options[:context_ids][context] -> id
|
id = options[:context_ids][context] -> id
|
||||||
true -> TwitterAPI.context_to_conversation_id(context)
|
true -> Utils.context_to_conversation_id(context)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
defmodule Pleroma.Web.CommonAPI.UtilsTest do
|
||||||
alias Pleroma.Builders.UserBuilder
|
alias Pleroma.Builders.UserBuilder
|
||||||
|
alias Pleroma.Object
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.Endpoint
|
alias Pleroma.Web.Endpoint
|
||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
|
@ -136,4 +137,20 @@ test "works for text/markdown with mentions" do
|
||||||
assert output == expected
|
assert output == expected
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "context_to_conversation_id" do
|
||||||
|
test "creates a mapping object" do
|
||||||
|
conversation_id = Utils.context_to_conversation_id("random context")
|
||||||
|
object = Object.get_by_ap_id("random context")
|
||||||
|
|
||||||
|
assert conversation_id == object.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns an existing mapping for an existing object" do
|
||||||
|
{:ok, object} = Object.context_mapping("random context") |> Repo.insert()
|
||||||
|
conversation_id = Utils.context_to_conversation_id("random context")
|
||||||
|
|
||||||
|
assert conversation_id == object.id
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.OStatus
|
alias Pleroma.Web.OStatus
|
||||||
|
@ -72,6 +73,8 @@ test "a note activity" do
|
||||||
note = insert(:note_activity)
|
note = insert(:note_activity)
|
||||||
user = User.get_cached_by_ap_id(note.data["actor"])
|
user = User.get_cached_by_ap_id(note.data["actor"])
|
||||||
|
|
||||||
|
convo_id = Utils.context_to_conversation_id(note.data["object"]["context"])
|
||||||
|
|
||||||
status = StatusView.render("status.json", %{activity: note})
|
status = StatusView.render("status.json", %{activity: note})
|
||||||
|
|
||||||
created_at =
|
created_at =
|
||||||
|
@ -122,7 +125,8 @@ test "a note activity" do
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
pleroma: %{
|
pleroma: %{
|
||||||
local: true
|
local: true,
|
||||||
|
conversation_id: convo_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -445,22 +445,6 @@ test "it assigns an integer conversation_id" do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "context_to_conversation_id" do
|
|
||||||
test "creates a mapping object" do
|
|
||||||
conversation_id = TwitterAPI.context_to_conversation_id("random context")
|
|
||||||
object = Object.get_by_ap_id("random context")
|
|
||||||
|
|
||||||
assert conversation_id == object.id
|
|
||||||
end
|
|
||||||
|
|
||||||
test "returns an existing mapping for an existing object" do
|
|
||||||
{:ok, object} = Object.context_mapping("random context") |> Repo.insert()
|
|
||||||
conversation_id = TwitterAPI.context_to_conversation_id("random context")
|
|
||||||
|
|
||||||
assert conversation_id == object.id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe "fetching a user by uri" do
|
describe "fetching a user by uri" do
|
||||||
test "fetches a user by uri" do
|
test "fetches a user by uri" do
|
||||||
id = "https://mastodon.social/users/lambadalambda"
|
id = "https://mastodon.social/users/lambadalambda"
|
||||||
|
|
|
@ -12,7 +12,6 @@ defmodule Pleroma.Web.TwitterAPI.ActivityViewTest do
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.TwitterAPI.ActivityView
|
alias Pleroma.Web.TwitterAPI.ActivityView
|
||||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
|
||||||
alias Pleroma.Web.TwitterAPI.UserView
|
alias Pleroma.Web.TwitterAPI.UserView
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -129,7 +128,7 @@ test "a create activity with a note" do
|
||||||
|
|
||||||
result = ActivityView.render("activity.json", activity: activity)
|
result = ActivityView.render("activity.json", activity: activity)
|
||||||
|
|
||||||
convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
|
convo_id = Utils.context_to_conversation_id(activity.data["object"]["context"])
|
||||||
|
|
||||||
expected = %{
|
expected = %{
|
||||||
"activity_type" => "post",
|
"activity_type" => "post",
|
||||||
|
@ -177,12 +176,12 @@ test "a list of activities" do
|
||||||
other_user = insert(:user, %{nickname: "shp"})
|
other_user = insert(:user, %{nickname: "shp"})
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
||||||
|
|
||||||
convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
|
convo_id = Utils.context_to_conversation_id(activity.data["object"]["context"])
|
||||||
|
|
||||||
mocks = [
|
mocks = [
|
||||||
{
|
{
|
||||||
TwitterAPI,
|
Utils,
|
||||||
[],
|
[:passthrough],
|
||||||
[context_to_conversation_id: fn _ -> false end]
|
[context_to_conversation_id: fn _ -> false end]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -197,7 +196,7 @@ test "a list of activities" do
|
||||||
|
|
||||||
assert result["statusnet_conversation_id"] == convo_id
|
assert result["statusnet_conversation_id"] == convo_id
|
||||||
assert result["user"]
|
assert result["user"]
|
||||||
refute called(TwitterAPI.context_to_conversation_id(:_))
|
refute called(Utils.context_to_conversation_id(:_))
|
||||||
refute called(User.get_cached_by_ap_id(user.ap_id))
|
refute called(User.get_cached_by_ap_id(user.ap_id))
|
||||||
refute called(User.get_cached_by_ap_id(other_user.ap_id))
|
refute called(User.get_cached_by_ap_id(other_user.ap_id))
|
||||||
end
|
end
|
||||||
|
@ -280,7 +279,7 @@ test "an announce activity" do
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"})
|
||||||
{:ok, announce, _object} = CommonAPI.repeat(activity.id, other_user)
|
{:ok, announce, _object} = CommonAPI.repeat(activity.id, other_user)
|
||||||
|
|
||||||
convo_id = TwitterAPI.context_to_conversation_id(activity.data["object"]["context"])
|
convo_id = Utils.context_to_conversation_id(activity.data["object"]["context"])
|
||||||
|
|
||||||
activity = Repo.get(Activity, activity.id)
|
activity = Repo.get(Activity, activity.id)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue