mirror of
https://github.com/jointakahe/takahe.git
synced 2024-11-25 00:30:59 +00:00
Perform shared inbox delivery
This commit is contained in:
parent
f4a8a96b81
commit
a875dd7a54
3 changed files with 99 additions and 9 deletions
|
@ -72,7 +72,10 @@ class FanOutStates(StateGraph):
|
|||
try:
|
||||
await post.author.signed_request(
|
||||
method="post",
|
||||
uri=fan_out.identity.inbox_uri,
|
||||
uri=(
|
||||
fan_out.identity.shared_inbox_uri
|
||||
or fan_out.identity.inbox_uri
|
||||
),
|
||||
body=canonicalise(post.to_create_ap()),
|
||||
)
|
||||
except httpx.RequestError:
|
||||
|
@ -85,7 +88,10 @@ class FanOutStates(StateGraph):
|
|||
try:
|
||||
await post.author.signed_request(
|
||||
method="post",
|
||||
uri=fan_out.identity.inbox_uri,
|
||||
uri=(
|
||||
fan_out.identity.shared_inbox_uri
|
||||
or fan_out.identity.inbox_uri
|
||||
),
|
||||
body=canonicalise(post.to_update_ap()),
|
||||
)
|
||||
except httpx.RequestError:
|
||||
|
@ -108,7 +114,10 @@ class FanOutStates(StateGraph):
|
|||
try:
|
||||
await post.author.signed_request(
|
||||
method="post",
|
||||
uri=fan_out.identity.inbox_uri,
|
||||
uri=(
|
||||
fan_out.identity.shared_inbox_uri
|
||||
or fan_out.identity.inbox_uri
|
||||
),
|
||||
body=canonicalise(post.to_delete_ap()),
|
||||
)
|
||||
except httpx.RequestError:
|
||||
|
@ -130,7 +139,10 @@ class FanOutStates(StateGraph):
|
|||
try:
|
||||
await interaction.identity.signed_request(
|
||||
method="post",
|
||||
uri=fan_out.identity.inbox_uri,
|
||||
uri=(
|
||||
fan_out.identity.shared_inbox_uri
|
||||
or fan_out.identity.inbox_uri
|
||||
),
|
||||
body=canonicalise(interaction.to_ap()),
|
||||
)
|
||||
except httpx.RequestError:
|
||||
|
@ -153,7 +165,10 @@ class FanOutStates(StateGraph):
|
|||
try:
|
||||
await interaction.identity.signed_request(
|
||||
method="post",
|
||||
uri=fan_out.identity.inbox_uri,
|
||||
uri=(
|
||||
fan_out.identity.shared_inbox_uri
|
||||
or fan_out.identity.inbox_uri
|
||||
),
|
||||
body=canonicalise(interaction.to_undo_ap()),
|
||||
)
|
||||
except httpx.RequestError:
|
||||
|
@ -165,7 +180,10 @@ class FanOutStates(StateGraph):
|
|||
try:
|
||||
await identity.signed_request(
|
||||
method="post",
|
||||
uri=fan_out.identity.inbox_uri,
|
||||
uri=(
|
||||
fan_out.identity.shared_inbox_uri
|
||||
or fan_out.identity.inbox_uri
|
||||
),
|
||||
body=canonicalise(fan_out.subject_identity.to_update_ap()),
|
||||
)
|
||||
except httpx.RequestError:
|
||||
|
@ -177,7 +195,10 @@ class FanOutStates(StateGraph):
|
|||
try:
|
||||
await identity.signed_request(
|
||||
method="post",
|
||||
uri=fan_out.identity.inbox_uri,
|
||||
uri=(
|
||||
fan_out.identity.shared_inbox_uri
|
||||
or fan_out.identity.inbox_uri
|
||||
),
|
||||
body=canonicalise(fan_out.subject_identity.to_delete_ap()),
|
||||
)
|
||||
except httpx.RequestError:
|
||||
|
@ -214,6 +235,9 @@ class FanOut(StatorModel):
|
|||
state = StateField(FanOutStates)
|
||||
|
||||
# The user this event is targeted at
|
||||
# We always need this, but if there is a shared inbox URL on the user
|
||||
# we'll deliver to that and won't have fanouts for anyone else with the
|
||||
# same one.
|
||||
identity = models.ForeignKey(
|
||||
"users.Identity",
|
||||
on_delete=models.CASCADE,
|
||||
|
|
|
@ -707,7 +707,20 @@ class Post(StatorModel):
|
|||
# If it's a local post, include the author
|
||||
if self.local:
|
||||
targets.add(self.author)
|
||||
return targets
|
||||
# Now dedupe the targets based on shared inboxes (we only keep one per
|
||||
# shared inbox)
|
||||
deduped_targets = set()
|
||||
shared_inboxes = set()
|
||||
for target in targets:
|
||||
if target.local or not target.shared_inbox_uri:
|
||||
deduped_targets.add(target)
|
||||
elif target.shared_inbox_uri not in shared_inboxes:
|
||||
shared_inboxes.add(target.shared_inbox_uri)
|
||||
deduped_targets.add(target)
|
||||
else:
|
||||
# Their shared inbox is already being sent to
|
||||
pass
|
||||
return deduped_targets
|
||||
|
||||
### ActivityPub (inbound) ###
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import pytest
|
|||
from asgiref.sync import async_to_sync
|
||||
|
||||
from activities.models import Post
|
||||
from users.models import Follow
|
||||
from users.models import Domain, Follow, Identity
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
@ -50,6 +50,59 @@ def test_post_targets_simple(identity, other_identity, remote_identity):
|
|||
assert targets == {other_identity}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_post_targets_shared(identity, other_identity):
|
||||
"""
|
||||
Tests that remote identities with the same shared inbox only get one target.
|
||||
"""
|
||||
# Create a pair of remote identities that share an inbox URI
|
||||
domain = Domain.objects.create(domain="remote.test", local=False, state="updated")
|
||||
remote1 = Identity.objects.create(
|
||||
actor_uri="https://remote.test/test1/",
|
||||
inbox_uri="https://remote.test/@test1/inbox/",
|
||||
shared_inbox_uri="https://remote.test/inbox/",
|
||||
profile_uri="https://remote.test/@test1/",
|
||||
username="test1",
|
||||
domain=domain,
|
||||
name="Test1",
|
||||
local=False,
|
||||
state="updated",
|
||||
)
|
||||
remote2 = Identity.objects.create(
|
||||
actor_uri="https://remote.test/test2/",
|
||||
inbox_uri="https://remote.test/@test2/inbox/",
|
||||
shared_inbox_uri="https://remote.test/inbox/",
|
||||
profile_uri="https://remote.test/@test2/",
|
||||
username="test2",
|
||||
domain=domain,
|
||||
name="Test2",
|
||||
local=False,
|
||||
state="updated",
|
||||
)
|
||||
|
||||
# Make a post mentioning one local and two remote identities
|
||||
post = Post.objects.create(
|
||||
content="<p>Test</p>",
|
||||
author=identity,
|
||||
local=True,
|
||||
)
|
||||
post.mentions.add(other_identity)
|
||||
post.mentions.add(remote1)
|
||||
post.mentions.add(remote2)
|
||||
targets = async_to_sync(post.aget_targets)()
|
||||
|
||||
# We should only have one of remote1 or remote2 in there as they share a
|
||||
# shared inbox URI
|
||||
assert (targets == {identity, other_identity, remote1}) or (
|
||||
targets
|
||||
== {
|
||||
identity,
|
||||
other_identity,
|
||||
remote2,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_post_local_only(identity, other_identity, remote_identity):
|
||||
"""
|
||||
|
|
Loading…
Reference in a new issue