feat(): push notifications via firebase admin

This commit is contained in:
doas root
2025-11-20 21:25:48 +03:00
parent c010984d64
commit fa24f4060f
22 changed files with 706 additions and 3 deletions
@@ -0,0 +1,8 @@
from abc import abstractmethod
from typing import Protocol
class NotificationService(Protocol):
@abstractmethod
async def send_notification(self, identifier: str, title: str, body: str) -> None:
raise NotImplementedError
@@ -0,0 +1,32 @@
from template_project.application.common.data_structure import to_data_structure
from template_project.application.common.identity_provider import IdentityProvider
from template_project.application.common.interactor import to_interactor
from template_project.application.common.notifications.service import NotificationService
from template_project.application.user.notification_device.data_gateway import NotificationDeviceDataGateway
from template_project.application.user.notification_device.errors import NotificationDeviceNotFoundError
@to_data_structure
class SendNotificationRequest:
title: str
body: str
@to_interactor
class NotificationInteractor:
identity_provider: IdentityProvider
notification_device_data_gateway: NotificationDeviceDataGateway
notification_service: NotificationService
async def send_notification(self, request: SendNotificationRequest) -> None:
current_user = await self.identity_provider.get_current_user()
notification_device = await self.notification_device_data_gateway.load_by_user_id(current_user.id)
if not notification_device:
raise NotificationDeviceNotFoundError
await self.notification_service.send_notification(
identifier=notification_device.device_id,
title=request.title,
body=request.body,
)
@@ -0,0 +1,11 @@
from abc import abstractmethod
from typing import Protocol
from template_project.application.user.entity import UserId
from template_project.application.user.notification_device.entity import NotificationDevice
class NotificationDeviceDataGateway(Protocol):
@abstractmethod
async def load_by_user_id(self, user_id: UserId) -> NotificationDevice | None:
raise NotImplementedError
@@ -0,0 +1,29 @@
from datetime import UTC, datetime
from typing import NewType, Self
from uuid import UUID
from uuid_utils.compat import uuid7
from template_project.application.common.entity import Entity, to_entity
from template_project.application.user.entity import UserId
NotificationDeviceId = NewType("NotificationDeviceId", UUID)
@to_entity
class NotificationDevice(Entity[NotificationDeviceId]):
user_id: UserId
device_id: str
@classmethod
def factory(
cls,
user_id: UserId,
device_id: str,
) -> Self:
return cls(
id=NotificationDeviceId(uuid7()),
user_id=user_id,
device_id=device_id,
created_at=datetime.now(tz=UTC),
)
@@ -0,0 +1,6 @@
from template_project.application.common.errors import ApplicationError, to_error
@to_error
class NotificationDeviceNotFoundError(ApplicationError):
pass