Pipeline Ingestion: Audio (Part 2)
This commit is contained in:
parent
3d5d8c05c9
commit
5316e231b0
10 changed files with 147 additions and 28 deletions
|
@ -85,7 +85,7 @@ defp increase_replies_count_if_reply(%{
|
||||||
|
|
||||||
defp increase_replies_count_if_reply(_create_data), do: :noop
|
defp increase_replies_count_if_reply(_create_data), do: :noop
|
||||||
|
|
||||||
@object_types ["ChatMessage", "Question", "Answer"]
|
@object_types ~w[ChatMessage Question Answer Audio]
|
||||||
@spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
|
@spec persist(map(), keyword()) :: {:ok, Activity.t() | Object.t()}
|
||||||
def persist(%{"type" => type} = object, meta) when type in @object_types do
|
def persist(%{"type" => type} = object, meta) when type in @object_types do
|
||||||
with {:ok, object} <- Object.create(object) do
|
with {:ok, object} <- Object.create(object) do
|
||||||
|
|
|
@ -41,34 +41,34 @@ def changeset(struct, data) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def fix_media_type(data) do
|
def fix_media_type(data) do
|
||||||
data =
|
data = Map.put_new(data, "mediaType", data["mimeType"])
|
||||||
data
|
|
||||||
|> Map.put_new("mediaType", data["mimeType"])
|
|
||||||
|
|
||||||
if MIME.valid?(data["mediaType"]) do
|
if MIME.valid?(data["mediaType"]) do
|
||||||
data
|
data
|
||||||
else
|
else
|
||||||
data
|
Map.put(data, "mediaType", "application/octet-stream")
|
||||||
|> Map.put("mediaType", "application/octet-stream")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def fix_url(data) do
|
defp handle_href(href, mediaType) do
|
||||||
case data["url"] do
|
[
|
||||||
url when is_binary(url) ->
|
%{
|
||||||
data
|
"href" => href,
|
||||||
|> Map.put(
|
"type" => "Link",
|
||||||
"url",
|
"mediaType" => mediaType
|
||||||
[
|
}
|
||||||
%{
|
]
|
||||||
"href" => url,
|
end
|
||||||
"type" => "Link",
|
|
||||||
"mediaType" => data["mediaType"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
_ ->
|
defp fix_url(data) do
|
||||||
|
cond do
|
||||||
|
is_binary(data["url"]) ->
|
||||||
|
Map.put(data, "url", handle_href(data["url"], data["mediaType"]))
|
||||||
|
|
||||||
|
is_binary(data["href"]) and data["url"] == nil ->
|
||||||
|
Map.put(data, "url", handle_href(data["href"], data["mediaType"]))
|
||||||
|
|
||||||
|
true ->
|
||||||
data
|
data
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,7 +41,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AudioValidator do
|
||||||
field(:like_count, :integer, default: 0)
|
field(:like_count, :integer, default: 0)
|
||||||
field(:announcement_count, :integer, default: 0)
|
field(:announcement_count, :integer, default: 0)
|
||||||
field(:inReplyTo, :string)
|
field(:inReplyTo, :string)
|
||||||
field(:uri, ObjectValidators.Uri)
|
field(:url, ObjectValidators.Uri)
|
||||||
# short identifier for PleromaFE to group statuses by context
|
# short identifier for PleromaFE to group statuses by context
|
||||||
field(:context_id, :integer)
|
field(:context_id, :integer)
|
||||||
|
|
||||||
|
@ -66,10 +66,24 @@ def cast_data(data) do
|
||||||
|> changeset(data)
|
|> changeset(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp fix_url(%{"url" => url} = data) when is_list(url) do
|
||||||
|
attachment =
|
||||||
|
Enum.find(url, fn x -> is_map(x) and String.starts_with?(x["mimeType"], "audio/") end)
|
||||||
|
|
||||||
|
link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end)
|
||||||
|
|
||||||
|
data
|
||||||
|
|> Map.put("attachment", [attachment])
|
||||||
|
|> Map.put("url", link_element["href"])
|
||||||
|
end
|
||||||
|
|
||||||
|
defp fix_url(data), do: data
|
||||||
|
|
||||||
defp fix(data) do
|
defp fix(data) do
|
||||||
data
|
data
|
||||||
|> CommonFixes.fix_defaults()
|
|> CommonFixes.fix_defaults()
|
||||||
|> CommonFixes.fix_attribution()
|
|> CommonFixes.fix_attribution()
|
||||||
|
|> fix_url()
|
||||||
end
|
end
|
||||||
|
|
||||||
def changeset(struct, data) do
|
def changeset(struct, data) do
|
||||||
|
@ -83,7 +97,7 @@ def changeset(struct, data) do
|
||||||
def validate_data(data_cng) do
|
def validate_data(data_cng) do
|
||||||
data_cng
|
data_cng
|
||||||
|> validate_inclusion(:type, ["Audio"])
|
|> validate_inclusion(:type, ["Audio"])
|
||||||
|> validate_required([:id, :actor, :attributedTo, :type, :context])
|
|> validate_required([:id, :actor, :attributedTo, :type, :context, :attachment])
|
||||||
|> CommonValidations.validate_any_presence([:cc, :to])
|
|> CommonValidations.validate_any_presence([:cc, :to])
|
||||||
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|
|> CommonValidations.validate_fields_match([:actor, :attributedTo])
|
||||||
|> CommonValidations.validate_actor_presence()
|
|> CommonValidations.validate_actor_presence()
|
||||||
|
|
|
@ -61,9 +61,20 @@ defp fix_context(data, meta) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp fix_addressing(data, meta) do
|
||||||
|
if object = meta[:object_data] do
|
||||||
|
data
|
||||||
|
|> Map.put_new("to", object["to"] || [])
|
||||||
|
|> Map.put_new("cc", object["cc"] || [])
|
||||||
|
else
|
||||||
|
data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp fix(data, meta) do
|
defp fix(data, meta) do
|
||||||
data
|
data
|
||||||
|> fix_context(meta)
|
|> fix_context(meta)
|
||||||
|
|> fix_addressing(meta)
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_data(cng, meta \\ []) do
|
def validate_data(cng, meta \\ []) do
|
||||||
|
|
|
@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.NoteValidator do
|
||||||
field(:like_count, :integer, default: 0)
|
field(:like_count, :integer, default: 0)
|
||||||
field(:announcement_count, :integer, default: 0)
|
field(:announcement_count, :integer, default: 0)
|
||||||
field(:inReplyTo, ObjectValidators.ObjectID)
|
field(:inReplyTo, ObjectValidators.ObjectID)
|
||||||
field(:uri, ObjectValidators.Uri)
|
field(:url, ObjectValidators.Uri)
|
||||||
|
|
||||||
field(:likes, {:array, :string}, default: [])
|
field(:likes, {:array, :string}, default: [])
|
||||||
field(:announcements, {:array, :string}, default: [])
|
field(:announcements, {:array, :string}, default: [])
|
||||||
|
|
|
@ -43,7 +43,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.QuestionValidator do
|
||||||
field(:like_count, :integer, default: 0)
|
field(:like_count, :integer, default: 0)
|
||||||
field(:announcement_count, :integer, default: 0)
|
field(:announcement_count, :integer, default: 0)
|
||||||
field(:inReplyTo, ObjectValidators.ObjectID)
|
field(:inReplyTo, ObjectValidators.ObjectID)
|
||||||
field(:uri, ObjectValidators.Uri)
|
field(:url, ObjectValidators.Uri)
|
||||||
# short identifier for PleromaFE to group statuses by context
|
# short identifier for PleromaFE to group statuses by context
|
||||||
field(:context_id, :integer)
|
field(:context_id, :integer)
|
||||||
|
|
||||||
|
|
|
@ -276,13 +276,12 @@ def fix_url(%{"url" => url} = object) when is_map(url) do
|
||||||
Map.put(object, "url", url["href"])
|
Map.put(object, "url", url["href"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def fix_url(%{"type" => object_type, "url" => url} = object)
|
def fix_url(%{"type" => "Video", "url" => url} = object) when is_list(url) do
|
||||||
when object_type in ["Video", "Audio"] and is_list(url) do
|
|
||||||
attachment =
|
attachment =
|
||||||
Enum.find(url, fn x ->
|
Enum.find(url, fn x ->
|
||||||
media_type = x["mediaType"] || x["mimeType"] || ""
|
media_type = x["mediaType"] || x["mimeType"] || ""
|
||||||
|
|
||||||
is_map(x) and String.starts_with?(media_type, ["audio/", "video/"])
|
is_map(x) and String.starts_with?(media_type, "video/")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
link_element =
|
link_element =
|
||||||
|
|
58
test/fixtures/tesla_mock/funkwhale_create_audio.json
vendored
Normal file
58
test/fixtures/tesla_mock/funkwhale_create_audio.json
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
"https://funkwhale.audio/ns",
|
||||||
|
{
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||||
|
"Hashtag": "as:Hashtag"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "Create",
|
||||||
|
"id": "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871/activity",
|
||||||
|
"actor": "https://channels.tests.funkwhale.audio/federation/actors/compositions",
|
||||||
|
"object": {
|
||||||
|
"id": "https://channels.tests.funkwhale.audio/federation/music/uploads/42342395-0208-4fee-a38d-259a6dae0871",
|
||||||
|
"type": "Audio",
|
||||||
|
"name": "Compositions - Test Audio for Pleroma",
|
||||||
|
"attributedTo": "https://channels.tests.funkwhale.audio/federation/actors/compositions",
|
||||||
|
"published": "2020-03-11T10:01:52.714918+00:00",
|
||||||
|
"to": "https://www.w3.org/ns/activitystreams#Public",
|
||||||
|
"url": [
|
||||||
|
{
|
||||||
|
"type": "Link",
|
||||||
|
"mimeType": "audio/ogg",
|
||||||
|
"href": "https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Link",
|
||||||
|
"mimeType": "text/html",
|
||||||
|
"href": "https://channels.tests.funkwhale.audio/library/tracks/74"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"content": "<p>This is a test Audio for Pleroma.</p>",
|
||||||
|
"mediaType": "text/html",
|
||||||
|
"tag": [
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"name": "#funkwhale"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"name": "#test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Hashtag",
|
||||||
|
"name": "#tests"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": "#funkwhale #test #tests",
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
"https://w3id.org/security/v1",
|
||||||
|
{
|
||||||
|
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.AudioHandlingTest do
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
setup_all do
|
||||||
|
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
test "it works for incoming listens" do
|
test "it works for incoming listens" do
|
||||||
_user = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
|
_user = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
|
||||||
|
|
||||||
|
@ -42,4 +47,34 @@ test "it works for incoming listens" do
|
||||||
assert object.data["album"] == "lain radio"
|
assert object.data["album"] == "lain radio"
|
||||||
assert object.data["length"] == 180_000
|
assert object.data["length"] == 180_000
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "Funkwhale Audio object" do
|
||||||
|
data = File.read!("test/fixtures/tesla_mock/funkwhale_create_audio.json") |> Poison.decode!()
|
||||||
|
|
||||||
|
{:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
|
||||||
|
|
||||||
|
assert object = Object.normalize(activity, false)
|
||||||
|
|
||||||
|
assert object.data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
|
||||||
|
|
||||||
|
assert object.data["cc"] == []
|
||||||
|
|
||||||
|
assert object.data["url"] == "https://channels.tests.funkwhale.audio/library/tracks/74"
|
||||||
|
|
||||||
|
assert object.data["attachment"] == [
|
||||||
|
%{
|
||||||
|
"mediaType" => "audio/ogg",
|
||||||
|
"type" => "Link",
|
||||||
|
"name" => nil,
|
||||||
|
"url" => [
|
||||||
|
%{
|
||||||
|
"href" =>
|
||||||
|
"https://channels.tests.funkwhale.audio/api/v1/listen/3901e5d8-0445-49d5-9711-e096cf32e515/?upload=42342395-0208-4fee-a38d-259a6dae0871&download=false",
|
||||||
|
"mediaType" => "audio/ogg",
|
||||||
|
"type" => "Link"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,6 +24,8 @@ test "Mastodon Question activity" do
|
||||||
|
|
||||||
object = Object.normalize(activity, false)
|
object = Object.normalize(activity, false)
|
||||||
|
|
||||||
|
assert object.data["url"] == "https://mastodon.sdf.org/@rinpatch/102070944809637304"
|
||||||
|
|
||||||
assert object.data["closed"] == "2019-05-11T09:03:36Z"
|
assert object.data["closed"] == "2019-05-11T09:03:36Z"
|
||||||
|
|
||||||
assert object.data["context"] == activity.data["context"]
|
assert object.data["context"] == activity.data["context"]
|
||||||
|
|
Loading…
Reference in a new issue