mastodon pins
This commit is contained in:
parent
3ec1dbd922
commit
17f28c0507
4 changed files with 146 additions and 4 deletions
|
@ -71,6 +71,14 @@ def contain_origin_from_id(id, %{"id" => other_id} = _params) when is_binary(oth
|
||||||
compare_uris(id_uri, other_uri)
|
compare_uris(id_uri, other_uri)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Mastodon pin activities don't have an id, so we check the object field, which will be pinned.
|
||||||
|
def contain_origin_from_id(id, %{"object" => object}) when is_binary(object) do
|
||||||
|
id_uri = URI.parse(id)
|
||||||
|
object_uri = URI.parse(object)
|
||||||
|
|
||||||
|
compare_uris(id_uri, object_uri)
|
||||||
|
end
|
||||||
|
|
||||||
def contain_origin_from_id(_id, _data), do: :error
|
def contain_origin_from_id(_id, _data), do: :error
|
||||||
|
|
||||||
def contain_child(%{"object" => %{"id" => id, "attributedTo" => _} = object}),
|
def contain_child(%{"object" => %{"id" => id, "attributedTo" => _} = object}),
|
||||||
|
|
|
@ -557,10 +557,19 @@ def handle_incoming(
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_incoming(%{"type" => type} = data, _options) when type in ~w(Add Remove) do
|
def handle_incoming(%{"type" => type} = data, _options) when type in ~w(Add Remove) do
|
||||||
with :ok <- ObjectValidator.fetch_actor_and_object(data),
|
with {:ok, user} <- ObjectValidator.fetch_actor(data),
|
||||||
%Object{} <- Object.normalize(data["object"], fetch: true),
|
%Object{} <- Object.normalize(data["object"], fetch: true) do
|
||||||
{:ok, activity, _meta} <- Pipeline.common_pipeline(data, local: false) do
|
# Mastodon sends pin/unpin objects without id, to, cc fields
|
||||||
{:ok, activity}
|
data =
|
||||||
|
data
|
||||||
|
|> Map.put_new("id", Utils.generate_activity_id())
|
||||||
|
|> Map.put_new("to", [Pleroma.Constants.as_public()])
|
||||||
|
|> Map.put_new("cc", [user.follower_address])
|
||||||
|
|
||||||
|
case Pipeline.common_pipeline(data, local: false) do
|
||||||
|
{:ok, activity, _meta} -> {:ok, activity}
|
||||||
|
error -> error
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
47
test/fixtures/statuses/masto-note.json
vendored
Normal file
47
test/fixtures/statuses/masto-note.json
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://www.w3.org/ns/activitystreams",
|
||||||
|
{
|
||||||
|
"ostatus": "http://ostatus.org#",
|
||||||
|
"atomUri": "ostatus:atomUri",
|
||||||
|
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||||
|
"conversation": "ostatus:conversation",
|
||||||
|
"sensitive": "as:sensitive",
|
||||||
|
"toot": "http://joinmastodon.org/ns#",
|
||||||
|
"votersCount": "toot:votersCount"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": "https://example.com/users/{{nickname}}/statuses/{{status_id}}",
|
||||||
|
"type": "Note",
|
||||||
|
"summary": null,
|
||||||
|
"inReplyTo": null,
|
||||||
|
"published": "2021-02-24T12:40:49Z",
|
||||||
|
"url": "https://example.com/@{{nickname}}/{{status_id}}",
|
||||||
|
"attributedTo": "https://example.com/users/{{nickname}}",
|
||||||
|
"to": [
|
||||||
|
"https://www.w3.org/ns/activitystreams#Public"
|
||||||
|
],
|
||||||
|
"cc": [
|
||||||
|
"https://example.com/users/{{nickname}}/followers"
|
||||||
|
],
|
||||||
|
"sensitive": false,
|
||||||
|
"atomUri": "https://example.com/users/{{nickname}}/statuses/{{status_id}}",
|
||||||
|
"inReplyToAtomUri": null,
|
||||||
|
"conversation": "tag:example.com,2021-02-24:objectId=15:objectType=Conversation",
|
||||||
|
"content": "<p></p>",
|
||||||
|
"contentMap": {
|
||||||
|
"en": "<p></p>"
|
||||||
|
},
|
||||||
|
"attachment": [],
|
||||||
|
"tag": [],
|
||||||
|
"replies": {
|
||||||
|
"id": "https://example.com/users/{{nickname}}/statuses/{{status_id}}/replies",
|
||||||
|
"type": "Collection",
|
||||||
|
"first": {
|
||||||
|
"type": "CollectionPage",
|
||||||
|
"next": "https://example.com/users/{{nickname}}/statuses/{{status_id}}/replies?only_other_accounts=true&page=true",
|
||||||
|
"partOf": "https://example.com/users/{{nickname}}/statuses/{{status_id}}/replies",
|
||||||
|
"items": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -716,6 +716,84 @@ test "accepts Add/Remove activities", %{conn: conn} do
|
||||||
user = refresh_record(user)
|
user = refresh_record(user)
|
||||||
refute user.pinned_objects[data["object"]]
|
refute user.pinned_objects[data["object"]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "mastodon pin/unpin", %{conn: conn} do
|
||||||
|
status_id = "105786274556060421"
|
||||||
|
|
||||||
|
status =
|
||||||
|
File.read!("test/fixtures/statuses/masto-note.json")
|
||||||
|
|> String.replace("{{nickname}}", "lain")
|
||||||
|
|> String.replace("{{status_id}}", status_id)
|
||||||
|
|
||||||
|
status_url = "https://example.com/users/lain/statuses/#{status_id}"
|
||||||
|
|
||||||
|
user =
|
||||||
|
File.read!("test/fixtures/users_mock/user.json")
|
||||||
|
|> String.replace("{{nickname}}", "lain")
|
||||||
|
|
||||||
|
actor = "https://example.com/users/lain"
|
||||||
|
|
||||||
|
Tesla.Mock.mock(fn
|
||||||
|
%{
|
||||||
|
method: :get,
|
||||||
|
url: ^status_url
|
||||||
|
} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: status,
|
||||||
|
headers: [{"content-type", "application/activity+json"}]
|
||||||
|
}
|
||||||
|
|
||||||
|
%{
|
||||||
|
method: :get,
|
||||||
|
url: ^actor
|
||||||
|
} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
body: user,
|
||||||
|
headers: [{"content-type", "application/activity+json"}]
|
||||||
|
}
|
||||||
|
end)
|
||||||
|
|
||||||
|
data = %{
|
||||||
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
|
"actor" => actor,
|
||||||
|
"object" => status_url,
|
||||||
|
"target" => "https://example.com/users/lain/collections/featured",
|
||||||
|
"type" => "Add"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert "ok" ==
|
||||||
|
conn
|
||||||
|
|> assign(:valid_signature, true)
|
||||||
|
|> put_req_header("content-type", "application/activity+json")
|
||||||
|
|> post("/inbox", data)
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||||
|
assert Activity.get_by_object_ap_id_with_object(data["object"])
|
||||||
|
user = User.get_cached_by_ap_id(data["actor"])
|
||||||
|
assert user.pinned_objects[data["object"]]
|
||||||
|
|
||||||
|
data = %{
|
||||||
|
"actor" => actor,
|
||||||
|
"object" => status_url,
|
||||||
|
"target" => "https://example.com/users/lain/collections/featured",
|
||||||
|
"type" => "Remove"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert "ok" ==
|
||||||
|
conn
|
||||||
|
|> assign(:valid_signature, true)
|
||||||
|
|> put_req_header("content-type", "application/activity+json")
|
||||||
|
|> post("/inbox", data)
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||||
|
assert Activity.get_by_object_ap_id_with_object(data["object"])
|
||||||
|
user = refresh_record(user)
|
||||||
|
refute user.pinned_objects[data["object"]]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/users/:nickname/inbox" do
|
describe "/users/:nickname/inbox" do
|
||||||
|
|
Loading…
Reference in a new issue