Skip to content

Commit

Permalink
feat: Creat notification FastAPI
Browse files Browse the repository at this point in the history
  • Loading branch information
권효진 authored and 권효진 committed Apr 2, 2024
1 parent 1d9a2f8 commit 7442a29
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 0 deletions.
42 changes: 42 additions & 0 deletions ara/controller/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from fastapi import APIRouter, Depends, HTTPException
from ara.controller.authentication import get_current_user
from ara.service.notification_service import NotificationService
from ara.domain.user import User
from ara.domain.exceptions import EntityDoesNotExist
from pydantic import BaseModel

router = APIRouter()
notification_service = NotificationService()

class NotificationRead(BaseModel):
notification_id: int

@router.get("/notifications")
async def list_notifications(current_user: User = Depends(get_current_user)):
notifications = notification_service.get_notifications_for_user(current_user)
return notifications

@router.post("/notifications/{notification_id}/read")
async def mark_notification_as_read(notification_id: int, current_user: User = Depends(get_current_user)):
try:
notification_service.mark_notification_as_read(notification_id, current_user)
except EntityDoesNotExist:
raise HTTPException(status_code=404, detail="Notification not found")
except PermissionError:
raise HTTPException(status_code=403, detail="You are not allowed to mark this notification as read")
return {"message": "Notification marked as read successfully"}

@router.post("/notifications/read-all")
async def mark_all_notifications_as_read(current_user: User = Depends(get_current_user)):
notification_service.mark_all_notifications_as_read(current_user)
return {"message": "All notifications marked as read successfully"}

@router.post("/notifications/send-push-notification")
async def send_push_notification(notification: NotificationRead, current_user: User = Depends(get_current_user)):
try:
notification_service.send_push_notification(notification.notification_id, current_user)
except EntityDoesNotExist:
raise HTTPException(status_code=404, detail="Notification not found")
except PermissionError:
raise HTTPException(status_code=403, detail="You are not allowed to send push notification for this notification")
return {"message": "Push notification sent successfully"}
2 changes: 2 additions & 0 deletions ara/domain/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class EntityDoesNotExist(Exception):
pass
14 changes: 14 additions & 0 deletions ara/domain/notification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pydantic import BaseModel
from typing import Optional

class Notification(BaseModel):
id: int
type: str
title: str
content: str
related_article_id: Optional[int]
related_comment_id: Optional[int]
is_read: bool

class Config:
orm_mode = True
24 changes: 24 additions & 0 deletions ara/infra/notification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from fastapi import HTTPException
from sqlalchemy.orm import Session
from ara.domain.notification import Notification
from ara.domain.user import User
from ara.domain.exceptions import EntityDoesNotExist
from typing import List

class NotificationRepository:
def __init__(self, db: Session):
self.db = db

def get(self, notification_id: int) -> Notification:
notification = self.db.query(Notification).filter(Notification.id == notification_id).first()
if not notification:
raise HTTPException(status_code=404, detail="Notification not found")
return notification

def save(self, notification: Notification):
self.db.add(notification)
self.db.commit()

def get_notifications_for_user(self, user: User) -> List[Notification]:
notifications = self.db.query(Notification).filter(Notification.user_id == user.id).all()
return notifications
77 changes: 77 additions & 0 deletions ara/service/notification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from fastapi import HTTPException
from sqlalchemy.orm import Session
from ara.infra.notification import NotificationRepository
from ara.domain.notification import Notification
from ara.domain.user import User
from ara.domain.exceptions import EntityDoesNotExist
from ara.infra.firebase import fcm_notify_comment # assuming fcm_notify_comment is imported from correct path
from ara.domain.article import Article # Import Article and UserProfile from appropriate paths
from ara.domain.user_profile import UserProfile
from ara.domain.comment import Comment

class NotificationService:
def __init__(self, notification_repo: NotificationRepository):
self.notification_repo = notification_repo

def get_display_name(self, article: Article, profile: UserProfile) -> str:
"""
Returns the display name for an article based on its name type and user profile.
"""
if article.name_type == NameType.REALNAME:
return profile.realname
elif article.name_type == NameType.REGULAR:
return profile.nickname
else:
return "익명"

async def notify_commented(self, comment: Comment) -> None:
"""
Notifies users when a comment is added.
"""
article = comment.parent_article if comment.parent_article else comment.parent_comment.parent_article

if comment.created_by != article.created_by:
await self._notify_article_commented(article, comment)

if comment.parent_comment and comment.created_by != comment.parent_comment.created_by:
await self._notify_comment_commented(article, comment)

async def _notify_article_commented(self, parent_article: Article, comment: Comment) -> None:
"""
Notifies the user when a comment is added to their article.
"""
name = self.get_display_name(parent_article, comment.created_by.profile)
title = f"{name} 님이 새로운 댓글을 작성했습니다."

# Save the notification
notification = Notification(
type="article_commented",
title=title,
content=comment.content[:32], # Truncate content if necessary
related_article=parent_article,
related_comment=None
)
await self.notification_repo.save(notification)

# Send push notification
await fcm_notify_comment(parent_article.created_by, title, comment.content[:32], f"post/{parent_article.id}")

async def _notify_comment_commented(self, parent_article: Article, comment: Comment) -> None:
"""
Notifies the user when a comment is added to their comment.
"""
name = self.get_display_name(parent_article, comment.created_by.profile)
title = f"{name} 님이 새로운 대댓글을 작성했습니다."

# Save the notification
notification = Notification(
type="comment_commented",
title=title,
content=comment.content[:32], # Truncate content if necessary
related_article=parent_article,
related_comment=comment.parent_comment
)
await self.notification_repo.save(notification)

# Send push notification
await fcm_notify_comment(comment.parent_comment.created_by, title, comment.content[:32], f"post/{parent_article.id}")

0 comments on commit 7442a29

Please sign in to comment.