From c6271931a60f3d6235fc9a873524fff5dc7ae227 Mon Sep 17 00:00:00 2001 From: giles Date: Wed, 25 Feb 2026 09:17:34 +0000 Subject: [PATCH] Show per-app actor in follow notifications on Hub Add app_domain to APNotification model and NotificationDTO so follow notifications display "followed you on blog" instead of just "followed you" when the follow targets a per-app actor. Co-Authored-By: Claude Opus 4.6 --- .../templates/federation/_notification.html | 2 +- ...1q9r0s1_add_app_domain_to_notifications.py | 23 +++++++++++++++++++ shared/contracts/dtos.py | 1 + shared/infrastructure/ap_inbox_handlers.py | 1 + shared/models/federation.py | 1 + shared/services/federation_impl.py | 1 + 6 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 shared/alembic/versions/w3u1q9r0s1_add_app_domain_to_notifications.py diff --git a/federation/templates/federation/_notification.html b/federation/templates/federation/_notification.html index d18ef4d..06fcd6e 100644 --- a/federation/templates/federation/_notification.html +++ b/federation/templates/federation/_notification.html @@ -16,7 +16,7 @@ {% if notif.notification_type == "follow" %} - followed you + followed you{% if notif.app_domain and notif.app_domain != "federation" %} on {{ notif.app_domain }}{% endif %} {% elif notif.notification_type == "like" %} liked your post {% elif notif.notification_type == "boost" %} diff --git a/shared/alembic/versions/w3u1q9r0s1_add_app_domain_to_notifications.py b/shared/alembic/versions/w3u1q9r0s1_add_app_domain_to_notifications.py new file mode 100644 index 0000000..df086bc --- /dev/null +++ b/shared/alembic/versions/w3u1q9r0s1_add_app_domain_to_notifications.py @@ -0,0 +1,23 @@ +"""Add app_domain to ap_notifications. + +Revision ID: w3u1q9r0s1 +Revises: v2t0p8q9r0 +""" +from alembic import op +import sqlalchemy as sa + +revision = "w3u1q9r0s1" +down_revision = "v2t0p8q9r0" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.add_column( + "ap_notifications", + sa.Column("app_domain", sa.String(30), nullable=True), + ) + + +def downgrade() -> None: + op.drop_column("ap_notifications", "app_domain") diff --git a/shared/contracts/dtos.py b/shared/contracts/dtos.py index 30ec3d6..c023580 100644 --- a/shared/contracts/dtos.py +++ b/shared/contracts/dtos.py @@ -316,3 +316,4 @@ class NotificationDTO: from_actor_domain: str | None = None from_actor_icon: str | None = None target_content_preview: str | None = None + app_domain: str | None = None diff --git a/shared/infrastructure/ap_inbox_handlers.py b/shared/infrastructure/ap_inbox_handlers.py index d972631..73eb115 100644 --- a/shared/infrastructure/ap_inbox_handlers.py +++ b/shared/infrastructure/ap_inbox_handlers.py @@ -253,6 +253,7 @@ async def handle_follow( actor_profile_id=actor_row.id, notification_type="follow", from_remote_actor_id=ra.id, + app_domain=app_domain, ) session.add(notif) diff --git a/shared/models/federation.py b/shared/models/federation.py index 3521d29..3e62139 100644 --- a/shared/models/federation.py +++ b/shared/models/federation.py @@ -422,6 +422,7 @@ class APNotification(Base): target_remote_post_id: Mapped[int | None] = mapped_column( Integer, ForeignKey("ap_remote_posts.id", ondelete="SET NULL"), nullable=True, ) + app_domain: Mapped[str | None] = mapped_column(String(30), nullable=True) read: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False, server_default="false") created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now(), diff --git a/shared/services/federation_impl.py b/shared/services/federation_impl.py index 3ff199c..46e7948 100644 --- a/shared/services/federation_impl.py +++ b/shared/services/federation_impl.py @@ -1620,6 +1620,7 @@ class SqlFederationService: target_content_preview=preview, created_at=notif.created_at, read=notif.read, + app_domain=notif.app_domain, )) return items