Fix boost reach (#511)

Fix boost not reaching all remote followers
pull/514/head
Humberto Rocha 2023-02-15 17:40:43 -05:00 zatwierdzone przez GitHub
rodzic 33b24d99bc
commit 427744f5a7
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
1 zmienionych plików z 46 dodań i 14 usunięć

Wyświetl plik

@ -1,3 +1,5 @@
from collections.abc import Iterable
from django.db import models, transaction
from django.utils import timezone
@ -31,23 +33,12 @@ class PostInteractionStates(StateGraph):
"""
interaction = await instance.afetch_full()
# Boost: send a copy to all people who follow this user (limiting
# to just local follows if it's a remote post)
# to just local follows if it's a remote boost)
if interaction.type == interaction.Types.boost:
async for follow in interaction.identity.inbound_follows.filter(
boosts=True
).select_related("source", "target"):
if interaction.post.local or follow.source.local:
await FanOut.objects.acreate(
type=FanOut.Types.interaction,
identity_id=follow.source_id,
subject_post=interaction.post,
subject_post_interaction=interaction,
)
# And one to the post's author, if the booster is local or they are
if interaction.identity.local or interaction.post.local:
for target in await interaction.aget_boost_targets():
await FanOut.objects.acreate(
type=FanOut.Types.interaction,
identity_id=interaction.post.author_id,
identity=target,
subject_post=interaction.post,
subject_post_interaction=interaction,
)
@ -224,6 +215,47 @@ class PostInteraction(StatorModel):
"identity", "post", "post__author"
).aget(pk=self.pk)
async def aget_boost_targets(self) -> Iterable[Identity]:
"""
Returns an iterable with Identities of followers that have unique
shared_inbox among each other to be used as target to the boost
"""
# Start including the post author
targets = {self.post.author}
# Include all followers that are following the boosts
async for follow in self.identity.inbound_follows.active().filter(
boosts=True
).select_related("source"):
targets.add(follow.source)
# Fetch the full blocks and remove them as targets
async for block in self.identity.outbound_blocks.active().filter(
mute=False
).select_related("target"):
try:
targets.remove(block.target)
except KeyError:
pass
deduped_targets = set()
shared_inboxes = set()
for target in targets:
if target.local:
# Local targets always gets the boosts
# despite its creator locality
deduped_targets.add(target)
elif self.identity.local:
# Dedupe the targets based on shared inboxes
# (we only keep one per shared inbox)
if 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)
return deduped_targets
### Create helpers ###
@classmethod