mirror of
https://github.com/jointakahe/takahe.git
synced 2024-11-29 10:40:59 +00:00
Implement reaction aggregation.
This commit is contained in:
parent
42b0b5831a
commit
b3e67ffe3a
2 changed files with 90 additions and 1 deletions
|
@ -610,12 +610,24 @@ class Post(StatorModel):
|
||||||
"likes": self.interactions.filter(
|
"likes": self.interactions.filter(
|
||||||
type=PostInteraction.Types.like,
|
type=PostInteraction.Types.like,
|
||||||
state__in=PostInteractionStates.group_active(),
|
state__in=PostInteractionStates.group_active(),
|
||||||
).count(),
|
)
|
||||||
|
.values("identity")
|
||||||
|
.distinct()
|
||||||
|
.count(), # This counts each user that's had any likes/reactions
|
||||||
"boosts": self.interactions.filter(
|
"boosts": self.interactions.filter(
|
||||||
type=PostInteraction.Types.boost,
|
type=PostInteraction.Types.boost,
|
||||||
state__in=PostInteractionStates.group_active(),
|
state__in=PostInteractionStates.group_active(),
|
||||||
).count(),
|
).count(),
|
||||||
"replies": Post.objects.filter(in_reply_to=self.object_uri).count(),
|
"replies": Post.objects.filter(in_reply_to=self.object_uri).count(),
|
||||||
|
"reactions": {
|
||||||
|
row["value"]: row["count"]
|
||||||
|
for row in self.interactions.filter(
|
||||||
|
type=PostInteraction.Types.like,
|
||||||
|
state__in=PostInteractionStates.group_active(),
|
||||||
|
)
|
||||||
|
.values("value")
|
||||||
|
.annotate(count=models.Count("identity"))
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if save:
|
if save:
|
||||||
self.save()
|
self.save()
|
||||||
|
|
|
@ -230,6 +230,83 @@ def test_react_undo_mismatched(
|
||||||
assert len(events) == 1
|
assert len(events) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@pytest.mark.parametrize("local", [True, False])
|
||||||
|
@pytest.mark.parametrize("reaction", ["\U0001F607"])
|
||||||
|
def test_react_stats(
|
||||||
|
identity: Identity,
|
||||||
|
other_identity: Identity,
|
||||||
|
remote_identity: Identity,
|
||||||
|
stator,
|
||||||
|
local: bool,
|
||||||
|
reaction: str,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Checks basic post stats generation
|
||||||
|
"""
|
||||||
|
post = Post.create_local(author=identity, content="I love birds!")
|
||||||
|
if local:
|
||||||
|
PostService(post).like_as(other_identity, reaction)
|
||||||
|
else:
|
||||||
|
message = {
|
||||||
|
"id": "test",
|
||||||
|
"type": "Like",
|
||||||
|
"actor": remote_identity.actor_uri,
|
||||||
|
"object": post.object_uri,
|
||||||
|
"content": reaction,
|
||||||
|
}
|
||||||
|
InboxMessage.objects.create(message=message)
|
||||||
|
|
||||||
|
# Run stator thrice - to receive the post, make fanouts and then process them
|
||||||
|
stator.run_single_cycle()
|
||||||
|
stator.run_single_cycle()
|
||||||
|
stator.run_single_cycle()
|
||||||
|
|
||||||
|
post.refresh_from_db()
|
||||||
|
|
||||||
|
assert "reactions" in post.stats
|
||||||
|
assert post.stats["reactions"] == {reaction: 1}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
@pytest.mark.parametrize("local", [True, False])
|
||||||
|
def test_react_stats_multiple(
|
||||||
|
identity: Identity,
|
||||||
|
other_identity: Identity,
|
||||||
|
remote_identity: Identity,
|
||||||
|
stator,
|
||||||
|
local: bool,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Ensures that multiple reactions get aggregated correctly.
|
||||||
|
|
||||||
|
Basically, if the same person leaves multiple reactions, aggregate all of them into one Like.
|
||||||
|
"""
|
||||||
|
post = Post.create_local(author=identity, content="I love birds!")
|
||||||
|
for i, reaction in enumerate("abc"):
|
||||||
|
if local:
|
||||||
|
PostService(post).like_as(other_identity, reaction)
|
||||||
|
else:
|
||||||
|
message = {
|
||||||
|
"id": f"test{i}",
|
||||||
|
"type": "Like",
|
||||||
|
"actor": remote_identity.actor_uri,
|
||||||
|
"object": post.object_uri,
|
||||||
|
"content": reaction,
|
||||||
|
}
|
||||||
|
InboxMessage.objects.create(message=message)
|
||||||
|
|
||||||
|
# Run stator thrice - to receive the post, make fanouts and then process them
|
||||||
|
stator.run_single_cycle()
|
||||||
|
stator.run_single_cycle()
|
||||||
|
stator.run_single_cycle()
|
||||||
|
|
||||||
|
post.refresh_from_db()
|
||||||
|
|
||||||
|
assert post.stats["reactions"] == {"a": 1, "b": 1, "c": 1}
|
||||||
|
assert post.stats["likes"] == 1
|
||||||
|
|
||||||
|
|
||||||
# TODO: Test that multiple reactions can be added and deleted correctly
|
# TODO: Test that multiple reactions can be added and deleted correctly
|
||||||
|
|
||||||
# TODO: How should plain likes and reactions from the same source be handled?
|
# TODO: How should plain likes and reactions from the same source be handled?
|
||||||
|
|
Loading…
Reference in a new issue