diff --git a/app/actor.py b/app/actor.py index 76e985b..05061c4 100644 --- a/app/actor.py +++ b/app/actor.py @@ -259,9 +259,11 @@ class ActorMetadata: is_following: bool is_follower: bool is_follow_request_sent: bool + is_follow_request_rejected: bool outbox_follow_ap_id: str | None inbox_follow_ap_id: str | None moved_to: typing.Optional["ActorModel"] + has_blocked_local_actor: bool ActorsMetadata = dict[str, ActorMetadata] @@ -304,6 +306,26 @@ async def get_actors_metadata( ) ) } + rejected_follow_requests = { + reject.activity_object_ap_id + for reject in await db_session.execute( + select(models.InboxObject.activity_object_ap_id).where( + models.InboxObject.ap_type == "Reject", + models.InboxObject.ap_actor_id.in_(ap_actor_ids), + ) + ) + } + blocks = { + block.ap_actor_id + for block in await db_session.execute( + select(models.InboxObject.ap_actor_id).where( + models.InboxObject.ap_type == "Block", + models.InboxObject.undone_by_inbox_object_id.is_(None), + models.InboxObject.ap_actor_id.in_(ap_actor_ids), + ) + ) + } + idx: ActorsMetadata = {} for actor in actors: if not actor.ap_id: @@ -326,9 +348,15 @@ async def get_actors_metadata( is_following=actor.ap_id in following, is_follower=actor.ap_id in followers, is_follow_request_sent=actor.ap_id in sent_follow_requests, + is_follow_request_rejected=bool( + sent_follow_requests[actor.ap_id] in rejected_follow_requests + ) + if actor.ap_id in sent_follow_requests + else False, outbox_follow_ap_id=sent_follow_requests.get(actor.ap_id), inbox_follow_ap_id=followers.get(actor.ap_id), moved_to=moved_to, + has_blocked_local_actor=actor.ap_id in blocks, ) return idx diff --git a/app/boxes.py b/app/boxes.py index cc21a9a..df8bd1e 100644 --- a/app/boxes.py +++ b/app/boxes.py @@ -1406,6 +1406,13 @@ async def _handle_undo_activity( inbox_object_id=ap_activity_to_undo.id, ) db_session.add(notif) + elif ap_activity_to_undo.ap_type == "Block": + notif = models.Notification( + notification_type=models.NotificationType.UNBLOCKED, + actor_id=from_actor.id, + inbox_object_id=ap_activity_to_undo.id, + ) + db_session.add(notif) else: logger.warning(f"Don't know how to undo {ap_activity_to_undo.ap_type} activity") @@ -1945,6 +1952,28 @@ async def _handle_like_activity( db_session.add(notif) +async def _handle_block_activity( + db_session: AsyncSession, + actor: models.Actor, + block_activity: models.InboxObject, +): + if block_activity.activity_object_ap_id != LOCAL_ACTOR.ap_id: + logger.warning( + "Received invalid Block activity " + f"{block_activity.activity_object_ap_id=}" + ) + await db_session.delete(block_activity) + return + + # Create a notification + notif = models.Notification( + notification_type=models.NotificationType.BLOCKED, + actor_id=actor.id, + inbox_object_id=block_activity.id, + ) + db_session.add(notif) + + async def _process_transient_object( db_session: AsyncSession, raw_object: ap.RawObject, @@ -2210,7 +2239,11 @@ async def save_to_inbox( # View is used by Peertube, there's nothing useful we can do with it await db_session.delete(inbox_object) elif activity_ro.ap_type == "Block": - pass + await _handle_block_activity( + db_session, + actor, + inbox_object, + ) else: logger.warning(f"Received an unknown {inbox_object.ap_type} object") diff --git a/app/models.py b/app/models.py index 0708341..78c1b14 100644 --- a/app/models.py +++ b/app/models.py @@ -551,6 +551,9 @@ class NotificationType(str, enum.Enum): UPDATED_WEBMENTION = "updated_webmention" DELETED_WEBMENTION = "deleted_webmention" + BLOCKED = "blocked" + UNBLOCKED = "unblocked" + class Notification(Base): __tablename__ = "notifications" diff --git a/app/templates/notifications.html b/app/templates/notifications.html index a5e069f..3cf5d5a 100644 --- a/app/templates/notifications.html +++ b/app/templates/notifications.html @@ -36,6 +36,12 @@ {%- elif notif.notification_type.value == "follow_request_rejected" %} {{ notif_actor_action(notif, "rejected your follow request") }} {{ utils.display_actor(notif.actor, actors_metadata) }} + {% elif notif.notification_type.value == "blocked" %} + {{ notif_actor_action(notif, "blocked you") }} + {{ utils.display_actor(notif.actor, actors_metadata) }} + {% elif notif.notification_type.value == "unblocked" %} + {{ notif_actor_action(notif, "unblocked you") }} + {{ utils.display_actor(notif.actor, actors_metadata) }} {%- elif notif.notification_type.value == "move" %} {# for move notif, the actor is the target and the inbox object the Move activity #}
diff --git a/app/templates/utils.html b/app/templates/utils.html index 9af1f21..57aec8b 100644 --- a/app/templates/utils.html +++ b/app/templates/utils.html @@ -216,6 +216,9 @@